403.
Each operation is gated on a capability granted by your plan; a missing one returns
403: Missing required capability: <capability>. See the capability table on each
endpoint.The wallet object
The transaction object
Transfer lifecycle and outcome delivery
Initiate transfer and sponsored Sign transaction requests are asynchronous by default: the request is validated and recorded, and the API answers202 with the PENDING transaction while the on-chain execution
continues. status moves through:
- Poll Get transaction by id
with the
data.idfrom the202(e.g. every 2–3 seconds) untilstatusisCOMPLETEDorFAILED. This endpoint is always authoritative. - Outcome webhook: pass
webhookUrlin the initiate body and the final transaction is POSTed to you (see below). - Reconcile anything unresolved on your side with
Get transaction history
filtered by
status=PENDINGorstatus=PROCESSING.
waitForCompletion: true to get the
legacy synchronous behavior: for transfers, 201 (completed) or 422 (failed)
with the settled result; for signs, 200 with the relay result (txHash,
gasUsed, feeWei). Expect 3–30s latency depending on the chain.
Signing on a non-EVM chain with an
addressIndex is local-only: nothing is
broadcast, so there is no transaction to poll. Those requests always answer
200 with the signed transaction, regardless of waitForCompletion.Lost the transaction id? Re-send the initiate request with the same
Idempotency-Key: the original 202 response, including the same data.id,
is replayed without creating a second transfer.Outcome webhook
When you passwebhookUrl, the service POSTs the final transaction there once
execution settles, in both async and sync modes:
event is wallet.transfer.completed or wallet.transfer.failed for transfers,
and wallet.sign.completed or wallet.sign.failed for sponsored signs; data is
the full transaction object, including explorerTxUrl and (on failure) error.
- Signature: each delivery carries
x-wallet-timestampandx-wallet-signature, where the signature isHMAC-SHA256("<timestamp>.<rawBody>")in hex. Pass your ownwebhookSecret(16–256 chars) alongsidewebhookUrlin the initiate request and verify with the value you sent; no out-of-band secret exchange needed. The secret is held in memory only, never persisted or logged. Reject timestamps older than 5 minutes to block replays. - Retries: 4 attempts (1s / 5s / 15s backoff, 10s timeout each). Respond
2xxquickly, before running your own processing. - Duplicates are possible: key your handling on
data.id. - Best-effort: treat the webhook as a notification and confirm via Get transaction by id. If no webhook arrives within ~30 seconds, fall back to polling.
- URL rules:
httpsonly in production; localhost, private, and link-local addresses are rejected with400 INVALID_WEBHOOK_URL.
