External Reconciliations

An external reconciliation is a dated record that an outside figure was compared with the ledger. The outside figure is one of two subjects:

  • a bank transaction (relation_type = PAYMT), matched against one or more journal entry lines;
  • a document reconciliation line — a line extracted from a supplier statement, an annual report or any other document that carries reconciliation lines, see Documents — addressed by its document: relation_type = the document’s type (e.g. AP_STATEMENT, ANNUAL_REPORT), relation_id = the document id, relation_line_id = the line id; matched against journal entry lines or an account balance. The line’s category decides the sign and the target accounts.

Unlike internal reconciliations (which match journal entry lines against each other), external reconciliations link accounting entries to their external counterparts.

Each reconciliation has entries of four kinds:

Kind Points at Amount
EXTERNAL A bank transaction (relation_type = PAYMT, relation_id) or a document reconciliation line (relation_type = the document’s type, relation_id = document id, relation_line_id = line id) The signed bank transaction amount, or the document line’s amount in ledger sign (target.ledger_sign × amount)
LEDGER_LINE A journal entry line (relation_type = JE, relation_id + relation_line_id) debit − credit of the line, in the reconciliation currency
LEDGER_BALANCE A general ledger account (relation_type = GENERAL_LEDGER_ACCOUNT, relation_id = the account id), optionally scoped to a sub-ledger dimension through secondary_relation_type / secondary_relation_id, as of as_of_date The account balance at that date, computed by the server
RECONCILING_ITEM Nothing — a free-text description A signed movement that explains part of the difference

All amounts are in ledger sign: debit positive, credit negative. The server computes three snapshot amounts from the entries and stores them on the reconciliation: expected_amount (sum of EXTERNAL entries), ledger_amount (sum of LEDGER_LINE or LEDGER_BALANCE entries) and difference (expected_amount − ledger_amount). For bank transactions the difference must be zero. For document reconciliation lines the difference must equal the sum of the RECONCILING_ITEM entries, so every record is fully explained when it is made.

A document reconciliation line exposes a derived status (OPEN, RECONCILED, EXPLAINED, DRIFTED) that re-runs the comparison against the current ledger on every read; see Reconciliation Line Status.

Endpoints

List External Reconciliations

GET /api/v2/external-reconciliations

Retrieves a paginated list of external reconciliations.

Query Parameters

Parameter Type Required Description
client_account_id integer Yes ID of the client account
from_date date No Filter from this date
to_date date No Filter to this date
relation_type string No Filter by entry relation type: PAYMT, JE, GENERAL_LEDGER_ACCOUNT, or a document type (e.g. AP_STATEMENT, ANNUAL_REPORT)
relation_id integer No Filter by entry relation ID. A document line’s records: relation_type=<document type>&relation_id=<document id>&relation_line_id=<line id>
relation_line_id integer No Filter by entry relation line ID
is_deleted boolean No Include retired (soft-deleted) reconciliations. Default false
page integer No Page number
per_page integer No Items per page

Response

{
  "data": [
    {
      "id": 1,
      "created_at": "2024-03-15T10:00:00Z",
      "created_by_id": 7,
      "client_account_id": 7,
      "sequence_number": 1,
      "expected_amount": "-1500.000000",
      "ledger_amount": "-1500.000000",
      "difference": "0.000000",
      "currency_code": "NOK",
      "note": null,
      "is_deleted": false,
      "deleted_at": null,
      "deleted_by_id": null,
      "entries": [
        {
          "id": 1,
          "kind": "EXTERNAL",
          "relation_type": "PAYMT",
          "relation_id": 86,
          "relation_line_id": null,
          "secondary_relation_type": null,
          "secondary_relation_id": null,
          "as_of_date": null,
          "description": null,
          "account_code": null,
          "amount": "-1500.000000",
          "currency_code": "NOK",
          "exchange_rate": "1.000000"
        },
        {
          "id": 2,
          "kind": "LEDGER_LINE",
          "relation_type": "JE",
          "relation_id": 456,
          "relation_line_id": 1,
          "secondary_relation_type": null,
          "secondary_relation_id": null,
          "as_of_date": null,
          "description": null,
          "account_code": null,
          "amount": "-1500.000000",
          "currency_code": "NOK",
          "exchange_rate": "1.000000"
        }
      ]
    }
  ],
  "meta": {
    "page": 1,
    "pages": 1,
    "per_page": 25,
    "records": 1
  }
}

Create External Reconciliation

POST /api/v2/external-reconciliations

Creates a new external reconciliation with entries.

Request Body

Field Type Required Description
client_account_id integer Yes The client account ID
note string No Free-text note on the reconciliation
entries array Yes Array of reconciliation entries

sequence_number, expected_amount, ledger_amount, difference, currency_code and reconciliation_method are computed by the server and ignored if sent.

is_draft may be sent. A draft is a prepared comparison that nobody has accepted yet: it gets no sequence_number and no reconciliation_method, and it does not count as reconciled anywhere (bank transactions and journal entry lines it references stay open). Saving it again with is_draft: false reconciles it and assigns both.

Entry Object

Field Type Required Description
kind string Yes EXTERNAL, LEDGER_LINE, LEDGER_BALANCE or RECONCILING_ITEM. Must agree with relation_type
relation_type string Per kind PAYMT or the document’s type (e.g. AP_STATEMENT, ANNUAL_REPORT) for EXTERNAL; JE for LEDGER_LINE; GENERAL_LEDGER_ACCOUNT for LEDGER_BALANCE; omitted for RECONCILING_ITEM
relation_id integer Per kind ID of the related record: the bank transaction, document, journal entry or general ledger account. Omitted for RECONCILING_ITEM
relation_line_id integer Per kind The line within the relation: the journal entry line id for LEDGER_LINE, the reconciliation line id for a document-line EXTERNAL; not used by other kinds
secondary_relation_type string No LEDGER_BALANCE only: the sub-ledger dimension the balance is scoped to — businesspartner, bankacc, project, department or asset. Set together with secondary_relation_id or not at all
secondary_relation_id integer No LEDGER_BALANCE only: ID of the dimension record (e.g. the business partner)
as_of_date date LEDGER_BALANCE The date the balance is taken as of. All LEDGER_BALANCE entries of one record must share it
description string RECONCILING_ITEM What the reconciling item is (e.g. “Invoice 1042 booked in the next period”)
account_code string — Read-only. The account code of a LEDGER_BALANCE entry’s account, echoed by the server
amount decimal Per kind For EXTERNAL: the signed bank transaction amount, or the document line’s amount in ledger sign (the server forces target.ledger_sign × amount whatever sign is sent). For LEDGER_LINE: debit − credit of the line (debit_fc − credit_fc when reconciling in a foreign currency); the server normalises the sign from the line itself. For LEDGER_BALANCE: ignored — the server computes the balance. For RECONCILING_ITEM: the signed amount it explains, non-zero
currency_code string Yes ISO 4217 currency code. All entries must share one currency
exchange_rate decimal No Exchange rate applied. If omitted, the server derives it from the matched record, or defaults to 1 when the entry currency equals the accounting currency; a 400 is returned only if neither source is available

Requirements per kind

  • EXTERNAL bank transaction — relation_type = PAYMT, relation_id, amount equal to the signed transaction amount, currency_code.
  • EXTERNAL document reconciliation line — relation_type = the document’s type, relation_id = the document id, relation_line_id = the line id, currency_code = the line’s currency, amount = ±the line’s printed amount. The server sets the sign from the line’s category: a TRADE_PAYABLE line on a supplier statement is your payable, so the entry amount is −amount; a DEPOSIT line is your asset, so it is +amount. Any document type is accepted; a line without a category is refused (Reconciliation line has no category).
  • LEDGER_LINE — relation_type = JE, relation_id, relation_line_id, amount, currency_code.
  • LEDGER_BALANCE — relation_type = GENERAL_LEDGER_ACCOUNT, relation_id = the account id, as_of_date, currency_code; optionally secondary_relation_type + secondary_relation_id. The server computes amount and echoes account_code.
  • RECONCILING_ITEM — description, a non-zero amount, currency_code; no relation.

Example Request

A 1 500 NOK payment out of the bank account, booked as a credit on account 1920:

{
  "client_account_id": 7,
  "entries": [
    {
      "kind": "EXTERNAL",
      "relation_type": "PAYMT",
      "relation_id": 86,
      "amount": "-1500.00",
      "currency_code": "NOK"
    },
    {
      "kind": "LEDGER_LINE",
      "relation_type": "JE",
      "relation_id": 456,
      "relation_line_id": 1,
      "amount": "-1500.00",
      "currency_code": "NOK"
    }
  ]
}

A deposit is the mirror image: the EXTERNAL amount is positive and the 1920 line is a debit, so the LEDGER_LINE amount is positive too.

A supplier statement’s closing balance (a BALANCE reconciliation line of 12 500 NOK owed to the supplier, line id 301 on document 4711) compared with the supplier’s balance on account 2400 as of the statement date. The ledger shows 11 300 NOK because one invoice was booked in the next period; a reconciling item explains the 1 200 NOK difference:

{
  "client_account_id": 7,
  "entries": [
    {
      "kind": "EXTERNAL",
      "relation_type": "AP_STATEMENT",
      "relation_id": 4711,
      "relation_line_id": 301,
      "amount": "-12500.00",
      "currency_code": "NOK"
    },
    {
      "kind": "LEDGER_BALANCE",
      "relation_type": "GENERAL_LEDGER_ACCOUNT",
      "relation_id": 864,
      "secondary_relation_type": "businesspartner",
      "secondary_relation_id": 56,
      "as_of_date": "2026-06-30",
      "currency_code": "NOK"
    },
    {
      "kind": "RECONCILING_ITEM",
      "description": "Invoice 1042 dated 2026-06-28 booked in July",
      "amount": "-1200.00",
      "currency_code": "NOK"
    }
  ]
}

The server stores expected_amount = -12500, ledger_amount = -11300 (the computed balance) and difference = -1200, matched by the item. The EXTERNAL amount may be sent as 12500.00; the line is TRADE_PAYABLE, so the server applies the −1 sign.

Finding candidates

Read the line with GET /api/v2/documents/{id}?with=reconciliation_lines.target (or document.reconciliation_lines.target on a voucher). target.accounts are the account codes to search and target.dimension the sub-ledger scope. For a TRANSACTIONAL line list journal entry lines with GET /api/v2/journal-entry-lines?client_account_id=…&account_code=<target codes>&relation_type=<dimension type>&relation_id=<dimension id>&from_date=…&to_date=…&include_externally_reconciled=false. For a BALANCE line read GET /api/v2/general-ledger-accounts/balances?client_account_id=…&account_code=<target codes>&as_of_date=…&relation_type=…&relation_id=… (see General Ledger Accounts); the balances are computed by the same function the sign-off stores. The line’s live record, if any, is GET /api/v2/external-reconciliations?relation_type=<document type>&relation_id=<document id>&relation_line_id=<line id>; DELETE it to retire.

Response

Returns the created external reconciliation with status 201 Created.

Update External Reconciliation

PATCH /api/v2/external-reconciliations/{id}
Content-Type: application/json

{
  "note": "Explained after the bank statement arrived",
  "items": [ { "description": "Card settlement posted next month", "amount": "4300.00" } ],
  "is_draft": false
}

note can be changed on any record. items replaces a draft’s reconciling items. is_draft: false reconciles a draft: the items must explain the whole difference and the ledger must not have moved since the draft was prepared (409 period_reconciliation.stale_draft). See Reconciliation Periods.

Delete External Reconciliation

DELETE /api/v2/external-reconciliations/{id}

Retires an external reconciliation. The row is kept with is_deleted set to true and deleted_at stamped, so the record of what was compared survives; it no longer appears in GET unless is_deleted=true is passed. The bank transaction, document reconciliation line and journal entry lines it referenced become reconcilable again. Deleting an already retired reconciliation is a no-op.

Response

Returns 204 No Content on success.

Attributes

Attribute Type Description
id integer Unique identifier (read-only)
created_at datetime Creation timestamp (read-only)
created_by_id integer ID of the user who created it (read-only)
client_account_id integer ID of the client account
sequence_number integer Sequence number for ordering (read-only); null while the record is a draft
is_draft boolean Prepared but not yet reconciled; drafts never count as reconciled (default false)
reconciliation_method string How the record was reconciled (read-only); null while it is a draft. EXTERNAL_MATCH (difference 0), EXPLAINED (difference covered by reconciling items), or one of the periodic reconciliation rules NO_ACTIVITY, ZERO_BALANCE, UNCHANGED, OPEN_ITEMS, CLEARED
expected_amount decimal Sum of EXTERNAL entries, in ledger sign (read-only)
ledger_amount decimal Sum of LEDGER_LINE or LEDGER_BALANCE entries, in ledger sign (read-only)
difference decimal expected_amount − ledger_amount; equals the sum of RECONCILING_ITEM entries (read-only)
currency_code string The entries’ shared currency (read-only)
note string Free-text note
is_deleted boolean Whether the reconciliation has been retired (read-only)
deleted_at datetime When it was retired (read-only)
deleted_by_id integer Who retired it (read-only)

Relationships

Relationship Type Description
entries ExternalReconciliationEntry[] The reconciliation entries (included by default)

Business Rules

For every record:

  • Exactly one EXTERNAL entry, and at least one ledger-side entry (LEDGER_LINE or LEDGER_BALANCE).
  • An entry’s currency_code must match the currency of the record it references, and all entries must share one currency.
  • A LEDGER_LINE amount may not exceed the unreconciled remainder of its line; its sign is taken from the line.
  • A cancelled or draft journal entry cannot be used as a ledger line.
  • kind must agree with relation_type (see the entry table); a LEDGER_LINE requires relation_line_id, a RECONCILING_ITEM carries no relation.

For bank transactions (EXTERNAL = PAYMT):

  • The EXTERNAL amount must exactly match the referenced bank transaction, including sign.
  • A bank transaction that is already reconciled cannot be reconciled again.
  • Every LEDGER_LINE must carry the bank-account dimension of the bank transaction’s account.
  • Only LEDGER_LINE entries are allowed on the ledger side, and the difference must be zero: the ledger lines must sum to the bank transaction amount.

For document reconciliation lines (EXTERNAL with a document type as relation_type):

  • A line can have at most one live record; retire the existing one first.
  • The EXTERNAL amount’s absolute value must equal the line’s printed amount and its currency must equal the line’s currency. The server sets the sign from the line’s category. Any document type is accepted; a line without a category is refused.
  • A TRANSACTIONAL line is reconciled against LEDGER_LINE entries only; a BALANCE line against LEDGER_BALANCE entries only.
  • Every LEDGER_LINE and LEDGER_BALANCE must be on one of the line’s target.accounts.
  • Where the category names a dimension the document supplies (target.dimension: the document’s business partner for TRADE_PAYABLE, TRADE_RECEIVABLE and LOAN, its bank account for DEPOSIT), every LEDGER_LINE must carry it and every LEDGER_BALANCE must be scoped to it, on every target account. A document without the value is not checked.
  • All LEDGER_BALANCE entries of one record share the same as_of_date.
  • The RECONCILING_ITEM entries must sum to difference; each item has a description and a non-zero amount.

Periodic subjects (written by the reconciliation engine, see Reconciliation Periods): BANK_BALANCE (a bank balance imported through a bank integration; the amount is the balance, the ledger side is the bank’s accounts scoped to that bank account), VATRP addressed without a relation_line_id (the settlement document of an approved return; the VAT accounts are expected to be empty) and RECONCILIATION_PERIOD (a rule-backed record; the expected amount is the last documented balance).

  • The ledger side is LEDGER_BALANCE entries only, all as of one date on or after the subject’s date.
  • Reconciling items may explain part of the difference while the record is a draft; a record can only leave draft state once they explain all of it.
  • While a live record references a line, the line’s amount, currency_code, transaction_date, reconciliation_type and category cannot be changed, and neither the line nor its document (or voucher) can be deleted.

Error Responses

Status Code Description
400 Invalid request (missing required fields, or a business rule above is violated)
403 Forbidden (no access to client account)
404 Reconciliation not found