Skip to content

Withdrawals

Request a withdrawal of fiat or crypto to a destination you have already registered, track it, and cancel it while it is still awaiting approval.

A withdrawal request does not move funds. It enters an approval queue, and money leaves only once Zodia Markets Operations has approved and processed the request. Until then you can track the request’s state, and while it is still awaiting approval you can cancel it.


Base URL https://trade-uk.sandbox.zodiamarkets.com for the UK sandbox. All paths below are relative to it. Production and AME hosts are on Environments
API key and secret See Signing requests
The Move Funds permission on the key Required by every endpoint here, including the two read-only list endpoints. A key without it gets 403 MOVE FUNDS permission required
The ROLE_OPERATIONS role on the account group you are transacting for See Account groups below
A registered destination An enabled and verified beneficiary bank account for fiat, or an enabled and whitelisted wallet for crypto. Register these before your first withdrawal request; neither can be created as part of one

The role must be granted as ROLE_OPERATIONS itself. A membership that carries only the individual permissions the role is composed of does not satisfy the check, and owning the account group does not either.


Operation Method and path
Submit a fiat request POST /api/3/withdrawal/fiat
Submit a crypto request POST /api/3/withdrawal/crypto
List fiat requests POST /api/3/withdrawal/fiat/list
List crypto requests POST /api/3/withdrawal/crypto/list
Cancel a fiat request POST /api/3/withdrawal/fiat/{uuid}/cancel
Cancel a crypto request POST /api/3/withdrawal/crypto/{uuid}/cancel

All six are POST and all six take a signed JSON body, including the two list endpoints. A read is a POST here because the anti-replay element travels in the signed body, not because it changes anything.



Every endpoint is a POST carrying a signed JSON body, authenticated with two headers:

Header Value
Rest-Key Your API key
Rest-Sign Signature over the request, computed with your API secret

The body always carries an anti-replay element alongside the operation’s own fields: either nonce or tonce. A request with neither is rejected.

  • nonce must be a whole number and strictly increasing for a given API key. A reused or lower value is rejected. It is tried first when both are present.
  • tonce is the current Unix time in microseconds, and is accepted only within two minutes of server time.

Signature computation is identical to the rest of the v3 API. See Generate Signature. Two points matter especially here:

Authentication failures return 401 with Unauthorized. That covers an unknown key, a bad signature, a missing or rejected nonce, a body that is not parseable JSON, and a throttled caller: rate limiting surfaces as 401 here, not 429.


Every operation is scoped to an account group, the entity whose balances and registered destinations you are acting on.

  • To submit or cancel, your key’s user must hold ROLE_OPERATIONS on the accountGroupUuid you name. Otherwise the call returns 403 You do not have permission to perform this action, which does not say which of the two gates it failed.
  • The list endpoints take no account-group parameter, and an accountGroupUuid sent in the body is ignored. They return requests across every account group where you hold ROLE_OPERATIONS and silently omit the rest.

Both lists return requests raised through this API by any member of the account group, not only your own. Requests raised by Zodia Markets Operations on your behalf are not returned.


The two families report state through different mechanisms and their vocabularies are not the same. Read the one that applies to the request you are looking at.

State Meaning Cancellable
PENDING_APPROVAL Submitted, awaiting review by Zodia Markets Operations Yes
PENDING Approved by Operations, withdrawal in progress No
PROCESSED Funds sent No
CANCELLED Cancelled by you, or declined by Operations No

Four states, and no FAILED.

State Meaning Cancellable
PENDING_APPROVAL Submitted, awaiting acceptance by Zodia Markets Operations Yes
PENDING Accepted by Operations, withdrawal in progress No
PROCESSED Funds sent No
FAILED Defined, but no current processing flow produces it. Tolerate it rather than expect it, and contact your relationship manager if you see it No
CANCELLED Cancelled by you, or declined by Operations No

For both families, PENDING_APPROVAL is the only state a request can be cancelled from, and CANCELLED does not distinguish a cancellation by you from a decision by Operations.

The window closes at different moments. A fiat request needs one operator approval. A crypto request is first accepted into the approval queue and then approved, two operator steps, and the cancel window closes at the first of them.


A submit is rejected with 422 Insufficient funds when the amount exceeds what is available to withdraw on that currency’s account: your total balance on it, less the withdrawal requests you already have in flight.

  • In-flight means requests still awaiting approval or accepted and in progress. Requests that have been processed or cancelled do not count.
  • Because in-flight requests are counted, several individually affordable requests can collectively exceed your balance, and the last one is rejected. If you get this unexpectedly, call the matching list endpoint to see what is still outstanding.
  • The comparison is not strict against the headroom: an amount exactly equal to it is accepted.
  • The figure is the account’s total balance, which includes funds committed elsewhere, not the available balance reported by Get Account Balances.

Failures return the relevant HTTP status with a two-key body:

{ "success": false, "message": "<reason>" }
Status Meaning message examples
401 Authentication, signature, nonce/tonce, unparseable body, or throttling Unauthorized
403 Invalid request body, missing Move Funds, or no ROLE_OPERATIONS on the account group Invalid signed params, MOVE FUNDS permission required, You do not have permission to perform this action
404 Cancel target not found in that account group Request not found
409 Cancel not allowed in the current state Request can not be cancelled in current state
422 Business validation failed. See the individual submit pages Insufficient funds and others
500 Unexpected error. The outcome is undefined, so follow the retry guidance above Error while processing request

A wrong HTTP method is the one failure that does not use this envelope: it returns { "apiVersion": ..., "timestamp": ..., "error": ... } instead. A client that parses only success and message should not assume every error body has them.


  • Content-Type: application/json on every request and response.
  • Fields with no value are omitted from responses rather than returned as null. Every field documented on the pages below is therefore optional in the response.
  • Monetary amounts are returned as strings to preserve exact decimals. Parse them as decimals, not floats.
  • Timestamps are ISO-8601 with milliseconds and a zone offset, for example 2026-08-04T10:15:30.451+01:00.
  • Successful submit and cancel calls return { "success": true, "uuid": "..." }. The list endpoints return a bare JSON array, with no envelope.
  • The name and alias fields inside beneficiary, bankAccount and wallet are resolved from a separate service. When it is unavailable the list still returns 200, but those fields are omitted while the uuid fields remain. A missing name does not mean there is no bank account.

Submit a USD withdrawal, confirm it, then cancel it while it is still awaiting approval.

1. Submit

POST /api/3/withdrawal/fiat
Rest-Key: <api key>
Rest-Sign: <signature over path and body>
Content-Type: application/json
{
"tonce": 1770888183656000,
"accountGroupUuid": "2073252c-81ed-41be-bf4d-d51b8f2246b8",
"ccy": "USD",
"amount": 2500.00,
"withdrawalMethod": "BANK_WIRE",
"bankAccountUuid": "7f3a9c21-4d5e-6f70-8192-a3b4c5d6e7f8",
"clientComment": "Monthly settlement"
}

2. Confirm it is awaiting approval

POST /api/3/withdrawal/fiat/list
Rest-Key: <api key>
Rest-Sign: <signature over path and body>
Content-Type: application/json
{ "tonce": 1770888183657000 }

3. Cancel it, with the request uuid in the path and accountGroupUuid in the body:

POST /api/3/withdrawal/fiat/e1b2c3d4-5a6b-7c8d-9e0f-1a2b3c4d5e6f/cancel
Rest-Key: <api key>
Rest-Sign: <signature over path and body>
Content-Type: application/json
{ "tonce": 1770888183658000, "accountGroupUuid": "2073252c-81ed-41be-bf4d-d51b8f2246b8" }

The request now reports state: CANCELLED.