Mahnwesen

Überfällige Rechnungen verfolgen, Mahnregeln festlegen und Zahlungserinnerungen versenden.

Overdue tracking, dunning policy, and payment reminders (Mahnwesen).

10 Operationen · Basis-URL https://api.fortlauf.de/v1

Operationen

  1. GET /dunning/overdue List overdue invoices (cursor-paginated, derived)
  2. GET /dunning/policy Get the entity's Mahnstufen policy
  3. PUT /dunning/policy Replace the entity's reminder ladder (admin-gated)
  4. PATCH /dunning/policy Set which record of sending a reminder requires
  5. PUT /dunning/policy/charges Set the late-payment interest and fee configuration, and nothing else
  6. GET /invoices/{id}/reminders The per-invoice reminder history / Mahnverlauf
  7. POST /invoices/{id}/reminders Send the next-due Mahnstufe for an invoice
  8. GET /invoices/{id}/reminders/preview Preview the next-due reminder (byte-faithful dry-run)
  9. GET /invoices/{id}/reminders/preview.pdf Preview the next-due Mahnung as a PDF (byte-faithful)
  10. GET /invoices/{id}/reminders/{reminderId}/artifact.pdf Read the frozen per-reminder Mahnung letter

List overdue invoices (cursor-paginated, derived)

GET /dunning/overdue

The derived overdue set: status='issued' AND payment_state IN ('open','partially_paid') AND COALESCE(due_date, issue_date+30) < CURRENT_DATE. A paid/overpaid/void/draft/scheduled invoice never appears (the payment_state filter is load-bearing — it excludes overpaid, unlike the inbound open-invoices read). Per row: the derived daysOverdue, openAmountMinor (= totalGross − amountPaid − the same-currency partial credit notes), the current Mahnstufe (highest reminder level snapshot), and the SERVER-COMPUTED nextAction descriptor (which level is next, whether it is sendable, and why not) — so web never derives the schedule. Mode-scoped; keyset over (effectiveDueDate, id) ASC. Mounted only where dunning is enabled` (else 404).

Erforderlicher Scope
documents:read
Zugang
API-Schlüssel oder angemeldete Sitzung

Parameter

Parameter In Typ Beschreibung
cursor Query string

Opaque keyset cursor from a prior page's nextCursor.

limit Query integer
Standard: 50
Bereich: ≥ 1, ≤ 100

Antworten

  • 200

    A page of overdue invoices (all fields server-derived) + an opaque nextCursor.

    application/json object

  • 400

    The query string was refused. Three distinguishable facts share this status, and a client should branch on the error code rather than on the status: unknown_query_parameter — the request named one or more query parameters this deployment does not define, and parameters lists their names. Nothing was filtered and nothing was written. This is a DEPLOY-ORDER signal: it is what a client released ahead of the API sees, and it replaces the older behaviour in which an unrecognised parameter was silently ignored and the request answered 200 OK with the UNFILTERED collection — indistinguishable, to the caller, from the filter having been applied. validation_error — a parameter this endpoint does define carried an unusable value (including a required one being absent or too short). issues[] names the parameter and what was wrong with it. invalid_cursor — on cursor-paginated endpoints, the pagination cursor is malformed. No response on this path ever echoes a submitted VALUE; only parameter names appear.

    application/json UnknownQueryParameterError | ValidationError

  • 403

    Caller lacks the documents:read scope.

  • 404

    Dunning is not enabled — the surface is not mounted.

Get the entity's Mahnstufen policy

GET /dunning/policy

The resolved per-entity dunning policy: the stored row, else the SHIPPED DEFAULT (the 4-level Zahlungserinnerung → 1./2./3. Mahnung set) so the feature works out of the box. ENTITY-scoped (not mode-scoped — one policy, the same in live + test). The interest/fee fields are INACTIVE (OFF / null / 0). Any active member may read.

Erforderlicher Scope
documents:read
Zugang
API-Schlüssel oder angemeldete Sitzung

Antworten

  • 200

    The resolved policy (isDefault = true when no row is stored yet).

    application/json DunningPolicy

  • 403

    Caller lacks the documents:read scope.

  • 404

    Dunning is not enabled — the surface is not mounted.

Replace the entity's reminder ladder (admin-gated)

PUT /dunning/policy

Replaces the entity's reminder ladder (ON CONFLICT (entity_id)). Admin-gated (requireRole('admin') — a readonly caller 403s). Validation: levels ordered by strictly-increasing sequence, unique level keys, dayOffset non-negative and strictly increasing by sequence, newDeadlineDays ≥ 1.

levels is the only property of this body and it is REQUIRED, so there is no omission question here at all: no other stored value can be reached from this operation. Late-payment interest and dunning fees are set with PUT /dunning/policy/charges; the send-evidence requirement with PATCH /dunning/policy. Supplying an interest or fee property here is REFUSED by name (dunning_charges_not_on_replace) and nothing is written — it is never silently dropped, because that would report a change that did not happen.

Erforderlicher Scope
documents:write
Zugang
API-Schlüssel oder angemeldete Sitzung

Request-Body erforderlich

application/json DunningPolicyInput

Antworten

  • 200

    The stored policy.

    application/json DunningPolicy

  • 400

    Validation error (ordering / uniqueness / bounds), or dunning_charges_not_on_replace — the body carried an interest or fee property, which belongs to PUT /dunning/policy/charges. Nothing was written.

  • 403

    Caller lacks the admin role or the documents:write scope.

  • 404

    Dunning is not enabled — the surface is not mounted.

Set which record of sending a reminder requires

PATCH /dunning/policy

Sets one setting and nothing else: which record of the invoice having gone out a reminder requires. Every other value on the policy is left exactly as it is — deliberately a separate operation from the whole policy replace, so saving reminder levels can never reset this rule without the caller intending it.

any — a dispatch you recorded yourself is enough. system_transmitted — only a dispatch this application performed counts.

Neither value permits a reminder for an invoice with no record of any kind. A reminder level, once sent, cannot be sent again.

Erforderlicher Scope
documents:write
Zugang
API-Schlüssel oder angemeldete Sitzung

Request-Body erforderlich

application/json object

Antworten

  • 200

    The stored policy.

    application/json DunningPolicy

  • 400

    Validation error.

  • 403

    Caller lacks the admin role or the documents:write scope.

  • 404

    Dunning is not enabled — the surface is not mounted.

Set the late-payment interest and fee configuration, and nothing else

PUT /dunning/policy/charges

Sets the entity's late-payment interest and dunning-fee configuration and nothing else. Every property is REQUIRED, so this body carries no omission question at all, and no other stored value can be reached from here — the reminder ladder and the send-evidence requirement are untouched. Unknown properties are refused.

Three properties are required-and-NULLABLE: null is a value you STATE (no rate is configured), and it is a different act from leaving the property out, which is refused.

The values are stored as passed and are NOT validated as active values; the shipped configuration is inactive (feature off, no rate, zero amounts) and this operation is the only way to move it. Admin-gated (requireRole('admin') — a readonly caller 403s). Creates the entity's policy row from the shipped default ladder if none exists yet, so the setting cannot silently fail to stick.

Erforderlicher Scope
documents:write
Zugang
API-Schlüssel oder angemeldete Sitzung

Request-Body erforderlich

application/json DunningPolicyCharges

Antworten

  • 200

    The stored policy, with the new interest/fee configuration.

    application/json DunningPolicy

  • 400

    Validation error — a property is missing, unknown, or out of bounds.

  • 403

    Caller lacks the admin role or the documents:write scope.

  • 404

    Dunning is not enabled — the surface is not mounted.

The per-invoice reminder history / Mahnverlauf

GET /invoices/{id}/reminders

The append-only reminder records for one invoice, oldest level first (ascending reminder level — reminders escalate contiguously). A PURE RLS-scoped read of the reminder facts; the invoice is NEVER mutated and the current Mahnstufe is not derived here (that is the highest reminder level on GET /dunning/overdue). METADATA-ONLY: the level, sent-at, channel, recipient, the facts stated (open amount, both deadlines) and the evidence — the rendered sent_subject/sent_body_html snapshot is retained on the row for evidence but deliberately NOT surfaced (GDPR, no over-exposure). A cross-scope or unknown invoice id, and an invoice with no reminders, both return an empty reminders array. Mounted only when dunning (else 404).

Erforderlicher Scope
documents:read
Zugang
API-Schlüssel oder angemeldete Sitzung

Parameter

Parameter In Typ Beschreibung
id erforderlich Pfad string (uuid)

The invoice whose Mahnverlauf to read.

Antworten

  • 200

    The invoice's reminders, level-ordered (possibly empty).

    application/json ReminderHistory

  • 403

    Caller lacks the documents:read scope.

  • 404

    Dunning is not enabled.

Send the next-due Mahnstufe for an invoice

POST /invoices/{id}/reminders

Sends the NEXT-DUE reminder level (the lowest the reminder level not yet sent whose dayOffset ≤ daysOverdue) in ONE transaction: it INSERTs the immutable immutable reminder record (snapshotting the level + the facts stated + the api-rendered subject/body) and INSERTs a an outbound-mail record of kind dunning the mail dispatcher sends. The invoice is NEVER mutated (a reminder references it; the 0058 guard holds). Exactly-once: the one record per invoice and level guard makes a duplicate same-level send roll back with no second email (→ 409 mahnstufe_already_sent). Honors the optional Idempotency-Key header (a client double-submit is a replay). Available only where dunning is enabled (else 404). The rendered subject/body are byte-identical to GET /invoices/{id}/reminders/preview for the same inputs (one shared render implementation — no drift).

Erforderlicher Scope
documents:write
Zugang
API-Schlüssel oder angemeldete Sitzung

Parameter

Parameter In Typ Beschreibung
id erforderlich Pfad string (uuid)

The overdue invoice to remind.

Idempotency-Key Header string

Optional client-supplied key that makes this mutating request safe to retry. The FIRST request runs and its outcome is recorded keyed by (tenant, route, key); a REPLAY (same key + byte-identical body, after the first completed) returns the recorded response verbatim WITHOUT re-executing — so a network-blip retry never creates a duplicate customer/subscription/key. A key reused with a DIFFERENT body is 409 IDEMPOTENCY_KEY_REUSED_WITH_DIFFERENT_BODY; a key whose first request is still in flight is 409 REQUEST_IN_PROGRESS (retryable). Keys expire after 24h — a key reused after expiry is a fresh request, not a replay. Transparent when omitted (the request runs normally).

Länge: max. 255

Antworten

  • 201

    The created reminder fact (or, on an Idempotency-Key replay, the recorded response).

    application/json Reminder

  • 403

    Caller lacks the documents:write scope.

  • 404

    Invoice not in scope, or dunning is not enabled.

  • 409

    correction_chain_indeterminate (one of this invoice's own cancellation documents has itself been cancelled, so the amount still owed cannot be determined automatically; returned ahead of every other reason, and NOTHING is written), cancelled_by_correction (an issued/paid 384, or a 381 that reverses this invoice IN FULL, settles it by document and not by money; returned ahead of not_overdue, and NOTHING is written — a 381 covering only PART of the invoice reduces the open amount instead and leaves the invoice dunnable for the remainder), not_sent (the platform has no record of ever sending this invoice, so it may not be dunned; also returned ahead of not_overdue, since waiting never clears it — send the invoice via POST /invoices/{id}/send first; NOTHING is written and the Mahnstufe stays free), not_overdue (paid/overpaid/void/draft/scheduled/not-yet-due), no_level_due (no level reached, or all reached levels sent), processing_restricted (DSGVO Art. 18), or mahnstufe_already_sent (the exactly-once dedup fired). Also IDEMPOTENCY_* on key conflicts.

  • 422

    no_recipient_email (no email on file — nothing written), email_settings_not_configured (no default SMTP config for this entity/mode — nothing written), or sandbox_recipient_not_allowed (test mode, sent by the platform's test sender: a recipient — including a copy or blind copy — is neither a confirmed reply address of the company nor the address of an active member of the account; the body names no address). Nothing is written and the Mahnstufe stays free.

  • 429

    sandbox_mail_daily_cap_reached — test mode, sent by the platform's test sender: this company has reached its daily limit of test-mode e-mails sent by the platform (counted per company over the Europe/Berlin calendar day: e-mails sent today plus e-mails still waiting to be sent). Nothing was written and nothing was sent; a reminder level stays free. The limit resets at midnight Europe/Berlin; Retry-After gives the seconds until then and limit the number. E-mails sent through the company's own mail server are not counted.

    • Retry-After integer

      Seconds until the next business day starts (Europe/Berlin midnight).

    application/json object

Preview the next-due reminder (byte-faithful dry-run)

GET /invoices/{id}/reminders/preview

A READ-ONLY dry-run that renders the next-due level's subject + body for an invoice WITHOUT writing or sending anything (no reminder row, no outbox row). Byte-identical to what POST /invoices/{id}/reminders would persist for the same inputs — the same "single rendering implementation, no drift" principle as the PDF preview. Blocked states (cancelled_by_correction / not_sent / not_overdue / no_level_due / no_recipient / processing_restricted) surface as a calm blockedReason (a 200 body with null subject/body), never a hard error. Available only where dunning is enabled (else 404).

Erforderlicher Scope
documents:read
Zugang
API-Schlüssel oder angemeldete Sitzung

Parameter

Parameter In Typ Beschreibung
id erforderlich Pfad string (uuid)

The invoice to preview a reminder for.

Antworten

  • 200

    The byte-faithful rendered reminder, or a calm blocked state.

    application/json ReminderPreview

  • 403

    Caller lacks the documents:read scope.

  • 404

    Invoice not in scope, or dunning is not enabled.

Preview the next-due Mahnung as a PDF (byte-faithful)

GET /invoices/{id}/reminders/preview.pdf

A READ-ONLY render of the next-due Mahnstufe as a plain-letter Mahnung PDF (DIN 5008), streamed WITHOUT writing or sending anything (no reminder row, no outbox row, no object stored). Rendered via the SAME render-dunning client + copy/cost resolvers a send freezes, so the preview is byte-faithful to the artifact a send would persist. Unwatermarked. Mounted only when dunning AND dunning PDFs are enabled (else 404). A blocked state (not overdue / no level due / restricted) is a mapped 4xx; a renderer failure is 502.

Erforderlicher Scope
documents:read
Zugang
API-Schlüssel oder angemeldete Sitzung

Parameter

Parameter In Typ Beschreibung
id erforderlich Pfad string (uuid)

The invoice to preview the next-due Mahnung for.

Antworten

  • 200

    The rendered Mahnung PDF (inline).

    application/pdf string (binary)

  • 403

    Caller lacks the documents:read scope.

  • 404

    Invoice not in scope, or dunning / dunning PDFs are not enabled.

  • 409

    correction_chain_indeterminate / cancelled_by_correction / not_sent / not_overdue / no_level_due / processing_restricted — nothing to preview.

  • 502

    render_failed — the Mahnung renderer is unavailable/errored.

Read the frozen per-reminder Mahnung letter

GET /invoices/{id}/reminders/{reminderId}/artifact.pdf

The CUSTOMER-FACING read of the FROZEN Mahnung PDF that was actually sent for a specific reminder (Mahnstufe) — not a re-render of the next-due preview. Requires documents:read; the {id} invoice is the authorization anchor: the {reminderId} must belong to that invoice under the caller's RLS scope. Streamed inline for the in-app Mahnverlauf viewer. Mounted only when dunning AND dunning PDFs are enabled (else 404). A reminder id belonging to another invoice/tenant, or a legacy email-only reminder with no frozen artifact, is a 404 (never leaks existence; the web shows no "Brief ansehen" affordance for such a row).

Erforderlicher Scope
documents:read
Zugang
API-Schlüssel oder angemeldete Sitzung

Parameter

Parameter In Typ Beschreibung
id erforderlich Pfad string (uuid)

The invoice the reminder belongs to (the authorization anchor).

reminderId erforderlich Pfad string (uuid)

The specific reminder (Mahnstufe) whose frozen letter to read.

Antworten

  • 200

    The frozen Mahnung PDF for that reminder (inline).

    application/pdf string (binary)

  • 403

    Caller lacks the documents:read scope.

  • 404

    The reminder is unknown, does not belong to {id}, is not in the caller's scope, has no frozen artifact (email-only), or dunning or dunning PDFs are not enabled.

Datenmodelle

Jedes Datenmodell dieser Gruppe einmal, mit allen Feldern – auch den verschachtelten. Verschachtelte Objekte sind aufklappbar; ein benannter Typ verweist auf seinen eigenen Abschnitt.

OverdueInvoice object

One row of the overdue read — every field is server-derived (no client computation).

Feld Typ Beschreibung
invoiceId erforderlich string (uuid)
invoiceNumber erforderlich string | null
customerId erforderlich string (uuid) | null
buyerName erforderlich string
currency erforderlich string
effectiveDueDate erforderlich string (date)

COALESCE(due_date, issue_date + 30).

daysOverdue erforderlich integer

CURRENT_DATE − effectiveDueDate (whole days).

openAmountMinor erforderlich integer

What is still owed, in minor units: totalGross − amountPaid − the same-currency partial credit notes.

totalGrossMinor erforderlich integer

The invoice gross in minor units (for the partial "von {gross}" sub-line).

currentLevelLabel erforderlich string | null

The derived current Mahnstufe label (highest reminder level snapshot), or null.

currentLevelSentAt erforderlich string (date-time) | null

When the current level was sent, or null.

nextAction erforderlich DunningNextAction

Verwendet von: GET /dunning/overdue

UnknownQueryParameterError object

The request named query parameters this endpoint does not define. A list endpoint refuses them rather than ignoring them, so a caller can never mistake an UNFILTERED collection for a filtered one.

Feld Typ Beschreibung
error erforderlich string
Werte: "unknown_query_parameter"
parameters erforderlich Array<string>

The unrecognised parameter NAMES, deduplicated and sorted. Bounded at ten entries, and a name longer than 64 characters is omitted — a parameter name is caller-supplied text, and this response never reflects unbounded caller input. The array may therefore be EMPTY while the refusal still stands: the refusal is decided by the request, not by the length of this list.

message string
requestId string

Verwendet von: GET /dunning/overdue

ValidationError object

A refused request body. error is validation_error when the body was read and failed validation (each problem is listed in issues), or invalid_json when the body is not valid JSON at all (then issues is absent). An unparsable body is answered 400 invalid_json on every operation that takes a JSON body. The submitted body is never echoed.

Feld Typ Beschreibung
error string
issues Array<object>
Felder
Feld Typ Beschreibung
path string
message string
code string

Optional machine-readable reason for the refusal, for a client that shows its own wording instead of message. Present only where an endpoint documents it; an issue without it is refused for the reason message states. Today: invalid_address (an entry of a copy list is not one valid address), too_many_addresses (more than 5 entries in one copy list), copies_require_email (copy recipients are set but email is empty), and service_timing_conflict (POST /invoices, PUT /invoices/{id}: the invoice would state both a single service date and a service period; the issue's path is deliveryDate). On the invoice saves and POST /invoices/preview-totals also reverse_charge_buyer_vat_id_required (a reverse-charge line needs the buyer's VAT identification number), vat_category_unavailable (the line's VAT category is not available), vat_rate_category_mismatch (the rate does not fit the line's VAT category), vat_exemption_reason_required / vat_exemption_reason_not_allowed (the exemption reason is missing, or not allowed for that category), and, only where the deployment enforces the check, unit_code_unknown, currency_code_unknown and vat_id_prefix_unknown (the same three also appear on quote and recurring-template saves, with the same paths). The set may grow, so treat an unknown value like an absent one. Never carries a submitted value.

Verwendet von: GET /dunning/overdue

DunningPolicy object

The resolved per-entity dunning policy. Every interest/fee field is INACTIVE by default (OFF / null / 0). isDefault = true when the shipped default was returned (no stored row yet).

Feld Typ Beschreibung
levels erforderlich Array<DunningLevel>
interestFeatureEnabled erforderlich boolean

Master toggle (OFF by default — nothing legally-loaded renders).

basiszinssatzBp erforderlich integer | null

§247 BGB Basiszinssatz in basis points; null → no interest (fail-quiet).

interestSpreadB2bBp erforderlich integer | null
interestSpreadB2cBp erforderlich integer | null
interestDayCountBasis erforderlich string | null
dunningFeeMinor erforderlich integer

Mahngebühr in minor units (conservative default 0).

verzugspauschaleB2bMinor erforderlich integer

§288 Abs.5 Verzugspauschale (B2B) in minor units (conservative default 0).

updatedAt string (date-time)

Present when resolved from a stored row.

isDefault erforderlich boolean

true when the shipped default was returned (no stored row).

Verwendet von: GET /dunning/policy , PUT /dunning/policy , PATCH /dunning/policy , PUT /dunning/policy/charges

DunningPolicyInput object

PUT /dunning/policy body — the reminder ladder, on its own. levels must be ordered by strictly-increasing sequence, with unique keys, non-negative dayOffset strictly increasing by sequence, and newDeadlineDays ≥ 1.

It is the only property and it is REQUIRED, so this body has no optional property and therefore no omission rule. No other stored value can be written through it: late-payment interest and dunning fees are set with PUT /dunning/policy/charges, and the send-evidence requirement with PATCH /dunning/policy. Sending an interest or fee property here is refused (dunning_charges_not_on_replace) and nothing is written.

Feld Typ Beschreibung
levels erforderlich Array<DunningLevel>
Elemente: min. 1

Verwendet von: PUT /dunning/policy

DunningPolicyCharges object

The late-payment interest and dunning-fee configuration, on its own. Every property is required — this body has no optional property and therefore no omission rule — and no other stored value can be written through it. Three properties are nullable: null means no value is configured and is something you STATE, which is not the same as leaving the property out (that is refused).

Feld Typ Beschreibung
interestFeatureEnabled erforderlich boolean

Master switch for stating late-payment interest and fees on a reminder. While it is false, nothing is stated and no amount is charged, whatever the other properties hold.

basiszinssatzBp erforderlich integer | null

The § 247 BGB base rate in basis points, or null when none is configured. Null suppresses interest entirely — no rate is ever guessed.

interestSpreadB2bBp erforderlich integer | null

The § 288 Abs. 2 spread over the base rate for business debtors, in basis points, or null when none is configured.

interestSpreadB2cBp erforderlich integer | null

The § 288 Abs. 1 spread over the base rate for consumer debtors, in basis points, or null when none is configured.

interestDayCountBasis erforderlich string | null

How days are counted when interest is derived (for example act/365), or null when none is configured.

Länge: max. 32
dunningFeeMinor erforderlich integer

The Mahngebühr in minor units. A money amount — it is stored exactly as stated and is suppressed together with interest while the master switch is off.

Bereich: ≥ 0
verzugspauschaleB2bMinor erforderlich integer

The § 288 Abs. 5 late-payment lump sum for business debtors, in minor units. A money amount, stored exactly as stated.

Bereich: ≥ 0

Verwendet von: PUT /dunning/policy/charges

ReminderHistory object

The per-invoice Mahnverlauf: the invoice's reminders, level-ordered.

Feld Typ Beschreibung
invoiceId erforderlich string (uuid)
reminders erforderlich Array<ReminderHistoryItem>

Verwendet von: GET /invoices/{id}/reminders

Reminder object

One sent reminder — the immutable immutable reminder record, snapshotting the level + facts stated + the api-rendered content. subject / bodyHtml are byte-identical to the T02b preview for the same inputs.

Feld Typ Beschreibung
id erforderlich string (uuid)
invoiceId erforderlich string (uuid)
levelSequence erforderlich integer

0 = Zahlungserinnerung, 1 = 1. Mahnung, …

levelKey erforderlich string
levelLabel erforderlich string
invoiceNumber erforderlich string | null
effectiveDueDate erforderlich string (date)

COALESCE(due_date, issue_date + 30).

daysOverdue erforderlich integer
openAmountMinor erforderlich integer

The open amount the reminder states, in minor units: totalGross − amountPaid − the same-currency partial credit notes, as derived when it is sent.

currency erforderlich string
newPaymentDeadline erforderlich string (date)

The new deadline this reminder sets (send date + newDeadlineDays).

channel erforderlich string
Werte: "email"
toEmail erforderlich string

Recipient at send time (never logged).

subject erforderlich string
bodyHtml erforderlich string
interestChargedMinor erforderlich integer

Interest/fee evidence — 0 unless interest and fees are switched on.

feeChargedMinor erforderlich integer

Interest/fee evidence — 0 unless interest and fees are switched on.

createdAt erforderlich string (date-time)

Verwendet von: POST /invoices/{id}/reminders

ReminderPreview object

The byte-faithful reminder dry-run. subject/bodyHtml are byte-identical to what a send persists for the same inputs, or null when blockedReason is set (a calm blocked state, not an error).

Feld Typ Beschreibung
levelKey erforderlich string | null
levelLabel erforderlich string | null
recipientEmail erforderlich string | null
openAmountMinor erforderlich integer

The open amount the reminder would state if sent now, in minor units: totalGross − amountPaid − the same-currency partial credit notes.

currency erforderlich string
originalDueDate erforderlich string (date)

COALESCE(due_date, issue_date + 30).

newDeadline erforderlich string (date) | null

The new deadline the send would set, or null when blocked.

daysOverdue erforderlich integer
subject erforderlich string | null

The api-rendered subject, or null when blocked.

bodyHtml erforderlich string | null
blockedReason erforderlich string | null

Why there is nothing to send now, or null when a reminder is sendable. correction_chain_indeterminate is returned FIRST of all: one of this invoice's own cancellation documents has itself been cancelled, so the amount still owed cannot be determined automatically and no reminder may state a figure. cancelled_by_correction is returned next, ahead of not_overdue, when an issued/paid 384 — or a 381 reversing this invoice IN FULL — references it: the user must be told which document settled it, not that the due date has not passed. A 381 covering only PART of the invoice reduces the open amount instead and leaves the invoice dunnable for the remainder. not_sent is returned SECOND, also ahead of not_overdue: the platform has no record of ever sending this invoice, so it may not be dunned, and the remedy is POST /invoices/{id}/send, never waiting.

Werte: "cancelled_by_correction", "correction_chain_indeterminate", "not_sent", "no_recipient", "no_level_due", "not_overdue", "processing_restricted"

Verwendet von: GET /invoices/{id}/reminders/preview

DunningNextAction object

The SERVER-COMPUTED next-action descriptor for one overdue invoice. web renders it verbatim — the Mahnstufe schedule stays server-side. Produced by the shared send-precondition helper so a future send path cannot drift from what the row hint shows.

Feld Typ Beschreibung
nextLevelKey erforderlich string | null

The next level's key, or null when all reached levels are sent.

nextLevelLabel erforderlich string | null

The next level's label (the dynamic kebab item label), or null.

sendable erforderlich boolean

Whether the next level can be sent right now.

blockedReason erforderlich string | null

Why the next level is not sendable, or null when sendable is true. correction_chain_indeterminate is ranked FIRST of all: one of this invoice's own cancellation documents has itself been cancelled, so the amount still owed cannot be determined automatically. Every other reason implies an amount; this one is the absence of one, so the invoice is withheld from automated dunning and shown to a human instead (it stays on the per-customer open items). It never clears by waiting or by sending. cancelled_by_correction means an issued/paid 384, or a 381 that reverses this invoice IN FULL, settles it — it is ranked next, ahead of every remaining reason, because a cancelled invoice is not merely "not yet due". A 381 that reverses only PART of the invoice does not produce this state: it reduces the open amount instead, and the invoice stays dunnable for the remainder. not_sent is ranked SECOND: the platform has no record of ever sending this invoice, so it may not be dunned. It deliberately outranks all_sent and no_level_due — those read as "wait", and a delivery gap never clears by waiting. The row is still returned by the overdue read (it is still money owed); only the send is blocked, until the seller sends the invoice.

Werte: "cancelled_by_correction", "correction_chain_indeterminate", "not_sent", "no_recipient", "no_level_due", "all_sent", "processing_restricted"
nextLevelAvailableFrom erforderlich string (date) | null

ISO date the next level becomes due, when it is not yet due (no_level_due), else null.

Verwendet von: GET /dunning/overdue

DunningLevel object

One Mahnstufe of a policy's escalation ladder (a snapshotted config unit).

Feld Typ Beschreibung
sequence erforderlich integer

0 = Zahlungserinnerung, 1 = 1. Mahnung, … (the ordering key).

Bereich: ≥ 0
key erforderlich string

Stable machine key, e.g. 'zahlungserinnerung' | 'mahnung_1'.

label erforderlich string

Human label, e.g. '1. Mahnung'.

dayOffset erforderlich integer

Days after the effective due date at which this level becomes due.

Bereich: ≥ 0
newDeadlineDays erforderlich integer

New payment deadline this level sets, in days from the send date.

Bereich: ≥ 1
subjectTemplate erforderlich string

German subject template (placeholder vocab).

bodyHtmlTemplate erforderlich string

German HTML body template (placeholder vocab).

Verwendet von: GET /dunning/policy , PUT /dunning/policy , PATCH /dunning/policy , PUT /dunning/policy/charges

ReminderHistoryItem object

One reminder in the history — the immutable immutable reminder record, METADATA-ONLY. The rendered subject/body snapshot is retained on the row for evidence but NOT surfaced here (GDPR, no over-exposure).

Feld Typ Beschreibung
id erforderlich string (uuid)
levelSequence erforderlich integer

0 = Zahlungserinnerung, 1 = 1. Mahnung, …

levelKey erforderlich string
levelLabel erforderlich string
channel erforderlich string
Werte: "email"
recipientEmail erforderlich string

Recipient at send time (never logged).

invoiceNumber erforderlich string
effectiveDueDate erforderlich string (date)

The effective due date stated on the reminder (COALESCE(due_date, issue_date + 30)).

daysOverdue erforderlich integer
openAmountMinor erforderlich integer

Stated open amount (minor units / cents).

currency erforderlich string
newPaymentDeadline erforderlich string (date)

The new deadline this reminder set.

interestChargedMinor erforderlich integer

Interest/fee evidence — 0 unless interest and fees are switched on.

feeChargedMinor erforderlich integer

Interest/fee evidence — 0 unless interest and fees are switched on.

interestRateBp erforderlich integer | null

The rate (basis points) applied, or null when no interest was stated.

interestDays erforderlich integer | null

The day span the interest covered, or null when none was stated.

createdAt erforderlich string (date-time)

Sent-at timestamp.

artifactAvailable erforderlich boolean

Whether a FROZEN Mahnung PDF exists for this reminder (readable at .../reminders/{reminderId}/artifact.pdf). The web shows the per-row "Brief ansehen" viewer link only when true; an email-only reminder (sent while dunning PDFs was off) stays metadata-only.

Verwendet von: GET /invoices/{id}/reminders

Nach oben · Alle Ressourcengruppen · OpenAPI-Spezifikation (YAML)