Skip to main content
Caratuva has a single API host. There is no separate sandbox URL. Instead, every request runs in test or live mode, and the mode is determined entirely by the credential you present. See the guide-side Test & live modes page for the conceptual overview; this page covers the request-level details.

Mode is carried by the key

API keys encode their mode in the prefix:
PrefixModeRails
pk_test_…testSandbox payment instance — KYB/KYC auto-approve, no real money.
pk_live_…liveProduction payment instance — real rails, real settlement.
A test key can only ever read and write test data; a live key, only live data. You don’t pass a mode parameter and you can’t override it with a header — the key is the mode. Issue one key per mode (see API keys). The API-key resource reports its mode via the testMode boolean, derived from the prefix:
{
  "keyPrefix": "pk_test_KEY_ID",
  "testMode": true
}

Dashboard sessions switch; keys don’t

Dashboard Bearer JWTs also carry a mode, and start in test. The dashboard re-mints the token to switch:
curl -X POST https://api.caratuva.com/v1/auth/switch-mode \
  -H "Authorization: Bearer <dashboard-jwt>" \
  -H "content-type: application/json" \
  -d '{ "mode": "live" }'
{ "token": "<new-jwt-bound-to-live>", "mode": "live" }
The new token is bound to the chosen mode; the dashboard stores it and uses it for subsequent requests. Switching to live requires the organization’s Production Access Request to have been approved by Caratuva (a manual approval, distinct from KYB); otherwise the call returns 400 ProductionAccessNotApproved. Live KYB is completed afterwards, on the Payout page, before the org can transact. API-key callers cannot use this endpoint — they already carry their mode in the key prefix. Calling it with an API key returns:
{
  "statusCode": 400,
  "error": "ModeSwitchNotAllowed",
  "message": "API-key callers select mode via their key prefix, not switch-mode."
}

Data isolation

Test and live are separate datasets. The same scoping that isolates one organization from another (see Authentication → Tenancy) also isolates test from live within your organization:
  • Invoices and payment intents are tagged with the mode they were created in; list and read endpoints only return the active mode’s records.
  • Buyers are scoped per mode — the same buyer email is a distinct record in test and in live, and KYC completed in one does not carry to the other.
  • Webhook deliveries reflect only the mode of the invoice that generated them.

Onboarding status

To check whether the caller’s active mode is ready to transact:
curl https://api.caratuva.com/v1/onboarding/status \
  -H "Authorization: Bearer <dashboard-jwt>"
{
  "mode": "live",
  "needsOnboarding": true,
  "tosAccepted": false,
  "kybStatus": null
}
  • mode — the active mode of the credential.
  • needsOnboardingtrue until this mode’s environment is activated. Test activates as soon as its sandbox KYB clears (auto-approved); live activates only on real KYB approval (after production access has been granted).
  • tosAccepted — whether the payment-provider Terms have been accepted for this mode.
  • kybStatus — the latest KYB submission status for this mode, or null if none has been started.

Behavior parity

Test mode runs the same code path as live against a sandbox payment instance — the same intent transitions, the same webhook event types, the same response shapes. The only differences are that the sandbox auto-approves compliance and never moves real funds. Build and test against pk_test_, then flip to pk_live_ for production.