Skip to main content
Mahnservice takes invoices from several places: connected bookkeeping systems, a CSV import, manual entry in the portal, and this API. They all land in one invoice list, but they are not all yours to change.

One writer per invoice

Every write in this API — correct, release, report a payment, cancel, write off, upload a document — applies only to invoices this API created. An invoice synchronized from a connected bookkeeping system is fully readable here (list, retrieve, its payments, its documents, its dunning state) and answers 409 not_api_invoice on every write, before any other conflict is evaluated. HEAD on the payments and documents routes mirrors the corresponding GET — same status, empty body — and never writes, whatever body accompanies it. That is not tidiness. Releasing a synced invoice would bypass the import cut-off date the customer configured; an API payment would collide with the bookkeeping system’s own payment detection; and a document upload would replace the accounting system’s original PDF. The bookkeeping system owns those rows. The practical consequence for an integration: a company that connects a bookkeeping system does not need this API for those invoices, and this API cannot be used to take them over. Read them, and write only what you submitted. Debtors and invoices cannot be deleted through the API. An invoice ends through payment, cancellation, or write-off.

API credentials and terms

Mahnservice requests use the current /mahnservice/v1/ routes and the same company-bound Bearer key as the Case Management API. Create the key in the developer portal. The X-On-Behalf-Of-Company header is not accepted on Mahnservice routes (400 unexpected_company_context). If a credential is not permitted for an operation, the API returns 403 permission_denied. Contact paywise support if access is unexpectedly denied. The API terms of use your company accepts for that key cover both APIs. A production write (every POST or PATCH except payment reporting) requires the current terms to have been accepted. Without acceptance the write returns 403 terms_acceptance_required; if the terms cannot be verified, it returns 503 api_terms_unavailable. Retry the latter later; the request was not applied. Reads, /info/, payment reporting, and the sandbox are exempt.

Reads and payment reporting survive a lapsed subscription

In production, Mahnservice is a subscribed product. Writes require an active subscription and answer 403 subscription_required without one — also when the subscription state cannot be verified at that moment. The sandbox allows integration testing without purchasing a subscription or providing a payment method. Two things stay open through a lapse:
  • every read, so an integration keeps reconciling instead of going blind;
  • payment reporting, deliberately. A customer whose subscription lapsed must still be able to stop dunning on an invoice that was paid. Leaving that path open is a product decision, not an oversight.
Everything else write-shaped — submitting, correcting, releasing, cancelling, writing off, uploading a document — needs the subscription. An administrative lock is different. When paywise has locked a company’s Mahnservice account, every write — payment reporting included, and regardless of the credential’s access_mode — answers 403 company_locked (“Your Mahnservice account is currently locked by paywise. Please contact support.”). The lock outranks the subscription check, so a locked company with a lapsed subscription hears company_locked, not subscription_required. Reads stay open. The three 403 codes on this API are therefore permission_denied (the credential is not permitted for the operation, or is not bound to a company), subscription_required, and company_locked; production writes additionally require the accepted API terms of use (403 terms_acceptance_required, see API credentials and terms). A credential must be bound to a company. A key without a company binding answers 403 permission_denied with “This credential is not bound to a company.” on every route, GET /mahnservice/v1/info/ included. Disabling API access for the key’s user and company in the portal’s API settings turns every request into 401 authentication_failed with “API access is disabled for this company.” (this switch also covers the legacy Case Management API v1; the current /v2/ APIs do not consult it).

Debt collection ends this API’s authority over a claim

When a claim is handed to paywise debt collection, its dunning_state becomes inkasso, and the collection case — not this API — decides the outcome:
  • cancel, write-off, PATCH, document upload, dunning/pause, and dunning/resume answer 409 invoice_in_inkasso. Retracting a transferred claim goes through paywise support.
  • A payment is recorded and does not settle the claim. Even a payment covering the full amount leaves the state at inkasso.
That last point is intended behaviour, and it is worth designing around. Reporting a payment on a transferred claim through this API stores it, and it does not close the collection case, reduce what the case is collecting, or notify the collection side. There is no write-back closing that loop. If a debtor pays you directly after a handover, report it to paywise support (or through the Case Management API against the mandate) so the collection case reflects it; the record you create here is data, not a settlement. The collection case starts when paywise accepts the handover order. If your company withdraws that order before acceptance, or paywise rejects it, no collection case will exist. The invoice then leaves inkasso for completed: current_level and next_action_date become null, updated advances, dunning does not resume, and no webhook is sent for this change. If the payments reported while the invoice was in inkasso cover its amount, it goes on to paid with the usual invoice.paid event instead. From then on it behaves like any completed invoice: cancel and write-off work again, and you can hand it over to collection again in the paywise Mahnservice app, which creates a new order.

Environments

Production and sandbox are separate hosts with separate, non-interchangeable credentials. A key works only in its own environment; a key of the other environment is refused with 401. GET /mahnservice/v1/info/ reports the installation in environment (sandbox or production), matching the X-Paywise-Environment response header. Check it before a rehearsal that writes. access_mode appears on the credential, on debtors, and on invoices. It is a read-only compatibility field for the credential’s data lane. Modern keys return production in both installations, including pw_sbx_ sandbox keys. That allows the sandbox to exercise the dunning lifecycle while outbound mail is still captured and all data stays in the sandbox. It does not select an environment or enable production effects. Legacy test-mode credentials still exist for some long-standing integrations; those invoices remain visible in the portal of their installation but are never dunned. Do not use access_mode to detect the sandbox or send it as a writable property. To develop against the sandbox, see Sandbox environment.