Reconcile a processor connection now
The reconciliation.runs.create operation: POST /api/v1/reconciliation/runs in the REST API and the reconciliation_runs_create tool in the MCP server.
/api/v1/reconciliation/runsAsks for a reconciliation run of one processor connection now, besides the daily one. The run happens in the
background within a minute (runRequestedAt is set until it finishes): it reads the connection's balance
transactions since its cursor, matches them to payments, refunds and disputes, posts the processor fees and
payouts not posted yet (each once), puts what doesn't match in the queue and raises RECON_UNMATCHED when it
queued something new. Poll reconciliation.connections.list for the result (lastRun). Asking again while a
run is pending runs it again; that is harmless.
At a glance
- REST:
POST /api/v1/reconciliation/runs - MCP tool:
reconciliation_runs_create - Operation ID:
reconciliation.runs.create - Scope: Legal entity
- Permission:
ledger:write - Risk tier:
write - Dry run: Supported (send
Ownrecord-Dry-Run: true) - Idempotency:
Idempotency-Keyrequired - Modes: Test and live
- Authentication: API key with the
ledger:writescope - Since: M8
Request
Body
A JSON object (Content-Type: application/json):
| Field | Type | Required | Description |
|---|---|---|---|
processorConnectionId | pcon_… ID | Yes | The connection to reconcile now (pcon_…). |
Response
202 Accepted with a JSON object:
| Field | Type | Description |
|---|---|---|
object | "reconciliation_connection" | |
processorConnectionId | pcon_… ID | |
livemode | boolean | |
processor | one of stripe, mollie, fake | |
label | string | |
status | one of active, degraded, disconnected | The connection's status: disconnected ones aren't read. |
cursor | date-time or null | The creation time of the latest balance transaction read; the next run reads from an hour before it. |
lastRun | object or null | |
lastSucceededAt | date-time or null | |
runRequestedAt | date-time or null | A run asked for that hasn't finished yet (the job runs it within a minute). |
openItems | integer | Open items of this connection in the queue. |
Examples
Reconcile the Stripe connection now
POST /api/v1/reconciliation/runs
Authorization: Bearer or_test_…
Idempotency-Key: 3f1c9a52-7d0e-4b8f-9a61-0c2d5e8b7f14
Content-Type: application/json
{
"processorConnectionId": "pcon_01m4vyt4mxe0s9zzk90373z6p6"
}
Response (202):
{
"object": "reconciliation_connection",
"processorConnectionId": "pcon_01m4vyt4mxe0s9zzk90373z6p6",
"livemode": false,
"processor": "stripe",
"label": "Stripe (test)",
"status": "active",
"cursor": "2026-11-05T00:10:00.000Z",
"lastRun": {
"trigger": "schedule",
"startedAt": "2026-11-05T04:00:00.000Z",
"finishedAt": "2026-11-05T04:00:12.000Z",
"status": "succeeded",
"readFrom": "2026-11-03T23:59:00.000Z",
"counts": {
"read": 42,
"recorded": 40,
"matched": 39,
"opened": 1,
"posted": 35,
"rechecked": 0,
"bankConfirmed": 1
},
"error": null
},
"lastSucceededAt": "2026-11-05T04:00:12.000Z",
"runRequestedAt": "2026-11-05T10:00:00.000Z",
"openItems": 1
}
Errors
| Code | HTTP status | When | What to do |
|---|---|---|---|
validation_failed | 400 | processorConnectionId isn't a processor connection ID. | Fix the fields listed in details.issues and send the request again. |
resource_not_found | 404 | This entity has no such processor connection in this mode. | Check the ID and that your credentials are scoped to the right organization, entity, brand and mode. |
reconciliation_connection_unsupported | 400 | The connection is disconnected: its balance transactions can't be read any more. | Reconciliation reads a connection's balance transactions: the connection must be active (not disconnected) and in the mode of the request. details.status is the connection's status. |
version_conflict | 409 | Another run was asked for at the same moment; retry. | Fetch the object again and retry the change. |
scope_required | 400 | The 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_denied | 403 | You 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_allowed | 403 | You 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_key_reused, idempotency_in_progress, approval_required, approval_rejected, approval_expired, stale_approval, approval_policy_denied, rate_limited, internal_error.