# Overview

Kaito provides **API-based connectivity** as a **payment rail** to move value across regions and rails:

- **FIAT <-> FIAT**
- **FIAT <-> CRYPTO**
- **CRYPTO <-> FIAT**
- **CRYPTO <-> CRYPTO**


You integrate once with the Kaito API, and Kaito handles routing, provider selection, fallbacks, and settlement orchestration (where applicable).

## Supported stablecoins

Kaito currently operates with the following stablecoins:

- **USDC** (USD Coin)
- **USDT** (Tether)


Kaito currently prefers to operate with these stablecoins for FIAT_CRYPTO and CRYPTO_FIAT flows.

## Key concepts

- **railType**: declares the flow type (FIAT_FIAT, FIAT_CRYPTO, CRYPTO_FIAT, CRYPTO_CRYPTO).
- **Quote**: locks pricing and routing for a short time window.
- **Execution plan**: optional multi-step plan derived from a quote.
- **Payment / Payout**:
  - **Payment**: typically used for CRYPTO_CRYPTO or FIAT_CRYPTO flows.
  - **Payout (off-ramp)**: used for CRYPTO_FIAT or FIAT_FIAT flows.
- **Webhooks**: receive asynchronous updates for state changes.
- **Idempotency-Key**: UUID v4 header to safely retry any POST request without risk of duplicate operations. Send on every POST. Window: 24 hours. Returns the original response on duplicate key + same payload; returns `409 Conflict` on duplicate key + different payload.
- **x-kaito-trace-id**: required for support and troubleshooting.


## Security model

All requests to the Kaito API must be made over **HTTPS**. Plain HTTP is rejected.

### Request authentication (Rail M2M)

The Rail M2M API is machine-to-machine. There is **no Bearer/JWT**. Each request carries an api-key identifier plus a per-request HMAC signature.

Every Rail M2M request must include all of the following headers:

| Header | Description |
|  --- | --- |
| `x-kaito-api-key` | Public Rail API key identifier (`rk_test_…` / `rk_live_…`). Identifies the calling client. |
| `x-kaito-timestamp` | Unix timestamp (seconds or milliseconds). Must be within ±300s of server time. |
| `x-kaito-trace-id` | Caller-generated correlation id. Echoed in the response header. |
| `x-kaito-signature` | Hex HMAC-SHA256 of the canonical request, signed with the per-key secret. |
| `x-kaito-content` | Hex SHA-256 of the raw request body. Required for `POST`/`PATCH`; optional for `GET`/`DELETE`. |


The secret never leaves the partner's side. The api-key is the public identifier the server uses to look up the secret (KMS-encrypted in our DynamoDB) and recompute the signature.

### Canonical signature

```text
<x-kaito-timestamp>.<HTTP_METHOD>.<rawPath>.<rawQueryString>.<x-kaito-trace-id>.<contentSha256>
```

- `rawPath` is the API Gateway path **after** the `/v1` mapping key is stripped — e.g. signing `POST /v1/quotes` uses `rawPath = "/quotes"`.
- `contentSha256` for an empty body is the SHA-256 of the empty string (`e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855`).


The signature is hex HMAC-SHA256 of the canonical string with the per-key secret. See [Kaito as a Payment Rail](/docs/10-payment-rail#authentication) for the full reference and a runnable Node.js example.

### Webhook signatures (outbound)

When Kaito sends events to your endpoint, each request includes:

| Header | Description |
|  --- | --- |
| `Kaito-Timestamp` | Unix epoch seconds of delivery time. |
| `Kaito-Signature` | `sha256=<hex>` — HMAC-SHA256 of `"{timestamp}.{raw_body}"` signed with your webhook secret. |


Verify the signature on your side to ensure the event originated from Kaito.