accounteddocs

Reconciliation

Run bank-to-ledger reconciliation and read the current matching status.

Endpoints


GET /api/v1/companies/:companyId/reconciliation/bank/status

reconciliation.bank.status · scope transactions:read

Bank-reconciliation health snapshot.

Returns matched / unmatched counts and the balance delta between the bank ledger and the GL for the requested window. Optional ?date_from / ?date_to (default: company history).

Use when: You're building a dashboard widget, an audit report, or a pre-close check that needs to know how many bank transactions are still unbooked.

Don't use for: Running the matcher: that's POST /reconciliation/bank/run. Per-transaction detail: use the transaction list with ?status=unbooked.

Pitfalls

  • A non-zero difference is normal between sync runs (uncleared cheques, in-flight transfers). Investigate only if it persists across reconciliations.
  • difference compares against gl_1930_period_movement (movement excl. opening balance), NOT gl_1930_balance. Do not display gl_1930_balance next to difference.
  • is_reconciled means |difference| < 0.01 for the window, an aggregate check, not a per-transaction guarantee.

Risk: low · Idempotent: yes · Reversible: no · Dry-run supported: no

Example response

{
  "data": {
    "bank_transaction_total": 48150,
    "gl_1930_balance": 98150,
    "gl_1930_period_movement": 48150,
    "gl_1930_opening_balance": 50000,
    "gl_1930_correction_adjustment": 0,
    "difference": 0,
    "is_reconciled": true,
    "matched_count": 142,
    "unmatched_transaction_count": 3,
    "unmatched_gl_line_count": 2
  },
  "meta": {
    "request_id": "req_…",
    "api_version": "2026-05-12"
  }
}

POST /api/v1/companies/:companyId/reconciliation/bank/run

reconciliation.bank.run · scope transactions:write

Run the bank-reconciliation matcher.

Walks all unbooked bank transactions in the requested date range and pairs them with open GL lines (1930-side) by amount + date proximity. Applies confirmed matches by setting transactions.journal_entry_id (the GL row already exists). Dry-runnable.

Use when: You want to auto-match outstanding bank transactions against existing journal entries: typically as the closing step of a sync. Dry-run first to inspect proposed matches.

Don't use for: Creating new journal entries: this only links bank transactions to existing GL lines. Matching to invoices: use :match-invoice or :match-supplier-invoice for explicit invoice payments.

Pitfalls

  • date_from / date_to default to the company's full bank history if omitted. Specify a window for predictable performance.
  • account_number defaults to 1930. Multi-account companies must pass the BAS code of the account they are reconciling (e.g. 1932 for a EUR account), or it silently reconciles 1930.
  • Idempotency-Key is mandatory.
  • Without confidence_threshold, a non-dry run applies EVERY match found, including fuzzy ones at confidence 0.75. Pass confidence_threshold (0.9 recommended, matching gnubok_auto_match_period) for unattended runs, or dry-run first and review matches.confidence before applying. Matches below the threshold are returned but not applied (skipped_below_threshold counts them).
  • The 366-day window bound only applies when BOTH date_from and date_to are set; a single-sided or absent window scans full history.

Risk: medium · Idempotent: yes · Reversible: no · Dry-run supported: yes

Example request

{
  "date_from": "2026-05-01",
  "date_to": "2026-05-31",
  "confidence_threshold": 0.9
}

Example response

{
  "data": {
    "matches": [],
    "applied": 0,
    "errors": 0,
    "skipped_below_threshold": 0
  },
  "meta": {
    "request_id": "req_…",
    "api_version": "2026-05-12"
  }
}