Skip to content

Going live

Going live is a change of workspace state, not a code change. Your integration keeps the same base URL and the same code; you swap a cpk_test_ key for a cpk_live_ one.

  1. Submit KYB. Business details, documents, and the structured identity of the people behind the business, all from the dashboard’s Settings.
  2. Complete the structured identity. Go-live requires at least one UBO, and every UBO and director must have their deep fields filled in. These are required at go-live, not at the first onboarding screen, so an account can look complete and still be blocked here.
  3. Wait for KYB approval. A workspace cannot be enabled while its KYB is anything other than APPROVED. Attempting it returns 422 with a message naming the current status.
  4. An operator enables live mode. This is not a self-service action.
  5. Create a cpk_live_ key and swap it in. Same base URL, same code, same signing recipe.

If step 2 or 3 is incomplete, the go-live call fails with 422 and tells you which of the two it was: an incomplete identity names the people and the missing fields; a KYB that is not approved names the status it is in.

Sandbox and Live share the code path, but resources are per network, and knowing that in advance is what makes go-live day uneventful. To re-create on the Live side:

  • API keys. A cpk_test_ key can never touch mainnet. Mint your cpk_live_ key from the dashboard, with the least-privilege scopes your integration actually uses.
  • Webhook endpoints. Endpoints are registered per network, each with its own secret. Register your production endpoints with a live key (or from the dashboard in Live mode) and store the new secrets; your sandbox endpoints will not receive live events.
  • Wallets and customers. Sandbox wallets live on the testnets. Your production wallets are created fresh with the live key: same requests, same code.
  • Withdrawal security. The allowlist, its beneficiaries and the withdrawal limits are Live-side configuration, on the dashboard’s Security page. Nothing you did in Sandbox pre-configures them.

Read this before your first live withdrawal

Section titled “Read this before your first live withdrawal”

A live workspace starts with the withdrawal allowlist ON. That is deliberate: it is secure by default, and it is the single most common first-day surprise.

The practical consequence is that your first live withdrawal is not a straight API call. The destination has to be on the allowlist first, and adding a beneficiary is a protected action rather than an ordinary write, with a cooling-off delay (24 h by default) before the new address becomes usable. Larger withdrawals are additionally held for a second member’s approval, according to the policy on your workspace.

Plan for it: add your first beneficiaries on go-live day, before you need them, so the cooling-off has elapsed by the time your first real withdrawal is due.

This differs from the Sandbox on purpose. Sandbox keys are not granted withdrawal scopes, precisely so that you do not learn a withdrawal flow that has no allowlist to satisfy and then meet these controls for the first time in production.

A checklist worth walking through once, seriously, before real money flows:

  • Branch on code, never on error text. The message wording can change; the code is the contract. See Error codes.
  • Credit on DEPOSIT_CONFIRMED only, and read required_confirmations off the deposit instead of hard-coding a threshold.
  • Verify every webhook signature and deduplicate on the delivery id, which is stable across retries. Recipe and contract in Webhooks.
  • Send an Idempotency-Key on mutating POSTs, so a network timeout never turns into a double action.
  • Guard the live secret. Store it in your secret manager, never in code or logs; consider the key’s optional IP allowlist and expiry.
  • Test your production webhook endpoint end to end before the first customer does it for you.
  • The base URL is the same. There is no separate live host.
  • The signing recipe is identical.
  • operationId values, and therefore your SDK method names, are unchanged.
  • The network is taken from the key: cpk_test_ is testnet, cpk_live_ is mainnet. You do not send it.