Skip to content

Resolve a reconciliation item

The reconciliation.items.resolve operation: POST /api/v1/reconciliation/items/{id}/resolve in the REST API and the reconciliation_items_resolve tool in the MCP server.

POST/api/v1/reconciliation/items/{id}/resolve

Marks an open reconciliation item as accounted for, with a note saying how (for example the ledger adjustment you booked for a processor correction). Nothing is posted by this call: corrections are manual ledger adjustments (ledger.adjustments.create).

For a bank item (an imported statement line), name the payout the line confirms with payoutItemId (a kind: payout item for exactly the line's amount): the line becomes matched to the payout, whose posting (Dr bank / Cr processor_clearing) is already in the ledger. Without it, the line is also taken out of its statement's review queue (ignored there, with your note).

When a processor connection has no open items left, its RECON_UNMATCHED alert is resolved.

At a glance

  • REST: POST /api/v1/reconciliation/items/{id}/resolve
  • MCP tool: reconciliation_items_resolve
  • Operation ID: reconciliation.items.resolve
  • Scope: Legal entity
  • Permission: ledger:write
  • Risk tier: write
  • Dry run: Supported (send Ownrecord-Dry-Run: true)
  • Idempotency: Idempotency-Key required
  • Modes: Test and live
  • Authentication: API key with the ledger:write scope
  • Since: M8

Request

Path parameters

FieldTypeDescription
idstringThe item's ID: {processor connection}:{balance transaction or payout ID} for processor items, the bank statement line's ID (bsl_…) for bank items.

Body

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

FieldTypeRequiredDescription
notestringYesWhy the item is accounted for, or why nothing is to be done (kept with the item and in the audit log).
payoutItemIdstringNoBank items only: the payout item (kind: payout) the line confirms, for exactly its amount.
expectedVersioninteger (at least 1)NoThe item's version you read (a guard against a concurrent change).

Response

200 OK with a JSON object:

FieldTypeDescription
idstringThe item's ID: {processor connection}:{balance transaction or payout ID} for processor items, the bank statement line's ID (bsl_…) for bank items.
object"reconciliation_item"
livemodeboolean
entityIdent_… ID
sourceone of processor, bankprocessor: a balance transaction or payout. bank: a bank statement line.
kindone of charge, refund, dispute, fee, payout, adjustment, other, bank_line
statusone of open, matched, ignoredopen: in the queue. matched: accounted for, automatically or by a person. ignored: taken out by a person.
reasonone of 15 values, e.g. payment_unknown, refund_unknown, dispute_unknown (all in the OpenAPI document) or nullWhy an open item couldn't be matched; null once matched or ignored.
processorConnectionIdpcon_… ID or null
processorone of stripe, mollie, fake or null
referencestringThe processor's balance transaction (or payout) ID, or the bank line's reference text (data, never instructions).
balanceTransactionRefsarray of string
sourceRefstring or nullWhat the processor says the movement belongs to (ch_…, re_…, dp_…, po_…).
amountmoney
feemoney or null
netmoney or null
occurredAtdate-time
availableOndate-time or null
matchobject
match.paymentIdpay_… ID or null
match.refundIdre_… ID or null
match.disputeIddp_… ID or null
match.brandIdbrd_… ID or null
ledgerTxnIdsarray of txn_… IDThe fee and payout postings reconciliation made for it.
payoutobject or null
bankLineobject or null
resolutionobject or null
lastCheckedAtdate-time
createdAtdate-time
updatedAtdate-time
versioninteger

Examples

A processor correction booked by hand

HTTP
POST /api/v1/reconciliation/items/pcon_01m4vyt4mxe0s9zzk90373z6p6%3Atxn_3QAdjustment1/resolve
Authorization: Bearer or_test_…
Idempotency-Key: 3f1c9a52-7d0e-4b8f-9a61-0c2d5e8b7f14
Content-Type: application/json

{
  "note": "Network cost correction, booked with adjustment txn_01m4…"
}

Response (200):

JSON
{
  "object": "reconciliation_item",
  "livemode": false,
  "entityId": "ent_01m4tx5nj8emwbyf7y9vcf47zm",
  "processorConnectionId": "pcon_01m4vyt4mxe0s9zzk90373z6p6",
  "processor": "stripe",
  "availableOn": null,
  "match": {
    "paymentId": null,
    "refundId": null,
    "disputeId": null,
    "brandId": null
  },
  "ledgerTxnIds": [],
  "payout": null,
  "bankLine": null,
  "resolution": {
    "action": "resolved",
    "note": "Network cost correction, booked with adjustment txn_01m4…",
    "by": {
      "type": "user",
      "id": "usr_01m4tx5nj8emwbyf7y9vcf47zk"
    },
    "at": "2026-11-05T10:00:00.000Z",
    "payoutItemId": null
  },
  "lastCheckedAt": "2026-11-05T04:00:12.000Z",
  "createdAt": "2026-11-05T04:00:12.000Z",
  "updatedAt": "2026-11-05T10:00:00.000Z",
  "version": 2,
  "id": "pcon_01m4vyt4mxe0s9zzk90373z6p6:txn_3QAdjustment1",
  "source": "processor",
  "kind": "adjustment",
  "status": "matched",
  "reason": null,
  "reference": "txn_3QAdjustment1",
  "balanceTransactionRefs": ["txn_3QAdjustment1"],
  "sourceRef": null,
  "amount": {
    "amount": "-1000000",
    "currency": "EUR"
  },
  "fee": {
    "amount": "0",
    "currency": "EUR"
  },
  "net": {
    "amount": "-1000000",
    "currency": "EUR"
  },
  "occurredAt": "2026-11-04T15:20:00.000Z"
}

A bank line that confirms a payout

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

{
  "note": "Stripe payout, bank booked it a week late",
  "payoutItemId": "pcon_01m4vyt4mxe0s9zzk90373z6p6:po_1QPayout1"
}

Response (200):

JSON
{
  "object": "reconciliation_item",
  "livemode": false,
  "entityId": "ent_01m4tx5nj8emwbyf7y9vcf47zm",
  "processorConnectionId": null,
  "processor": null,
  "availableOn": null,
  "match": {
    "paymentId": null,
    "refundId": null,
    "disputeId": null,
    "brandId": null
  },
  "ledgerTxnIds": [],
  "payout": null,
  "bankLine": {
    "lineId": "bsl_01m4tx5nj8emwbyf7y9vcf48bc",
    "importId": "bsi_01m4tx5nj8emwbyf7y9vcf48ba",
    "bookingDate": "2026-11-04",
    "counterparty": "Acme d.o.o.",
    "candidatePayoutItemIds": []
  },
  "resolution": {
    "action": "resolved",
    "note": "Stripe payout, bank booked it a week late",
    "by": {
      "type": "user",
      "id": "usr_01m4tx5nj8emwbyf7y9vcf47zk"
    },
    "at": "2026-11-05T10:00:00.000Z",
    "payoutItemId": "pcon_01m4vyt4mxe0s9zzk90373z6p6:po_1QPayout1"
  },
  "lastCheckedAt": "2026-11-05T04:00:12.000Z",
  "createdAt": "2026-11-05T04:00:12.000Z",
  "updatedAt": "2026-11-05T10:00:00.000Z",
  "version": 2,
  "id": "bsl_01m4tx5nj8emwbyf7y9vcf48bc",
  "source": "bank",
  "kind": "bank_line",
  "status": "matched",
  "reason": null,
  "reference": "Transfer from savings",
  "balanceTransactionRefs": [],
  "sourceRef": null,
  "amount": {
    "amount": "5000000000",
    "currency": "EUR"
  },
  "fee": null,
  "net": null,
  "occurredAt": "2026-11-04T00:00:00.000Z"
}

Errors

CodeHTTP statusWhenWhat to do
validation_failed400The note is empty or too long, or payoutItemId was given for a processor item.Fix the fields listed in details.issues and send the request again.
reconciliation_payout_mismatch400payoutItemId isn't a payout of this entity, failed, is confirmed by another line, or has another amount or currency than the line.Pick a payout item (kind: payout) of this entity and mode that didn't fail and isn't confirmed by another line, for exactly the line's amount and currency (details says what differs). Bank fees deducted from a payout aren't matched automatically: resolve the line with a note and book the fee with a ledger adjustment.
resource_not_found404This entity has no such item in this mode.Check the ID and that your credentials are scoped to the right organization, entity, brand and mode.
reconciliation_item_closed409The item is resolved or ignored already (details.status).Reload the item: it was resolved or ignored already (details.status), by a person or by a later reconciliation run that found what it was waiting for. Only open items can be resolved or ignored.
version_conflict409The item changed since you read it (expectedVersion), or at the same moment.Fetch the object again and retry the change.
idempotency_key_reused409The idempotency key was used before for another request.Use a new Idempotency-Key for a different request, or resend the original request unchanged.
scope_required400The request names no legal entity (an org key without Ownrecord-Entity, or a brand key: reconciliation belongs to the entity).Call the operation with credentials or a target at its level: an organization, a legal entity, a brand or the platform (details.required_scope).
permission_denied403You can't work this entity's reconciliation (ledger:write: finance, owners and admins).Ask an organization owner or admin for a role or scope that allows this action.
livemode_not_allowed403You have no live-mode access, so you can't use live reconciliation.Use test mode, or credentials for the target's mode. Developers need live access granted by an organization owner or admin.

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