maesn
Use case

Tax automation starts with a rate that explains itself

Twelve of the connected accounting systems expose their tax rates today, and they do not agree on what a tax rate is. Maesn delivers them in one shape, says what a system left out, and writes the finished booking back into the ledger it came from.

One rate, as delivered/taxRates
percentage21
typedecides the rest
INCLUSIVEThe 21 is already inside the amount.
EXCLUSIVEThe 21 is added on top of the amount.

Four values are documented for that field. It appears in the field list of one of the twelve systems that publish tax rates.

Trusted by winning software teams
HubSpotTipaltiPaywiseRallyQredNordhealthFindityFintoClockinProvetHeroHolviLanes & PlanesHubSpotTipaltiPaywiseRallyQredNordhealthFindityFintoClockinProvetHeroHolviLanes & Planes
The problem

The tax rate arrives, the rule for applying it does not

A tax product reads rates out of its customers' accounting systems. Across the twelve that publish them, the documented field lists differ in ways that change the arithmetic.

What the rate may be applied tousage
not documented
bexio, Business Central, Dinero, Snelstart, Xero
5 systems
INVOICEBILL
QuickBooks, Twinfield
2 systems
INVOICEBILLCASH
DATEV Unternehmen Online, DATEV Rechnungswesen
2 systems
INVOICEBILLALL
Exact Online, Procountor
2 systems
INVOICEBILLJOURNAL_ENTRYALL
Moneybird
1 system
Two more field lists worth reading
  • Business Central documents four fields for a tax rate, and percentage is not among them.
  • Procountor states that only one of code and percentage is provided per entry, so a rate may arrive as a code with no number at all.

Start with the field that decides the most. A rate can be inclusive or exclusive, meaning the percentage is either already inside the amount or added on top of it, and the reference is explicit that this is what the field is for. It appears in the field list of one system out of the twelve. On the other eleven you receive a number and no statement of how to use it.

That is not a rounding problem. A product that treats every percentage the same way is not wrong in an edge case, it is wrong every time it meets the other convention, and it is wrong by exactly the size of the tax. The individual numbers were never going to be the hard part of this integration. What each system means by them is.

The list above is the second half of it. What a rate may be applied to comes in four documented shapes, and in five systems it is not documented at all. Two of those shapes decide whether a system fits a given product at all. Exactly one names journal entries as a permitted use, which is the one a platform that books rather than invoices needs, and only the two DATEV products name a cash use, which is a distinction German bookkeeping makes and most of the others do not. Underneath sit two more field lists worth reading closely. Business Central documents four fields for a tax rate and the percentage is not one of them, while Xero documents two fields in total. Both are useful systems with strong coverage elsewhere. They simply do not answer this question the same way, and no amount of client-side cleverness turns an undocumented field into a known one.

How Maesn solves it

One tax rate object, and a place for what is missing

The same endpoint on every system, the same field names in the response, and an envelope that states when a system did not fill one of them.

The same keys on every system

A tax rate is one object with one set of field names, whether it came from a Dutch, German or Finnish system. Your code reads one shape and stops branching per vendor.

The application rule as a field

Where the system publishes how a rate is meant to be applied, it arrives in a typed field with documented values rather than inside a label a human wrote.

A named place for what is missing

The response envelope carries a warnings array, and the example in the reference reads exactly "Field not used by target system". An unfilled field is stated rather than silently defaulted.

GET /accounting/taxRates
{
"meta": {
"warnings": ["Field not used by target system"],
"pagination": { "total": 125, "perPage": 50, "currentPage": 1 }
},
"data": [
{
"id": "b0450a0a-4164-4b5a-b006-1f3e835c32ff",
"code": "02",
"name": "21 PERCENT",
"description": "BTW hoog tarief, exclusief",
"percentage": 21,
"type": "EXCLUSIVE",
"usage": "INVOICE"
}
]
}

The shape on the right is the whole normalization argument in one response. A tax rate is a rate, a code, a label, an application rule and a permitted use, and it carries those names whether it came from a Dutch, a German or a Finnish system. That is the same principle the rest of the API is built on, described in full under the common data model, and tax is where it earns its keep fastest, because the alternative is a per-vendor mapping table that has to be right about arithmetic.

What Maesn does not do is fill in the rule a system never published. This is the honest half of the answer, and it is the same two-layer distinction that runs through these pages: normalization makes twelve field lists into one shape, and it cannot invent information that was not in any of them. Where the source system publishes the application rule, you get it in a typed field. Where it does not, the response says so instead of quietly defaulting, since the warnings array in the envelope exists for exactly that and the reference's example for it reads Field not used by target system.

One practical detail before the first call. Seven of the twelve field lists carry a note that a company identifier, and for one system an environment name, has to be supplied unless you use the interactive authentication flow, where the customer picks it once and the choice is stored on the connection. That is a property of the authentication layer rather than of tax, and it is the difference between one connection and a support ticket about the wrong company's rates.

What you get

From the rate you read to the journal entry you post

Reading rates is the start of the job, not the job. A tax product proves itself when the booking lands in the customer's ledger correctly, and the documented flow for that is a short chain of reads followed by a single write.

What the guide has you read
GET /accounts
The account and the contra account
GET /taxRates
The rates or tax codes in use
GET /dimensions
Classes, locations, departments
GET /journals
Where a system keeps several

The last two are conditional: the guide asks for them only where a customer uses them.

one connection, one shape
What lands in the ledger
  • One entry in the system's structure
  • Receipts attached in the same request
  • Bulk upload where a system takes it
  • A status you can check, not a hope

The write is one call, and two properties of it are worth knowing before you design around it. Receipts, statements and vouchers go up in the same multipart request as the entry, so the document and the booking are never two jobs that can half succeed. And where a system takes entries as a batch, as DATEV Rechnungswesen does, the documented step after the upload is to ask a task endpoint whether the batch was actually processed. That is no special mechanism for tax, it is the same asynchronous pattern the rest of the API uses, and it is the difference between believing a batch went in and knowing it.

The chain also explains why tax automation is rarely only about tax. The rates are one read of four, and the other three are the ledger structures the entry needs in order to be valid at all. Bills carry rates on the payable side, described under accounts payable, and invoices carry them on the receivable side, under invoice creation. The permitted-use field names those two documents by name on seven of the twelve systems, which is the docs telling you, in an enum, that these three use cases are one integration.

Proof

One published customer in exactly this category

A customer in this category
Smarta Steuern
Smarta Steuern, a tax automation SaaS, runs on this API.

It is one of the named customers Maesn publishes, in exactly this category. What they built with it is theirs to describe, so this page does not.

Four customers have told their story in full, in other categories.

That is one customer, and it is stated as one customer. The named categories Maesn publishes run far wider than tax, and the platforms that carry a tax workflow next to their own are collected on the SaaS industry page, where the same connection is the last step of fifteen different professions.

Key facts

What the booking chain needs, counted per system

One row per step of the documented flow, counted from the per-system documentation.

Across the 29 connected systems
What you needTodayOn demandSystem cannot
Chart of accounts, reading1982
Tax rates, reading12143
Dimensions, reading3179
Journals, reading5159
Journal entries, writing10118
Trial balance, for reporting2720
Rows three and four are the two steps the booking guide itself marks as conditional, which is consistent with how thinly they are covered: it asks for dimensions where the customer uses them and for journals where a system keeps several. The last row is the honest limit of this use case. A trial balance is what a filing or a reporting product would want, and two systems expose it today, so nothing on this page promises one.

The two rows that carry this use case are the chart of accounts and the tax rates, and both are among the better covered objects in the model. Writing entries back is supported on exactly as many systems as reading them, which is the number that decides whether a tax product can complete its own workflow or has to hand the last step to a human with a CSV file.

Read the thin rows as the guide reads them rather than as a shortfall. Dimensions and journals are the two steps it marks conditional, wanted only where a customer works with dimensions or a system keeps several journals, so a small number there is describing how rare the requirement is as much as how rare the support is. Where a system keeps a tax structure the shared model has no field for, reaching past the model is documented too: a raw data flag is available on ten of these twelve systems, and it returns the system's own payload next to the normalized object. Reading only what changed since your last run works the same way here as it does for every other list endpoint, which matters less for rates, since they change rarely, than it does for the entries you post against them.

DATEVAbout the systems, not about a customerMaesn is a DATEV Interface Partner (Schnittstellenanbieter).Both DATEV products in the reference publish tax rates, and they are the two that document a cash usage alongside invoice and bill. Germany's tax practice runs there, which is why the partnership matters more here than any claim about coverage.
Where the line runs

We deliver the rates, you decide which one applies

On a tax page this is the section to read first. The line between delivering a rate and applying it is also the line between an integration problem and a regulated one.

What Maesn delivers
  • The rates as published
  • The same shape everywhere
  • The rule where it exists
  • The booking, written back
What stays your product
  • Which rate a line gets
  • Country and period rules
  • When a booking is sent
  • What a filing has to show

Everything on the left is a property of the connection. The rates arrive as the target system publishes them, in one shape across twelve systems, with the application rule included wherever the system states it and marked as absent where it does not. The booking goes back the same way, into the structure the customer's accountant already works in, rather than into a format somebody has to import.

Everything on the right is your product, and on this use case that is a sharper statement than usual. Choosing the rate for a line is a tax decision. So is knowing which rate was valid in a given period, what a jurisdiction expects on the document, and what a filing has to contain. Those answers change by country and by year, they carry consequences for your customer, and a data layer that offered them would be guessing on your behalf in a domain where guessing has a price.

Two smaller properties belong here rather than in a footnote. Requests are processed as they come in, and what Maesn keeps is the record that a transfer happened rather than the transferred data, which is a shorter conversation to have with a customer whose tax data you touch. And the decision of when a booking leaves your product is yours by design: the documented flow puts the trigger in your hands, whether that is a button, an event or a nightly run.

The rate on a line is what has to be answered for at period close by financial teams.

Tax Automation FAQ

Common questions

Does Maesn calculate tax?

No, and that line is deliberate rather than a gap. Maesn delivers the tax rates a system publishes, in one shape, along with whatever the system says about applying them. Which rate belongs on which line, in which country, at which point in time, is your product's judgement and often a regulated one. A layer that made that call for you would be taking on a liability it cannot carry.

Which systems can we read tax rates from today?

Twelve of the connected systems support it today, fourteen more are marked on demand in their own documentation and three cannot do it at all. The twelve are bexio, Business Central, both DATEV products, Dinero, Exact Online, Moneybird, Procountor, QuickBooks, Snelstart, Twinfield and Xero. That set is worth knowing precisely, because it is the same twelve whose field lists the reference describes one by one.

What is the type field, and why does it matter so much?

It states how the rate relates to an amount, with four documented values: inclusive, exclusive, zero tax and no tax. It is the difference between a percentage that is already inside the price and one that is added on top, which is the difference between an invoice that is right and one that is wrong by exactly that percentage. In the reference it appears in the field list of one of the twelve systems.

So what do we do on the other eleven?

You get the rate as the system publishes it, and the application rule comes from somewhere else: your own configuration, the customer's setup, or a convention for that market. The reference's own example is a warning worth reading twice, because its sample description says "BTW hoog tarief, exclusief". The rule is sitting in a human-written label there, in Dutch. That is a hint for a person, not a field to parse, and treating every percentage identically is the failure this page is about.

What does the usage field tell us?

What the rate may be applied to. It comes in four documented shapes across the twelve systems, and five of them do not document it at all. Two DATEV products list a cash option next to invoice and bill, two systems list an all option, and Moneybird alone includes journal entries. If your product picks rates for bookings rather than for invoices, that single difference decides which systems can serve you without a manual mapping.

Can we create or change a tax rate through the API?

No system supports that today. Tax rates are a read in practice: the numbers in the tables here are all reading, and creating, updating and deleting stand at zero across every connected system, with the rest marked on demand or unsupported. In this use case that is the right direction anyway, since the tax configuration belongs to the accountant who set it up, not to the product that consumes it.

How does a booking actually get written back?

Through the documented flow this page is built on. Your customer authorises once, you read the chart of accounts, the tax rates and, where relevant, dimensions and journals, then your own trigger decides when to transfer and one call creates the journal entry. Receipts and vouchers travel in the same multipart request rather than as a second job, which matters when a booking has to be auditable later.

Can we send bookings in bulk, and how do we know they were accepted?

Where the system supports it, yes. DATEV Rechnungswesen takes journal entries as a batch, and the documented follow-up is to poll a task endpoint to confirm the batch was processed rather than assuming it. That is the same asynchronous pattern the rest of the API uses for long-running work, so it is one mechanism to learn instead of a special case for tax.

What if a system holds a tax structure the shared model does not carry?

There is a documented way to reach it. A raw data flag returns the target system's own payload alongside the normalized object, and it is documented on ten of the twelve systems that publish tax rates. For anything the model has no field for at all, a native call through the pass-through endpoint reaches the system directly on the connection you already have.

Do you deliver VAT returns or a trial balance?

No, and the numbers say why rather than the marketing. A trial balance is what a filing or reporting product would build on, and two of the connected systems expose one today. So this use case is about the rates, the ledger structures and writing bookings back, and anything shaped like a tax return stays outside it. Naming that limit is cheaper for both of us than discovering it in an integration.

Build once on the Unified API.

See how tax automation works for your integration, or dive into the technical reference.