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 answers409 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 answer403 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.
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, itsdunning_state becomes
inkasso, and the collection case — not this API — decides the outcome:
cancel,write-off,PATCH, document upload,dunning/pause, anddunning/resumeanswer409 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.
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 with401.
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.
