Skip to content

Match a bank statement line to an invoice

The bank_statements.lines.match operation: POST /api/v1/bank_statements/lines/{id}/match in the REST API and the bank_statements_lines_match tool in the MCP server.

POST/api/v1/bank_statements/lines/{id}/match

Pays an open (or uncollectible) invoice of the entity with a line from the review queue: the transfer's booking date becomes the payment date and its reference the payment reference, as invoices.mark_paid records them (Dr bank / Cr receivable, invoice.paid; a past-due or unpaid subscription recovers). The line's amount must be the invoice's amount due in the same currency: invoices are paid in full only.

Financial tier: an approval policy may require a second person. Dry-run it first.

At a glance

  • REST: POST /api/v1/bank_statements/lines/{id}/match
  • MCP tool: bank_statements_lines_match
  • Operation ID: bank_statements.lines.match
  • Scope: Legal entity
  • Permission: invoices:write
  • Risk tier: financial
  • Dry run: Supported (send Ownrecord-Dry-Run: true)
  • Idempotency: Idempotency-Key required
  • Modes: Test and live
  • Authentication: API key with the invoices:write scope
  • Since: M5

Request

Path parameters

FieldTypeDescription
idbsl_… ID

Body

A JSON object (Content-Type: application/json):

FieldTypeRequiredDescription
invoiceIdinv_… IDYesThe invoice the line pays: its amount due must equal the line's amount.
expectedVersioninteger (at least 1)No

Response

200 OK with a JSON object:

FieldTypeDescription
object"bank_statement_match"
lineobject
line.idbsl_… ID
line.object"bank_statement_line"
line.entityIdent_… ID
line.livemodeboolean
line.importIdbsi_… ID
line.rowintegerThe line's row in its file (the header is row 1).
line.bookingDatestring
line.amountmoneySigned: incoming money is positive.
line.referencestring
line.counterpartystring
line.matchStatusone of unmatched, matched, partial, ignoredmatched (paid an invoice), partial and unmatched (the review queue) or ignored.
line.reviewobject or nullWhy the line wasn't matched automatically, and the invoices it may pay.
line.invoiceIdinv_… ID or nullThe invoice the line paid (matched) or points to (partial).
line.brandIdbrd_… ID or null
line.ledgerTransactionIdtxn_… ID or null
line.payoutItemIdstring or nullThe processor payout (a reconciliation item) a matched line confirms instead of paying an invoice.
line.matchedByone of automatic, manual or null
line.matchedAtdate-time or null
line.ignoredReasonstring or null
line.versioninteger
line.createdAtdate-time
line.updatedAtdate-time
invoiceobject
invoice.idinv_… ID
invoice.numberstring
invoice.statusstring
invoice.brandIdbrd_… ID

Examples

The transfer pays the invoice its amount points to

HTTP
POST /api/v1/bank_statements/lines/bsl_01m4tx5nj8emwbyf7y9vcf48bc/match
Authorization: Bearer or_test_…
Idempotency-Key: 3f1c9a52-7d0e-4b8f-9a61-0c2d5e8b7f14
Content-Type: application/json

{
  "invoiceId": "inv_01m4tx5nj8emwbyf7y9vcf48bd"
}

Response (200):

JSON
{
  "object": "bank_statement_match",
  "line": {
    "id": "bsl_01m4tx5nj8emwbyf7y9vcf48bc",
    "object": "bank_statement_line",
    "entityId": "ent_01m4tx5nj8emwbyf7y9vcf47zm",
    "livemode": false,
    "importId": "bsi_01m4tx5nj8emwbyf7y9vcf48ba",
    "row": 3,
    "bookingDate": "2026-11-04",
    "amount": {
      "amount": "450000000",
      "currency": "EUR"
    },
    "reference": "Invoice 2026-000132",
    "counterparty": "Berg Software AG",
    "matchStatus": "matched",
    "review": {
      "reason": "amount_only",
      "candidateInvoiceIds": ["inv_01m4tx5nj8emwbyf7y9vcf48bd"],
      "candidates": [
        {
          "invoiceId": "inv_01m4tx5nj8emwbyf7y9vcf48bd",
          "number": "GEN-2026-000132",
          "brandId": "brd_01m4tx5nj8emwbyf7y9vcf47z0"
        }
      ]
    },
    "invoiceId": "inv_01m4tx5nj8emwbyf7y9vcf48bd",
    "brandId": "brd_01m4tx5nj8emwbyf7y9vcf47z0",
    "ledgerTransactionId": "txn_01m4tx5nj8emwbyf7y9vcf48be",
    "payoutItemId": null,
    "matchedBy": "manual",
    "matchedAt": "2026-11-05T10:00:00.000Z",
    "ignoredReason": null,
    "version": 2,
    "createdAt": "2026-11-05T09:00:00.000Z",
    "updatedAt": "2026-11-05T10:00:00.000Z"
  },
  "invoice": {
    "id": "inv_01m4tx5nj8emwbyf7y9vcf48bd",
    "number": "GEN-2026-000132",
    "status": "paid",
    "brandId": "brd_01m4tx5nj8emwbyf7y9vcf47z0"
  }
}

Errors

CodeHTTP statusWhenWhat to do
validation_failed400A field is malformed or out of range.Fix the fields listed in details.issues and send the request again.
resource_not_found404No line, or no issued invoice of this entity, has this ID.Check the ID and that your credentials are scoped to the right organization, entity, brand and mode.
bank_statement_line_resolved409The line was matched or ignored already.Read the line: matchStatus and invoiceId say how it was resolved. A matched line paid its invoice; reverse that with the invoice's own actions if it was wrong.
bank_statement_amount_mismatch400The line's amount isn't the invoice's amount due (full payments only).Match the line to the invoice whose amount due it pays exactly (same currency). Partial payments and overpayments stay in the review queue: resolve them with the customer, then ignore the line with a reason.
invoice_status_invalid409The invoice can't be paid: it is paid, voided or a checkout receipt.Check the invoice's status (details.status) and what it still allows (details.allowed_actions). Drafts are edited and finalized; open invoices are sent, paid, voided or marked uncollectible; paid and void invoices don't change (corrections are credit notes).
version_conflict409The line (expectedVersion) or the invoice changed meanwhile; retry.Fetch the object again and retry the change.
permission_denied403The credentials can't record invoice payments for this entity (invoices:write, finance).Ask an organization owner or admin for a role or scope that allows this action.

It can also return these common errors: api_version_unsupported, invalid_json, unsupported_media_type, authentication_required, api_key_invalid, scope_required, idempotency_key_required, idempotency_key_reused, idempotency_in_progress, approval_required, approval_rejected, approval_expired, stale_approval, approval_policy_denied, rate_limited, internal_error.