Posted Payments
Posted payments represent completed payment transactions in the system. They include details about the payment source and the actual transfer of funds.
A posted payment can also be a draft: a proposal (typically from Snapbooks automation for a bank transaction) that stores the transfer, account entries and reconciliation entries but has not been booked. A draft creates no journal entry, no reconciliation and no document status change, and its transfer stays at payment_status NONE until it is booked with PATCH /payments/{id}.
Endpoints
| Method | Endpoint | Description |
|---|---|---|
| GET | /payments | List posted payments |
| GET | /payments/{id} | Get a specific posted payment |
| POST | /payments | Create a posted payment (or a draft with "is_draft": true) |
| PATCH | /payments/{id} | Book a draft: body is exactly {"is_draft": false} |
| DELETE | /payments/{id} | Discard a draft (booked payments cannot be deleted; reverse their journal entry instead) |
Query Parameters
The GET /payments 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 |
| source_type | string | No | Filter by a single source type (e.g. INVOICE) |
| source_id | integer | No | Filter by source ID |
| is_draft | boolean | No | true returns drafts only, false booked payments only; omitted returns both |
| page | integer | No | Page number for pagination |
| per_page | integer | No | Number of items per page |
Create Posted Payment
POST /api/v2/payments
Creates a posted payment (or, with "is_draft": true, a draft proposal — see the note on drafts above).
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
| client_account_id | integer | Yes | The client account the payment belongs to |
| source_type | string | No | The type of source that generated this payment |
| source_id | integer | No | The ID of the source |
| source_line_id | integer | No | The ID of the source line item |
| memo | string | No | Description or memo for the payment |
| is_draft | boolean | No | Create as an unbooked draft instead of posting immediately (default: false) |
| transfer | object | Yes | The transfer to create. Accepts the same fields as Payment Transfer, plus debtor.bank_account_id, creditor.bank_account_id, reconciliation_entries, and account_entries |
Example Request
{
"client_account_id": 1,
"source_type": "INVOICE",
"source_id": 123,
"memo": "Invoice payment",
"transfer": {
"payment_type": "CREDIT_TRANSFER",
"amount": "1000.00",
"currency_code": "EUR",
"requested_transfer_date": "2023-05-11",
"debtor": { "bank_account_id": 1 },
"creditor": { "bank_account_id": 2 },
"reconciliation_entries": [
{
"relation_type": "ARINV",
"relation_id": 123,
"amount": "1000.00",
"currency_code": "EUR"
}
]
}
}
Response
Returns the created posted payment with status 201 Created. See Attributes below.
Attributes
| Attribute | Type | Description |
|---|---|---|
| id | integer | The unique identifier of the posted payment |
| client_account_id | integer | The ID of the client account |
| source_type | string | The type of source that generated this payment |
| source_id | integer | The ID of the source |
| source_line_id | integer | The ID of the source line item |
| memo | string | Description or memo for the payment |
| is_draft | boolean | true while the payment is an unbooked proposal |
| created_by_id | integer | The user who created the payment; 2 is Snapbooks automation |
| updated_by_id | integer | The user who last changed the payment, for example the one who booked a draft |
| human_touched_at | datetime | When a human last created or edited the payment; null if only automation has touched it |
| transfer | PaymentTransfer | The transfer details |
Payment Transfer
Each posted payment includes a transfer with the following attributes:
| Attribute | Type | Description |
|---|---|---|
| id | integer | The unique identifier of the transfer |
| created_at | datetime | When the transfer was created |
| created_by_id | integer | The ID of the user who created the transfer |
| requested_transfer_date | date | The requested date for the transfer |
| payment_type | string | The type of transfer (CREDIT_TRANSFER, SALARY, TAX, INTERCOMPANY, MIXED) |
| payment_status | string | The current status of the transfer |
| rejection_code | string | Code indicating reason for rejection, if applicable |
| rejection_message | string | Detailed message about rejection, if applicable |
| booking_date | date | The date the transfer was booked |
| booking_reference | string | Reference number for the booking |
| amount | decimal | The transfer amount |
| currency_code | string | The currency code of the transfer |
| exchange_rate | decimal | The exchange rate used |
| creditor_reference | string | Reference for the creditor |
Relationships
| Relationship | Type | Description |
|---|---|---|
| transfer.debtor | [BankAccount, BusinessPartner] | The debtor’s bank account and business partner details |
| transfer.creditor | [BankAccount, BusinessPartner] | The creditor’s bank account and business partner details |
| transfer.reconciliation_entries | [PaymentReconciliationEntry] | Reconciliation entries for the transfer |
| transfer.account_entries | [PaymentAccountEntry] | Account entries for the transfer |
Example Response
{
"id": 1,
"client_account_id": 1,
"source_type": "INVOICE",
"source_id": 123,
"source_line_id": 456,
"memo": "Invoice payment",
"transfer": {
"id": 1,
"created_at": "2023-05-10T12:00:00Z",
"created_by_id": 1,
"requested_transfer_date": "2023-05-11",
"payment_type": "CREDIT_TRANSFER",
"payment_status": "COMPLETED",
"rejection_code": null,
"rejection_message": null,
"booking_date": "2023-05-11",
"booking_reference": "REF123",
"amount": "1000.00",
"currency_code": "EUR",
"exchange_rate": "1.0000",
"creditor_reference": "INV123",
"debtor": {
"bank_account_id": 1,
"business_partner_id": 1,
"bank_account": {
"id": 1,
"account_number": "DE89370400440532013000"
},
"business_partner": {
"id": 1,
"name": "ACME Corp"
}
},
"creditor": {
"bank_account_id": 2,
"business_partner_id": 2,
"bank_account": {
"id": 2,
"account_number": "FR7630006000011234567890189"
},
"business_partner": {
"id": 2,
"name": "Supplier Inc"
}
},
"reconciliation_entries": [],
"account_entries": []
}
}
Booking and discarding drafts
PATCH /payments/{id} accepts only {"is_draft": false}. Booking re-validates the proposal against the current ledger and then posts it exactly like a direct POST: the journal entry, reconciliation, external reconciliation and document status changes are created at that point, and created_by_id is kept, so a draft booked unchanged stays attributed to automation. Responses:
| Status | Meaning |
|---|---|
| 200 | Booked (or already booked; the call is idempotent) |
| 400 | Unsupported field, is_draft: true on a booked payment, or the proposal does not validate |
| 409 | The proposal is outdated (the bank transaction was settled another way, or a referenced document or bank account changed). The draft has been removed |
DELETE /payments/{id} removes a draft and returns 204. It returns 400 for a booked payment.
Notes
- The client_account_id must be one of the eligible client accounts for the authenticated user.
- When creating a posted payment, the created_by_id is automatically set to the authenticated user’s ID.
- The source_type and source_id fields help track the origin of the payment (e.g., an invoice or other document).
- Bank account and business partner relationships can be included by specifying them in the with_relations parameter.
- All amounts are returned as string representations of decimal numbers.
- Dates are returned in ISO 8601 format.
- The source_type filter accepts a single value; it is not a list parameter.