Skip to main content
Each Mahnservice invoice can carry one PDF, up to 10 MiB (10,485,760 bytes) and 100 pages. Upload the bytes as multipart file or JSON base64, with an optional filename. Remote document URLs are not accepted. Uploading again replaces the current document, and is allowed only while the invoice is held. After release, uploads return 409 already_released; a settled, archived, or collection-transferred invoice answers 409 invoice_paid, invoice_cancelled, invoice_written_off, invoice_archived, or invoice_in_inkasso, a bookkeeping invoice 409 not_api_invoice — see the precedence table. The bytes are inspected synchronously before anything is stored. A file that is not a PDF is 400 unsupported, a truncated PDF without its %%EOF marker 400 corrupt, a password-protected PDF 400 encrypted, and a PDF above 100 pages 400 page_limit_exceeded — the same codes the Case Management API uses, reported on file or base64. A PDF whose markers are intact but whose body cannot be parsed is accepted at upload, exactly as on the Case Management API, and processed asynchronously like any other PDF. filename (JSON) and the multipart file name are percent-decoded once and then validated as a single line: control characters are 400 control_characters on filename or file, invisible format characters are stripped, only the base name is kept, and a name that decodes to empty, ., or .. is 400 invalid (Provide a valid file name.); omit filename to fall back to document.pdf. If the document store refuses the write, the upload is 503 service_unavailable with Retry-After; nothing is stored and a previous document stays in place.

Upload and keep the document id

cURL
201 Created returns the document, with its own id. The Location response header points to its detail endpoint. Scanning runs asynchronously; an accepted upload is not yet ready to enclose with a dunning notice.
Pending document

Wait for a terminal scanning result

Poll GET /mahnservice/v1/invoices/{uuid}/documents/{document_uuid}/ using the invoice id and the returned document id. You can also read GET /mahnservice/v1/invoices/{uuid}/documents/: it returns an unpaginated array containing zero or one document. size and download_url are null until the document is ready and stay null on a rejected or failed document — its bytes are discarded. On the invoice, has_document becomes true only when the current document is ready; document contains its id, status and download URL. A replacement starts scanning again, so wait for the replacement’s result too. A document whose scan completes after the invoice was paid, cancelled, written off, or archived lands on rejected rather than ready: a settled invoice never gains a document. The invoice’s updated marker advances when the document reaches ready, rejected, or failed, not on internal scan retries. There is no document retry endpoint. To replace a rejected or failed upload, send the PDF bytes again to the same documents collection. Do not repost a pending upload merely because a poll has not finished yet.

Release and download

An invoice can be released without an attachment. If you have uploaded a document, it must be ready before release: pending, rejected and failed all cause 409 document_not_ready. A polling deadline expiring means your integration should stop and check again later; it does not mean the scan failed. When ready, download_url names the authenticated download endpoint GET /mahnservice/v1/invoices/{uuid}/documents/{document_uuid}/download/. Send your Bearer credential when following it. Downloading before readiness returns 404; an object missing from storage is 404 as well, and a storage fault is 503 service_unavailable with Retry-After — retry the download. HEAD on the documents collection mirrors GET and never uploads. The quickstart’s complete Python workflow uploads a local PDF and polls with a bounded wait before releasing.