Confirm a bank operation's reconciliation
POST/api/v1/bank_operations/:bank_operation_id/reconciliation
Settles the operation against the invoices you name - writing one Invoice::Payment per allocation and recomputing the accounting entry from the confirmed set.
The body carries the COMPLETE intended allocation set, and a partial body is not a partial update. The set you send is the set that ends up confirmed: an allocation confirmed today and absent from this body is withdrawn, one present at a different amount is re-confirmed at the new one, and one that already matches is left untouched - so re-sending an identical body writes nothing. It is ALL-OR-NOTHING: if any member is refused, none of them lands.
The response is the recomputed operation. Ask for ?include=allocations,bank_accounting_entry and you read the confirmed set and its balanced lines back in the same round trip - a 300.00 movement split 200/100 comes back as TWO allocations and three lines, never as one mutated line.
Two tokens do two different jobs, and this endpoint requires both. Idempotency-Key protects against a DUPLICATED request; expected_version protects against a STALE one - a call computed from a picture of the allocation set that has since moved. Read version on the operation, send it back here.
Request
Responses
- 200
- 401
- 403
- 404
- 409
- 422
The recomputed bank operation.
The request carries no bearer token, or one that is invalid or expired.
The token does not hold the write scope, or the bank_reconciliation feature is off for the operation's workspace. An operation your token cannot read is a 404, never a 403.
No operation with this id is reachable by the token's grants. One belonging to another workspace answers the same way, so the response cannot be used to probe for one.
stale_version: the expected_version you sent is no longer the operation's current one, so the picture your set was computed from has moved. NOTHING WAS WRITTEN. details carries the CURRENT state - the version, the operation and its active allocations - so you re-render from it and retry with details.current_version rather than re-fetching. A confirmation from another operation recorded at the same moment on the same invoice can also move it: when that race leaves this operation with no active allocation, the loser is answered here; otherwise it receives the 422 refusal that the invoice's new state calls for. (idempotency_key_reuse and idempotency_request_in_progress also answer 409 on this path, with no details.)
The request cannot be performed. code says which refusal it is: validation_failed for a missing or non-integer expected_version, an empty or unreadable allocations list, one invoice named twice, an invoice that is not this operation's company's, or a domain rule an individual allocation breaks; allocation_exceeds_operation when the set would settle more than the movement carries; entry_already_exported when the operation's accounting entry has already left the books; operation_failed when another reconciliation touching the same invoices was being recorded at the same moment and the replay collided again - nothing was written, so read the operation again and resend; reconfirmation_out_of_order when confirming an allocation next to a later allocation that stays confirmed would post the rounding cent in a different order from the accounting entry - details.allocations names the invoices, and the remedy is to send the set without the later allocations first, then the complete set again.
entry_already_exported and reconfirmation_out_of_order are deliberately 422 and not 409. A 409 means the request is stale and a retry at a fresher version can succeed; an exported entry makes the request impossible AT ANY VERSION, and the remedy is a reclassification entry rather than a rewrite. An out-of-order re-confirmation fails at any version too: surviving payments are never re-posted, so the later allocations have to come off first.