Pending Transfers
POST /v1/transfers
A pending transfer reserves funds without finalizing them. The amount is held on the debit account but not yet credited to the receiver. You then post (confirm) or void (cancel) it.
How it works
Step 1: Reserve. Create a pending transfer. The debit account's debits_pending increases. The credit account's credits_pending increases. Neither account's posted balances change. The funds are locked.
Step 2: Resolve. Do one of three things:
Post it. The reserved amount moves from pending to posted. The debit account's debits_posted increases, the credit account's credits_posted increases. The money has moved.
Void it. The reserved amount is released. Both accounts return to their state before the pending transfer. The money never moved.
Let it expire. If you set a timeout and the transfer is not posted or voided in time, it auto-voids. The funds are released automatically.
When to use
Authorization holds. A ride-hailing app holds the estimated fare when the ride starts, then posts the actual fare when it ends.
Escrow. Hold buyer funds until the seller delivers, then post. If the deal falls through, void.
Approval workflows. Reserve funds when a request is submitted. Post after manager approval. Void if rejected.
Request
{
"debit_account_id": "ba9755d7e835cdeea6bca803721c7eba",
"credit_account_id": "19d64e32e2da3c3dbd1ebaba9860ab9",
"amount": 50000,
"ledger": 1001,
"code": 100,
"pending": true,
"timeout": 3600
}
| Field | Required | Description |
|---|---|---|
pending | Yes | Set to true |
timeout | No | Seconds until auto-void. Omit for no expiry. |
The timeout is an interval in seconds, not an absolute timestamp. If you set timeout: 3600, the transfer expires 1 hour after creation.
Response 201
{
"data": {
"tenant_id": "f714f6af-...",
"transfer": {
"id": "a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4",
"debit_account_id": "ba9755d7e835cdeea6bca803721c7eba",
"credit_account_id": "19d64e32e2da3c3dbd1ebaba9860ab9",
"amount": 50000,
"ledger": 1001,
"code": 100,
"status": "pending",
"timeout": 3600,
"created_at": "2026-04-06T22:50:00Z"
}
}
}
Balance validation is immediate
Pending transfers validate the balance at creation time, not at post time. If the debit account does not have enough funds when you create the pending transfer, it fails immediately. It does not wait until you post it to check.
This means posting and voiding will never fail due to balance constraints. The funds were already validated and reserved.
Partial posting
When you post a pending transfer, you can post a smaller amount than was originally held. The remainder is released back to the debit account.
A ride costs an estimated 15,000. You hold 15,000. The actual fare is 12,000. You post 12,000. The remaining 3,000 is released.
A pending transfer can only be resolved once
You cannot post a transfer twice, void it after posting, or post it after voiding. Each pending transfer has exactly one resolution.
| Attempt | Result |
|---|---|
| Post then post again | already_posted error |
| Void then void again | already_voided error |
| Post then void | already_posted error |
| Void then post | already_voided error |
| Expired then post | expired error |
Headers
Authorization: Bearer qk_live_...
Idempotency-Key: <unique-string>
Content-Type: application/json