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

# Chipper Platform API Reference

> Base URLs, authentication, versioning, pagination, and error shapes for the Chipper Platform API.

The Chipper Platform API is a REST API that accepts JSON bodies and returns JSON responses. It runs as two fully separate stacks: **sandbox** for integration and testing, and **production** for real money.

## Base URLs

| Stack          | Base URL                                  |
| -------------- | ----------------------------------------- |
| **Sandbox**    | `https://sandbox-api.platform.chipper.ai` |
| **Production** | `https://api.platform.chipper.ai`         |

A `sk_test_…` key only works against sandbox; a `sk_live_…` key only works against production. Using the wrong pair returns `401`.

## Authentication

Every request carries your API key in the `Authorization` header:

```bash theme={null}
Authorization: Bearer sk_test_...
```

Keys are created in the dashboard under **Developers → API keys** and shown once at creation. See [Authentication](/authentication) for scopes, IP allowlists, and spend caps.

## API versioning

Send the `chipper-version` header with the current version date:

```text theme={null}
chipper-version: 2026-02-20
```

The version is echoed back on every response. Omitting it uses the current version. Breaking changes ship under a new version date; additive changes (new fields, new endpoints) do not require a version bump and the old version keeps working.

## Pagination

All list endpoints accept `limit` (1–100, default 20) and `cursor`. Results are newest first.

```json theme={null}
{
  "data": [ ... ],
  "hasMore": true,
  "nextCursor": "pay_ghs_..."
}
```

Pass `nextCursor` as `cursor` on the next request to walk forward. `nextCursor` is `null` on the last page. Cursors are opaque strings — do not construct them.

## Response envelopes

Single resources are wrapped in a key named after the resource:

```json theme={null}
{ "payout": { "id": "pay_ghs_...", "status": "completed", ... } }
```

Lists use the shape above with a `data` array.

## Errors

Every error uses the same shape:

```json theme={null}
{
  "error": "insufficient_funds",
  "message": "Insufficient funds",
  "details": { "available": "120.00", "required": "150.00", "currency": "GHS" },
  "requestId": "req_q7vei435zifs51ia0lqr"
}
```

`error` is a stable machine-readable code to branch on. `requestId` matches the `x-request-id` response header — include it when contacting support. See [Errors](/concepts/errors) for the full code reference.

## Rate limits

**100 requests per second per API key**, sliding window. Exceeding the limit returns `429 rate_limited` with `details.retryAfter`. For bulk operations, use `POST /v1/recipients/bulk` and `POST /v1/validate/bulk` (up to 100 items each).

## Money

All amounts in responses are decimal strings (`"150.00"`), never floats. Parse with a decimal library when doing arithmetic. See [Money & Currencies](/concepts/money) for currency codes and zero-decimal currencies.

## Idempotency

Money-moving endpoints (`payouts`, `collections`, `orders`, `conversions`) accept an `externalReference` — your unique string for the operation. Retrying with the same value returns the original resource (`200` instead of `201`) and never creates a duplicate. See [Idempotency](/concepts/idempotency).
