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

# Raw HTTP

> Use the API without an SDK: headers, the four calls, and everything the SDK would otherwise handle for you, so you can implement it in any language.

The API is four JSON endpoints under `https://api.trycurious.ai/v1`; every SDK behaviour is documented, so calling them directly is a first-class choice. The full field reference is the [API reference](https://docs.trycurious.ai/api-reference/overview.md).

## Every request

```http theme={null}
POST /v1/decide HTTP/1.1
Host: api.trycurious.ai
Authorization: Bearer curious_sk_test_…
Content-Type: application/json
```

Every response carries `X-Request-Id`; keep it in your logs. Errors are always `{ "error": "<code>", "message": "<text>" }`; see [Errors](https://docs.trycurious.ai/api-reference/errors.md).

## The four calls

```bash decide theme={null}
curl https://api.trycurious.ai/v1/decide \
  -H "Authorization: Bearer $CURIOUS_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "element": "welcome_email_subject",
    "user_id": "user_123",
    "control": "Welcome to Acme",
    "rewards": [
      { "name": "email_clicked", "window_seconds": 86400 }
    ],
    "idempotency_key": "9c1d2e3f-0b7a-4c2d-8e1f-3a4b5c6d7e8f"
  }'
```

```bash declare theme={null}
curl https://api.trycurious.ai/v1/declare \
  -H "Authorization: Bearer $CURIOUS_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "element": "pricing_hero",
    "control": "Ship better experiments",
    "rewards": [
      { "name": "signed_up", "window_seconds": 604800 }
    ]
  }'
```

```bash events theme={null}
curl https://api.trycurious.ai/v1/events \
  -H "Authorization: Bearer $CURIOUS_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "user_id": "user_123",
    "name": "email_clicked",
    "id": "evt_8f3a",
    "timestamp": "2026-04-30T22:33:42Z"
  }'
```

```bash identify theme={null}
curl https://api.trycurious.ai/v1/identify \
  -H "Authorization: Bearer $CURIOUS_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "anonymous_id": "anon_456",
    "user_id": "user_123",
    "identifiers": { "email": "alice@example.com" },
    "attributes": { "plan": "pro" }
  }'
```

## What to build around the calls

These are the behaviours the server SDK implements; do the same in your client.

* **A deadline and a fallback on `decide`.** Set a client timeout (the SDK's default is 1.5 seconds) and render your own content when it passes or on any non-200. Do not retry a `decide`: a retry creates a second decision that ends the first's window. If you must retry, send the same `idempotency_key` so the retry replays rather than re-decides. See [Fallbacks and timeouts](https://docs.trycurious.ai/guides/fallbacks.md).
* **Stable `id`s on events, and retries only under them.** Generate the `id` before the first attempt. Retry network failures, `408`, `429` (after `Retry-After`) and `5xx` with exponential backoff; do not retry other `4xx`. See [Idempotency](https://docs.trycurious.ai/api-reference/idempotency.md).
* **Batch events** (up to 200 per request) rather than sending one request per event; handle per-item results, since one bad item never fails the others. See [Batch calls](https://docs.trycurious.ai/guides/batch.md).
* **Treat `502` and dropped connections as ambiguous.** The origin may have committed; retry only with the same keys.
* **Send `identify` immediately and await it** before a decision that should see the merged profile. See [Identify users](https://docs.trycurious.ai/guides/identify.md).
* **Keep secret keys on servers.** A browser gets a publishable key, which can decide against declared elements and report events, and nothing else. See [Keys and environments](https://docs.trycurious.ai/guides/keys.md).
* **Never log a request body or a key.** Log the `X-Request-Id`, the status and the `error` code.

## Regions

The API is served from one region today and routes requests there without any header from you. There is nothing to configure.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.