Skip to navigation

Send funds

View as MarkdownOpen in Claude

Signs and broadcasts a transfer, and returns as soon as the network accepts it.

⚠️ A txHash is not a confirmation. Poll /txid until status flips from pending to success or failed.

The fee comes out of the amount — for native assets

Native transfers (BTC, ETH, BNB, POL, TRX, SOL) are sent net of the network fee: the recipient receives amount − fee, not amount. The transfer is sized so that the total leaving the wallet equals exactly the amount you asked for. If you need the recipient to receive an exact figure, add the fee (quote it with /fee) to the amount you send.

Token transfers (USDT, USDC) deliver the full amount. Their fee is paid separately, in the chain’s native coin — so a token wallet also needs a native balance for gas.

Amounts

amount is a human-decimal string ("0.5"), matched against /^\d+(\.\d+)?$/ and parsed to base units with the asset’s decimals. Never send base units, and never send a float you produced by arithmetic.

Minimums are enforced: 0.00001 BTC, and 0.0001 for a native EVM send (ETH, BNB, POL). Token sends must be greater than zero. An amount with more decimal places than the asset supports is rejected.

Sender

The sender is resolved server-side from userId + assetId. A client can never supply a private key or a from-address. recipient must differ from the sender.

Idempotency — X-Request-Id is required here

/send is the one endpoint where you must supply X-Request-Id (omitting it is a 400). It is the idempotency key, and it is what makes a retry safe.

The contract: one id per logical transfer, the same id on every retry of it, a fresh id for a new transfer. Generate it before the first attempt and store it alongside your intent record — if you mint a new id on retry, you have authorised a second transfer, and the service will send it.

Repeating a request with the same id resolves against the original:

Original attemptRepeat with the same id
CompletedThe stored result is replayed — the same txHash, nothing new broadcast.
Still in flight409 — the outcome isn’t known yet. Reconcile via /transactions; never blind-retry.
Failed before broadcastThe retry proceeds normally.
Same id, different assetId / recipient / amount422 — the id is already committed to a different transfer.

A failure is only re-armed for retry when it is definitely pre-broadcast (bad input, wrong password, a broadcast the chain positively rejected). Ambiguous failures — a timeout, a dropped connection, an unknown 500 — deliberately leave the transfer claimed, because the transaction may be on-chain. Retrying those with the same id returns 409 until the claim expires (48 hours), which is the service refusing to double-send on your behalf.

Authentication

AuthorizationBearer

A 15-minute token from /auth. Required on every endpoint except /auth.

Headers

X-Request-IdstringRequiredformat: "^[A-Za-z0-9._-]{1,64}$"<=64 characters

Required on /send, and client-supplied — it is the idempotency key for the transfer.

One id per logical transfer; the same id on every retry of it; a fresh id for a new transfer. 1–64 characters of A-Za-z0-9._-. Omitting it is a 400.

X-USER-IDstringOptionalformat: "^[0-9a-fA-F]{24}$"

Optional. When present it overrides any userId in the body.

Request

This endpoint expects an object.
userIdstringRequiredformat: "^[0-9a-fA-F]{24}$"

24-character hex id, returned by /create.

assetIdenumRequired

Primary asset selector. An all-digit string ("21") is accepted and normalised to an integer.

  • 1 — BITCOIN BTC (native, 8 decimals)
  • 2 — ETHEREUM ETH (native, 18 decimals)
  • 21 — ETHEREUM USDT (ERC20, 6 decimals)
  • 22 — ETHEREUM USDC (ERC20, 6 decimals)
  • 3 — BSC BNB (native, 18 decimals)
  • 31 — BSC USDT (BEP20, 18 decimals)
  • 32 — BSC USDC (BEP20, 18 decimals)
  • 4 — TRON TRX (native, 6 decimals)
  • 41 — TRON USDT (TRC20, 6 decimals)
  • 42 — TRON USDC (TRC20, 6 decimals) — not on every endpoint
  • 5 — POLYGON POL (native, 18 decimals)
  • 51 — POLYGON USDT (ERC20, 6 decimals) — not on every endpoint
  • 52 — POLYGON USDC (ERC20, 6 decimals)
  • 6 — SOLANA SOL (native, 9 decimals)
  • 61 — SOLANA USDT (SPL, 6 decimals) — not on every endpoint
  • 62 — SOLANA USDC (SPL, 6 decimals)
recipientstringRequired
Destination address on the asset's chain. Must differ from the sender.
amountstringRequiredformat: "^\d+(\.\d+)?$"

Human-decimal amount, e.g. "0.5". Never base units, never a float.

passwordstringRequired>=8 characters

Keystore password (AES-256-GCM, scrypt KDF). Unrecoverable — required by /send and /extend.

Response

OK
resultobject
requestIdstring

Echo of the inbound X-Request-Id, or a generated one.

Errors

400
Bad Request Error
401
Unauthorized Error
402
Payment Required Error
403
Forbidden Error
404
Not Found Error
409
Conflict Error
422
Unprocessable Entity Error
502
Bad Gateway Error
503
Service Unavailable Error