maesn
For developers

How to integrate with sevdesk: Two bookkeeping versions in one tenant

The sevdesk token is simple, the pagination is ordinary and there are no webhooks to configure. What costs you a week is sevdesk-Update 2.0, the bookkeeping change sevdesk shipped in 2024: the same tenant returns one shape for older records and another for newer ones, and which tax rule you may write depends on a setting only that client knows.

Lennart Svensson, CTO and Co-Founder at Maesn
Lennart Svensson
CTO and Co-Founder · · Updated
Illustration for How to Integrate with sevdesk: Two Bookkeeping Versions
The context

The token never expires, and it dies with the user

Getting in is the easy part. Every sevdesk administrator has one token, a hexadecimal string of 32 characters, and it goes into the Authorization header on every call. There is no OAuth dance, no refresh cycle and no expiry to schedule around.

The catch is what the token is attached to. Sevdesk puts it plainly: “The api tokens have an infinite lifetime and, in other words, exist as long as the sevdesk user exists.” The next line is a warning in capitals, that the user should never be deleted. Remove that person from the account and the integration stops, with 401 and no notice.

The whole authentication, and one paginated readHTTP
GET /api/v1/Invoice?limit=50&offset=0&countAll=true HTTP/1.1
Host: my.sevdesk.de
Authorization: b7794de0085f5cd00560f160f290af38
Accept: application/json
User-Agent: Acme Billing by Acme GmbH

The token is the header value on its own, with no scheme in front of it. Sevdesk also asks for a meaningful User-Agent, in its words so it “can offer better support in case of queries from customers”.

Token format, header and lifetime from sevdesk’s authentication section, checked 11 August 2026. The token in the sample is the one sevdesk prints in its own documentation, so it is an illustration rather than a working credential.

Your customer can replace the token, and only they can send it to you

Sevdesk lets the token be replaced. A generate new control sits beside it in your customer’s account and is confirmed with their password. The part to plan for is what happens next: the replacement exists only in their account, sevdesk does not notify you, and the old token stops working the moment the new one is created.

So give your customers a way to hand you a new token from inside your own product, before the first one is ever replaced. Without it, every rotation becomes a support conversation with a broken integration behind it.

One more line is worth reading twice, because it decides your onboarding copy. Sevdesk warns that a token cannot be shown again after it is created: “it is advisable to save the api token as we will NOT be able to retrieve it afterwards”. Whoever collects it from the customer only gets one attempt.

The problem

One tenant can return two bookkeeping versions

This is the part the older write-ups miss, and it is the one that costs a week. In 2024 sevdesk changed its bookkeeping engine in a release it calls sevdesk-Update 2.0, and the change did not migrate the past. Records created under the old system keep returning the old shape while new ones return the new one, from the same account, on the same endpoint.

Concretely: orders, invoices, vouchers and credit notes created under system 1.0 still come back with a taxType such as default. The same objects created since the update come back with a numbered taxRule instead. Your parser meets both, and nothing in the payload says which is which.

One sevdesk tenantTwo response shapes
Created in system 1.0
"taxType": "default"

Still returned for every record that existed before the update.

Created in sevdesk-Update 2.0
"taxRule": 1

Returned for everything created since, with a numbered rule instead of a name.

Neither payload tells you which world you are in. The bookkeeping system version is its own call, and it is the one that decides which tax rules a write may use.

The split runs through the account, not between accounts. Fields and behaviour from sevdesk's update notes.
The call that belongs before every other oneHTTP
GET /api/v1/Tools/bookkeepingSystemVersion HTTP/1.1
Host: my.sevdesk.de
Authorization: <your customer's api token>
Accept: application/json

One call per connected tenant, cached for the session. It decides which tax vocabulary a write may use, and it is the only place the answer exists.

The update, the field change and the version endpoint from sevdesk’s sevdesk-Update 2.0 notes, checked 11 August 2026. Sevdesk describes the old system as available to some customers until the end of 2024, so new connections land on the new one while their history does not.

Sevdesk offers a bridge rather than a cliff. Where you still send taxType with the values default, eu or ss, those are mapped onto the new rules for a transition period. The recommendation is to move anyway, because the new set has options the old one never had.

What is gone without a bridge is taxType: custom together with a custom taxSet. Sevdesk removed it for a reason it states directly, a high likelihood of non compliant accounting, and the same pass removed custom accounting types as well.

A normalised data model is the obvious answer to a system with two vocabularies, and it is what the common data model does for this and for the 30+ systems next to it.

The problem

Which tax rule you may use depends on the client

Reading tolerates both worlds. Writing does not, because the new model ties three things together: the rule, the rate that rule permits and the account behind it. Get the combination wrong and the write comes back 422 rather than being quietly accepted.

The shape of the constraint is easy to underestimate. Of the ten revenue rules for a standard taxpayer, exactly two allow the rates a German invoice usually carries: the ordinary one and intra community supplies. Five permit a single value, and that value is zero. The three One Stop Shop rules depend on the destination country.

Revenue rules for a standard taxpayer, with the rates each one permits
Tax ruleAllowed ratesReplaces
1 · Umsatzsteuerpflichtige Umsätze0.0 · 7.0 · 19.0taxType: default
2 · Ausfuhren0.0No predecessor
3 · Innergemeinschaftliche Lieferungen0.0 · 7.0 · 19.0taxType: eu
4 · Steuerfreie Umsätze §4 UStG0.0No predecessor
5 · Reverse Charge §13b UStG (field 60)0.0No predecessor
21 · Reverse Charge §18b UStG (field 21)0.0No predecessor
17 · Nicht im Inland steuerbar0.0taxType: noteu
18–20 · One Stop Shopdepends on countryNo predecessor

Rules, permitted rates and the deprecated properties from sevdesk’s tax rules table, checked 11 August 2026. The table above is the revenue half for a standard taxpayer. Sevdesk publishes three more, for expenses and for small business owners, and a small business client has exactly one revenue rule available.

A rate that belongs to its ruleJSON
{
"invoiceType": "RE",
"taxRule": 1,
"invoicePos": [
{ "quantity": 1, "price": 1000.0, "taxRate": 19.0 }
]
}

With taxRule: 2 the same position would have to carry 0.0, and 19.0 would be rejected. The pairing is the validation, not the number on its own.

Ask the account, do not hardcode the table

Which accounts, rates and rules fit together is not a constant. It depends on the client’s own settings, small business status among them, and sevdesk exposes a Receipt Guidance endpoint for exactly that question. Reading it once per tenant is cheaper than discovering the answer through 422 responses, and it is the only version of this list that stays correct.

Two more rules changed shape rather than value, and both bite at the end of a flow. A voucher can no longer be created as paid, only as DRAFT or UNPAID, with a separate call to book the amount afterwards. And enshrined stopped being a property you set: it has its own endpoint now, once for vouchers and once for bank transactions.

Advance and partial invoices carry their own restriction, and it is narrow. They can only be created under the ordinary revenue rule, or under the small business rule for a small business client. The One Stop Shop rules exclude them entirely, along with e-invoices and custom revenue accounts.

How it works

Pagination hides the total, and the count is a string

Reading is conventional, with two details that catch people. Sevdesk pages with limit and offset, the limit sits between 1 and 1000, and there are no cursors. The total number of records is not included unless you ask for it with countAll=true, which defaults to false.

When it does arrive, it arrives as a string. The response reads {"total": "157", "objects": [...]} with the number in quotation marks, so a strictly typed parser that expects an integer in that field will fail on it rather than convert it. Declare it as a string and convert it yourself, and the surprise disappears.

Worth noting against the maximum: sevdesk’s own guidance is to “keep limit values reasonable (between 10-100) to avoid performance issues”. The ceiling is 1000, the recommendation is a tenth of it, and the offset model slows down as you walk deeper into a large set.

One parameter repays learning early. embed pulls nested resources out in full instead of as an id and a name, and it takes several names separated by commas. An invoice that would otherwise cost you a second call per contact can arrive complete, which matters more here than on systems with generous limits, because the cost of the extra round trip is entirely yours.

Pagination parameters, the response format and the quoted guidance from sevdesk’s API requests section, checked 11 August 2026.

How that reads once it is normalised across systems, including the ones that page with cursors instead, is the unified pagination and filtering page.

How it works

Sending no version header pins you to the oldest

Sevdesk versions individual resources rather than the API as a whole, through an X-Version header on the request. Leave it out and you get default, and sevdesk defines default as the value that should “always reference the oldest version”.

That is the reverse of the habit most platforms teach. Elsewhere, sending nothing keeps you on the current shape; here it freezes you on the oldest one a resource has, quietly and for as long as you never look. Set the header deliberately, per resource, and write the value down somewhere your team will find it.

The reference adds one trap underneath: a resource can exist under default and not under 1.0, so a version number is not automatically safer than the default. And every response carries a Deprecation header, either true or a timestamp. That header is the earliest warning you get that a resource is going away, and nothing else will tell you.

Resource versioning, the definition of default and the deprecation header from sevdesk’s API requests section, checked 11 August 2026.

How it works

Nothing calls you, and nothing throttles you either

Sevdesk sends no events. Not a thin set, not a beta: the word webhook does not appear anywhere in its reference, and no object in our own coverage data carries a native event. Whatever you learn about a customer’s books, you learn by asking.

The second half is the one that changes the design. Sevdesk publishes no rate limit either. There is no documented ceiling, no quota and no 429 in its status code table. So the platform neither tells you when something happened nor tells you how often you may ask.

Who sets the paceMeasured in the documentation
Events sevdesk sends you
None
No webhooks, no callbacks, no subscriptions. The word does not occur in the reference.
Rate limit sevdesk publishes
None
No documented ceiling and no 429 in the status code table. Its own advice is to keep limit between 10 and 100.

Both blanks point the same way. With no event to react to and no ceiling to respect, the polling interval is a product decision rather than a constraint you discover in production.

Both figures are absences measured in the reference rather than estimates.

Counted across sevdesk’s complete API reference on 11 August 2026: zero occurrences of webhook or callback, zero of rate limit, quota or 429. The event coverage figure is counted from our own generated coverage data, where 8 of the 30+ connected systems carry a native event and sevdesk is not one of them.

Practically, the sync design is yours to choose and yours to defend. Poll the objects that change often at a rhythm that matches how quickly your product must know, keep the rest slow, and remember that every cycle costs a call whether or not anything moved.

What the same problem looks like when one event model is put over systems that have events and systems that do not is on the unified webhooks page.

How it works

A 500 can mean your request was malformed

Since every call is yours to make, every failure is yours to interpret, and one line in sevdesk’s status code table should change your retry logic. Sevdesk writes that a 500 normally means something went wrong on its side, “however, sometimes this error will appear if we missed to catch an error which is normally a 400 status code”.

A 500 is therefore not reliable evidence that the problem is temporary. A blind exponential backoff will retry some malformed requests forever, growing its wait each time, against a payload that was never going to be accepted. Log the request body with the failure, and stop retrying a 500 that comes back identical.

The status code table and the quotation from sevdesk’s API requests section, checked 11 August 2026.

What you get

Going live needs no approval, the listing needs ten users

After DATEV this reads like a different industry. Sevdesk asks for nothing before you build and nothing before you go live. In its own words, anyone can build an integration against its documented interface and “eine Freigabe oder Zustimmung durch sevdesk ist nicht notwendig”, no release and no consent required.

The partner programme is a separate track, and it starts once the integration is real. You publish it yourself and run it with ten users in production, which is where sevdesk expects you to find and fix the rough edges together with them.

Only then does an application form appear, and with it the one review in the whole process: sevdesk checks the integration against accounting requirements. A short onboarding follows to coordinate both sides, and the partnership launches with visibility in the sevdesk ecosystem.

All five steps and both quotations from sevdesk’s technology partner page, checked 11 August 2026, in German. Our own documentation describes the same route and is worth reading alongside it, with one nuance it leaves out: there is no approval to go live, and there is a review to become a partner.

For a test account there is one route and it costs nothing. Sevdesk recommends creating a trial rather than developing against a live account, and notes that a trial sits in the highest tariff, so every sevdesk function can be tested against it.

The trial recommendation and the tariff from the “Your First Request” section of sevdesk’s API reference, checked 11 August 2026: “A trial account will be in the highest tariff (materials management), so every sevdesk function can be tested”.

Where our part ends

What Maesn covers, and what stays with you

The connection itself is short work here, and that is exactly why the rest deserves the attention. What we take off the list:

  • The two vocabularies collapse into one. Whether a record predates the 2024 update or not, it reaches your code in the same shape as an invoice from any other system, so the version split stops being a branch in your parser.
  • Pagination is normalised. The count you have to request, the string total and the offset walk are handled behind one interface that pages the same way for every system.
  • The key never has to travel by email. Your customer enters it in a hosted step or in your own interface through the headless route, and the token is stored per tenant. What the connection looks like object by object is on the sevdesk API page.

What stays with you, and one of these is a decision rather than a task:

  • The polling interval. We do not turn sevdesk into an event source, because it is not one. How fresh your product needs to be, and what that costs in calls, is a product decision we can inform and not replace.
  • The tax rule your write carries. Receipt Guidance tells you which rule and rate combinations sevdesk will accept for a given client. It cannot tell you which of those is the right one for the document in front of you, because that is an accounting judgement about your customer’s business rather than a mapping we could make for you.
  • The partner application, and the person behind the token. Reaching ten production users and filing the partner form is yours to do. Keeping the sevdesk user whose account issued the token in existence is your customer’s, and if they delete that person the connection stops. Neither is something we can do through an API, so both belong in your onboarding rather than in your integration.
FAQ

Frequently asked questions

What authentication does the sevdesk interface use?

A static token, a hexadecimal string of 32 characters, sent in the Authorization header. There is no OAuth, no refresh and no expiry. Sevdesk states the token lives as long as the sevdesk user does, which is why that user should never be deleted.

Can a sevdesk token be rotated?

Yes. Sevdesk documents a generate new control beside the token, confirmed with the account password. What it cannot do is rotate itself: the new value has to reach you, so plan a path for a customer to hand over a replacement without support work.

Does sevdesk support webhooks?

No. The word does not appear anywhere in its documentation, and no object in our coverage data carries a native event. You read on a schedule you choose, and since sevdesk publishes no rate limit either, nothing external sets that schedule for you.

How do I know which sevdesk bookkeeping version a client uses?

You ask, with the bookkeeping system version endpoint under Tools. It is not part of any payload. The answer decides whether older records reach you carrying taxType or the newer taxRule, and both can appear in one tenant.

Why does creating a sevdesk invoice return 422?

Usually because the tax rate does not belong to the tax rule. Most rules allow only 0.0, while the standard revenue rule allows 0.0, 7.0 and 19.0. The Receipt Guidance endpoint returns the combinations a given client may use, including whether they are a small business.

Do I need approval from sevdesk before going live?

No. Sevdesk states that building against its documented interface needs no release or consent. The partner programme is separate: you publish yourself, run the integration with ten users in production, then apply through a form and sevdesk reviews it against accounting requirements.

Build once on the Unified API.

Sevdesk has two bookkeeping versions, DATEV has two approval meetings and Xero meters what you read. Build against one interface and each of those becomes a row in a table rather than a project.