| Scheme | Header | Used by |
|---|---|---|
| API key | X-API-Key: pk_<mode>_<id>.<secret> | Server-to-server clients on the seller side. |
| Bearer JWT | Authorization: Bearer <jwt> | Dashboard sessions. |
API keys
An API key has the wire format:<mode>istestorlive.<id>is the public lookup half — safe to log.<secret>is shown exactly once at creation. Caratuva stores only a hash; the plaintext cannot be recovered. If you lose it, revoke the key and create a new one.
Tenancy
Every authenticated request resolves to an organization derived from the credential — the JWT’sorgId claim or the API key’s owning organization. There is no header-based override; tenancy is always carried by the credential.
This means:
- An API key can never act on behalf of a different organization, regardless of headers.
- A leaked API key affects exactly one organization, and you can revoke it without touching any other.
- All read endpoints automatically scope to your organization. You can never list or fetch another organization’s data.
Idempotency
Resource-creating endpoints (POST /v1/invoices and POST /v1/payment-intents) accept an Idempotency-Key header. The recommended value is a fresh UUID per logical operation.
- The first create with a given key creates the resource.
- A replay with the same key returns the existing resource, re-serialized from storage — so the payload reflects the resource’s current state (not a byte-for-byte copy of the original response), and no side effects run twice.
- The match is on the key alone — the request body is not compared. A replay with the same key but a different body still returns the original resource; the new body is ignored. Use a fresh key whenever you intend to create a different resource.
- Idempotency is keyed per
(organization, key)on the created resource and has no expiry — replays stay idempotent for the lifetime of that resource. - If a key is already bound to a resource created through a different path (e.g. a dashboard invoice when you
POST /v1/payment-intents), the API returns409 IdempotencyKeyConflict— use a fresh key.
Test vs. live mode
API keys with thepk_test_ prefix are recognized as test-mode credentials. Test mode runs the entire flow end-to-end — KYC, payment collection, FX, settlement, webhooks — against a sandbox payment instance. KYB and buyer KYC auto-approve, and no real money moves. See Environments for how mode is carried on each request.
Use test mode for:
- Local development.
- CI / integration tests.
- Staging environments.
- Demos.
pk_live_* keys hit the real rails. Never use them outside production.
CORS
The API accepts cross-origin browser requests only from Caratuva’s own allowlisted web origins (the dashboard, the hosted buyer portal, and the marketing site); it is not open to arbitrary browser origins. Your B2B integration must call the API server-to-server — never embed an API key in browser code. Buyer-side flows go through the hosted payment page onpay.caratuva.com, not your own browser code.
Time
The API returns timestamps in RFC 3339 / ISO 8601 with explicit timezone (2026-05-02T14:00:00.000Z). Always send timestamps with timezone information; bare local times will be rejected.
Content type
Requests and responses areapplication/json. The API rejects requests without Content-Type: application/json on mutating endpoints.
Logging tips
- The
<id>half of an API key is safe to log; the<secret>half is not. - The
Idempotency-Keyheader is safe to log and useful for tracing. - Do not log
Authorization: Bearer <jwt>headers — JWTs are short-lived but still secret-bearing.