StabisoDocs

API reference

Dunning

Customer statements: the open items of one customer on a day, tied to the receivables control account, as JSON, CSV or a PDF in the customer's language, archived with its hash when a person issues it. Vendor statements: the movements on a vendor's account between two days with the running balance. Reminder letters: which customers are due one, the letter in their language, archived, sent or recorded as handed over. No fee and no interest; nothing here posts.

Operation Summary Scope Idempotency-Key
GET /v1/documents/{document_id}/dunning-block Get whether the reminders of an invoice are stopped read
POST /v1/documents/{document_id}/dunning-block Stop the reminders of an invoice post required
DELETE /v1/documents/{document_id}/dunning-block Resume the reminders of an invoice post
GET /v1/entities/{entity}/customers/{party}/activity Get a customer's activity statement: invoices, credit notes and payments read
POST /v1/entities/{entity}/customers/{party}/reminders Make a reminder letter to a customer post required
GET /v1/entities/{entity}/customers/{party}/statement Get a customer's statement of account read
POST /v1/entities/{entity}/customers/{party}/statement/issue Issue a customer's statement: archive its PDF post required
GET /v1/entities/{entity}/reminder-settings Get the fees and default interest of the reminder levels read
PUT /v1/entities/{entity}/reminder-settings Save the fees and default interest of the reminder levels admin
GET /v1/entities/{entity}/reminders List the reminder letters read
GET /v1/entities/{entity}/reminders/proposal List the customers due a reminder letter read
GET /v1/entities/{entity}/vendors/{party}/statement Get a vendor's statement: what we owe, by bill, credit note and payment read
GET /v1/reminders/{notice_id} Get a reminder letter read
POST /v1/reminders/{notice_id}/mark-sent Record that a reminder letter was handed over post required
GET /v1/reminders/{notice_id}/pdf Download a reminder letter read
POST /v1/reminders/{notice_id}/send Send a reminder letter by e-mail post required
POST /v1/reminders/{notice_id}/withdraw Withdraw a reminder letter not handed over post required

GET /v1/documents/{document_id}/dunning-block

Get whether the reminders of an invoice are stopped

The stop on the invoice's reminders, with who set it, when and why; block is null when reminders go out as usual.

Required scope read (admin implies every scope)
Operation id get_dunning_block_v1_documents__document_id__dunning_block_get

Parameters

In Name Type Required Description
path document_id string yes Document id (uuid) or number, e.g. INV-2026-000001.

Example request

curl "$ERP_URL/v1/documents/INV-2026-000001/dunning-block" \
  -H "Authorization: Bearer $ERP_KEY"

Responses

Status Meaning Body
200 OK DunningBlockState
401 Missing or invalid API key (unauthorized). ErrorEnvelope
403 The caller lacks the required scope (missing_right, with scope), the key belongs to no person where a person is needed (forbidden), or the approval policy denies the action (policy_denied, with action and rule_id). ErrorEnvelope
404 The resource does not exist, or belongs to another organization (not_found). ErrorEnvelope
422 Validation failed: the error envelope (validation_failed). For a malformed body or parameter its message is in sentences ("Line 2: the quantity must be above zero") and fields lists each error with pydantic's loc, type and msg beside its sentence (message) and its parts, to word it in another language: items (name and number from 1: line 2), field (its name as sent) and the rule it breaks with its limit, count and choices (none for a validator's own sentence); FastAPI's own detail list stays beside the envelope. HTTPValidationError

Example response (shape)

{
  "document_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "block": {
    "document_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "number": "string",
    "reason": "string",
    "blocked_by": {},
    "blocked_at": "2026-09-21T09:30:00Z"
  }
}

POST /v1/documents/{document_id}/dunning-block

Stop the reminders of an invoice

Stop the reminders of a posted sales invoice, with why (a dispute, for instance): the reminder proposal leaves it out and lists it apart with the reason, so no letter names it and it is charged no fee and no interest while the stop holds. It stays open and payable. A person does it (the policy action release_dunning; an agent key answers 403). 409 dunning_block_exists when its reminders are stopped already, 409 dunning_block_not_invoice for another document. Needs an Idempotency-Key.

Required scope post (admin implies every scope)
Idempotency-Key required
Operation id block_reminders_v1_documents__document_id__dunning_block_post

Parameters

In Name Type Required Description
path document_id string yes Document id (uuid) or number, e.g. INV-2026-000001.

Request body

application/json (required): DunningBlockInput

Field Type Required Description
reason string yes Why the reminders stop. (min length 1; max length 500)

Example request

curl -X POST "$ERP_URL/v1/documents/INV-2026-000001/dunning-block" \
  -H "Authorization: Bearer $ERP_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
  "reason": "The customer disputes the delivered quantity"
}'

Responses

Status Meaning Body
201 Created DunningBlockState
401 Missing or invalid API key (unauthorized). ErrorEnvelope
403 The caller lacks the required scope (missing_right, with scope), the key belongs to no person where a person is needed (forbidden), or the approval policy denies the action (policy_denied, with action and rule_id). ErrorEnvelope
404 The resource does not exist, or belongs to another organization (not_found). ErrorEnvelope
409 The request conflicts with the data: an Idempotency-Key reused with a different request, a closed period, or an integrity rule of the database (conflict, integrity_violation). ErrorEnvelope
422 Validation failed: the error envelope (validation_failed). For a malformed body or parameter its message is in sentences ("Line 2: the quantity must be above zero") and fields lists each error with pydantic's loc, type and msg beside its sentence (message) and its parts, to word it in another language: items (name and number from 1: line 2), field (its name as sent) and the rule it breaks with its limit, count and choices (none for a validator's own sentence); FastAPI's own detail list stays beside the envelope. HTTPValidationError

Example response (shape)

{
  "document_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "block": {
    "document_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "number": "string",
    "reason": "string",
    "blocked_by": {},
    "blocked_at": "2026-09-21T09:30:00Z"
  }
}

DELETE /v1/documents/{document_id}/dunning-block

Resume the reminders of an invoice

Lift the stop: the invoice is due its next reminder again as if it had not been stopped (interest runs from its due date or the last day a letter charged, as before). The stop and who lifted it stay on record. A person does it; 409 dunning_block_missing when its reminders are not stopped.

Required scope post (admin implies every scope)
Idempotency-Key not used
Operation id resume_reminders_v1_documents__document_id__dunning_block_delete

Parameters

In Name Type Required Description
path document_id string yes Document id (uuid) or number, e.g. INV-2026-000001.

Example request

curl -X DELETE "$ERP_URL/v1/documents/INV-2026-000001/dunning-block" \
  -H "Authorization: Bearer $ERP_KEY"

Responses

Status Meaning Body
200 OK DunningBlockState
401 Missing or invalid API key (unauthorized). ErrorEnvelope
403 The caller lacks the required scope (missing_right, with scope), the key belongs to no person where a person is needed (forbidden), or the approval policy denies the action (policy_denied, with action and rule_id). ErrorEnvelope
404 The resource does not exist, or belongs to another organization (not_found). ErrorEnvelope
409 The request conflicts with the data: an Idempotency-Key reused with a different request, a closed period, or an integrity rule of the database (conflict, integrity_violation). ErrorEnvelope
422 Validation failed: the error envelope (validation_failed). For a malformed body or parameter its message is in sentences ("Line 2: the quantity must be above zero") and fields lists each error with pydantic's loc, type and msg beside its sentence (message) and its parts, to word it in another language: items (name and number from 1: line 2), field (its name as sent) and the rule it breaks with its limit, count and choices (none for a validator's own sentence); FastAPI's own detail list stays beside the envelope. HTTPValidationError

Example response (shape)

{
  "document_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "block": {
    "document_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "number": "string",
    "reason": "string",
    "blocked_by": {},
    "blocked_at": "2026-09-21T09:30:00Z"
  }
}

GET /v1/entities/{entity}/customers/{party}/activity

Get a customer's activity statement: invoices, credit notes and payments

What the customer owes us and how it came about: per currency, the opening balance on start, every invoice, credit note and payment received up to end (with a payment's reversal and a later application of an amount on account or a credit note) with the running balance, and the closing balance, in the currency of each movement. open_items are the items still open at the end of end, as on the open-items statement of that day (GET .../statement?as_of=); closing_functional is the customer's balance on the receivables control account in the functional currency, the statement's reconciliation.control_balance.

It is read from the customer's own lines on the receivables control account, so the closing balance is the one in the books. Read-only: it posts nothing, it is not archived and it is not a request for payment. 404 for an unknown entity or customer (a vendor is not a customer: its statement is GET .../vendors/{party}/statement), 422 when start is after end.

Required scope read (admin implies every scope)
Operation id get_customer_activity_v1_entities__entity__customers__party__activity_get

Parameters

In Name Type Required Description
path entity string yes Entity code, e.g. CH01 (GET /v1/entities).
path party string yes Customer code, e.g. C-DE, or its id. A vendor is not a customer: its statement is GET .../vendors/{party}/statement.
query start string (date) yes The first day of the period, ISO 8601. What the customer owed before it is the opening balance.
query end string (date) yes The last day of the period, ISO 8601, not before start.
query format "csv" | "json" | "pdf" json (default): the statement; csv: one row per movement with the opening and closing balance of each currency; pdf: an A4 PDF in the customer's language (language chooses another), rendered now and not stored. (default "json")
query language "de" | "en" | "fr" | "it" | "sv" or null format=pdf only: de, fr, it, en or sv. Omitted: the customer's language, else the language of its country.
query download boolean csv and pdf: true sends the file as an attachment. (default false)

Example request

curl "$ERP_URL/v1/entities/CH01/customers/C-DE/activity?start=2026-07-01&end=2026-09-30" \
  -H "Authorization: Bearer $ERP_KEY"

Responses

Status Meaning Body
200 JSON (the statement), CSV (its movements) or the PDF in the customer's language. CustomerActivity, text/csv, application/pdf
401 Missing or invalid API key (unauthorized). ErrorEnvelope
403 The caller lacks the required scope (missing_right, with scope), the key belongs to no person where a person is needed (forbidden), or the approval policy denies the action (policy_denied, with action and rule_id). ErrorEnvelope
404 The resource does not exist, or belongs to another organization (not_found). ErrorEnvelope
422 Validation failed: the error envelope (validation_failed). For a malformed body or parameter its message is in sentences ("Line 2: the quantity must be above zero") and fields lists each error with pydantic's loc, type and msg beside its sentence (message) and its parts, to word it in another language: items (name and number from 1: line 2), field (its name as sent) and the rule it breaks with its limit, count and choices (none for a validator's own sentence); FastAPI's own detail list stays beside the envelope. HTTPValidationError

Example response (shape)

{
  "entity": "string",
  "party_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "party_code": "string",
  "party": "string",
  "start": "2026-09-21",
  "end": "2026-09-21",
  "language": "de",
  "currencies": [
    {
      "currency": "string",
      "opening": "string",
      "increases": "string",
      "decreases": "string",
      "closing": "string",
      "lines": [
        null
      ]
    }
  ],
  "functional_currency": "string",
  "closing_functional": "string",
  "open_items": [
    {
      "document_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "number": "string",
      "kind": "payment_on_account",
      "document_date": "2026-09-21",
      "due_date": "2026-09-21",
      "currency": "string",
      "amount": "string",
      "open": "string",
      "open_functional": "0.00",
      "reserved": false,
      "days_overdue": 1,
      "bucket": "string"
    }
  ]
}

POST /v1/entities/{entity}/customers/{party}/reminders

Make a reminder letter to a customer

Make the letter to the customer in currency (omitted: the one currency it is due a reminder in, its own of several), dated today in the entity's country with today's amounts: it names the customer's invoices in that currency that are due a reminder (all of them, or documents), at the highest level they reached (each invoice's own when they differ), and asks for their open amount within 10 days. The PDF is in the customer's language (language chooses another) and is archived with its SHA-256 (the document archive, kind dunning_notice); the letter never changes. Then send it (POST /v1/reminders/{id}/send) or record how it was handed over (POST /v1/reminders/{id}/mark-sent): the next level counts from that day.

The letter deducts what the customer has to its credit in the currency and not yet applied (credit notes with something open, receipts' amounts on account), as far as no letter still standing deducted it already: the letters together never ask for less than is owed.

A person makes it: the policy action release_dunning is denied to agents, and an agent key answers 403 whatever the policy says. It claims no fee and no interest and posts nothing. 409 no_reminder_due when nothing is due, 409 reminder_covered_by_credits when the customer's credits cover the invoices asked for, 422 reminder_not_due for an invoice asked for that is not, 422 reminder_currency_needed when no currency is named and the customer is due reminders in several, none its own, 422 reminder_in_future or reminder_backdated for an as_of other than today. Needs an Idempotency-Key.

Required scope post (admin implies every scope)
Idempotency-Key required
Operation id create_reminder_v1_entities__entity__customers__party__reminders_post

Parameters

In Name Type Required Description
path entity string yes Entity code, e.g. CH01 (GET /v1/entities).
path party string yes Customer code, e.g. C-DE, or its id. A vendor is not a customer: its statement is GET .../vendors/{party}/statement.

Request body

application/json (required): ReminderCreateInput

Field Type Required Description
as_of string (date) or null The day of the letter: today in the entity's country, the only day a letter is dated (its amounts are today's). Omitted: today.
currency string or null The currency of the letter. Omitted: the one the customer (or the invoices named) is due a reminder in; of several, the customer's own (422 reminder_currency_needed when it is not one of them). (min length 3; max length 3)
documents array of string (uuid) or null Only these invoices (each must be due a reminder); omitted: every invoice of the customer in the currency that is due one. (min items 1)
language "de" | "en" | "fr" | "it" | "sv" or null Language of the letter; omitted: the customer's language.

Example request

curl -X POST "$ERP_URL/v1/entities/CH01/customers/C-DE/reminders" \
  -H "Authorization: Bearer $ERP_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{}'

Responses

Status Meaning Body
201 Created ReminderOut
401 Missing or invalid API key (unauthorized). ErrorEnvelope
403 The caller lacks the required scope (missing_right, with scope), the key belongs to no person where a person is needed (forbidden), or the approval policy denies the action (policy_denied, with action and rule_id). ErrorEnvelope
404 The resource does not exist, or belongs to another organization (not_found). ErrorEnvelope
409 The request conflicts with the data: an Idempotency-Key reused with a different request, a closed period, or an integrity rule of the database (conflict, integrity_violation). ErrorEnvelope
422 Validation failed: the error envelope (validation_failed). For a malformed body or parameter its message is in sentences ("Line 2: the quantity must be above zero") and fields lists each error with pydantic's loc, type and msg beside its sentence (message) and its parts, to word it in another language: items (name and number from 1: line 2), field (its name as sent) and the rule it breaks with its limit, count and choices (none for a validator's own sentence); FastAPI's own detail list stays beside the envelope. HTTPValidationError

Example response (shape)

{
  "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "entity": "string",
  "party_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "party_code": "string",
  "party": "string",
  "currency": "string",
  "level": 1,
  "letter_date": "2026-09-21",
  "deadline_date": "2026-09-21",
  "language": "de",
  "total": "string",
  "fee": "0.00",
  "charge": {
    "document_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "number": "string",
    "status": "string",
    "charged": true
  },
  "file": {
    "file_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "filename": "string",
    "sha256": "string",
    "size": 1
  },
  "created_by": {},
  "created_at": "2026-09-21T09:30:00Z",
  "items": [
    {
      "document_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "number": "string",
      "level": 1,
      "due_date": "2026-09-21",
      "days_overdue": 1,
      "open_amount": "string",
      "flat_fee": "0.00",
      "interest": "0.00",
      "interest_rate": "string",
      "interest_from": "2026-09-21",
      "interest_until": "2026-09-21",
      "interest_parts": [
        null
      ]
    }
  ],
  "dispatches": [
    {
      "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "channel": "email",
      "handed_over_on": "2026-09-21",
      "recipients": [
        "string"
      ],
      "subject": "string",
      "message_id": "string",
      "sent_by": {},
      "sent_at": "2026-09-21T09:30:00Z"
    }
  ],
  "state": "handed_over",
  "withdrawal": {
    "reason": "string",
    "withdrawn_by": {},
    "withdrawn_at": "2026-09-21T09:30:00Z"
  },
  "email": "string"
}

GET /v1/entities/{entity}/customers/{party}/statement

Get a customer's statement of account

The open items of one customer on a day: what the customer still owes us then.

It is the aging report restricted to the customer, from the same positions and rules: allocations (payments, credit notes, a cash discount taken) count from the day they took effect, so those dated after as_of do not; a part payment lowers the open amount of its invoice; a credit note is a negative item; a payment waiting for approval reserves its amount (reserved). items are oldest due date first, balances give the balance and the open amount per age band for each currency, and totals_functional the same in the entity's functional currency.

It ties to the ledger. reconciliation compares totals_functional.total with the customer's own lines on the receivables control account up to as_of: they are equal, apart from the period-end revaluation postings that sit on the control account (unrealised_fx, named); unexplained is zero, and anything else would be a posting no document carries. issued lists the statements of this day that were archived.

A statement is read-only: it posts nothing, and it is not a request for payment. 404 for an unknown entity or customer (a vendor is not a customer: its statement is GET .../vendors/{party}/statement). Interest accrued but not yet charged comes in a later slice of ADR-0028.

Required scope read (admin implies every scope)
Operation id get_statement_v1_entities__entity__customers__party__statement_get

Parameters

In Name Type Required Description
path entity string yes Entity code, e.g. CH01 (GET /v1/entities).
path party string yes Customer code, e.g. C-DE, or its id. A vendor is not a customer: its statement is GET .../vendors/{party}/statement.
query as_of string (date) yes The day the statement is as of, ISO 8601, e.g. 2026-09-30. Allocations dated after it, and documents dated after it, are not counted. Required: a statement is evidence of a day, so the day is always named.
query format "csv" | "json" | "pdf" json (default): the statement; csv: one row per open item; pdf: the statement as an A4 PDF in the customer's language (language chooses another). For pdf, the archived file is returned when the statement of this customer, day and language was issued (POST .../statement/issue; the header X-Statement-Archived: true says so), otherwise the PDF is rendered now and nothing is stored. (default "json")
query language "de" | "en" | "fr" | "it" | "sv" or null format=pdf only: de, fr, it, en or sv. Omitted: the customer's language, else the language of its country. Another language is another file.
query download boolean csv and pdf: true sends the file as an attachment; false (default) inline. (default false)

Example request

curl "$ERP_URL/v1/entities/CH01/customers/C-DE/statement?as_of=2026-09-30" \
  -H "Authorization: Bearer $ERP_KEY"

Responses

Status Meaning Body
200 JSON (the statement), CSV (its open items) or the PDF in the customer's language. Statement, text/csv, application/pdf
401 Missing or invalid API key (unauthorized). ErrorEnvelope
403 The caller lacks the required scope (missing_right, with scope), the key belongs to no person where a person is needed (forbidden), or the approval policy denies the action (policy_denied, with action and rule_id). ErrorEnvelope
404 The resource does not exist, or belongs to another organization (not_found). ErrorEnvelope
422 Validation failed: the error envelope (validation_failed). For a malformed body or parameter its message is in sentences ("Line 2: the quantity must be above zero") and fields lists each error with pydantic's loc, type and msg beside its sentence (message) and its parts, to word it in another language: items (name and number from 1: line 2), field (its name as sent) and the rule it breaks with its limit, count and choices (none for a validator's own sentence); FastAPI's own detail list stays beside the envelope. HTTPValidationError

Example response (shape)

{
  "as_of": "2026-09-25",
  "balances": [
    {
      "balance": "681.00",
      "buckets": {
        "1-30": "0.00",
        "31-60": "0.00",
        "61-90": "681.00",
        "90+": "0.00",
        "current": "0.00"
      },
      "currency": "CHF",
      "documents": 1,
      "overdue": "681.00",
      "overdue_documents": 1
    }
  ],
  "entity": "CH01",
  "functional_currency": "CHF",
  "issued": [
    {
      "file_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
      "filename": "statement-C-CH-2026-09-25-de.pdf",
      "issued_at": "2026-09-26T08:15:00Z",
      "issued_by": {
        "id": "user:alice",
        "name": "Alice",
        "type": "human"
      },
      "language": "de",
      "sha256": "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08",
      "size": 4213
    }
  ],
  "items": [
    {
      "amount": "1081.00",
      "bucket": "61-90",
      "currency": "CHF",
      "days_overdue": 86,
      "document_date": "2026-06-01",
      "document_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "due_date": "2026-07-01",
      "kind": "sales_invoice",
      "number": "INV-2026-000001",
      "open": "681.00",
      "open_functional": "681.00",
      "reserved": false
    }
  ],
  "language": "de",
  "party": "Matter Treuhand AG",
  "party_code": "C-CH",
  "party_id": "0b7d1c3e-5a4e-4d0a-9f7a-2f6d1c1d8a11",
  "reconciliation": {
    "control_account": "1100",
    "control_balance": "681.00",
    "difference": "0.00",
    "pending_settlements": "0.00",
    "totals_functional": "681.00",
    "unexplained": "0.00",
    "unrealised_fx": "0.00"
  },
  "totals_functional": {
    "1-30": "0.00",
    "31-60": "0.00",
    "61-90": "681.00",
    "90+": "0.00",
    "current": "0.00",
    "total": "681.00"
  }
}

POST /v1/entities/{entity}/customers/{party}/statement/issue

Issue a customer's statement: archive its PDF

Store the PDF of the customer's statement on as_of in the document archive, so that what the customer was told on that day can be shown later.

The exact bytes are kept with their SHA-256 (document.kind customer_statement, the customer, the day and the language in its metadata; the audit event is statement.issue). There is one file per customer, day and language: a second issue returns the first file with created false, and nothing is rewritten (the archive wins, as for invoices). The statement is deterministic for a day: the same ledger gives the same bytes. Download the file with GET .../statement?format=pdf and the same as_of and language.

Only a person issues, and it needs the post scope: an agent key answers 403 whatever its scopes. 422 for an as_of after today (it would not be what the customer was told), 404 for an unknown entity or customer. A statement posts nothing and is not a request for payment. Needs an Idempotency-Key.

Required scope post (admin implies every scope)
Idempotency-Key required
Operation id issue_statement_v1_entities__entity__customers__party__statement_issue_post

Parameters

In Name Type Required Description
path entity string yes Entity code, e.g. CH01 (GET /v1/entities).
path party string yes Customer code, e.g. C-DE, or its id. A vendor is not a customer: its statement is GET .../vendors/{party}/statement.

Request body

application/json (required): StatementIssueInput

Field Type Required Description
as_of string (date) yes The day the statement is as of, ISO 8601; not in the future.
language "de" | "en" | "fr" | "it" | "sv" or null Language of the PDF; omitted: the customer's language. Another language is another archived file.

Example request

curl -X POST "$ERP_URL/v1/entities/CH01/customers/C-DE/statement/issue" \
  -H "Authorization: Bearer $ERP_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
  "as_of": "2026-09-30"
}'

Responses

Status Meaning Body
201 Created StatementIssued
401 Missing or invalid API key (unauthorized). ErrorEnvelope
403 The caller lacks the required scope (missing_right, with scope), the key belongs to no person where a person is needed (forbidden), or the approval policy denies the action (policy_denied, with action and rule_id). ErrorEnvelope
404 The resource does not exist, or belongs to another organization (not_found). ErrorEnvelope
409 The request conflicts with the data: an Idempotency-Key reused with a different request, a closed period, or an integrity rule of the database (conflict, integrity_violation). ErrorEnvelope
422 Validation failed: the error envelope (validation_failed). For a malformed body or parameter its message is in sentences ("Line 2: the quantity must be above zero") and fields lists each error with pydantic's loc, type and msg beside its sentence (message) and its parts, to word it in another language: items (name and number from 1: line 2), field (its name as sent) and the rule it breaks with its limit, count and choices (none for a validator's own sentence); FastAPI's own detail list stays beside the envelope. HTTPValidationError

Example response (shape)

{
  "created": true,
  "download": "/v1/entities/CH01/customers/C-CH/statement?as_of=2026-09-25&format=pdf&language=de",
  "file": {
    "file_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
    "filename": "statement-C-CH-2026-09-25-de.pdf",
    "issued_at": "2026-09-26T08:15:00Z",
    "issued_by": {
      "id": "user:alice",
      "name": "Alice",
      "type": "human"
    },
    "language": "de",
    "sha256": "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08",
    "size": 4213
  }
}

GET /v1/entities/{entity}/reminder-settings

Get the fees and default interest of the reminder levels

What a reminder letter of each level charges: the fee per letter and the flat fee once per invoice to a business customer (in the functional currency), and the yearly default-interest rate for business customers and for consumers (actual/365, from the due date). Until settings are saved (configured false) the country's defaults apply: Switzerland and Liechtenstein 5 % a year and no fee; Germany the base rate plus 9 points (business) or 5 points (consumers), shown at today's base rate and charged at each day's (it changes on 1 January and 1 July), and EUR 40 once per invoice to a business customer; elsewhere nothing. A German rate saved at its default keeps following the base rate; a rate changed is fixed.

Required scope read (admin implies every scope)
Operation id get_reminder_settings_v1_entities__entity__reminder_settings_get

Parameters

In Name Type Required Description
path entity string yes Entity code, e.g. CH01 (GET /v1/entities).

Example request

curl "$ERP_URL/v1/entities/CH01/reminder-settings" \
  -H "Authorization: Bearer $ERP_KEY"

Responses

Status Meaning Body
200 OK ReminderSettingsOut
401 Missing or invalid API key (unauthorized). ErrorEnvelope
403 The caller lacks the required scope (missing_right, with scope), the key belongs to no person where a person is needed (forbidden), or the approval policy denies the action (policy_denied, with action and rule_id). ErrorEnvelope
404 The resource does not exist, or belongs to another organization (not_found). ErrorEnvelope
422 Validation failed: the error envelope (validation_failed). For a malformed body or parameter its message is in sentences ("Line 2: the quantity must be above zero") and fields lists each error with pydantic's loc, type and msg beside its sentence (message) and its parts, to word it in another language: items (name and number from 1: line 2), field (its name as sent) and the rule it breaks with its limit, count and choices (none for a validator's own sentence); FastAPI's own detail list stays beside the envelope. HTTPValidationError

Example response (shape)

{
  "entity": "string",
  "currency": "string",
  "configured": true,
  "levels": [
    {
      "level": 1,
      "fee": "string",
      "flat_fee": "string",
      "interest_rate": "string",
      "consumer_interest_rate": "string"
    }
  ],
  "defaults": [
    {
      "level": 1,
      "fee": "string",
      "flat_fee": "string",
      "interest_rate": "string",
      "consumer_interest_rate": "string"
    }
  ]
}

PUT /v1/entities/{entity}/reminder-settings

Save the fees and default interest of the reminder levels

Replace what each of the three levels charges (each level once; 422 reminder_settings_levels otherwise). Letters already made keep what they charged; the change is in the audit trail with the values before and after.

Required scope admin (admin implies every scope)
Idempotency-Key not used
Operation id put_reminder_settings_v1_entities__entity__reminder_settings_put

Parameters

In Name Type Required Description
path entity string yes Entity code, e.g. CH01 (GET /v1/entities).

Request body

application/json (required): ReminderSettingsInput

Field Type Required Description
levels array of ReminderLevelFees-Input yes The three levels, each once. (min items 3; max items 3)

Example request

curl -X PUT "$ERP_URL/v1/entities/CH01/reminder-settings" \
  -H "Authorization: Bearer $ERP_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "levels": [
    {
      "consumer_interest_rate": "5",
      "fee": "0",
      "flat_fee": "0",
      "interest_rate": "5",
      "level": 1
    },
    {
      "consumer_interest_rate": "5",
      "fee": "20",
      "flat_fee": "0",
      "interest_rate": "5",
      "level": 2
    },
    {
      "consumer_interest_rate": "5",
      "fee": "30",
      "flat_fee": "0",
      "interest_rate": "5",
      "level": 3
    }
  ]
}'

Responses

Status Meaning Body
200 OK ReminderSettingsOut
401 Missing or invalid API key (unauthorized). ErrorEnvelope
403 The caller lacks the required scope (missing_right, with scope), the key belongs to no person where a person is needed (forbidden), or the approval policy denies the action (policy_denied, with action and rule_id). ErrorEnvelope
404 The resource does not exist, or belongs to another organization (not_found). ErrorEnvelope
409 The request conflicts with the data: an Idempotency-Key reused with a different request, a closed period, or an integrity rule of the database (conflict, integrity_violation). ErrorEnvelope
422 Validation failed: the error envelope (validation_failed). For a malformed body or parameter its message is in sentences ("Line 2: the quantity must be above zero") and fields lists each error with pydantic's loc, type and msg beside its sentence (message) and its parts, to word it in another language: items (name and number from 1: line 2), field (its name as sent) and the rule it breaks with its limit, count and choices (none for a validator's own sentence); FastAPI's own detail list stays beside the envelope. HTTPValidationError

Example response (shape)

{
  "entity": "string",
  "currency": "string",
  "configured": true,
  "levels": [
    {
      "level": 1,
      "fee": "string",
      "flat_fee": "string",
      "interest_rate": "string",
      "consumer_interest_rate": "string"
    }
  ],
  "defaults": [
    {
      "level": 1,
      "fee": "string",
      "flat_fee": "string",
      "interest_rate": "string",
      "consumer_interest_rate": "string"
    }
  ]
}

GET /v1/entities/{entity}/reminders

List the reminder letters

The letters made in the entity, oldest first, with the invoices each named, each hand-over and its state (unsent, out_of_date, handed_over, withdrawn).

Required scope read (admin implies every scope)
Operation id list_reminders_v1_entities__entity__reminders_get

Parameters

In Name Type Required Description
path entity string yes Entity code, e.g. CH01 (GET /v1/entities).
query party string or null Only this customer's (code or id).
query document string (uuid) or null Only the letters naming this invoice (its id).

Example request

curl "$ERP_URL/v1/entities/CH01/reminders" \
  -H "Authorization: Bearer $ERP_KEY"

Responses

Status Meaning Body
200 OK array of ReminderOut
401 Missing or invalid API key (unauthorized). ErrorEnvelope
403 The caller lacks the required scope (missing_right, with scope), the key belongs to no person where a person is needed (forbidden), or the approval policy denies the action (policy_denied, with action and rule_id). ErrorEnvelope
404 The resource does not exist, or belongs to another organization (not_found). ErrorEnvelope
422 Validation failed: the error envelope (validation_failed). For a malformed body or parameter its message is in sentences ("Line 2: the quantity must be above zero") and fields lists each error with pydantic's loc, type and msg beside its sentence (message) and its parts, to word it in another language: items (name and number from 1: line 2), field (its name as sent) and the rule it breaks with its limit, count and choices (none for a validator's own sentence); FastAPI's own detail list stays beside the envelope. HTTPValidationError

Example response (shape)

[
  {
    "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "entity": "string",
    "party_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "party_code": "string",
    "party": "string",
    "currency": "string",
    "level": 1,
    "letter_date": "2026-09-21",
    "deadline_date": "2026-09-21",
    "language": "de",
    "total": "string",
    "fee": "0.00",
    "charge": {
      "document_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "number": null,
      "status": "string",
      "charged": true
    },
    "file": {
      "file_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "filename": "string",
      "sha256": "string",
      "size": 1
    },
    "created_by": {},
    "created_at": "2026-09-21T09:30:00Z",
    "items": [
      {
        "document_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
        "number": "string",
        "level": 1,
        "due_date": "2026-09-21",
        "days_overdue": 1,
        "open_amount": "string",
        "flat_fee": "0.00",
        "interest": "0.00",
        "interest_rate": null,
        "interest_from": null,
        "interest_until": null,
        "interest_parts": [
          null
        ]
      }
    ],
    "dispatches": [
      {
        "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
        "channel": "email",
        "handed_over_on": "2026-09-21",
        "recipients": [
          null
        ],
        "subject": null,
        "message_id": null,
        "sent_by": {},
        "sent_at": "2026-09-21T09:30:00Z"
      }
    ],
    "state": "handed_over",
    "withdrawal": {
      "reason": "string",
      "withdrawn_by": {},
      "withdrawn_at": "2026-09-21T09:30:00Z"
    },
    "email": "string"
  }
]

GET /v1/entities/{entity}/reminders/proposal

List the customers due a reminder letter

Which customers are due a reminder letter today (in the entity's country; as_of says which day that is), one row per customer and currency, with the invoices it would name and its level: 1 payment reminder, 2 second reminder, 3 final reminder (levels says when each is due: a Swiss entity reminds 10 days after the due date, then 20 days after the reminder was handed over, then 10; a German one 7, 14 and 10). An invoice is due its next level when it is open today and long enough past its due date, or since the last letter that named it was handed over. There is no other day: the clock runs on real time and the amounts are today's. unsent lists the letters made and not handed over yet: they start no clock, so the next level waits for them. out_of_date lists those that can no longer be sent (an amount on them changed, or they are more than 7 days old): withdraw them.

Read-only; no fee and no interest is claimed. A customer that is another entity of the organization is not reminded.

Required scope read (admin implies every scope)
Operation id get_reminder_proposal_v1_entities__entity__reminders_proposal_get

Parameters

In Name Type Required Description
path entity string yes Entity code, e.g. CH01 (GET /v1/entities).

Example request

curl "$ERP_URL/v1/entities/CH01/reminders/proposal" \
  -H "Authorization: Bearer $ERP_KEY"

Responses

Status Meaning Body
200 OK ReminderProposal
401 Missing or invalid API key (unauthorized). ErrorEnvelope
403 The caller lacks the required scope (missing_right, with scope), the key belongs to no person where a person is needed (forbidden), or the approval policy denies the action (policy_denied, with action and rule_id). ErrorEnvelope
404 The resource does not exist, or belongs to another organization (not_found). ErrorEnvelope
422 Validation failed: the error envelope (validation_failed). For a malformed body or parameter its message is in sentences ("Line 2: the quantity must be above zero") and fields lists each error with pydantic's loc, type and msg beside its sentence (message) and its parts, to word it in another language: items (name and number from 1: line 2), field (its name as sent) and the rule it breaks with its limit, count and choices (none for a validator's own sentence); FastAPI's own detail list stays beside the envelope. HTTPValidationError

Example response (shape)

{
  "entity": "string",
  "as_of": "2026-09-21",
  "levels": [
    {
      "level": 1,
      "days_after": 1,
      "deadline_days": 1
    }
  ],
  "due": [
    {
      "party_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "party_code": "string",
      "party": "string",
      "currency": "string",
      "level": 1,
      "language": "de",
      "total": "string",
      "fee": "0.00",
      "email": "string",
      "invoices": [
        null
      ],
      "credits": [
        null
      ]
    }
  ],
  "unsent": [
    {
      "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "entity": "string",
      "party_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "party_code": "string",
      "party": "string",
      "currency": "string",
      "level": 1,
      "letter_date": "2026-09-21",
      "deadline_date": "2026-09-21",
      "language": "de",
      "total": "string",
      "fee": "0.00",
      "charge": null,
      "file": {
        "file_id": null,
        "filename": null,
        "sha256": null,
        "size": null
      },
      "created_by": {},
      "created_at": "2026-09-21T09:30:00Z",
      "items": [
        null
      ],
      "dispatches": [
        null
      ],
      "state": "handed_over",
      "withdrawal": null,
      "email": "string"
    }
  ],
  "out_of_date": [
    {
      "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "entity": "string",
      "party_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "party_code": "string",
      "party": "string",
      "currency": "string",
      "level": 1,
      "letter_date": "2026-09-21",
      "deadline_date": "2026-09-21",
      "language": "de",
      "total": "string",
      "fee": "0.00",
      "charge": null,
      "file": {
        "file_id": null,
        "filename": null,
        "sha256": null,
        "size": null
      },
      "created_by": {},
      "created_at": "2026-09-21T09:30:00Z",
      "items": [
        null
      ],
      "dispatches": [
        null
      ],
      "state": "handed_over",
      "withdrawal": null,
      "email": "string"
    }
  ],
  "blocked": [
    {
      "document_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "number": "string",
      "party_code": "string",
      "party": "string",
      "currency": "string",
      "due_date": "2026-09-21",
      "days_overdue": 1,
      "open": "string",
      "reason": "string",
      "blocked_by": {},
      "blocked_at": "2026-09-21T09:30:00Z"
    }
  ],
  "sending_configured": true
}

GET /v1/entities/{entity}/vendors/{party}/statement

Get a vendor's statement: what we owe, by bill, credit note and payment

What we owe the vendor and how it came about: per currency, the opening balance on start, every bill, credit note and payment up to end with the running balance, and the closing balance, in the currency of each movement (a vendor billing in euros has a block in euros). open_items are the bills and credit notes still open at the end of end, as in the payables aging; closing_functional is the vendor's balance on the payables control account in the functional currency.

It is read from the vendor's own lines on the payables control account, so the closing balance is the one in the books; compare it with the closing balance of the statement the vendor sent. their_reference is the vendor's own number of each bill. Read-only: it posts nothing. 404 for an unknown entity or vendor (a customer is not a vendor), 422 when start is after end.

Required scope read (admin implies every scope)
Operation id get_vendor_statement_v1_entities__entity__vendors__party__statement_get

Parameters

In Name Type Required Description
path entity string yes Entity code, e.g. CH01 (GET /v1/entities).
path party string yes Vendor code, e.g. V-BM, or its id. A customer is not a vendor.
query start string (date) yes The first day of the period, ISO 8601. What we owed before it is the opening balance.
query end string (date) yes The last day of the period, ISO 8601, not before start.
query format "csv" | "json" | "pdf" json (default): the statement; csv: one row per movement with the opening and closing balance of each currency; pdf: an A4 PDF in the vendor's language (language chooses another), rendered now and not stored. (default "json")
query language "de" | "en" | "fr" | "it" | "sv" or null format=pdf only: de, fr, it, en or sv.
query download boolean csv and pdf: true sends the file as an attachment. (default false)

Example request

curl "$ERP_URL/v1/entities/CH01/vendors/V-BM/statement?start=2026-07-01&end=2026-09-30" \
  -H "Authorization: Bearer $ERP_KEY"

Responses

Status Meaning Body
200 JSON (the statement), CSV (its movements) or the PDF in the vendor's language. VendorStatement, text/csv, application/pdf
401 Missing or invalid API key (unauthorized). ErrorEnvelope
403 The caller lacks the required scope (missing_right, with scope), the key belongs to no person where a person is needed (forbidden), or the approval policy denies the action (policy_denied, with action and rule_id). ErrorEnvelope
404 The resource does not exist, or belongs to another organization (not_found). ErrorEnvelope
422 Validation failed: the error envelope (validation_failed). For a malformed body or parameter its message is in sentences ("Line 2: the quantity must be above zero") and fields lists each error with pydantic's loc, type and msg beside its sentence (message) and its parts, to word it in another language: items (name and number from 1: line 2), field (its name as sent) and the rule it breaks with its limit, count and choices (none for a validator's own sentence); FastAPI's own detail list stays beside the envelope. HTTPValidationError

Example response (shape)

{
  "entity": "string",
  "party_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "party_code": "string",
  "party": "string",
  "start": "2026-09-21",
  "end": "2026-09-21",
  "language": "de",
  "currencies": [
    {
      "currency": "string",
      "opening": "string",
      "increases": "string",
      "decreases": "string",
      "closing": "string",
      "lines": [
        null
      ]
    }
  ],
  "functional_currency": "string",
  "closing_functional": "string",
  "open_items": [
    {
      "document_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "number": "string",
      "kind": "payment_on_account",
      "document_date": "2026-09-21",
      "due_date": "2026-09-21",
      "currency": "string",
      "amount": "string",
      "open": "string",
      "open_functional": "0.00",
      "reserved": false,
      "days_overdue": 1,
      "bucket": "string"
    }
  ]
}

GET /v1/reminders/{notice_id}

Get a reminder letter

The letter, the invoices it names, its file, its hand-overs and its state. 404 when unknown.

Required scope read (admin implies every scope)
Operation id get_reminder_v1_reminders__notice_id__get

Parameters

In Name Type Required Description
path notice_id string (uuid) yes Reminder letter id (GET /v1/entities/{entity}/reminders).

Example request

curl "$ERP_URL/v1/reminders/3fa85f64-5717-4562-b3fc-2c963f66afa6" \
  -H "Authorization: Bearer $ERP_KEY"

Responses

Status Meaning Body
200 OK ReminderOut
401 Missing or invalid API key (unauthorized). ErrorEnvelope
403 The caller lacks the required scope (missing_right, with scope), the key belongs to no person where a person is needed (forbidden), or the approval policy denies the action (policy_denied, with action and rule_id). ErrorEnvelope
404 The resource does not exist, or belongs to another organization (not_found). ErrorEnvelope
422 Validation failed: the error envelope (validation_failed). For a malformed body or parameter its message is in sentences ("Line 2: the quantity must be above zero") and fields lists each error with pydantic's loc, type and msg beside its sentence (message) and its parts, to word it in another language: items (name and number from 1: line 2), field (its name as sent) and the rule it breaks with its limit, count and choices (none for a validator's own sentence); FastAPI's own detail list stays beside the envelope. HTTPValidationError

Example response (shape)

{
  "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "entity": "string",
  "party_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "party_code": "string",
  "party": "string",
  "currency": "string",
  "level": 1,
  "letter_date": "2026-09-21",
  "deadline_date": "2026-09-21",
  "language": "de",
  "total": "string",
  "fee": "0.00",
  "charge": {
    "document_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "number": "string",
    "status": "string",
    "charged": true
  },
  "file": {
    "file_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "filename": "string",
    "sha256": "string",
    "size": 1
  },
  "created_by": {},
  "created_at": "2026-09-21T09:30:00Z",
  "items": [
    {
      "document_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "number": "string",
      "level": 1,
      "due_date": "2026-09-21",
      "days_overdue": 1,
      "open_amount": "string",
      "flat_fee": "0.00",
      "interest": "0.00",
      "interest_rate": "string",
      "interest_from": "2026-09-21",
      "interest_until": "2026-09-21",
      "interest_parts": [
        null
      ]
    }
  ],
  "dispatches": [
    {
      "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "channel": "email",
      "handed_over_on": "2026-09-21",
      "recipients": [
        "string"
      ],
      "subject": "string",
      "message_id": "string",
      "sent_by": {},
      "sent_at": "2026-09-21T09:30:00Z"
    }
  ],
  "state": "handed_over",
  "withdrawal": {
    "reason": "string",
    "withdrawn_by": {},
    "withdrawn_at": "2026-09-21T09:30:00Z"
  },
  "email": "string"
}

POST /v1/reminders/{notice_id}/mark-sent

Record that a reminder letter was handed over

Record that a person handed the letter over outside this system: by their own e-mail, by post, on the customer's portal. Nothing is sent. The first hand-over starts the clock of the next level. Only a person records (the policy action send_document; an agent key answers 403). 409 reminder_withdrawn for a withdrawn letter; 422 for a day before the letter (handover_before_document), after today (handover_in_future) or more than 7 days ago (handover_too_old): the clock of the next level runs on real days. Needs an Idempotency-Key.

Required scope post (admin implies every scope)
Idempotency-Key required
Operation id mark_reminder_sent_v1_reminders__notice_id__mark_sent_post

Parameters

In Name Type Required Description
path notice_id string (uuid) yes Reminder letter id (GET /v1/entities/{entity}/reminders).

Request body

application/json (required): ReminderMarkSentInput

Field Type Required Description
channel "email" | "other" | "portal" | "post" yes email (from a person's own mailbox), post, portal or other.
recipient string yes Who got it. (min length 1; max length 200)
handed_over_on string (date) yes The day it was handed over: not before the letter, not after today, and within the last 7 days.

Example request

curl -X POST "$ERP_URL/v1/reminders/3fa85f64-5717-4562-b3fc-2c963f66afa6/mark-sent" \
  -H "Authorization: Bearer $ERP_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
  "channel": "post",
  "handed_over_on": "2026-10-10",
  "recipient": "Berlin GmbH"
}'

Responses

Status Meaning Body
201 Created ReminderOut
401 Missing or invalid API key (unauthorized). ErrorEnvelope
403 The caller lacks the required scope (missing_right, with scope), the key belongs to no person where a person is needed (forbidden), or the approval policy denies the action (policy_denied, with action and rule_id). ErrorEnvelope
404 The resource does not exist, or belongs to another organization (not_found). ErrorEnvelope
409 The request conflicts with the data: an Idempotency-Key reused with a different request, a closed period, or an integrity rule of the database (conflict, integrity_violation). ErrorEnvelope
422 Validation failed: the error envelope (validation_failed). For a malformed body or parameter its message is in sentences ("Line 2: the quantity must be above zero") and fields lists each error with pydantic's loc, type and msg beside its sentence (message) and its parts, to word it in another language: items (name and number from 1: line 2), field (its name as sent) and the rule it breaks with its limit, count and choices (none for a validator's own sentence); FastAPI's own detail list stays beside the envelope. HTTPValidationError

Example response (shape)

{
  "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "entity": "string",
  "party_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "party_code": "string",
  "party": "string",
  "currency": "string",
  "level": 1,
  "letter_date": "2026-09-21",
  "deadline_date": "2026-09-21",
  "language": "de",
  "total": "string",
  "fee": "0.00",
  "charge": {
    "document_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "number": "string",
    "status": "string",
    "charged": true
  },
  "file": {
    "file_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "filename": "string",
    "sha256": "string",
    "size": 1
  },
  "created_by": {},
  "created_at": "2026-09-21T09:30:00Z",
  "items": [
    {
      "document_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "number": "string",
      "level": 1,
      "due_date": "2026-09-21",
      "days_overdue": 1,
      "open_amount": "string",
      "flat_fee": "0.00",
      "interest": "0.00",
      "interest_rate": "string",
      "interest_from": "2026-09-21",
      "interest_until": "2026-09-21",
      "interest_parts": [
        null
      ]
    }
  ],
  "dispatches": [
    {
      "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "channel": "email",
      "handed_over_on": "2026-09-21",
      "recipients": [
        "string"
      ],
      "subject": "string",
      "message_id": "string",
      "sent_by": {},
      "sent_at": "2026-09-21T09:30:00Z"
    }
  ],
  "state": "handed_over",
  "withdrawal": {
    "reason": "string",
    "withdrawn_by": {},
    "withdrawn_at": "2026-09-21T09:30:00Z"
  },
  "email": "string"
}

GET /v1/reminders/{notice_id}/pdf

Download a reminder letter

The archived PDF of the letter, as it was made (checked against its SHA-256, which the header X-Content-SHA256 carries).

Required scope read (admin implies every scope)
Operation id get_reminder_pdf_v1_reminders__notice_id__pdf_get

Parameters

In Name Type Required Description
path notice_id string (uuid) yes Reminder letter id (GET /v1/entities/{entity}/reminders).
query download boolean true sends the file as an attachment; false inline. (default false)

Example request

curl "$ERP_URL/v1/reminders/3fa85f64-5717-4562-b3fc-2c963f66afa6/pdf" \
  -H "Authorization: Bearer $ERP_KEY"

Responses

Status Meaning Body
200 The PDF. application/pdf
401 Missing or invalid API key (unauthorized). ErrorEnvelope
403 The caller lacks the required scope (missing_right, with scope), the key belongs to no person where a person is needed (forbidden), or the approval policy denies the action (policy_denied, with action and rule_id). ErrorEnvelope
404 The resource does not exist, or belongs to another organization (not_found). ErrorEnvelope
422 Validation failed: the error envelope (validation_failed). For a malformed body or parameter its message is in sentences ("Line 2: the quantity must be above zero") and fields lists each error with pydantic's loc, type and msg beside its sentence (message) and its parts, to word it in another language: items (name and number from 1: line 2), field (its name as sent) and the rule it breaks with its limit, count and choices (none for a validator's own sentence); FastAPI's own detail list stays beside the envelope. HTTPValidationError

POST /v1/reminders/{notice_id}/send

Send a reminder letter by e-mail

E-mail the archived letter to the customer, as an invoice is sent: to to (only the customer's own addresses) or its billing address, within the organization's hourly limit. The hand-over is recorded with the message id; the next level counts from today.

Only a person sends (the policy action send_document; an agent key answers 403). 409 in a test copy (it never e-mails customers, who may be real ones), reminder_withdrawn for a withdrawn letter, reminder_out_of_date when an amount on it changed since its day or it is more than 7 days old (withdraw it and make a new one), and when this server has no mail server (download the letter instead); 422 for an address that is not the customer's; 429 beyond the hourly limit; 502 when the mail server refuses, and nothing is recorded. Needs an Idempotency-Key.

Required scope post (admin implies every scope)
Idempotency-Key required
Operation id send_reminder_v1_reminders__notice_id__send_post

Parameters

In Name Type Required Description
path notice_id string (uuid) yes Reminder letter id (GET /v1/entities/{entity}/reminders).

Request body

application/json (required): ReminderSendInput

Field Type Required Description
to array of string or null Addresses of the customer (as for an invoice); omitted: its billing address. (min items 1; max items 5)
message string or null A text placed before the standard text. (max length 1000)

Example request

curl -X POST "$ERP_URL/v1/reminders/3fa85f64-5717-4562-b3fc-2c963f66afa6/send" \
  -H "Authorization: Bearer $ERP_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{}'

Responses

Status Meaning Body
201 Created ReminderOut
401 Missing or invalid API key (unauthorized). ErrorEnvelope
403 The caller lacks the required scope (missing_right, with scope), the key belongs to no person where a person is needed (forbidden), or the approval policy denies the action (policy_denied, with action and rule_id). ErrorEnvelope
404 The resource does not exist, or belongs to another organization (not_found). ErrorEnvelope
409 The request conflicts with the data: an Idempotency-Key reused with a different request, a closed period, or an integrity rule of the database (conflict, integrity_violation). ErrorEnvelope
422 Validation failed: the error envelope (validation_failed). For a malformed body or parameter its message is in sentences ("Line 2: the quantity must be above zero") and fields lists each error with pydantic's loc, type and msg beside its sentence (message) and its parts, to word it in another language: items (name and number from 1: line 2), field (its name as sent) and the rule it breaks with its limit, count and choices (none for a validator's own sentence); FastAPI's own detail list stays beside the envelope. HTTPValidationError
429 A per-organization limit was reached, e.g. messages sent per hour (rate_limited, with retry_after_seconds). ErrorEnvelope

Example response (shape)

{
  "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "entity": "string",
  "party_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "party_code": "string",
  "party": "string",
  "currency": "string",
  "level": 1,
  "letter_date": "2026-09-21",
  "deadline_date": "2026-09-21",
  "language": "de",
  "total": "string",
  "fee": "0.00",
  "charge": {
    "document_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "number": "string",
    "status": "string",
    "charged": true
  },
  "file": {
    "file_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "filename": "string",
    "sha256": "string",
    "size": 1
  },
  "created_by": {},
  "created_at": "2026-09-21T09:30:00Z",
  "items": [
    {
      "document_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "number": "string",
      "level": 1,
      "due_date": "2026-09-21",
      "days_overdue": 1,
      "open_amount": "string",
      "flat_fee": "0.00",
      "interest": "0.00",
      "interest_rate": "string",
      "interest_from": "2026-09-21",
      "interest_until": "2026-09-21",
      "interest_parts": [
        null
      ]
    }
  ],
  "dispatches": [
    {
      "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "channel": "email",
      "handed_over_on": "2026-09-21",
      "recipients": [
        "string"
      ],
      "subject": "string",
      "message_id": "string",
      "sent_by": {},
      "sent_at": "2026-09-21T09:30:00Z"
    }
  ],
  "state": "handed_over",
  "withdrawal": {
    "reason": "string",
    "withdrawn_by": {},
    "withdrawn_at": "2026-09-21T09:30:00Z"
  },
  "email": "string"
}

POST /v1/reminders/{notice_id}/withdraw

Withdraw a reminder letter not handed over

Withdraw a letter that was not handed over (out of date, or made by mistake), with why. The withdrawal is written once: the letter is never sent or recorded after it, and the invoices it named are due their next letter again as if it had not been made. Only a person withdraws (the policy action release_dunning; an agent key answers 403). 409 reminder_handed_over once it was handed over, reminder_withdrawn when it was withdrawn already. Needs an Idempotency-Key.

Required scope post (admin implies every scope)
Idempotency-Key required
Operation id withdraw_reminder_v1_reminders__notice_id__withdraw_post

Parameters

In Name Type Required Description
path notice_id string (uuid) yes Reminder letter id (GET /v1/entities/{entity}/reminders).

Request body

application/json (required): ReminderWithdrawInput

Field Type Required Description
reason string yes Why it is withdrawn. (min length 1; max length 500)

Example request

curl -X POST "$ERP_URL/v1/reminders/3fa85f64-5717-4562-b3fc-2c963f66afa6/withdraw" \
  -H "Authorization: Bearer $ERP_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
  "reason": "The customer paid part of it meanwhile"
}'

Responses

Status Meaning Body
201 Created ReminderOut
401 Missing or invalid API key (unauthorized). ErrorEnvelope
403 The caller lacks the required scope (missing_right, with scope), the key belongs to no person where a person is needed (forbidden), or the approval policy denies the action (policy_denied, with action and rule_id). ErrorEnvelope
404 The resource does not exist, or belongs to another organization (not_found). ErrorEnvelope
409 The request conflicts with the data: an Idempotency-Key reused with a different request, a closed period, or an integrity rule of the database (conflict, integrity_violation). ErrorEnvelope
422 Validation failed: the error envelope (validation_failed). For a malformed body or parameter its message is in sentences ("Line 2: the quantity must be above zero") and fields lists each error with pydantic's loc, type and msg beside its sentence (message) and its parts, to word it in another language: items (name and number from 1: line 2), field (its name as sent) and the rule it breaks with its limit, count and choices (none for a validator's own sentence); FastAPI's own detail list stays beside the envelope. HTTPValidationError

Example response (shape)

{
  "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "entity": "string",
  "party_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "party_code": "string",
  "party": "string",
  "currency": "string",
  "level": 1,
  "letter_date": "2026-09-21",
  "deadline_date": "2026-09-21",
  "language": "de",
  "total": "string",
  "fee": "0.00",
  "charge": {
    "document_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "number": "string",
    "status": "string",
    "charged": true
  },
  "file": {
    "file_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "filename": "string",
    "sha256": "string",
    "size": 1
  },
  "created_by": {},
  "created_at": "2026-09-21T09:30:00Z",
  "items": [
    {
      "document_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "number": "string",
      "level": 1,
      "due_date": "2026-09-21",
      "days_overdue": 1,
      "open_amount": "string",
      "flat_fee": "0.00",
      "interest": "0.00",
      "interest_rate": "string",
      "interest_from": "2026-09-21",
      "interest_until": "2026-09-21",
      "interest_parts": [
        null
      ]
    }
  ],
  "dispatches": [
    {
      "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "channel": "email",
      "handed_over_on": "2026-09-21",
      "recipients": [
        "string"
      ],
      "subject": "string",
      "message_id": "string",
      "sent_by": {},
      "sent_at": "2026-09-21T09:30:00Z"
    }
  ],
  "state": "handed_over",
  "withdrawal": {
    "reason": "string",
    "withdrawn_by": {},
    "withdrawn_at": "2026-09-21T09:30:00Z"
  },
  "email": "string"
}

Schemas

ActivityCurrency

The movements of one currency, from the opening to the closing balance.

Field Type Required Description
currency string yes ISO 4217 currency of the amounts.
opening string yes What we owed at the start of the first day.
increases string yes The sum of the positive movements.
decreases string yes The sum of the negative movements (a negative amount).
closing string yes What we owed at the end of the last day: opening + increases + decreases. Compare it with the closing balance of the statement the vendor sent.
lines array of ActivityLine yes The movements, oldest first.

ActivityLine

One movement on the vendor's account: a bill, a credit note, a payment.

Field Type Required Description
day string (date) yes The day it was booked.
kind "application" | "credit_note" | "invoice" | "other" | "payment" | "payment_reversal" | "write_off" yes invoice (the vendor's bill), credit_note, payment (what we paid, or a refund received), payment_reversal, application (an amount on account or a credit note applied to a bill later, ADR-0045: one line off the payment or credit note, one on the bill), write_off (a customer invoice written off as uncollectable), or other (an opening balance or a manual entry).
reference string yes Our number: the bill's, the payment's or the entry's.
their_reference string or null yes The vendor's own number of the bill or credit note, to find it on the vendor's statement.
document_id string (uuid) or null yes The bill or credit note it concerns.
document_number string or null yes Our number of that bill or credit note (for a payment: the one it settles).
entry_id string (uuid) yes The journal entry that booked it.
amount string yes In the currency of the block: positive when it raises what we owe (a bill), negative when it lowers it (a payment, a credit note).
balance string yes What we owe after it: the running balance.

CustomerActivity

A customer's activity statement: what the customer owes us, by invoice, credit note and payment, between two days.

Field Type Required Description
entity string yes Entity code.
party_id string (uuid) yes Id of the customer.
party_code string yes Code of the customer.
party string yes Name of the customer.
start string (date) yes The first day of the period.
end string (date) yes The last day of the period.
language "de" | "en" | "fr" | "it" | "sv" yes The language of its PDF: the customer's, else the one spoken in its country.
currencies array of CustomerActivityCurrency yes One block per currency the customer has movements or a balance in, by code: the currency of each invoice, credit note and payment.
functional_currency string yes The entity's functional currency.
closing_functional string yes What the customer owes at the end of end in the functional currency: its lines on the receivables control account, revaluations included (the control_balance of the open-items statement of that day).
open_items array of StatementItem yes The invoices, credit notes and amounts on account still open at the end of end, oldest due date first (credit notes negative): the open-items statement of that day.

CustomerActivityCurrency

The movements of one currency, from the opening to the closing balance.

Field Type Required Description
currency string yes ISO 4217 currency of the amounts.
opening string yes What the customer owed at the start of the first day.
increases string yes The sum of the positive movements.
decreases string yes The sum of the negative movements (a negative amount).
closing string yes What the customer owed at the end of the last day: opening + increases + decreases. A negative amount is a credit of the customer.
lines array of CustomerActivityLine yes The movements, oldest first.

CustomerActivityLine

One movement on the customer's account: an invoice, a credit note, a payment received.

Field Type Required Description
day string (date) yes The day it was booked.
kind "application" | "credit_note" | "invoice" | "other" | "payment" | "payment_reversal" | "write_off" yes invoice, credit_note, payment (a payment received, or a refund paid out), payment_reversal, application (an amount on account or a credit note applied to an invoice later, ADR-0045: one line off the payment or credit note, one on the invoice), or other (an opening balance or a manual entry).
reference string yes Our number: the invoice's, the credit note's, the payment's or the entry's.
document_id string (uuid) or null yes The invoice or credit note it concerns.
document_number string or null yes The number of that invoice or credit note (for a payment: the one it pays).
entry_id string (uuid) yes The journal entry that booked it.
amount string yes In the currency of the block: positive when it raises what the customer owes (an invoice), negative when it lowers it (a payment, a credit note).
balance string yes What the customer owes after it: the running balance.

DunningBlockInput

Field Type Required Description
reason string yes Why the reminders stop. (min length 1; max length 500)

DunningBlockOut

The reminders of an invoice are stopped (for instance while the customer disputes it).

Field Type Required Description
document_id string (uuid) yes Id of the invoice.
number string yes Invoice number.
reason string yes Why the reminders stop.
blocked_by object yes Who stopped them: type, id and name.
blocked_at string (date-time) yes When (UTC).

DunningBlockState

Whether the reminders of an invoice are stopped.

Field Type Required Description
document_id string (uuid) yes Id of the invoice.
block DunningBlockOut or null yes The stop while it holds; null when reminders go out as usual.

DunningLevelOut

One level of reminder and when it is due.

Field Type Required Description
level integer yes 1 payment reminder, 2 second reminder, 3 final reminder.
days_after integer yes Level 1: days after the due date; later levels: days after the previous letter was handed over.
deadline_days integer yes Days the letter gives to pay, from its day.

InterestPart

Part of an invoice's default interest that one rate covers, when the rate changed in the span: a German company's default rates follow the base rate, which changes on 1 January and 1 July, and the days on each side of the change are charged at their own rate.

Field Type Required Description
interest_rate string yes The yearly rate in percent of these days.
interest_from string (date) yes The part runs from the day after this one.
interest_until string (date) yes The last day of the part.
interest string yes The interest of these days, in the invoice's currency.

ReminderBlocked

An open invoice whose reminders a person stopped: no letter names it while the stop holds.

Field Type Required Description
document_id string (uuid) yes Id of the invoice.
number string yes Invoice number.
party_code string yes Code of the customer.
party string yes Name of the customer.
currency string yes ISO 4217 currency.
due_date string (date) yes Due date.
days_overdue integer yes Days past the due date today (0 or less: not due).
open string yes What is open today.
reason string yes Why the reminders are stopped.
blocked_by object yes Who stopped them: type, id and name.
blocked_at string (date-time) yes When (UTC).

ReminderChargeOut

The sales invoice that books a letter's fees and interest, made at its first hand-over.

Field Type Required Description
document_id string (uuid) yes Id of the invoice.
number string or null yes Its number; null while it waits for approval.
status string yes posted, pending_approval, rejected (by the approver, or withdrawn from approval), draft (a rejected invoice reopened) or void (reopened and voided).
charged boolean yes False once the invoice is rejected or void: the letter's charges were not booked, and a later letter charges the same interest days and flat fees again.

ReminderCreateInput

Field Type Required Description
as_of string (date) or null The day of the letter: today in the entity's country, the only day a letter is dated (its amounts are today's). Omitted: today.
currency string or null The currency of the letter. Omitted: the one the customer (or the invoices named) is due a reminder in; of several, the customer's own (422 reminder_currency_needed when it is not one of them). (min length 3; max length 3)
documents array of string (uuid) or null Only these invoices (each must be due a reminder); omitted: every invoice of the customer in the currency that is due one. (min items 1)
language "de" | "en" | "fr" | "it" | "sv" or null Language of the letter; omitted: the customer's language.

ReminderCredit

What the customer has to its credit in the letter's currency, deducted from what the letter asks for: a credit note with something open, or a receipt's amount on account (ADR-0045). Each credit is deducted once: what a letter still standing (not withdrawn, naming an invoice still open that no later letter names) deducted is not deducted again.

Field Type Required Description
kind "payment_on_account" | "sales_credit_note" yes sales_credit_note, or payment_on_account: what is left on account of a receipt, not yet applied to an invoice.
document_id string (uuid) yes Id of the credit note, or of the receipt.
number string yes Number of the credit note or the receipt.
date string (date) yes Date of the credit note or the receipt.
open string yes What the letter deducts of it (positive): what is left of it today, less what letters still standing deducted already. An application waiting for approval reserves its amount.

ReminderDispatchOut

Field Type Required Description
id string (uuid) yes Id of the hand-over.
channel "email" | "other" | "portal" | "post" | "system_email" yes system_email (this server sent it) or what a person recorded: email, post, portal, other.
handed_over_on string (date) yes The day it was handed over.
recipients array of string yes To whom.
subject string or null yes Subject of the e-mail; null for a recorded one.
message_id string or null yes Message-ID of the e-mail; null otherwise.
sent_by object yes Who: type, id and name.
sent_at string (date-time) yes When it was sent or recorded (UTC).

ReminderDue

A customer that is due a reminder letter in one currency.

Field Type Required Description
party_id string (uuid) yes Id of the customer.
party_code string yes Code of the customer.
party string yes Name of the customer.
currency string yes The currency of the letter.
level integer yes The letter's level: the highest next level of its invoices.
language "de" | "en" | "fr" | "it" | "sv" yes The customer's language: that of the letter.
total string yes What the letter would ask for: the invoices' open amounts less credits, plus fee and the flat fees and interest of the invoices. A customer whose credits cover its overdue invoices is due no letter.
fee string The fee of the letter's level, in its currency (converted from the functional currency at today's rate); 0 for none. (default "0.00")
email string or null yes Where an e-mail would go by default: the customer's billing address.
invoices array of ReminderInvoice yes The invoices due a reminder.
credits array of ReminderCredit The customer's credit notes with something open and receipts' amounts on account in the currency, as far as no letter still standing deducted them, which the letter deducts.

ReminderFile

The archived PDF of a letter.

Field Type Required Description
file_id string (uuid) yes Id of the archived file (document.id).
filename string yes File name, e.g. reminder-C-DE-2026-10-10-1.pdf.
sha256 string yes SHA-256 of the archived bytes.
size integer yes Size in bytes.

ReminderInvoice

An overdue invoice and where its reminders stand.

Field Type Required Description
document_id string (uuid) yes Id of the invoice.
number string yes Invoice number.
document_date string (date) yes Invoice date.
due_date string (date) yes Due date.
days_overdue integer yes Days past the due date today.
currency string yes ISO 4217 currency.
open string yes What is open today, in the invoice's currency.
last_level integer yes The level of the last letter that named it; 0 for none.
last_sent_on string (date) or null yes The day that letter was first handed over; null when none was, or never.
next_level integer yes The level the next letter gives it.
flat_fee string The flat fee the letter charges once for this invoice (a business customer; Germany: EUR 40, § 288 para. 5 BGB), in its currency; 0 for none. (default "0.00")
interest string Default interest the letter charges on this invoice, in its currency: actual/365 on what was open each day from interest_from (exclusive) to interest_until; 0 for none. (default "0.00")
interest_rate string or null The yearly rate in percent (when it changed in the span, that of the letter's day: see interest_parts); null when no interest is charged.
interest_from string (date) or null The interest runs from the day after this one: the due date, or the last day an earlier letter charged interest for (no day is charged twice).
interest_until string (date) or null The last day the interest covers: the letter's day.
interest_parts array of InterestPart When the rate changed in the span (the German base rate on 1 January or 1 July), the parts at each rate, in order, adding up to interest; empty when one rate covers it all.

ReminderItemOut

Field Type Required Description
document_id string (uuid) yes Id of the invoice.
number string yes Invoice number.
level integer yes The level the invoice reached with this letter.
due_date string (date) yes Its due date.
days_overdue integer yes Days past the due date on the letter's day.
open_amount string yes What was open on the letter's day.
flat_fee string The flat fee charged for it. (default "0.00")
interest string The default interest charged on it. (default "0.00")
interest_rate string or null Yearly rate in percent.
interest_from string (date) or null The interest runs from the day after this one.
interest_until string (date) or null The last day the interest covers.
interest_parts array of InterestPart When the rate changed in the span (the German base rate on 1 January or 1 July), the parts at each rate, in order, adding up to interest; empty when one rate covers it all.

ReminderLevelFees-Input

What a reminder of one level charges.

Field Type Required Description
level integer yes 1 payment reminder, 2 second, 3 final reminder. (min 1; max 3)
fee decimal string yes Fee per letter of this level, in the company's functional currency (a letter in another currency converts it at the letter's day); 0 for none. (min 0)
flat_fee decimal string yes Flat fee charged once per invoice to a business customer, in the functional currency (Germany: EUR 40 on the first reminder, § 288 para. 5 BGB); 0 for none. When the charge of the letter that set it is rejected or voided, the next letter charges it. (min 0)
interest_rate decimal string yes Default interest for business customers, percent a year (actual/365), from the due date; 0 for none. (min 0; max 100)
consumer_interest_rate decimal string yes Default interest for consumers (customers that are not a business), percent a year; 0 for none. (min 0; max 100)

ReminderLevelFees-Output

What a reminder of one level charges.

Field Type Required Description
level integer yes 1 payment reminder, 2 second, 3 final reminder. (min 1; max 3)
fee string yes Fee per letter of this level, in the company's functional currency (a letter in another currency converts it at the letter's day); 0 for none.
flat_fee string yes Flat fee charged once per invoice to a business customer, in the functional currency (Germany: EUR 40 on the first reminder, § 288 para. 5 BGB); 0 for none. When the charge of the letter that set it is rejected or voided, the next letter charges it.
interest_rate string yes Default interest for business customers, percent a year (actual/365), from the due date; 0 for none.
consumer_interest_rate string yes Default interest for consumers (customers that are not a business), percent a year; 0 for none.

ReminderMarkSentInput

Field Type Required Description
channel "email" | "other" | "portal" | "post" yes email (from a person's own mailbox), post, portal or other.
recipient string yes Who got it. (min length 1; max length 200)
handed_over_on string (date) yes The day it was handed over: not before the letter, not after today, and within the last 7 days.

ReminderOut

A reminder letter: what it asked for, its file and its hand-overs.

Field Type Required Description
id string (uuid) yes Id of the letter.
entity string yes Entity code.
party_id string (uuid) yes Id of the customer.
party_code string yes Code of the customer.
party string yes Name of the customer.
currency string yes ISO 4217 currency.
level integer yes 1 payment reminder, 2 second reminder, 3 final reminder.
letter_date string (date) yes The day of the letter.
deadline_date string (date) yes The day by which it asks for payment.
language "de" | "en" | "fr" | "it" | "sv" yes The language of the letter.
total string yes What it asks for: the open amounts of its invoices less the customer's credits it deducts, plus its fee and the flat fees and interest of its invoices, on the letter's day.
fee string The fee of its level; 0 for none. (default "0.00")
charge ReminderChargeOut or null The sales invoice of its fees and interest (outside VAT), made when it was first handed over; null before, or when it charges nothing.
file ReminderFile yes The archived PDF.
created_by object yes Who made it.
created_at string (date-time) yes When.
items array of ReminderItemOut yes The invoices it names.
dispatches array of ReminderDispatchOut yes Each hand-over, oldest first. Empty: made but not sent, which starts no clock for the next level.
state "handed_over" | "out_of_date" | "unsent" | "withdrawn" yes unsent (made, not handed over, still right: send or record it), out_of_date (not handed over, and an amount on it changed since or it is more than 7 days old: it cannot be sent; withdraw it and make a new one), handed_over or withdrawn.
withdrawal ReminderWithdrawalOut or null Who withdrew it, when and why; null when nobody did.
email string or null yes Where an e-mail would go by default: the customer's billing address.

ReminderProposal

Which customers are due a reminder letter today, and the letters not yet sent.

Field Type Required Description
entity string yes Entity code.
as_of string (date) yes Today, in the entity's country: the day of the letters.
levels array of DunningLevelOut yes The levels and when each is due.
due array of ReminderDue yes One row per customer and currency that is due a letter, by customer code.
unsent array of ReminderOut yes Letters made, not handed over yet and still right: send or record them, or the next level never comes.
out_of_date array of ReminderOut Letters not handed over that are out of date (an amount on them changed, or they are more than 7 days old): they cannot be sent and hold back the next letter until they are withdrawn.
blocked array of ReminderBlocked Open invoices whose reminders a person stopped (a dispute): left out of every letter, with why.
sending_configured boolean yes Whether this server sends e-mail (false in a test copy, which never does).

ReminderSendInput

Field Type Required Description
to array of string or null Addresses of the customer (as for an invoice); omitted: its billing address. (min items 1; max items 5)
message string or null A text placed before the standard text. (max length 1000)

ReminderSettingsInput

Field Type Required Description
levels array of ReminderLevelFees-Input yes The three levels, each once. (min items 3; max items 3)

ReminderSettingsOut

The fees and default interest of each reminder level of a company.

Field Type Required Description
entity string yes Entity code.
currency string yes The functional currency the fees are in.
configured boolean yes Whether a person saved settings; false: the country's defaults apply.
levels array of ReminderLevelFees-Output yes The three levels, in order.
defaults array of ReminderLevelFees-Output yes The country's defaults: Switzerland and Liechtenstein 5 % a year and no fee; Germany the base rate plus 9 points (business) or 5 points (consumers), shown at today's base rate and charged at each day's (split where it changes, on 1 January or 1 July), and EUR 40 once per invoice to a business customer; elsewhere nothing.

ReminderWithdrawInput

Field Type Required Description
reason string yes Why it is withdrawn. (min length 1; max length 500)

ReminderWithdrawalOut

Field Type Required Description
reason string yes Why it was withdrawn.
withdrawn_by object yes Who: type, id and name.
withdrawn_at string (date-time) yes When (UTC).

Statement

A customer's statement of account: the open items on a day.

Field Type Required Description
entity string yes Entity code.
party_id string (uuid) yes Id of the customer.
party_code string yes Code of the customer.
party string yes Name of the customer.
as_of string (date) yes The day the statement is as of.
language "de" | "en" | "fr" | "it" | "sv" yes The language of its PDF: the customer's, else the one spoken in its country.
items array of StatementItem yes Open items, oldest due date first; credit notes are negative items.
balances array of StatementBalance yes The balance and its age structure per currency, by currency code.
functional_currency string yes The entity's functional currency.
totals_functional map of string yes The open amount per age band and total in the functional currency: the figures reconciliation ties to the ledger.
reconciliation StatementReconciliation yes The total against the customer's lines on the control account.
issued array of StatementFile yes Statements of this customer and day that were archived (POST .../issue), oldest first, one per language.

StatementBalance

The open items of one currency: the balance and what is overdue, by age.

Field Type Required Description
currency string yes ISO 4217 currency.
balance string yes The open amount in this currency; credit notes reduce it.
overdue string yes The part of the balance that is past its due date (every band but current).
documents integer yes How many items are listed in this currency.
overdue_documents integer yes How many of them are past their due date (bucket is not current).
buckets map of string yes The open amount per age band, every band present: current, 1-30, 31-60, 61-90, 90+. They add up to balance.

StatementFile

A statement kept in the document archive.

Field Type Required Description
file_id string (uuid) yes Id of the archived file (document.id).
filename string yes File name, e.g. statement-C-CH-2026-09-30-de.pdf.
language "de" | "en" | "fr" | "it" | "sv" yes Language the PDF was issued in.
sha256 string yes SHA-256 of the archived bytes.
size integer yes Size in bytes.
issued_by object yes Who issued it: type, id and name.
issued_at string (date-time) yes When it was archived.

StatementIssueInput

Field Type Required Description
as_of string (date) yes The day the statement is as of, ISO 8601; not in the future.
language "de" | "en" | "fr" | "it" | "sv" or null Language of the PDF; omitted: the customer's language. Another language is another archived file.

StatementIssued

The result of issuing a statement.

Field Type Required Description
file StatementFile yes The archived PDF.
created boolean yes True when this call archived the file; false when the statement of this customer, day and language was archived before and that file is returned (the archive wins: what the customer was told is not rewritten).
download string yes The path that returns the PDF (GET .../statement?format=pdf), which serves the archived file for this day and language.

StatementItem

One open item: an invoice or bill, or a credit note or a payment's amount on account as a negative item.

Field Type Required Description
document_id string (uuid) yes Id of the invoice, bill or credit note; of the receipt or payment for an amount on account.
number string yes Document number, e.g. INV-2026-000012.
kind "payment_on_account" | "purchase_bill" | "purchase_credit_note" | "sales_credit_note" | "sales_invoice" yes sales_invoice or sales_credit_note on a customer's statement, purchase_bill or purchase_credit_note on a vendor's; payment_on_account on either: what is left on account of a receipt or payment, not yet applied (never overdue).
document_date string (date) yes Document date.
due_date string (date) yes Due date.
currency string yes ISO 4217 currency of the amounts.
amount string yes Gross total, negative for a credit note.
open string yes What is open on as_of, negative for a credit note: the total less the allocations dated on or before as_of (payments, credit notes, a cash discount taken).
open_functional string The carrying amount the ledger holds for the item in the entity's functional currency on as_of, negative for a credit note. (default "0.00")
reserved boolean True when payments waiting for approval reserve the whole open amount: open is zero, the ledger still carries the item. (default false)
days_overdue integer yes Days past the due date on as_of; 0 when not yet due.
bucket string yes current, 1-30, 31-60, 61-90 or 90+ days overdue.

StatementReconciliation

The statement's total against the ledger: the customer's lines on the receivables control account up to the day.

Field Type Required Description
control_account string yes Code of the receivables control account.
control_balance string yes The balance of this customer's lines on the control account in the ledger as of as_of, in the functional currency (what the customer owes us).
totals_functional string yes The statement's total in the functional currency: the sum of the items' open_functional, the carrying amounts the ledger holds.
difference string yes control_balance less totals_functional.
unrealised_fx string yes Entries of source fx (period-end revaluations) on the customer's control lines up to as_of that no reversal has cancelled yet: they sit on the control account but on no document.
pending_settlements string yes A memo: the functional amount of payments and applications waiting for approval on the listed items (an application on both of its items). They reserve the open amount in the document currency but are not booked, so they are in neither control_balance nor totals_functional.
unexplained string yes difference less unrealised_fx: zero when the statement ties to the ledger; anything else is a posting on the control account that no document carries.

VendorStatement

A vendor's statement: what we owe the vendor, by bill, credit note and payment.

Field Type Required Description
entity string yes Entity code.
party_id string (uuid) yes Id of the vendor.
party_code string yes Code of the vendor.
party string yes Name of the vendor.
start string (date) yes The first day of the period.
end string (date) yes The last day of the period.
language "de" | "en" | "fr" | "it" | "sv" yes The language of its PDF: the vendor's, else the one spoken in its country.
currencies array of ActivityCurrency yes One block per currency the vendor has movements or a balance in, by code; the vendor's own currency is among them when it has any.
functional_currency string yes The entity's functional currency.
closing_functional string yes What we owe the vendor at the end of end in the functional currency: its lines on the payables control account, revaluations included.
open_items array of StatementItem yes The bills and credit notes still open at the end of end, oldest due date first (credit notes negative): the same open items as the payables aging.
Stabiso, the Enterprise System of Record · generated from the code and its guides · release 6f03a5e846b3