Make a transfer
For integration engineers. Transfer GBP tokens from one customer's account to another's, follow the operation to CONFIRMED, and read both balances.
Who this is for
Engineers who have a funded ACC-0001 and an ACTIVE ACC-0002 from the earlier steps. By the end of this step 250.00 GBP has moved from CUST-0001 to CUST-0002.
How a transfer works
A TRANSFER moves tokens from the account in accountRef to the account in counterpartyRef. It is the one operation type that requires a counterparty.
- Both references name accounts, never customers.
- Both accounts must exist, hold the operation's
assetId, and beACTIVE. - The asset must have an
ACTIVEcontract.
The balance is not checked at submission. A transfer for more than ACC-0001 holds is accepted with 202 and fails during settlement. Check available first if your process needs to refuse early.
Like every token operation, a transfer is accepted first and settles asynchronously. Neither balance changes until it reaches CONFIRMED.
Carry the transfer into your integration
Store the bank's payment reference alongside the source account, beneficiary account, asset, amount and returned operation ID. Validate bank-side customer/payment checks before submission. Quant Flow executes the supported token transfer; it does not complete a separate cash payment in your core banking system.
Expose pending and terminal outcomes separately to the caller of your adapter. Persist signed events before acknowledging them, use operation reads to recover missing events and reconcile both accounts after confirmation. Approval, signing and settlement failures need their documented handling; elapsed time alone does not justify a second transfer. Use Production readiness for evidence and Daily operations and monitoring for ongoing checks.
Worked example
Submit the transfer
POST /api/transactions HTTP/1.1
Host: api.qfp.quantnetwork.net
Authorization: Bearer eyJraWQiOiJ...
API-Version: 1.0.0
Content-Type: application/json
Idempotency-Key: a61e3b27-0d94-4c58-b7f2-6e8d1c0a4b39
{
"txType": "TRANSFER",
"assetId": "GBP",
"accountRef": "ACC-0001",
"counterpartyRef": "ACC-0002",
"amount": "250.00"
}Illustrative example built from the schema.
HTTP/1.1 202 Accepted
Content-Type: application/json
{
"transactionId": "5b2e8d41-9c07-4a63-8e15-7f3a0d6c2b98",
"txType": "TRANSFER",
"assetId": "GBP",
"accountRef": "ACC-0001",
"customerRef": "CUST-0001",
"counterpartyRef": "ACC-0002",
"amount": "250.00",
"params": {},
"state": "POLICY_PENDING",
"createdAt": "2026-08-06T10:04:31.207Z",
"updatedAt": "2026-08-06T10:04:31.207Z"
}A transfer carries no named call arguments, so params is {} when none were supplied. The example illustrates the policy-enabled path; a transfer accepted without policy starts in BATCHED.
Follow it to a terminal state
GET /api/transactions/5b2e8d41-9c07-4a63-8e15-7f3a0d6c2b98 HTTP/1.1
Host: api.qfp.quantnetwork.net
Authorization: Bearer eyJraWQiOiJ...
API-Version: 1.0.0Illustrative example built from the schema.
{
"transactionId": "5b2e8d41-9c07-4a63-8e15-7f3a0d6c2b98",
"txType": "TRANSFER",
"assetId": "GBP",
"accountRef": "ACC-0001",
"customerRef": "CUST-0001",
"counterpartyRef": "ACC-0002",
"amount": "250.00",
"params": {},
"state": "CONFIRMED",
"txHash": "0x2c7e9a1f4b8d3065e1a7c9f2b5d8e0a3c6f9b2d5e8a1c4f7b0d3e6a9c2f5b8e1",
"blockNumber": 18447012,
"createdAt": "2026-08-06T10:04:31.207Z",
"updatedAt": "2026-08-06T10:06:02.884Z"
}Read both balances
GET /api/accounts/ACC-0001/balances HTTP/1.1
Host: api.qfp.quantnetwork.net
Authorization: Bearer eyJraWQiOiJ...
API-Version: 1.0.0Illustrative example built from the schema.
{
"accountRef": "ACC-0001",
"customerRef": "CUST-0001",
"assetId": "GBP",
"total": "750.00",
"available": "750.00",
"locked": "0.00",
"asOf": "2026-08-06T10:06:10.032Z"
}GET /api/accounts/ACC-0002/balances HTTP/1.1
Host: api.qfp.quantnetwork.net
Authorization: Bearer eyJraWQiOiJ...
API-Version: 1.0.0Illustrative example built from the schema.
{
"accountRef": "ACC-0002",
"customerRef": "CUST-0002",
"assetId": "GBP",
"total": "250.00",
"available": "250.00",
"locked": "0.00",
"asOf": "2026-08-06T10:06:10.518Z"
}View in API Reference
- Submit a token operation ·
POST- Get one token operation ·
GET- Get an account's balances ·
GET
Errors and edge cases
| Status or outcome | When | What to do |
|---|---|---|
400 | counterpartyRef omitted; either account does not exist, holds a different asset or is not ACTIVE; amount not positive or too precise; the asset has no ACTIVE contract; Idempotency-Key missing or invalid | Fix the request. Do not retry unchanged |
200 instead of 202 | The Idempotency-Key was already used | The body is the first operation as it now stands. No second transfer was created |
state: FAILED after 202 | The transfer did not settle, for example because ACC-0001 did not hold enough | Read failureCode and reasonCode. See Handle failures |
state: HELD or AWAITING_APPROVAL | An insufficient-balance gate parked it, or policy/custody requires an approver | See Policy, approvals and audit |
An inactive counterparty:
Illustrative example built from the schema.
HTTP/1.1 400 Bad Request
Content-Type: application/json
{
"timestamp": "2026-08-06T10:04:31.207Z",
"status": 400,
"error": "Bad Request",
"message": "Account 'ACC-0002' is PENDING; token operations require an active account."
}To hold funds for a counterparty and pay them later (for example on delivery), use a LOCK and a RELEASE. See Transfers, locks and releases.
Follow a Recipe
Step through the code in JavaScript or Python, inspect illustrative responses, and open the connected endpoint schemas.
API Reference
Open an endpoint for request fields, response examples and the interactive API console.
| Operation | Method |
|---|---|
| Submit a token operation | POST |
| Get one token operation | GET |
| Get an account's balances | GET |
Related pages
Updated 4 days ago

