> ## Documentation Index
> Fetch the complete documentation index at: https://docs.caratuva.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Authentication

> API keys, bearer tokens, idempotency, and per-organization tenancy.

The Caratuva API supports two authentication schemes:

| 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.                          |

For B2B integrators, the API key is the credential you'll use everywhere. JWTs are issued to the dashboard frontend and are not directly relevant to server-to-server integrations.

## API keys

An API key has the wire format:

```
pk_<mode>_<id>.<secret>
```

* `<mode>` is `test` or `live`.
* `<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.

See [API keys](/api-reference/api-keys) for issuance, listing, revocation, scopes, and rotation.

## Tenancy

Every authenticated request resolves to an organization derived from the credential — the JWT's `orgId` 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.

```
Idempotency-Key: <a fresh UUID per logical operation>
```

Behavior:

* 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 returns `409 IdempotencyKeyConflict` — use a fresh key.

Always send an idempotency key on retries — network errors and transient 5xxs happen, and the safe pattern is "send again with the same key".

## Test vs. live mode

API keys with the `pk_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](/api-reference/environments) for how mode is carried on each request.

Use test mode for:

* Local development.
* CI / integration tests.
* Staging environments.
* Demos.

Test mode and live mode are fully isolated. Test invoices, test buyers, test webhook deliveries are stored in a separate dataset; they never appear in the live mode dashboard or vice versa.

`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 on `pay.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 are `application/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-Key` header is safe to log and useful for tracing.
* Do not log `Authorization: Bearer <jwt>` headers — JWTs are short-lived but still secret-bearing.
