Skip to main content
A withdrawal sends an account’s USDC to the destination you registered for the user. The request names only an amount: it cannot name an address, so funds go nowhere else. All four need a partner key with the partner:accounts scope, and name the account in the path (no Kash-Account header).

Networks

The network fee is charged in USDC, and what Kash collects for it is capped at 1 USDC. The refusal threshold is different: an amount no larger than the most the fee can cost at the current SOL price is refused with 400 WITHDRAWAL_BELOW_MINIMUM, whose detail names that figure in atomic units. The figure is usually a small fraction of 1 USDC, is higher when the recipient’s USDC account on Solana must be created, moves with the SOL price, and can exceed 1 USDC when SOL is expensive. A retry of an amount close to it may pass or fail later.

Quote first

The quote and the withdrawal share these checks, with the same codes:
  • an account with no wallet yet: 409 ACCOUNT_NOT_ACTIVE;
  • the Arc minimum and the network fee: 400 WITHDRAWAL_BELOW_MINIMUM;
  • the balance: 409 INSUFFICIENT_BALANCE;
  • for Arc, the bridge: 422 DESTINATION_NOT_SUPPORTED where it has no route, 503 DEPENDENCY_UNAVAILABLE when it would cost more than the API allows or cannot be priced.
Only the withdrawal also checks that the account is active (a suspended account can be quoted but not withdrawn from), the 24-hour hold after a destination change (409 WITHDRAWALS_HELD) and the Idempotency-Key. A quote is therefore not a promise that the withdrawal will be accepted. A quote moves nothing. Show your users receiveAtomic before they confirm.

Request a withdrawal

amountAtomic is a positive whole number of USDC atomic units, as a string. Idempotency-Key is required: without it the request is refused with 400 VALIDATION_FAILED, because a retry must never become a second withdrawal. The answer is 202 Accepted with the withdrawal in pending. It completes later; you receive webhooks as it moves.
Retrying with the same Idempotency-Key returns the same withdrawal and moves no more money: within 24 hours the stored 202 is replayed with Idempotent-Replay: true, and after that the withdrawal is returned with 200 and _meta.idempotent: true. The same key with a different amount is refused with 409 IDEMPOTENCY_KEY_CONFLICT. Keys are scoped to the account.

Refusals

Each refusal is decided before anything is recorded, so nothing moves.

Statuses

A withdrawal is never failed while its transaction can still land: its end is decided from the chain, and for Arc from Relay’s status, never from a timeout. A bridge fill that fails is refunded by Relay to the account’s Solana wallet.

Amounts delivered

On a failed or cancelled withdrawal, deliveredAmountAtomic and minimumDeliveredAtomic are both null: nothing was delivered.

Webhooks

On bridge_failed, contact ZeroID support with the withdrawalId.

The 24-hour hold

Changing an account’s destination with PATCH /v1/partner/accounts/{accountId} pauses its withdrawals for 24 hours from the change. A leaked key therefore cannot redirect an account and empty it at once, and the account.destination_changed webhook gives you that window to catch a change you did not make. Re-sending the current destination does not restart the hold.

Read withdrawals

The list is newest first, with cursor pagination (limit 1 to 100, default 20). A withdrawal that is not this account’s is 404 RESOURCE_NOT_FOUND. With @kashdao/sdk 0.4.0 these routes are on kash.partnerAccounts.withdrawals: quote(accountId, { amountAtomic }), create(accountId, { amountAtomic }, { idempotencyKey }) (the key is required), get(accountId, withdrawalId), list(accountId) and waitForCompletion(accountId, withdrawalId), which polls until the withdrawal is completed, failed or cancelled.

Next

Release

End your link to an empty account.

Webhooks

Withdrawal payloads in full.