Go to production
The sandbox is testnet-only. Going live means pointing at the production endpoint and having your controls in place before real value moves. Nothing about the API surface changes — the guarantees you built against are the same.
Endpoints
Section titled “Endpoints”| Environment | Base URL | Chains |
|---|---|---|
| Sandbox | https://api.mpc-dev.xkova.com/v1 | Avalanche Fuji, Base Sepolia, Bitcoin signet |
| Production | https://api.mpc.xkova.com/v1 | mainnets — available at launch |
Switch by changing baseUrl and using mainnet chainIds
(Send on EVM). Use a separate API key
per environment so a sandbox key can never touch production.
Before you flip the switch
Section titled “Before you flip the switch”Pick the right tier per vault. The tier is fixed at creation and decides who
must authorize a signature. For funds you control, self gives true self-custody;
for user wallets, hosted gates each signature on the user’s token. Review
How it works.
Set spend controls. Configure per-transaction and per-day limits and your
recipient/asset policy on each vault. These are checked before any share
participates — a violation is rejected with no partial signature. Start
conservative.
Make every send idempotent. Derive idempotencyKey from your own operation
ID, persist it before you call, and reuse it on retry. This is your protection
against double-spending on a timeout or crash. See
Send on EVM.
Use webhooks, and reconcile. Register a webhook and verify every delivery’s
signature (Webhooks). Keep a slower getTransaction
reconciliation loop as a backstop for missed deliveries. Never assume a POST
that returned 202 has settled.
Protect the API seed. It lives in a secrets manager, never in source or logs. Mint one key per service so a leak is contained; revoking a key is immediate and does not touch funds. Rotate by minting, cutting over, then revoking.
Handle errors by code, not message. Branch on the stable code slug and
the HTTP status, not on human-readable text (Errors). Treat
rate_limited and unavailable as retryable with backoff; treat rejected
transactions as terminal and surface the reason.
Operational expectations
Section titled “Operational expectations”- Everything money-moving is asynchronous. Design your flows around states and webhooks, not blocking calls.
- Rotation is invisible to you. Vault resharing does not change addresses; signing pauses briefly. Don’t hardcode assumptions about instant availability.
- Retry on the retryable, fail closed on the rest. A refused signature never produces a partial result — there is nothing to clean up, only to surface.
Launch checklist
Section titled “Launch checklist”- Production API key minted and stored in a secrets manager.
- Vaults created at the intended tier; limits and policy configured.
- Idempotency keys persisted before each send.
- Webhook endpoint verifying signatures, plus a reconciliation loop.
- Error handling branches on
code; retryable vs terminal separated. - Alerting on
failed/rejectedtransactions and onfrozenvaults.