StabisoDocs

API reference

Banking

Bank statement import (camt.053, camt.054, CSV), matching and posting.

Operation Summary Scope Idempotency-Key
GET /v1/bank-lines/{line_id}/candidates List matching documents for a bank line read
POST /v1/bank-lines/{line_id}/ignore Ignore a bank line post
POST /v1/bank-lines/{line_id}/link Link a bank line to a booked payment draft
POST /v1/bank-lines/{line_id}/match Match a bank line to documents draft
POST /v1/bank-lines/{line_id}/post Post a bank line to an account draft
POST /v1/bank-lines/{line_id}/reopen Reopen an ignored bank line post
POST /v1/bank-lines/{line_id}/unmatch Undo the match of a bank line post
GET /v1/entities/{entity}/bank-lines List bank statement lines read
GET /v1/entities/{entity}/bank-reconciliation Reconcile a bank account read
GET /v1/entities/{entity}/bank-reconciliations List bank reconciliations read
POST /v1/entities/{entity}/bank-reconciliations Mark a bank account reconciled post
POST /v1/entities/{entity}/bank-reconciliations/{reconciliation_id}/reset Reset a bank reconciliation approve
GET /v1/entities/{entity}/bank-statements List bank statements read
POST /v1/entities/{entity}/bank-statements Import a bank statement draft
POST /v1/entities/{entity}/bank-statements/preview Preview a CSV bank file draft
POST /v1/entities/{entity}/payment-status-reports Import the bank's status report on a payment file draft

GET /v1/bank-lines/{line_id}/candidates

List matching documents for a bank line

Open documents and booked payments that could settle the line, scored with reasons.

For a credit the documents are posted sales invoices and purchase credit notes, for a debit posted purchase bills and sales credit notes, in any currency (at most 10): one in another currency than the line's gives its open amount at the booking day's rate (line_open). Each gives its open amount, any cash discount available at the booking date and the reasons for its score (structured reference, reference text, exact amount, IBAN, counterparty name). Candidates of kind payment are payments already booked from the line's bank account, in its direction, that no bank line settles yet: in the line's currency at the exact amount, or in another currency (a line in the functional currency) within 2% of what they booked, with the bank's difference; link the line to one with POST .../link rather than post it to an account, which would book the payment twice. For a credit, candidates of kind return are outgoing payments of the line's bank account the bank executed and that are still posted, which the line may return (ADR-0062): linking one reverses that payment by the line. Best score first. Refused with 409 when the line is no longer unmatched.

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

Parameters

In Name Type Required Description
path line_id string (uuid) yes Bank statement line id (GET /v1/entities/{entity}/bank-lines).

Example request

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

Responses

Status Meaning Body
200 OK array of Candidate
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",
    "payment_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "number": "string",
    "external_number": "string",
    "kind": "string",
    "party": "string",
    "party_code": "string",
    "due_date": "2026-09-21",
    "currency": "string",
    "open": "string",
    "line_open": "0.00",
    "cash_discount": "0.00",
    "difference": "0.00",
    "score": 1,
    "reasons": [
      "string"
    ],
    "reason_words": [
      {
        "words": "string",
        "code": "string",
        "details": null,
        "text": "string"
      }
    ]
  }
]

POST /v1/bank-lines/{line_id}/ignore

Ignore a bank line

Mark an unmatched line as ignored, with a reason, so it no longer needs matching.

Nothing is posted. Use it for lines that need no booking, for example a transfer that is recorded elsewhere. POST /v1/bank-lines/{line_id}/reopen undoes it. Refused with 409 when the line is not unmatched.

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

Parameters

In Name Type Required Description
path line_id string (uuid) yes Bank statement line id (GET /v1/entities/{entity}/bank-lines).

Request body

application/json (required): IgnoreRequest

Field Type Required Description
reason string Why the line needs no booking, e.g. Internal transfer, booked on 1020; required (refused with ignore_reason_missing when empty). (default "")

Example request

curl -X POST "$ERP_URL/v1/bank-lines/3fa85f64-5717-4562-b3fc-2c963f66afa6/ignore" \
  -H "Authorization: Bearer $ERP_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "reason": "Internal transfer, booked on 1020"
}'

Responses

Status Meaning Body
200 OK BankLineOut
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",
  "statement_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "booking_date": "2026-09-21",
  "value_date": "2026-09-21",
  "amount": "string",
  "currency": "string",
  "counterparty_name": "string",
  "counterparty_iban": "string",
  "reference": "string",
  "end_to_end_id": "string",
  "remittance": "string",
  "status": "string",
  "match": {},
  "posting_date": "2026-09-21",
  "closed_period": "string",
  "payment_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "journal_entry_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
}

POST /v1/bank-lines/{line_id}/link

Link a bank line to a booked payment

Settle the line by a payment already booked, which it executes (a candidate of kind payment): nothing is booked again. For a payment in another currency than the line's, the bank's difference to what the payment booked (its conversion rate against the ECB rate of the payment date) is booked against the bank account as a realised exchange gain or loss, through the approval policy (difference_entry); a rejected entry returns the line to unmatched. The line becomes matched. Refused: 409 when the line is not unmatched; 422 when the payment is not a booked payment of the line's bank account and direction that no other line settles (bank_line_payment_not_booked), or its amount does not fit (bank_line_amount_differs: a payment in the line's currency fits only at its exact amount, one in another currency within 2%). The line's own entry is dated on (default: the booking date, or when its period is closed the first day of the next open period, the line's posting_date); the payment stands as booked, in a closed month too.

Linking a credit to an outgoing payment (a candidate of kind return) records that the money came back (ADR-0062): the payment is reversed by the line, the bank account debited by what came back, and the bills it paid are open again once the reversal is posted (it follows the approval policy and the four-eyes rules; difference_entry is the reversal). Refused (422) when the payment is not an outgoing payment of the line's bank account that the bank executed and that is still posted (bank_line_not_returnable).

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

Parameters

In Name Type Required Description
path line_id string (uuid) yes Bank statement line id (GET /v1/entities/{entity}/bank-lines).

Request body

application/json (required): LinkRequest

Field Type Required Description
payment string yes Id or number of a payment already booked from the line's bank account (a candidate of kind payment), which the line executes.
on string (date) or null Posting date of the line's own entry (an exchange difference, the move from payments in transit, or the reversal of a returned payment), ISO 8601: a day in an open period, not before the line's booking date (422 bank_posting_before_line). Default: the booking date, or when its period is closed the first day of the next open period (the line's posting_date). The line keeps its booking date on the statement.

Example request

curl -X POST "$ERP_URL/v1/bank-lines/3fa85f64-5717-4562-b3fc-2c963f66afa6/link" \
  -H "Authorization: Bearer $ERP_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "payment": "PAY-2026-000003"
}'

Responses

Status Meaning Body
200 OK LinkResult
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)

{
  "line": {
    "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "statement_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "booking_date": "2026-09-21",
    "value_date": "2026-09-21",
    "amount": "string",
    "currency": "string",
    "counterparty_name": "string",
    "counterparty_iban": "string",
    "reference": "string",
    "end_to_end_id": "string",
    "remittance": "string",
    "status": "string",
    "match": {},
    "posting_date": "2026-09-21",
    "closed_period": "string",
    "payment_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "journal_entry_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
  },
  "payment_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "payment_number": "string",
  "difference": "string",
  "difference_entry": {
    "entry_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "status": "string",
    "number": "string",
    "policy": {
      "decision": null,
      "reason": null,
      "rule_id": null,
      "table_id": null
    },
    "approval_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "reason": "string"
  }
}

POST /v1/bank-lines/{line_id}/match

Match a bank line to documents

Settle the line against open documents of one party by recording a payment.

The allocations must add up to the absolute amount of the line; the payment is incoming for a credit and outgoing for a debit, dated on (default: the booking date, or when its period is closed the first day of the next open period, the line's posting_date). A document in another currency than the line's is settled by the allocation's document_amount (its open amount, when the line pays it in full), the difference booked as realised FX. The payment entry follows the approval policy, so the result can be pending approval (submit.policy). The line becomes matched. Refused: 409 when the line is not unmatched or the period of on is closed; 422 when the documents belong to different parties, the allocations do not add up, a document cannot be settled (wrong kind, not posted, amount above what is open), or on is before the booking date (bank_posting_before_line).

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

Parameters

In Name Type Required Description
path line_id string (uuid) yes Bank statement line id (GET /v1/entities/{entity}/bank-lines).

Request body

application/json (required): MatchRequest

Field Type Required Description
allocations array of AllocationInput-Input The documents the line settles, each with the amount applied; with on_account the amounts must add up to the absolute amount of the line, and all documents must belong to one customer or vendor.
on_account decimal string The part of the line allocated to no document: it stays on the party's account until it is applied (an overpayment, an advance). Default 0. (min 0; default "0")
party string or null Code (or id) of the customer or vendor, needed when no document is allocated (the whole line on account); otherwise the documents' party, which it must match.
on string (date) or null Posting date, ISO 8601: a day in an open period, not before the line's booking date (422 bank_posting_before_line). Default: the booking date, or when its period is closed the first day of the next open period (the line's posting_date). The line keeps its booking date on the statement.

Example request

curl -X POST "$ERP_URL/v1/bank-lines/3fa85f64-5717-4562-b3fc-2c963f66afa6/match" \
  -H "Authorization: Bearer $ERP_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "allocations": [
    {
      "amount": "1500.00",
      "document": "INV-2026-000001"
    }
  ]
}'

Responses

Status Meaning Body
200 OK PaymentResult
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)

{
  "payment_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "status": "string",
  "fx_difference": "string",
  "discount": "0.00",
  "in_transit": false,
  "submit": {
    "entry_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "status": "string",
    "number": "string",
    "policy": {
      "decision": "allow",
      "reason": "string",
      "rule_id": "string",
      "table_id": "string"
    },
    "approval_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "reason": "string"
  },
  "warnings": [
    "string"
  ],
  "warning_reasons": [
    {
      "words": "string",
      "code": "string",
      "details": {},
      "text": "string"
    }
  ]
}

POST /v1/bank-lines/{line_id}/post

Post a bank line to an account

Book a line directly against an account (bank fees, interest).

Creates a two-line journal entry dated on (default: the booking date, or when its period is closed the first day of the next open period, the line's posting_date): the bank account against account, in the line's currency, and submits it. The response carries the approval policy decision (policy: allow, require_approval or deny); the line becomes matched and returns to unmatched if the entry is rejected. Refused with 409 when the line is not unmatched or the period of on is closed, with 422 bank_posting_before_line when on is before the booking date, with 404 when the counter account does not exist.

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

Parameters

In Name Type Required Description
path line_id string (uuid) yes Bank statement line id (GET /v1/entities/{entity}/bank-lines).

Request body

application/json (required): PostLineInput

Field Type Required Description
account string yes Counter account, e.g. bank fees or interest income.
description string or null Entry description. Default: the line's remittance text, else its reference.
dimensions map of string Cost centre, profit centre or project of the counter line, by dimension code: {"cost_centre": "CC-200"} (GET /v1/dimensions); active values valid on the booking date only.
on string (date) or null Posting date, ISO 8601: a day in an open period, not before the line's booking date (422 bank_posting_before_line). Default: the booking date, or when its period is closed the first day of the next open period (the line's posting_date). The line keeps its booking date on the statement.

Example request

curl -X POST "$ERP_URL/v1/bank-lines/3fa85f64-5717-4562-b3fc-2c963f66afa6/post" \
  -H "Authorization: Bearer $ERP_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "account": "6940",
  "description": "Bank fees September 2026"
}'

Responses

Status Meaning Body
200 OK SubmitResult
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)

{
  "entry_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "status": "string",
  "number": "string",
  "policy": {
    "decision": "allow",
    "reason": "string",
    "rule_id": "string",
    "table_id": "string"
  },
  "approval_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "reason": "string"
}

POST /v1/bank-lines/{line_id}/reopen

Reopen an ignored bank line

Undo 'ignore': the line is unmatched again (a matched line is undone with POST /v1/bank-lines/{line_id}/unmatch). Safe to repeat without an Idempotency-Key: a line that is not ignored is refused with 409.

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

Parameters

In Name Type Required Description
path line_id string (uuid) yes Bank statement line id (GET /v1/entities/{entity}/bank-lines).

Example request

curl -X POST "$ERP_URL/v1/bank-lines/3fa85f64-5717-4562-b3fc-2c963f66afa6/reopen" \
  -H "Authorization: Bearer $ERP_KEY"

Responses

Status Meaning Body
200 OK BankLineOut
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",
  "statement_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "booking_date": "2026-09-21",
  "value_date": "2026-09-21",
  "amount": "string",
  "currency": "string",
  "counterparty_name": "string",
  "counterparty_iban": "string",
  "reference": "string",
  "end_to_end_id": "string",
  "remittance": "string",
  "status": "string",
  "match": {},
  "posting_date": "2026-09-21",
  "closed_period": "string",
  "payment_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "journal_entry_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
}

POST /v1/bank-lines/{line_id}/unmatch

Undo the match of a bank line

Undo the match of a matched line, with a reason (required, at most 500 characters).

What the match did is undone (outcome): a line only linked to a payment booked before (a payment released in a payment file) is unlinked and the payment stands; a payment or posting the match made that still waits for approval is withdrawn (rejected, nothing was posted); a posted payment is reversed as POST /v1/payments/{payment_id}/reverse does, and a posted posting of the line (fees, interest) is reversed as a journal entry, dated on (default: today for a payment, the posting's date for a posting). Each reversal follows its approval policy: pending_approval means it waits for a second person (approval_id) and the line stays matched, with match.undo, until it is approved. Otherwise the line is unmatched again, and the close job's matcher leaves it to a person.

Only a person undoes a match (403 for an agent). Refused with 409: the line is not matched, its undoing already waits for approval, or the period of the date is closed. Safe to repeat without an Idempotency-Key: a second request is refused with 409.

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

Parameters

In Name Type Required Description
path line_id string (uuid) yes Bank statement line id (GET /v1/entities/{entity}/bank-lines).

Request body

application/json (required): UnmatchRequest

Field Type Required Description
on string (date) or null Date of the reversal entry when undoing the match reverses a posted payment or posting, ISO 8601: not before it, in an open period. Default: today for a payment, the posting's own date for a posting.
reason string yes Why the match is undone (required, at most 500 characters): on the reversal, in the approval request and in the audit trail. (min length 1; max length 500)

Example request

curl -X POST "$ERP_URL/v1/bank-lines/3fa85f64-5717-4562-b3fc-2c963f66afa6/unmatch" \
  -H "Authorization: Bearer $ERP_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "on": "2026-10-10",
  "reason": "Wrong invoice"
}'

Responses

Status Meaning Body
200 OK UnmatchResult
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)

{
  "line": {
    "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "statement_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "booking_date": "2026-09-21",
    "value_date": "2026-09-21",
    "amount": "string",
    "currency": "string",
    "counterparty_name": "string",
    "counterparty_iban": "string",
    "reference": "string",
    "end_to_end_id": "string",
    "remittance": "string",
    "status": "string",
    "match": {},
    "posting_date": "2026-09-21",
    "closed_period": "string",
    "payment_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "journal_entry_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
  },
  "outcome": "pending_approval",
  "reversal_entry_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "approval_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
}

GET /v1/entities/{entity}/bank-lines

List bank statement lines

Statement lines by status (default unmatched; all for every status).

Lines come in booking-date order. Amounts are signed in the line's currency: positive is money in, negative money out. match says how a matched or ignored line was settled. An unmatched line gives the day a match or posting books it on by default (posting_date): its booking date, or when that is in a closed period (closed_period) the first day of the next open period.

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

Parameters

In Name Type Required Description
path entity string yes Entity code, e.g. CH01 (GET /v1/entities).
query status "all" | "ignored" | "matched" | "unmatched" or null Line status: unmatched (default), matched, ignored or all. (default "unmatched")
query statement string (uuid) or null Only the lines of this statement (id from the statement list).

Example request

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

Responses

Status Meaning Body
200 OK array of BankLineOut
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",
    "statement_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "booking_date": "2026-09-21",
    "value_date": "2026-09-21",
    "amount": "string",
    "currency": "string",
    "counterparty_name": "string",
    "counterparty_iban": "string",
    "reference": "string",
    "end_to_end_id": "string",
    "remittance": "string",
    "status": "string",
    "match": {},
    "posting_date": "2026-09-21",
    "closed_period": "string",
    "payment_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "journal_entry_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
  }
]

GET /v1/entities/{entity}/bank-reconciliation

Reconcile a bank account

The bank account's statement balance on the date against its ledger balance, and the items that explain the difference.

Bank items are statement lines up to the date that the ledger does not show by then: unmatched, ignored, waiting_for_approval (the booking waits for a second person) or booked_later. Ledger items are posted entries on the account from the first statement's start (since) to the date that no statement line up to the date books, such as a payment recorded as executed that a later statement shows (one the bank has not executed yet is in transit, ADR-0060, not on the account); an entry and its reversal in that range cancel out. unexplained is the difference less the opening difference, less the bank items, plus the ledger items: zero when everything is accounted for. done is the record when a person marked this account and date reconciled.

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

Parameters

In Name Type Required Description
path entity string yes Entity code, e.g. CH01 (GET /v1/entities).
query account string or null GL bank account code, e.g. 1020. Default: the main bank account.
query on string (date) or null Statement date. Default: the end date of the account's latest statement, else today.
query statement_balance decimal string or null The closing balance on the bank's statement, used only when no imported statement for the date carries one (a CSV file).

Example request

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

Responses

Status Meaning Body
200 OK BankReconciliationView
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)

{
  "account": "string",
  "account_name": "string",
  "currency": "string",
  "on": "2026-09-21",
  "accounts": [
    {
      "code": "string",
      "name": "string",
      "currency": "string"
    }
  ],
  "statements": [
    {
      "to_date": "2026-09-21",
      "statement_ref": "string",
      "closing_balance": "string"
    }
  ],
  "since": "2026-09-21",
  "statement_ref": "string",
  "statement_balance": "string",
  "ledger_balance": "string",
  "difference": "string",
  "opening_difference": "string",
  "bank_items": [
    {
      "line_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "booking_date": "2026-09-21",
      "amount": "string",
      "counterparty": "string",
      "text": "string",
      "statement_ref": "string",
      "reason": "booked_later"
    }
  ],
  "bank_items_total": "string",
  "ledger_items": [
    {
      "entry_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "number": "string",
      "entry_date": "2026-09-21",
      "description": "string",
      "source": "string",
      "amount": "string"
    }
  ],
  "ledger_items_total": "string",
  "unexplained": "string",
  "done": {
    "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "account": "string",
    "statement_date": "2026-09-21",
    "currency": "string",
    "statement_balance": "string",
    "ledger_balance": "string",
    "bank_items_total": "string",
    "ledger_items_total": "string",
    "unexplained": "string",
    "note": "string",
    "done_by": {},
    "done_at": "2026-09-21T09:30:00Z",
    "reset_reason": "string",
    "reset_by": {},
    "reset_at": "2026-09-21T09:30:00Z"
  }
}

GET /v1/entities/{entity}/bank-reconciliations

List bank reconciliations

The reconciliations people marked done, latest statement date first. A record that was reset stays in the list with reset_at, reset_by and reset_reason; only one record per account and date stands.

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

Parameters

In Name Type Required Description
path entity string yes Entity code, e.g. CH01 (GET /v1/entities).
query account string or null Only this bank account, e.g. 1020.
query limit integer At most this many (up to 1000). (min 1; max 1000; default 100)

Example request

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

Responses

Status Meaning Body
200 OK array of ReconciliationDone
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",
    "account": "string",
    "statement_date": "2026-09-21",
    "currency": "string",
    "statement_balance": "string",
    "ledger_balance": "string",
    "bank_items_total": "string",
    "ledger_items_total": "string",
    "unexplained": "string",
    "note": "string",
    "done_by": {},
    "done_at": "2026-09-21T09:30:00Z",
    "reset_reason": "string",
    "reset_by": {},
    "reset_at": "2026-09-21T09:30:00Z"
  }
]

POST /v1/entities/{entity}/bank-reconciliations

Mark a bank account reconciled

Record that the account is reconciled on the statement date: who, when, and the balances and item totals as they are now. The record changes only by a reset.

Only a person does it (403 for an agent). Refused: 409 reconciliation_done when the account and date were marked before (a controller resets that record first, POST .../bank-reconciliations/{reconciliation_id}/reset); 422 reconciliation_in_future for a date after today, statement_balance_missing when no imported statement for the date carries a closing balance and none is given, statement_balance_differs when the given balance is not the statement's, and reconciliation_unexplained (amount, currency) when part of the difference is unexplained and there is no note. Safe to repeat without an Idempotency-Key: a second request is refused with 409.

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

Parameters

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

Request body

application/json (required): ReconcileInput

Field Type Required Description
account string yes GL bank account code, e.g. 1020.
on string (date) yes The statement date reconciled.
statement_balance decimal string or null The closing balance on the bank's statement, needed only when no imported statement for the date carries one (a CSV file).
note string or null Why the account is reconciled although part of the difference is unexplained; required then. (max length 500)

Example request

curl -X POST "$ERP_URL/v1/entities/CH01/bank-reconciliations" \
  -H "Authorization: Bearer $ERP_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "account": "1020",
  "on": "2026-09-30"
}'

Responses

Status Meaning Body
201 Created ReconciliationDone
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",
  "account": "string",
  "statement_date": "2026-09-21",
  "currency": "string",
  "statement_balance": "string",
  "ledger_balance": "string",
  "bank_items_total": "string",
  "ledger_items_total": "string",
  "unexplained": "string",
  "note": "string",
  "done_by": {},
  "done_at": "2026-09-21T09:30:00Z",
  "reset_reason": "string",
  "reset_by": {},
  "reset_at": "2026-09-21T09:30:00Z"
}

POST /v1/entities/{entity}/bank-reconciliations/{reconciliation_id}/reset

Reset a bank reconciliation

Take back a reconciliation marked done, for instance one made with a wrong bank balance, with a reason (required, at most 500 characters). The record stays, with reset_at, reset_by and reset_reason, and the reset is in the audit trail (bank.reconcile_reset); the account and date can then be reconciled again.

Whoever may reopen a period may do it: the approve scope and the approval policy's reopen_period action (agents are denied, 403). Refused: 404 when the record is not one of the entity; 409 reconciliation_reset_already when it was reset before, and reconciliation_later (later) when the account was reconciled on a later date that still stands: reset the latest first. Safe to repeat without an Idempotency-Key: a second request is refused with 409.

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

Parameters

In Name Type Required Description
path entity string yes Entity code, e.g. CH01 (GET /v1/entities).
path reconciliation_id string (uuid) yes Reconciliation id (GET /v1/entities/{entity}/bank-reconciliations).

Request body

application/json (required): ResetInput

Field Type Required Description
reason string yes Why the reconciliation is reset (required, at most 500 characters): on the record and in the audit trail. (min length 1; max length 500)

Example request

curl -X POST "$ERP_URL/v1/entities/CH01/bank-reconciliations/3fa85f64-5717-4562-b3fc-2c963f66afa6/reset" \
  -H "Authorization: Bearer $ERP_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "reason": "Bank balance typed as 113,900.00"
}'

Responses

Status Meaning Body
200 OK ReconciliationDone
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",
  "account": "string",
  "statement_date": "2026-09-21",
  "currency": "string",
  "statement_balance": "string",
  "ledger_balance": "string",
  "bank_items_total": "string",
  "ledger_items_total": "string",
  "unexplained": "string",
  "note": "string",
  "done_by": {},
  "done_at": "2026-09-21T09:30:00Z",
  "reset_reason": "string",
  "reset_by": {},
  "reset_at": "2026-09-21T09:30:00Z"
}

GET /v1/entities/{entity}/bank-statements

List bank statements

Imported statements and notifications, newest first, with their lines by status.

Each statement gives its account, period, opening and closing balance as reported by the bank, and how many of its lines are unmatched, matched or ignored.

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

Parameters

In Name Type Required Description
path entity string yes Entity code, e.g. CH01 (GET /v1/entities).
query limit integer Maximum number of statements to return (up to 1000). (max 1000; default 100)

Example request

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

Responses

Status Meaning Body
200 OK array of StatementOut
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",
    "statement_ref": "string",
    "account": "string",
    "account_name": "string",
    "iban": "string",
    "currency": "string",
    "format": "string",
    "from_date": "2026-09-21",
    "to_date": "2026-09-21",
    "opening_balance": "string",
    "closing_balance": "string",
    "created_at": "2026-09-21T09:30:00Z",
    "lines": 1,
    "unmatched": 1,
    "matched": 1,
    "ignored": 1
  }
]

POST /v1/entities/{entity}/bank-statements

Import a bank statement

Import a camt.053 statement, a camt.054 notification (ISO 20022, SPS), an MT940 statement or a CSV file.

Send a multipart form: the file in field file and format set to camt053 (default), camt054, mt940 or csv; for CSV also csv_mapping. An MT940 statement whose account line holds no IBAN (a German bank code and account number) goes to account, else the entity's bank account; one whose transactions do not add up from its opening to its closing balance is refused (mt940_balance_mismatch). One file can hold several statements, so the response lists one result each (lines imported, skipped as duplicates by bank reference, matched and still unmatched). Credits are matched to open invoices by their QR or ISO 11649 reference first, then by reference text, amount and counterparty; a line that executes a payment already booked (a payment run's) is linked to it by its number as end-to-end id or in the text, and never booked again; the matches create payments that follow the approval policy. A CSV statement is named after its account and dates, e.g. CSV 1020 01.09.2026-30.09.2026. Refused: 409 when the statement reference or its transactions were imported before; 422 for a file over 10 MB, an unreadable file, a currency that differs from the bank account's, or an account that is not a bank account.

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

Parameters

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

Request body

multipart/form-data (required): Body_import_statement_v1_entities__entity__bank_statements_post

Field Type Required Description
file string yes The statement file (multipart form field file), at most 10 MB.
format "camt053" | "camt054" | "csv" | "mt940" File format: camt053 (statement, the default), camt054 (debit/credit notification), mt940 (SWIFT MT940 statement) or csv (columns described by csv_mapping). (default "camt053")
account string or null GL bank account code the statement belongs to, e.g. 1020. Default: the account registered for the statement's IBAN, else the entity's bank account.
csv_mapping string or null CSV only: a JSON object (as a string) naming the file's columns, with keys date, amount, credit and debit (separate columns of money in and out, in place of amount), currency, counterparty, iban, reference, description, bank_reference, date_format (strptime, default %Y-%m-%d), decimal_comma, delimiter and default_currency. Default: columns named date, amount, counterparty, reference, description. A named column the file lacks is refused (csv_column_missing); POST .../bank-statements/preview guesses the mapping and shows what it reads.
auto_match boolean Run the automatic matcher on the imported lines (default true); false leaves every line unmatched. (default true)

Example request

curl -X POST "$ERP_URL/v1/entities/CH01/bank-statements" \
  -H "Authorization: Bearer $ERP_KEY" \
  -F "file=@statement.xml"

Responses

Status Meaning Body
201 Created array of ImportResult
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)

[
  {
    "statement_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "statement_ref": "string",
    "imported": 1,
    "duplicates": 1,
    "matched": 1,
    "unmatched": 1
  }
]

POST /v1/entities/{entity}/bank-statements/preview

Preview a CSV bank file

Read a CSV bank file as the import would, without storing anything.

Without csv_mapping the mapping is guessed: the delimiter (;, , or tab), the columns by their header names in German, French, Italian or English (a signed amount, or separate credit and debit columns), the date format and a decimal comma, from the values. The answer has the file's columns, the mapping used (send it with the import), the transactions read (the first 200, with count of all), their dates and sums, how many the account already holds (duplicates, which the import skips) and the statement's name. A file the mapping cannot read is not refused: problem says why (a missing column, a line that cannot be read), with the code the import would refuse it with. Refused: 422 for a file over 10 MB, a csv_mapping that is not a mapping, or an account that is not a bank account.

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

Parameters

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

Request body

multipart/form-data (required): Body_preview_statement_v1_entities__entity__bank_statements_preview_post

Field Type Required Description
file string yes The CSV file (multipart form field file), at most 10 MB.
format "csv" File format: csv. (default "csv")
account string or null GL bank account code the lines would be booked on, e.g. 1020. Default: the entity's bank account.
csv_mapping string or null A JSON object (as a string) naming the file's columns, as for the import. Default: guessed from the file.

Example request

curl -X POST "$ERP_URL/v1/entities/CH01/bank-statements/preview" \
  -H "Authorization: Bearer $ERP_KEY" \
  -F "file=@statement.xml"

Responses

Status Meaning Body
200 OK CsvPreview
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)

{
  "columns": [
    "string"
  ],
  "mapping": {
    "date": "date",
    "amount": "amount",
    "credit": "string",
    "debit": "string",
    "currency": "string",
    "counterparty": "counterparty",
    "iban": "string",
    "reference": "reference",
    "description": "description",
    "bank_reference": "string",
    "date_format": "%Y-%m-%d",
    "decimal_comma": false,
    "delimiter": ",",
    "default_currency": "string"
  },
  "account": "string",
  "account_name": "string",
  "currency": "string",
  "statement_ref": "string",
  "count": 1,
  "lines": [
    {
      "booking_date": "2026-09-21",
      "value_date": "2026-09-21",
      "amount": "string",
      "currency": "string",
      "counterparty_name": "string",
      "counterparty_iban": "string",
      "reference": "string",
      "end_to_end_id": "string",
      "remittance": "string",
      "bank_reference": "string",
      "returned": {}
    }
  ],
  "from_date": "2026-09-21",
  "to_date": "2026-09-21",
  "money_in": "string",
  "money_out": "string",
  "duplicates": 1,
  "problem": {
    "code": "string",
    "message": "string",
    "details": {}
  }
}

POST /v1/entities/{entity}/payment-status-reports

Import the bank's status report on a payment file

Import the bank's pain.002 Customer Payment Status Report on a pain.001 file the entity released (ADR-0062).

Each payment the report rejects (the whole file, a batch of it or the payment itself, status RJCT) is reversed through its approval policy, with the bank's reason (code, text): the bills it paid are open again once the reversal is posted, and the payment's row says why (bank_refusal). A reversal still needs a second person under the four-eyes rules (one asked by an agent, or of a payment someone else recorded); the bank's report stands for the confirmation that the bank did not pay it. Nothing is done twice: a payment already reversed, or whose reversal waits, is reported as such, so the same report can be imported again. A payment a bank statement line shows executed is left as it is (executed). Refused (422): a file that is no pain.002 report, one on a payment file the entity did not make (status_report_unknown_file), or one naming a payment not in that file.

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

Parameters

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

Request body

multipart/form-data (required): Body_import_status_report_v1_entities__entity__payment_status_reports_post

Field Type Required Description
file string yes The pain.002 file (multipart form field file), at most 10 MB.

Example request

curl -X POST "$ERP_URL/v1/entities/CH01/payment-status-reports" \
  -H "Authorization: Bearer $ERP_KEY" \
  -F "file=@statement.xml"

Responses

Status Meaning Body
201 Created StatusReportResult
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)

{
  "message_id": "string",
  "payment_file": "string",
  "rejected": [
    {
      "payment_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "number": "string",
      "party": "string",
      "amount": "string",
      "currency": "string",
      "code": "string",
      "text": "string",
      "outcome": "already_reversed"
    }
  ],
  "accepted": 1
}

Schemas

BankItem

A statement line up to the date that the ledger does not show by then.

Field Type Required Description
line_id string (uuid) yes The statement line (GET .../bank-lines).
booking_date string (date) yes Day the bank booked it, ISO 8601.
amount string yes What is missing from the ledger, signed (positive is money in): the line's amount, or the part of it not booked by the date.
counterparty string or null yes Who paid or was paid, as the bank names them.
text string or null yes The line's reference or remittance text.
statement_ref string yes The statement the line came with.
reason "booked_later" | "ignored" | "unmatched" | "waiting_for_approval" yes unmatched: nobody matched it yet; ignored: a person ignored it, so it is never booked; waiting_for_approval: its booking waits for a second person; booked_later: it is booked after the date.

BankLineOut

Field Type Required Description
id string (uuid) yes Bank line id.
statement_id string (uuid) or null Statement the line was imported with.
booking_date string (date) yes Booking date at the bank, ISO 8601: the statement's date, and the date postings use unless its period is closed (posting_date).
value_date string (date) or null Value date, ISO 8601, when the file gives one.
amount string yes Signed amount in currency: positive is money in, negative money out.
currency string yes Currency code of the line.
counterparty_name string or null yes Name of the other party as on the statement.
counterparty_iban string or null yes IBAN of the other party, when given.
reference string or null yes Payment reference (QR or ISO 11649 creditor reference), when given.
end_to_end_id string or null End-to-end id; equals the number of a payment sent in a pain.001 file.
remittance string or null yes Free remittance text.
status string yes unmatched, matched or ignored.
match object or null yes How the line was settled, null while unmatched: kind (payment, journal, ignored, or return for a credit that returned an outgoing payment, with its payment number, ADR-0062), method (rule, manual or agent), reasons, by (the actor), status of the payment or entry, booked_on when it was booked on another day than the booking date (its period was closed), or reason for ignored lines; undo (status pending_approval, approval_id) while undoing the match waits for a second person, and on an unmatched line undone or rejected when a match was taken back.
posting_date string (date) or null For an unmatched line: the day a match or posting books it on by default, its booking date, or when that is in a closed period the first day of the next open period (send another as on); null for a line that is not unmatched.
closed_period string or null For an unmatched line whose booking date is in a closed period: that period, e.g. 2026-08, the reason posting_date is later; else null.
payment_id string (uuid) or null Payment created by a match, when the line was matched to documents.
journal_entry_id string (uuid) or null Journal entry created by posting the line to an account.

BankReconciliationView

Field Type Required Description
account string yes The bank account reconciled.
account_name string yes The account's name in the user's language.
currency string yes The currency the account holds; every amount is in it.
on string (date) yes The statement date the balances are taken on.
accounts array of ReconcileAccount yes The entity's bank accounts.
statements array of StatementDate yes The account's statements with an end date, newest first (camt.054 notifications carry no balance and are left out).
since string (date) or null yes The first day of the account's statements: entries before it are not compared. Null when no statement was imported for the account.
statement_ref string or null yes The statement ending on the date, if any.
statement_balance string or null yes The statement's closing balance, or the balance given in the request when no statement for the date carries one; null when neither is known.
ledger_balance string yes The posted balance of the account on the date.
difference string or null yes Statement balance less ledger balance.
opening_difference string yes The first statement's opening balance less the ledger balance the day before it: what differed already before any statement line.
bank_items array of BankItem yes In the bank, not yet in the ledger.
bank_items_total string yes The sum of the bank items.
ledger_items array of LedgerItem yes In the ledger, not yet in the bank.
ledger_items_total string yes The sum of the ledger items.
unexplained string or null yes What the items do not explain: difference less opening difference, less bank items, plus ledger items. Zero when the account is reconciled.
done ReconciliationDone or null yes The record of the person who marked this account and date reconciled.

Body_import_statement_v1_entities__entity__bank_statements_post

Field Type Required Description
file string yes The statement file (multipart form field file), at most 10 MB.
format "camt053" | "camt054" | "csv" | "mt940" File format: camt053 (statement, the default), camt054 (debit/credit notification), mt940 (SWIFT MT940 statement) or csv (columns described by csv_mapping). (default "camt053")
account string or null GL bank account code the statement belongs to, e.g. 1020. Default: the account registered for the statement's IBAN, else the entity's bank account.
csv_mapping string or null CSV only: a JSON object (as a string) naming the file's columns, with keys date, amount, credit and debit (separate columns of money in and out, in place of amount), currency, counterparty, iban, reference, description, bank_reference, date_format (strptime, default %Y-%m-%d), decimal_comma, delimiter and default_currency. Default: columns named date, amount, counterparty, reference, description. A named column the file lacks is refused (csv_column_missing); POST .../bank-statements/preview guesses the mapping and shows what it reads.
auto_match boolean Run the automatic matcher on the imported lines (default true); false leaves every line unmatched. (default true)

Body_import_status_report_v1_entities__entity__payment_status_reports_post

Field Type Required Description
file string yes The pain.002 file (multipart form field file), at most 10 MB.

Body_preview_statement_v1_entities__entity__bank_statements_preview_post

Field Type Required Description
file string yes The CSV file (multipart form field file), at most 10 MB.
format "csv" File format: csv. (default "csv")
account string or null GL bank account code the lines would be booked on, e.g. 1020. Default: the entity's bank account.
csv_mapping string or null A JSON object (as a string) naming the file's columns, as for the import. Default: guessed from the file.

Candidate

Field Type Required Description
document_id string (uuid) or null yes Id of the open document; null for a booked payment (kind payment).
payment_id string (uuid) or null For a booked payment (kind payment): its id. Link the line to it with POST /v1/bank-lines/{line_id}/link: the payment is not booked again.
number string or null yes Our document number, e.g. INV-2026-000001, or the payment's, e.g. PAY-2026-000003.
external_number string or null yes The counterparty's own number (a vendor's invoice number).
kind string yes Document kind: sales_invoice, purchase_credit_note, purchase_bill or sales_credit_note; payment for a payment already booked from the line's bank account that no bank line settles yet; return for an outgoing payment the bank executed that a credit line may return (linking it reverses the payment).
party string yes Customer or vendor name.
party_code string yes Customer or vendor code, e.g. C-DE.
due_date string (date) yes Due date, ISO 8601; a booked payment's payment date.
currency string yes Document currency: the line's, or another one (a EUR invoice paid into a CHF account, ADR-0054).
open string yes Amount still open, a decimal string in the document currency; for a booked payment the amount it booked on the bank account, in the line's currency.
line_open string The open amount in the line's currency: open itself, or for a document in another currency open at the booking day's rate. A line within 1% of it pays the document in full; match it with the allocation's document_amount set to open. (default "0.00")
cash_discount string Discount the line may take. (default "0.00")
difference string For a booked payment in another currency than the line's: the bank's amount less the booked amount (negative when the bank took more). Matching books it as a realised exchange gain or loss; 0 otherwise. (default "0.00")
score integer yes Match score: the points of the reasons, 100 structured reference or a booked payment's end-to-end id, 50 reference text, 30 exact open amount (or after discount), 25 IBAN, 15 counterparty name or a booked amount the bank converted.
reasons array of string yes Why the document scores: one sentence per reason.
reason_words array of Reason The same reasons by code (vocabulary bankMatch.reason) with the values they name, in the order of reasons: the screens word them in the person's language.

CsvMapping

Column names in the file; amounts may use a decimal comma.

Field Type Required Description
date string The booking date column. (default "date")
amount string or null The signed amount column (negative is money out); not used when credit or debit is named. (default "amount")
credit string or null A column of money in, for files with separate columns.
debit string or null A column of money out, for files with separate columns: the line's amount is credit less debit, whatever the sign the file writes them with.
currency string or null A currency column; without one, default_currency applies.
counterparty string or null The column naming who paid or was paid. (default "counterparty")
iban string or null The column of the counterparty's IBAN.
reference string or null The column of the payment reference. (default "reference")
description string or null The column of the booking text. (default "description")
bank_reference string or null A column of the bank's unique transaction id: a later file that overlaps skips the lines it holds by it.
date_format string How the dates are written, as a strptime pattern, e.g. %d.%m.%Y. (default "%Y-%m-%d")
decimal_comma boolean True when amounts are written 1.234,50 instead of 1,234.50. (default false)
delimiter string The column separator: , ; or a tab. (min length 1; max length 1; default ",")
default_currency string or null For files without a currency column; default: the bank account's currency. (pattern ^[A-Z]{3}$)

CsvPreview

What importing a CSV file would do, read with mapping; nothing is stored.

Field Type Required Description
columns array of string yes The column names in the file's first line.
mapping CsvMapping yes The mapping the file was read with: the one sent, or the guess from the file's header names and values when none was sent. Send it with the import.
account string yes Code of the bank account the lines would be booked on.
account_name string yes Name of that account.
currency string yes The account's currency.
statement_ref string or null yes The name the statement would get, e.g. CSV 1020 01.09.2026-30.09.2026; null when the file cannot be read.
count integer yes Number of transactions read (lines with an amount of 0 are left out).
lines array of ParsedLine yes The first 200 transactions read.
from_date string (date) or null yes The earliest booking date.
to_date string (date) or null yes The latest booking date.
money_in string yes Sum of the credits.
money_out string yes Sum of the debits, as a positive amount.
duplicates integer yes Transactions the account already holds; the import skips them.
problem BlockerOut or null yes Why the file cannot be read with this mapping, as the import would refuse it (csv_column_missing with column, csv_line_unreadable with line, csv_line_no_currency, csv_no_transactions, statement_currency_differs, statement_imported); null when it can be imported.

IgnoreRequest

Field Type Required Description
reason string Why the line needs no booking, e.g. Internal transfer, booked on 1020; required (refused with ignore_reason_missing when empty). (default "")

ImportResult

Field Type Required Description
statement_id string (uuid) yes Id of the stored statement (GET .../bank-statements).
statement_ref string yes The statement's reference as given by the bank; for a CSV file its account and dates, e.g. CSV 1020 01.09.2026-30.09.2026.
imported integer yes Number of lines stored.
duplicates integer yes Number of lines skipped because their bank reference was imported before.
matched integer yes Number of imported lines the automatic matcher settled.
unmatched integer yes Number of imported lines left for a person or agent (imported - matched).

LedgerItem

A posted entry on the bank account up to the date that no statement line by then shows.

Field Type Required Description
entry_id string (uuid) yes The journal entry (GET /v1/journal-entries/{id}).
number string or null yes The entry's number, e.g. JE-2026-000009.
entry_date string (date) yes The entry's date, ISO 8601.
description string yes The entry's description.
source string yes What made the entry, e.g. ap (a vendor payment) or manual.
amount string yes How it moved the account, signed (debit positive).

LinkRequest

Field Type Required Description
payment string yes Id or number of a payment already booked from the line's bank account (a candidate of kind payment), which the line executes.
on string (date) or null Posting date of the line's own entry (an exchange difference, the move from payments in transit, or the reversal of a returned payment), ISO 8601: a day in an open period, not before the line's booking date (422 bank_posting_before_line). Default: the booking date, or when its period is closed the first day of the next open period (the line's posting_date). The line keeps its booking date on the statement.

LinkResult

Field Type Required Description
line BankLineOut yes The bank line, now matched to the payment.
payment_id string (uuid) yes Id of the booked payment.
payment_number string or null yes Its number, e.g. PAY-2026-000003.
difference string yes The bank's amount less the amount the payment booked, in the line's currency (negative when the bank took more); 0 for a payment in the line's currency.
difference_entry SubmitResult or null yes The line's own entry, submitted through the approval policy: for a payment that awaited execution on the payments-in-transit account (ADR-0060), the amount moved from that account to the bank account (with the bank's exchange difference, if any); else the entry that books the difference against the bank account as a realised exchange gain or loss. Null for a payment booked on the bank account without a difference.

MatchRequest

Field Type Required Description
allocations array of AllocationInput-Input The documents the line settles, each with the amount applied; with on_account the amounts must add up to the absolute amount of the line, and all documents must belong to one customer or vendor.
on_account decimal string The part of the line allocated to no document: it stays on the party's account until it is applied (an overpayment, an advance). Default 0. (min 0; default "0")
party string or null Code (or id) of the customer or vendor, needed when no document is allocated (the whole line on account); otherwise the documents' party, which it must match.
on string (date) or null Posting date, ISO 8601: a day in an open period, not before the line's booking date (422 bank_posting_before_line). Default: the booking date, or when its period is closed the first day of the next open period (the line's posting_date). The line keeps its booking date on the statement.

ParsedLine

One transaction as read from a statement file.

Field Type Required Description
booking_date string (date) yes Day the bank booked it, ISO 8601.
value_date string (date) or null Value day, ISO 8601, if given.
amount string yes Signed amount: positive is money in, negative out. (pattern ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$)
currency string yes ISO 4217 code of the amount.
counterparty_name string or null Who paid or was paid.
counterparty_iban string or null The counterparty's IBAN.
reference string or null Structured reference (QR or ISO 11649) or reference text.
end_to_end_id string or null End-to-end id of a payment file's payment (camt only).
remittance string or null The booking or remittance text.
bank_reference string or null The bank's own id of the transaction: a later file holding it again skips it.
returned map of string or null or null On a credit that returns an outgoing payment (camt only: RtrInf, or the bank transaction code ICDT/RRTN), or a debit that returns a direct debit we collected (RtrInf, or IDDT/UPDD or IDDT/PRDD), the bank's reason: code (ISO 20022) and text.

PostLineInput

Field Type Required Description
account string yes Counter account, e.g. bank fees or interest income.
description string or null Entry description. Default: the line's remittance text, else its reference.
dimensions map of string Cost centre, profit centre or project of the counter line, by dimension code: {"cost_centre": "CC-200"} (GET /v1/dimensions); active values valid on the booking date only.
on string (date) or null Posting date, ISO 8601: a day in an open period, not before the line's booking date (422 bank_posting_before_line). Default: the booking date, or when its period is closed the first day of the next open period (the line's posting_date). The line keeps its booking date on the statement.

ReconcileAccount

Field Type Required Description
code string yes GL account code, e.g. 1020.
name string yes Account name in the user's language.
currency string yes The currency the account holds.

ReconcileInput

Field Type Required Description
account string yes GL bank account code, e.g. 1020.
on string (date) yes The statement date reconciled.
statement_balance decimal string or null The closing balance on the bank's statement, needed only when no imported statement for the date carries one (a CSV file).
note string or null Why the account is reconciled although part of the difference is unexplained; required then. (max length 500)

ReconciliationDone

Field Type Required Description
id string (uuid) yes Id of the record.
account string yes The bank account reconciled, e.g. 1020.
statement_date string (date) yes The statement date reconciled, ISO 8601.
currency string yes The currency the account holds.
statement_balance string yes The bank's closing balance on the date.
ledger_balance string yes The account's posted balance on the date.
bank_items_total string yes Statement lines up to the date not in the ledger then.
ledger_items_total string yes Posted entries up to the date no statement line showed then.
unexplained string yes What the items did not explain; zero mostly.
note string or null yes Why it was marked reconciled with an unexplained rest.
done_by object yes Who marked it done (name, type, id).
done_at string (date-time) yes When it was marked reconciled, ISO 8601.
reset_reason string or null Why the record was reset; null while it stands.
reset_by object or null Who reset it (name, type, id); null while it stands.
reset_at string (date-time) or null When it was reset, ISO 8601; null while it stands. A reset record no longer counts: the date can be reconciled again.

RejectedPayment

Field Type Required Description
payment_id string (uuid) yes Id of the payment the bank rejected.
number string yes Its number, the end-to-end id of the payment file.
party string yes The vendor's (or customer's) name.
amount string yes Its amount, in its currency.
currency string yes ISO 4217 currency of the payment.
code string or null yes The bank's reason as an ISO 20022 code, if given.
text string or null yes The bank's own words, if any.
outcome "already_reversed" | "executed" | "not_posted" | "pending_approval" | "reversal_waits" | "reversed" yes What the import did: reversed (the bills it paid are open again), pending_approval (the reversal waits for a second person), already_reversed or reversal_waits (an earlier import or a person did it: nothing again), executed (a bank statement line shows the bank executed it: left to a person) or not_posted.

ResetInput

Field Type Required Description
reason string yes Why the reconciliation is reset (required, at most 500 characters): on the record and in the audit trail. (min length 1; max length 500)

StatementDate

Field Type Required Description
to_date string (date) yes Last day the statement covers.
statement_ref string yes The statement's reference as given by the bank.
closing_balance string or null yes Closing balance the bank reported; null when the file carries none (CSV).

StatementOut

Field Type Required Description
id string (uuid) yes Statement id; use it as the statement filter of the bank-lines list.
statement_ref string yes The statement's reference as given by the bank; for a CSV file its account and dates, e.g. CSV 1020 01.09.2026-30.09.2026.
account string yes GL bank account code the statement belongs to.
account_name string yes Name of that GL account.
iban string or null yes IBAN of the bank account, when the file names it.
currency string yes Currency code of the statement.
format string yes File format it was imported from: camt053, camt054, mt940 or csv.
from_date string (date) or null yes First day the statement covers, ISO 8601, when known.
to_date string (date) or null yes Last day the statement covers, ISO 8601, when known.
opening_balance string or null yes Opening balance reported by the bank (decimal string); null if absent.
closing_balance string or null yes Closing balance reported by the bank; null for notifications.
created_at string (date-time) yes When the statement was imported (UTC timestamp).
lines integer yes Number of lines of the statement.
unmatched integer yes Lines still waiting to be matched, posted or ignored.
matched integer yes Lines settled by a payment or an entry.
ignored integer yes Lines marked as needing no booking.

StatusReportResult

Field Type Required Description
message_id string yes The status report's own message id.
payment_file string yes Message id of the payment file it reports on.
rejected array of RejectedPayment yes The payments the bank rejected, each with what the import did.
accepted integer yes How many other payments of the file the report did not reject.

UnmatchRequest

Field Type Required Description
on string (date) or null Date of the reversal entry when undoing the match reverses a posted payment or posting, ISO 8601: not before it, in an open period. Default: today for a payment, the posting's own date for a posting.
reason string yes Why the match is undone (required, at most 500 characters): on the reversal, in the approval request and in the audit trail. (min length 1; max length 500)

UnmatchResult

Field Type Required Description
line BankLineOut yes The line after the request.
outcome "pending_approval" | "reversed" | "unlinked" | "withdrawn" yes unlinked: the line was linked to a payment booked before (a released payment), which stands; withdrawn: the payment or posting the match made still waited for approval and is rejected; reversed: the payment or posting the match made is reversed; pending_approval: its reversal waits for a second person (approval_id) and the line stays matched until it is approved. In every other case the line is unmatched again.
reversal_entry_id string (uuid) or null The reversal entry, when one was made (posted or waiting).
approval_id string (uuid) or null The approval request the reversal waits for, if it does.
Stabiso, the Enterprise System of Record · generated from the code and its guides · release 20b7dd5b0c4d