maesn
Use case

Accounts payable, all the way into the ledger

An AP product lives or dies on whether the posting lands correctly in the system your customer's accountant actually opens. Maesn delivers the suppliers, accounts, tax rates and dimensions that a correct posting needs, in one shape, across every connected system.

Before one bill postsfour reads
Suppliers in sync/contacts
Chart of accounts/accounts
Tax rates/taxRates
Dimensions/dimensions
one shape, every system
Then the write
POST /bills
POST /payments
Trusted by winning software teams
HubSpotTipaltiPaywiseRallyQredNordhealthFindityFintoClockinProvetHeroHolviLanes & PlanesHubSpotTipaltiPaywiseRallyQredNordhealthFindityFintoClockinProvetHeroHolviLanes & Planes
The problem

Accounts payable needs five things before one bill posts

Accounts payable looks like a write and behaves like a dependency chain. The documented sequence spends most of its steps before the first record is created.

What must already be true
/contactsSuppliers matched
/accountsThe ledger
/taxRatesTax codes in use
/dimensionsClasses, departments
What your product decides
  • Which account a bill lands in
  • Whether tax is set or chosen
  • Conditional rules per department
  • Override at the moment of sync
Then you write
POST /bills
POST /payments

Automatically, or when your user exports it. The docs leave that to your application.

And then it stays currentThe lastModified parameter works on every GET endpoint, so detecting what changed is a filter rather than a diff you build.

The create call is the short part. A bill needs a supplier it belongs to, a general ledger account it posts against and a tax code the receiving system recognizes, and each of those lives in the customer's own configuration rather than in your product. If the customer works with classes, locations or departments, those dimensions have to be read too, because a posting without them is filed in the wrong place even when every amount is right.

That is why the first stage of the sequence is reading rather than writing, and why supplier synchronization comes first. A bill references a vendor, so if your records and the accounting platform disagree about who that vendor is, you either get a rejected write or a duplicate that somebody has to clean up later. Getting that agreement in place is its own piece of work, which is why it has a use case of its own.

What Maesn changes is not the number of steps but how many times you implement them. The same four reads and the same two writes work the same way whether the customer is on DATEV, Exact Online or Xero, because they arrive through one normalized data model instead of in each vendor's own vocabulary. The sequence stays; the per-system rebuild goes.

How Maesn solves it

One connection for reading bills and writing them back

AP is rarely only outbound. Showing a user their own bills and putting your result back into the ledger travel over the same connection and the same authorization.

Both directions, one connection
Reading what is already there

To show your user their own bills, not a copy of them.

GET /bills

The list, filtered by date or status.

GET /bills/{id}

One bill in full, including line items.

GET /bills/{id}/document

The original document as the supplier sent it.

GET /bookingProposals

Bills captured elsewhere and uploaded since.

Writing what you produced

To put the result back where their accountant looks.

POST /bills

A bill your product produced.

POST /payments

The payment that settles it.

POST /bookingProposals

A document plus the data read off it.

POST /files

The document itself, where a system takes it.

The read side is what makes an AP product feel like it belongs to the customer rather than sitting beside their books. The documented read sequence lets you ask for bills filtered by date or status, open a single one with its line items, and fetch the original document as the supplier sent it, which is what an approval step actually needs to show somebody. Bills that never originated in the accounting platform are reachable too, through the booking proposal endpoints, so a document your product captured last week is not invisible this week.

Keeping that current is a filter rather than a comparison. The lastModified parameter works on the GET endpoints, so you ask for what changed since the last time you looked instead of storing a copy of everything and diffing it, and the same filtering and paging behaves identically on every system. Where a system emits events, webhooks do the job with less traffic still, which is exactly what the documentation recommends.

One boundary runs here. Writing the journal entries that follow a reconciliation is a different documented flow and belongs to payment reconciliation, not to this sequence. If what you need is to create an outgoing invoice rather than record an incoming bill, that is invoice creation.

How Maesn solves it

Two documented ways to capture a supplier invoice

Getting a supplier invoice into an accounting system has two documented routes, and the difference between them is who reads the invoice. Upload the file on its own and the system runs character recognition across the page, so the result is limited to what is legible on it. Send the structured data with the document and you can supply more detail than the document shows while avoiding mistakes from that recognition step.

Upload the document

OCR reads it

Requires Belegbilderservice enabled

You sendPOST /files
It readsthe document surface
You geta proposal to check

Upload document and data

no OCR guesswork

Requires Rechnungsdatenservice 1.0, a fiscal year, write rights

You sendPOST /bookingProposals
It readsthe fields you supply
You checkGET /asyncTask

Neither route is free of preconditions, and they are the kind that surface late if nobody checked. The file route needs the Belegbilderservice enabled in the end user's account. The structured route needs Rechnungsdatenservice 1.0, at least one fiscal year set up and the rights to write both accounts payable and accounts receivable, which is a conversation with the customer rather than a line of code. The full requirements per route are in the DATEV capture guide, and the vendor-side detail sits on the DATEV Unternehmen Online page.

Because the structured upload is processed rather than accepted on the spot, confirming it is its own step: you check GET /asyncTask to see whether the system took it. That is the same mechanism described under asynchronous processing, so the pattern for a long-running write is one your code learns once and reuses.

Proof

An AP platform already runs on this

Tipalti realizes their European integrations via Maesn.

With Maesn, we accelerated our European expansion by making complex ERP integrations seamless across Benelux and DACH. As an AP platform, reliable access to key local ERP systems is critical and Maesn gives us exactly that.
Saad Abouyahya
Sr. Manager, Global Technology Platforms & Strategic Partnerships at Tipalti

Tipalti is one of the larger accounts payable platforms and uses Maesn for several ERP integrations, Exact Online among them, to reach customers across the Benelux and DACH markets. The interesting part for anyone evaluating this is what an AP platform needs from an integration layer: not breadth for its own sake, but dependable access to the specific local systems its customers keep their books in.

Key facts

Accounts payable coverage, system by system

An average would hide the thing you need to know. These are the AP objects, counted per system, with what is supported today kept apart from what each system's documentation marks on demand.

Across the 29 connected systems
What you needTodayOn demandSystem cannot
Supplier records1928
Chart of accounts1982
Tax rates12143
Dimensions3179
Bills, reading8174
Bills, writing3224
Payments, writing6158
Captured documents10172
Read across, not down: a system in the third column has no such concept to write to, which no integration layer can invent. The middle column is what that system's documentation marks as on demand, which is worth asking us about for the systems you care about.

Two of these rows deserve a comment rather than a number. Dimensions are supported by fewer systems today than the rest of the chain, which is a fair reflection of how many accounting platforms treat classes and departments as an advanced feature. And captured documents turn out to be the broadest write in accounts payable, wider than creating a bill directly, which is worth knowing if you are deciding where to start.

The right-hand column is the honest one. When a target system has no concept of an object, there is nothing to normalize and nothing to write to, and an integration layer that reported full coverage there would be reporting a wish. The middle column is what each system's own documentation marks as on demand, and it is worth a specific conversation rather than an assumption in either direction. Separately from all three, reaching past the model covers the cases where one installation carries something the shared schema does not.

Where the line runs

We deliver the structures, you set the rules

The documentation is direct about where the line falls, and repeating that line here is more useful than promising accounts payable end to end.

What Maesn absorbs
  • Every system's word for a supplier
  • The connection and its refresh
  • Tenant identifiers, filled in
  • Change detection as a filter
What stays your product
  • Which account a bill posts to
  • Whether tax is derived or picked
  • How rules and overrides behave
  • When a bill leaves your product

The left column is the part that never stops needing maintenance: every system's own vocabulary for a supplier and an account, the authorization behind each connection and its refresh, the identifiers that say which tenant a call belongs to, and the specific way each platform wants a bill or a payment handed over. Those are absorbed once and stay absorbed, which is the whole reason to build on one authentication layer rather than per vendor.

The right column is your product, and it should be. How a bill is categorized is a decision about your customer's accounting policy, and the documentation says as much: the logic depends on your application. A layer that made that choice for you would be guessing at a policy it cannot see. What it can do is hand you the accounts, the tax rates and the dimensions in a form you can put in front of a user without translating them first.

Read the two columns together and the trade is clear. You keep the decisions that are specific to what you built, and you stop re-implementing the same four reads and two writes for every accounting system your next customer happens to use.

Seen from the other side of the ledger, an approval that never reached the system is what financial teams, who carry the consequence rather than the code.

Accounts Payable FAQ

Common questions

What does it actually take to post one bill into a customer's accounting system?

More than a create call. The documented sequence starts with suppliers: they have to exist and match on both sides, or the bill has nothing to attach to. Then you read the chart of accounts, because a bill needs a general ledger account, and the tax rates, because the amount needs a tax code the system recognizes. Dimensions come next if the customer uses classes, locations or departments. Only then do POST /bills and POST /payments have everything they need.

Do we have to synchronize suppliers first, or can we skip that?

The documentation makes it the first step, and the reason is practical rather than procedural. A bill references a supplier, so if your database and your customer's accounting platform disagree about who that supplier is, the write either fails or creates a duplicate vendor. Getting that agreement in place first is what makes everything after it repeatable.

Who decides which account a bill is posted against?

Your product does, and the documentation is explicit that the business logic depends on your application. Maesn delivers the accounts, tax rates and dimensions in one shape so you can present them in your own interface. Whether that becomes a single dropdown, a rule like posting IT department costs to one account, or a choice your user makes at the moment of export is your design decision.

Can we read bills as well as create them?

Yes, and in more detail than a list. GET /bills returns bills filtered by criteria such as bill date or status, GET /bills/{id} returns one bill in full including its line items, and there is a separate endpoint for the original document. Bills that were created somewhere else and uploaded to the accounting platform are reachable through the booking proposal endpoints.

Can we show our users the original invoice document?

Yes. GET /bills/{id}/document returns the original PDF as it sits in the accounting system, and captured documents have the equivalent endpoint under booking proposals. That matters for approval flows, where somebody has to look at the document itself and not only at the numbers read off it.

What is a booking proposal?

It is the object for a document that entered the accounting system without being created there. A supplier invoice you captured in your product and pushed across arrives as a booking proposal for the accountant to confirm, rather than as a finished posting. It is also how you reach bills that were captured elsewhere and uploaded since.

What is the difference between uploading a document and uploading data with it?

Both are documented routes and they differ in who reads the invoice. Upload the file on its own and the accounting system runs optical character recognition over it, which means the result is only as good as what it can see on the page. Send the structured data alongside the document and you can provide more detail than the document shows while avoiding mistakes from character recognition. The second route asks more of your product and gives a more predictable result.

What does DATEV require before we can capture documents?

Different things per route, and they are worth checking before you build. Uploading document files needs the Belegbilderservice enabled in the end user's DATEV account. Uploading documents together with structured data needs Rechnungsdatenservice 1.0, at least one fiscal year set up, and the access rights to write accounts payable and accounts receivable. DATEV also publishes interface requirements your application has to meet, including displaying certain user information in your own interface.

How do we know an upload actually went through?

For the structured route the documentation has you check GET /asyncTask, which reports whether the upload was processed. That is the same asynchronous task mechanism used elsewhere in the API, so the pattern for confirming a long-running write is one your code learns once.

How do we keep everything current after the first sync?

With a filter rather than a comparison. The lastModified query parameter works on the GET endpoints, so asking for what changed since a point in time replaces building and storing your own deltas. Where a system emits events, webhooks make the same job cheaper still, and the documentation flags them as the more efficient route.

Does every connected system support every part of this?

No, and there are three cases. Some objects are supported today across most systems, some are marked on demand in that system's documentation, and for some the target system has no equivalent concept at all, which no integration layer can create for it. The table on this page keeps those three apart rather than averaging them into one number, and the figures come straight from the per-system documentation. For anything in the middle column, ask us about the specific system you need.

Build once on the Unified API.

See how accounts payable works for your integration, or dive into the technical reference.