Documentation Index
Fetch the complete documentation index at: https://docs.centryos.xyz/llms.txt
Use this file to discover all available pages before exploring further.
Endpoint
- Method:
POST
- URL:
{{LIQUIDITY_URL}}/v1/ext/linked-accounts/:currency/:linkedAccountId/withdrawal
- Auth: Bearer
{{accessToken}} (scope external.apis)
- Rate limit: 1 withdrawal per minute per user (and IP). Returns 429 if exceeded.
Path Parameters
| Parameter | Type | Required | Description |
|---|
currency | string | Yes | Currency code. Supported: USD only. |
linkedAccountId | string | Yes | UUID of the linked payout account (bank or card) to send funds to. Must be a valid UUID of an existing linked account associated with the authenticated entity. See Link Bank Account, Link Card Account, or Link International Bank Account for how to link an account. |
| Header | Required | Description |
|---|
Authorization | Yes | Bearer <token> with scope external.apis. |
Content-Type | Yes | application/json. |
Request Body
| Field | Type | Required | Description |
|---|
amount | number | Yes | Payout amount in dollars (e.g. 100.50 for $100.50 USD). Must be > 0. |
walletType | string | Yes | Must be "SPEND" (uppercase). Withdrawal is from the SPEND wallet tied to the linked account. |
reason | string | No | Optional reason or reference for the payout (e.g. "Contractor payment"). |
routingType | string | No | Only required when requesting a real-time payment. Pass "RTP" to use real-time payment rails. Omit for standard bank transfer (default). Ignored for card linked accounts. Allowed values: ACH, RTP, WIRE, BANK. |
transactionType | string | No | If "payout" (case-insensitive), treated as PAYMENT flow; otherwise defaults to PAYOUT. |
Note: MFA is not required. Do not send mfaCode.
Request
curl -X POST "{{LIQUIDITY_URL}}/v1/ext/linked-accounts/USD/{{linkedAccountId}}/withdrawal" \
-H "Authorization: Bearer {{accessToken}}" \
-H "Content-Type: application/json" \
-d '{
"amount": 100.50,
"walletType": "SPEND",
"reason": "Contractor payment"
}'
To request a real-time payment instead of a standard bank transfer:
curl -X POST "{{LIQUIDITY_URL}}/v1/ext/linked-accounts/USD/{{linkedAccountId}}/withdrawal" \
-H "Authorization: Bearer {{accessToken}}" \
-H "Content-Type: application/json" \
-d '{
"amount": 100.50,
"walletType": "SPEND",
"reason": "Contractor payment",
"routingType": "RTP"
}'
Response (200)
{
"success": true,
"message": "Payment queued",
"data": {
"id": "<transaction-uuid>",
"status": "<TransactionStatus>",
"fees": "<fee amount as string>",
"amount": "<total debit amount (amount + fees) as string>"
}
}
Response Fields
| Field | Type | Description |
|---|
success | boolean | Whether the request succeeded. |
message | string | Status message (e.g. "Payment queued"). |
data.id | string | Transaction UUID for tracking. |
data.status | string | Transaction status. See statuses below. |
data.fees | string | Fee amount charged as a string. |
data.amount | string | Total amount debited (payout amount + fees) as string. |
Transaction Statuses
| Status | Meaning |
|---|
SUCCESS | Payout dispatched successfully. |
PENDING | Payout accepted and in progress; final confirmation is asynchronous. |
AWAITING_APPROVAL | Payout requires internal approval before it is processed. Funds are not debited yet. You will receive a webhook or can poll the transaction status endpoint once approved. |
Error (4xx / 5xx)
{
"success": false,
"message": "<error detail>",
"fatal": true
}
Error Cases
| Situation | HTTP | Message / cause |
|---|
Missing or invalid amount | 400 | Validation error — amount is required and must be a positive number. |
Missing or invalid walletType | 400 | walletType must be "SPEND" (uppercase). |
Invalid routingType | 400 | Only ACH, RTP, WIRE, BANK are allowed. |
| Unauthorized / wrong scope | 401 | Invalid or expired token, or missing external.apis scope. |
| Linked account not found | 404 | Wrong linkedAccountId or account not accessible by this entity. |
| Application token expired | 400 | Payment-link token is expired or inactive. |
| Amount mismatch (payment link) | 400 | Merchant-funded withdrawal: body amount does not match the token amount. |
| Insufficient balance | 400 | "Insufficient Funds #912" — SPEND wallet balance is too low. |
| Payout not enabled | 403 | Payouts are not enabled for this account. Contact support. |
| Failed to process payout | 500 | The payment processor rejected the disbursement. Verify that the linked account is active, within transaction limits, and that the recipient details are correct. If the issue persists, contact support with the transaction ID. |
| Rate limit exceeded | 429 | 1 withdrawal per minute per user. Retry after 60 seconds. |
Payout Types
The payout method is determined by the type of linked account. For bank accounts, you can optionally override to real-time payment by passing routingType: "RTP".
| Linked account type | routingType in body | Result |
|---|
| Bank | Omitted (default) | Standard bank transfer. |
| Bank | "RTP" | Real-time payment. |
| Bank | "ACH" or "BANK" | Standard bank transfer. |
| Bank | "WIRE" | Wire transfer. |
| Card | Any or omitted | Push-to-card; routingType is ignored. |
Validation Rules
amount — Required. Number greater than 0.
walletType — Required. Must be "SPEND" (uppercase).
reason — Optional. String.
routingType — Optional. If provided, must be one of: ACH, RTP, WIRE, BANK. Omit for default bank transfer behaviour.
currency — From path parameter. Must be USD.
linkedAccountId — From path parameter. Must be a valid UUID of a linked account for the authenticated entity.
- MFA — Not required. Do not include
mfaCode.
Payment-Link / Merchant-Funded
If the request is made in the context of a payment link with withdrawalSource === 'MERCHANT_WALLET':
- The
amount in the body must exactly match the amount on the application token; otherwise returns 400 "Malformed request".
- On success, the application token is invalidated immediately and cannot be reused.
Notes
- The linked account must be associated with the authenticated entity’s SPEND wallet.
- A success response means the payout has been queued or dispatched. Final settlement may be asynchronous — use the transaction status endpoint or webhooks to confirm.
- No idempotency keys are supported. Implement client-side deduplication if needed.
- Rate limited to 1 request per minute per user.