Reconciliations
Reconciliations are used to match and verify financial transactions across different accounts or statements. They help ensure the accuracy of accounting records by confirming that transactions are properly recorded and balanced.
Endpoints
| Method |
Endpoint |
Description |
| GET |
/reconciliations |
List reconciliations |
| POST |
/reconciliations |
Create a reconciliation |
| PATCH |
/reconciliations/{id} |
Approve a draft reconciliation |
| DELETE |
/reconciliations/{id} |
Delete a reconciliation |
Query Parameters
The GET /reconciliations endpoint supports the following query parameters:
| Parameter |
Type |
Required |
Description |
| client_account_id |
integer |
Yes |
Filter by client account ID. Must be one of the user’s eligible client accounts |
| date_from |
date |
No |
Filter entries from this date (inclusive) |
| date_to |
date |
No |
Filter entries to this date (inclusive) |
| journal_entry_line_id |
integer |
No |
Filter to reconciliations whose entries reference this journal entry line |
| journal_entry_id |
integer |
No |
Filter to reconciliations whose entries belong to this journal entry |
| is_draft |
boolean |
No |
Filter to draft proposals (true) or committed reconciliations (false). Omit to return both |
| page |
integer |
No |
Page number for pagination (default: 0) |
| per_page |
integer |
No |
Number of items per page (default: 100) |
| with |
string |
No |
Comma-separated list of relations to include. Supported: entries, entries.journal_entry_line, created_by |
Attributes
| Attribute |
Type |
Description |
| id |
integer |
The unique identifier of the reconciliation |
| created_at |
datetime |
The date and time when the reconciliation was created |
| created_by_id |
integer |
The ID of the user that created the reconciliation |
| client_account_id |
integer |
The ID of the client account associated with the reconciliation |
| sequence_number |
integer |
The sequence number of the reconciliation. null while the reconciliation is a draft — sequence numbers are assigned only on commit |
| reconciliation_date |
date |
The date of the reconciliation |
| is_draft |
boolean |
Whether this is an unapproved proposal (true) or a committed reconciliation (false) |
Relationships
All relationships are opt-in and must be requested via the with query parameter.
| Relationship |
Type |
Description |
| created_by |
User |
The user who created the reconciliation |
| entries |
ReconciliationEntry |
The entries in this reconciliation |
| entries.journal_entry_line |
JournalEntryLine |
The journal entry line behind each entry (request via with=entries.journal_entry_line) |
Reconciliation Entry
| Attribute |
Type |
Description |
| id |
integer |
The unique identifier of the reconciliation entry |
| journal_entry_id |
integer |
The ID of the associated journal entry |
| journal_entry_line_id |
integer |
The ID of the associated journal entry line |
| debit |
decimal |
The debit amount in the base currency |
| debit_fc |
decimal |
The debit amount in foreign currency |
| credit |
decimal |
The credit amount in the base currency |
| credit_fc |
decimal |
The credit amount in foreign currency |
Example Request
GET /api/v2/reconciliations?client_account_id=7&with=entries,entries.journal_entry_line,created_by
Example Response
{
"data": [
{
"id": 1,
"created_at": "2023-05-10T12:00:00Z",
"created_by_id": 1,
"client_account_id": 7,
"sequence_number": 1,
"reconciliation_date": "2023-05-10",
"entries": [
{
"id": 1,
"journal_entry_id": 1,
"journal_entry_line_id": 1,
"debit": "100.00",
"debit_fc": "100.00",
"credit": "0.00",
"credit_fc": "0.00",
"journal_entry_line": {
"id": 1,
"posting_date": "2023-05-10",
"description": "Bank transaction",
"account_code": "1920",
"account_id": 1,
"debit": "100.00",
"credit": "0.00"
}
}
],
"created_by": {
"id": 1,
"first_name": "John",
"last_name": "Doe"
}
}
],
"meta": {
"page": 0,
"pages": 1,
"per_page": 100,
"records": 1
}
}
Create Reconciliation
POST /api/v2/reconciliations
Creates a committed reconciliation matching two or more journal entry lines. The entries relation is included in the response by default.
Request Body
| Field |
Type |
Required |
Description |
| client_account_id |
integer |
Yes |
The client account ID. Must be one of the user’s eligible accounts |
| date |
date |
Yes |
The reconciliation date |
| entry_lines |
array |
Yes |
At least two entries (see Entry line fields below) |
Entry line fields
| Field |
Type |
Required |
Description |
| journal_entry_line_id |
integer |
Yes |
The journal entry line being reconciled |
| journal_entry_id |
integer |
No |
Defaults to the journal entry line’s own journal entry |
| debit |
decimal |
No |
Debit amount in base currency. Defaults to the journal entry line’s debit/credit when every amount field is omitted |
| credit |
decimal |
No |
Credit amount in base currency |
| debit_fc |
decimal |
No |
Debit amount in foreign currency |
| credit_fc |
decimal |
No |
Credit amount in foreign currency |
| exchange_rate |
decimal |
No |
Defaults to the journal entry line’s exchange rate |
This endpoint always creates a committed reconciliation (is_draft: false) — is_draft cannot be set through the request body. Draft (proposal) reconciliations are produced only by Snapbooks’ internal automatic-matching pipeline and approved via Update Reconciliation.
Across all entries, local-currency (debit/credit) amounts must balance to zero. If every entry shares one foreign currency and only the local-currency side is unbalanced, an offsetting FX gain/loss (agio) entry is posted automatically; any other imbalance is rejected.
Example Request
{
"client_account_id": 7,
"date": "2026-04-10",
"entry_lines": [
{ "journal_entry_line_id": 101, "debit": "0", "credit": "500.00" },
{ "journal_entry_line_id": 205, "debit": "500.00", "credit": "0" }
]
}
Response
Returns the created reconciliation with status 201 Created, including its entries.
{
"id": 42,
"created_at": "2026-04-10T09:15:00Z",
"created_by_id": 7,
"client_account_id": 7,
"sequence_number": 12,
"reconciliation_date": "2026-04-10",
"is_draft": false,
"entries": [
{
"id": 88,
"journal_entry_id": 501,
"journal_entry_line_id": 101,
"debit": "0.00",
"debit_fc": "0.00",
"credit": "500.00",
"credit_fc": "500.00"
},
{
"id": 89,
"journal_entry_id": 502,
"journal_entry_line_id": 205,
"debit": "500.00",
"debit_fc": "500.00",
"credit": "0.00",
"credit_fc": "0.00"
}
]
}
Error Responses
| Status |
Description |
| 400 |
Missing JSON body |
| 400 |
Fewer than two entries, a duplicate journal_entry_line_id reference, an entry missing amounts, or the entries don’t balance |
| 403 |
Missing or invalid client_account_id, or no access to the client account |
Update Reconciliation
PATCH /api/v2/reconciliations/{id}
Approves a draft reconciliation, committing it. is_draft is the only mutable field, and only in the draft → committed direction — reopening a committed reconciliation back to draft is rejected. To undo a committed reconciliation, use Delete Reconciliation instead.
Path Parameters
| Parameter |
Type |
Description |
| id |
integer |
Reconciliation ID |
Request Body
| Field |
Type |
Required |
Description |
| is_draft |
boolean |
Yes |
Must be false to approve the draft. No other fields are accepted |
Behavior
- If the reconciliation is already committed, the request is a no-op and returns the current state with
200 OK.
- Otherwise, each cited journal entry line is re-checked to confirm it still has enough open amount to absorb the draft’s applied amount. If a cited line (or its journal entry) was cancelled or reconciled elsewhere since the draft was proposed, the stale draft is deleted and the request fails with
409 Conflict.
- On success, the reconciliation is assigned a
sequence_number, is_draft becomes false, and the cited journal entry lines and linked documents update their reconciled status — the same effect as Create Reconciliation.
Example Request
Response
Returns the updated reconciliation with status 200 OK, including its entries.
Error Responses
| Status |
Description |
| 400 |
Missing/non-boolean is_draft, an unsupported field in the request body, or an attempt to move a committed reconciliation back to draft |
| 403 |
No access to the reconciliation’s client account |
| 404 |
Reconciliation not found |
| 409 |
The draft proposal is stale — a cited line no longer has enough open amount to approve it. The draft is deleted as part of this response; re-propose it if still needed |
Delete Reconciliation
DELETE /api/v2/reconciliations/{id}
Permanently removes a reconciliation. The journal entry lines remain in place — only the reconciliation linkage is dropped.
Response
Returns 204 No Content with an empty body on success.
Error Responses
| Status |
Description |
| 403 |
No access to the reconciliation’s client account |
| 404 |
Reconciliation not found |
Notes
- The
client_account_id must be one of the eligible client accounts for the authenticated user.
- Reconciliations can only be created, updated, or deleted if they belong to one of the user’s eligible client accounts.
- The
entries, entries.journal_entry_line, and created_by relations are opt-in on GET — request them through with. POST and PATCH responses include entries by default.
- All amounts are returned as string representations of decimal numbers.
- All dates are returned in ISO 8601 format.
- The
_fc suffix on amount fields represents “foreign currency” amounts.