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

# Introduction

> A resource-oriented, JSON-over-HTTPS API for managing restaurant organizations, locations, and their settings.

The Chataigne API is organized around REST. It has predictable, resource-oriented URLs, accepts and returns [JSON-encoded](https://www.json.org/json-en.html) bodies, and uses standard HTTP response codes, authentication, and verbs. You can use it to manage your restaurant organizations, their locations, and every setting that drives ordering, delivery, opening hours, and the AI clerk.

```text Base URL theme={null}
https://server.chataigne.ai
```

All requests must be made over HTTPS. Calls made over plain HTTP will fail. Requests without authentication will also fail.

<CardGroup cols={2}>
  <Card title="Quickstart" icon="rocket" href="/quickstart">
    Make your first authenticated request in under five minutes.
  </Card>

  <Card title="Authentication" icon="key" href="/concepts/authentication">
    API keys, surfaces, and the `x-api-key` header.
  </Card>
</CardGroup>

## The two surfaces

Chataigne exposes two distinct API surfaces. Each surface has its own base path, its own key type, and its own access boundary. A key issued for one surface is rejected on the other.

| Surface           | Base path   | Key prefix  | Use it to                                                                 |
| ----------------- | ----------- | ----------- | ------------------------------------------------------------------------- |
| **Chataigne API** | `/v1`       | `ch_org_`   | Read and manage a single organization, its locations, and their settings. |
| **Admin API**     | `/admin/v1` | `ch_admin_` | Provision new organizations and locations across your account.            |

Both surfaces authenticate with the `x-api-key` HTTP header.

<CodeGroup>
  ```bash Chataigne API (/v1) theme={null}
  curl https://server.chataigne.ai/v1/organizations \
    -H "x-api-key: ch_org_..."
  ```

  ```bash Admin API (/admin/v1) theme={null}
  curl https://server.chataigne.ai/admin/v1/organizations \
    -H "x-api-key: ch_admin_..."
  ```
</CodeGroup>

<Warning>
  Surfaces are strictly isolated. Sending an admin key (`ch_admin_…`) to `/v1`, or an organization key (`ch_org_…`) to `/admin/v1`, returns `403 authorization_error`. A missing key returns `401 authentication_error`. A dashboard session cannot be used on either surface — only API keys are accepted.
</Warning>

## Resources

Every object returned by the API is a typed resource. Resources share a common shape:

<ResponseField name="id" type="string">
  An opaque, prefixed identifier (for example `org_…`, `loc_…`, `scl_…`). Treat ids as case-sensitive strings — never parse meaning from them.
</ResponseField>

<ResponseField name="object" type="string">
  A string describing the resource type, such as `organization`, `location`, or `special_closing`.
</ResponseField>

<ResponseField name="created_at" type="string">
  ISO 8601 UTC timestamp marking when the resource was created.
</ResponseField>

<ResponseField name="updated_at" type="string">
  ISO 8601 UTC timestamp marking when the resource was last modified.
</ResponseField>

All field names use `snake_case`.

### Core resources

* **`organization`** — `id` (`org_…`), `name`, `location_ids`, `active_location_ids`. Expandable: `locations`.
* **`location`** — `id` (`loc_…`), `organization_id`, `name`, `currency`, `country`, `timezone`, `default_language`, `address`.
* **`special_closing`** — `id` (`scl_…`), `location_id`, `starts_at`, `ends_at`, `reason`.

### Settings sub-resources

Each location carries a set of settings objects you can read and update independently: `order_settings`, `opening_hours`, `delivery_settings`, `acceptance_settings`, and `ai_instructions`.

```json A location with its address theme={null}
{
  "id": "loc_8f2c1a9d",
  "object": "location",
  "organization_id": "org_4b7e2f10",
  "name": "Pizzeria Centrale",
  "currency": "CHF",
  "country": "CH",
  "timezone": "Europe/Zurich",
  "default_language": "fr",
  "address": {
    "line1": "Rue du Marché 12",
    "line2": null,
    "postal_code": "1204",
    "city": "Genève",
    "country": "CH",
    "latitude": 46.2044,
    "longitude": 6.1432
  },
  "created_at": "2026-01-14T09:30:00Z",
  "updated_at": "2026-05-02T16:45:12Z"
}
```

## Lists and pagination

List endpoints return a `list` object with cursor-based pagination. The `data` array holds the resources, `has_more` indicates whether further pages exist, and `url` echoes the request path.

```json theme={null}
{
  "object": "list",
  "data": [
    { "id": "loc_8f2c1a9d", "object": "location", "name": "Pizzeria Centrale" }
  ],
  "has_more": true,
  "url": "/v1/locations"
}
```

Paginate with the following query parameters:

<ParamField query="limit" type="integer" default="10">
  Number of objects to return, between `1` and `100`.
</ParamField>

<ParamField query="starting_after" type="string">
  A resource id that defines your place in the list. Returns objects created after this id. Mutually exclusive with `ending_before`.
</ParamField>

<ParamField query="ending_before" type="string">
  A resource id that defines your place in the list. Returns objects created before this id. Mutually exclusive with `starting_after`.
</ParamField>

You can also filter lists by timestamp with `created_after`, `created_before`, `updated_after`, and `updated_before` (ISO 8601). Lists are ordered by `created_at` by default.

## Expanding responses

Some resources reference others by id. Use `expand[]` to inline the full object in the response instead of just its id.

<CodeGroup>
  ```bash curl theme={null}
  curl "https://server.chataigne.ai/v1/organizations/org_4b7e2f10?expand[]=locations" \
    -H "x-api-key: ch_org_..."
  ```

  ```javascript Node.js theme={null}
  const res = await fetch(
    "https://server.chataigne.ai/v1/organizations/org_4b7e2f10?expand[]=locations",
    { headers: { "x-api-key": process.env.CHATAIGNE_API_KEY } }
  );
  const organization = await res.json();
  ```
</CodeGroup>

With `expand[]=locations`, the organization's `locations` field is returned as an array of full `location` objects rather than ids.

## Errors

Chataigne uses conventional HTTP status codes to indicate the success or failure of a request. Error responses include a structured `error` object.

```json theme={null}
{
  "error": {
    "type": "invalid_request_error",
    "code": "parameter_invalid",
    "message": "currency must be one of CHF, EUR, GBP, BRL, USD, MXN.",
    "param": "currency",
    "request_id": "req_9c4a1e22"
  }
}
```

| Type                    | HTTP status | Meaning                                                                             |
| ----------------------- | ----------- | ----------------------------------------------------------------------------------- |
| `invalid_request_error` | 400         | The request was malformed or a parameter was invalid.                               |
| `authentication_error`  | 401         | No valid API key was provided.                                                      |
| `authorization_error`   | 403         | The key is valid but not permitted on this surface or resource.                     |
| `not_found_error`       | 404         | The requested resource does not exist.                                              |
| `conflict_error`        | 409         | The request conflicts with the current state (for example, a concurrent duplicate). |
| `idempotency_error`     | 409         | An idempotency key was reused with a different request body.                        |
| `rate_limit_error`      | 429         | Too many requests were sent in a given window.                                      |
| `api_error`             | 500         | Something went wrong on Chataigne's end.                                            |

## Idempotency

The API supports [idempotency](/concepts/idempotency) for safely retrying requests without accidentally performing the same operation twice. Send an `Idempotency-Key` header on resource-creating `POST` requests — it is required.

<CodeGroup>
  ```bash curl theme={null}
  curl https://server.chataigne.ai/admin/v1/organizations \
    -H "x-api-key: ch_admin_..." \
    -H "Idempotency-Key: 6f1d3b8a-2c47-4e90-9a1b-0d2f7c5e1234" \
    -H "Content-Type: application/json" \
    -d '{"name": "Pizzeria Centrale"}'
  ```

  ```javascript Node.js theme={null}
  import { randomUUID } from "node:crypto";

  const res = await fetch("https://server.chataigne.ai/admin/v1/organizations", {
    method: "POST",
    headers: {
      "x-api-key": process.env.CHATAIGNE_ADMIN_KEY,
      "Idempotency-Key": randomUUID(),
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ name: "Pizzeria Centrale" }),
  });
  const organization = await res.json();
  ```
</CodeGroup>

<Note>
  Replaying the same key with the same body returns the original response, with the header `Idempotent-Replayed: true`. Replaying a key with a **different** body returns `409 idempotency_error`. A concurrent in-flight duplicate returns `409 conflict_error`. Keys are retained for **24 hours**.
</Note>

## Request IDs

Every response carries an `X-Request-Id` header. Error bodies mirror it as `error.request_id`. Log this value — it lets the Chataigne team trace any individual request. You can also supply your own correlation id by echoing it back through the `x-request-id` request header.

## Rate limits

Rate limits are applied per key and per surface. The public `/v1` limit is currently **1000 requests per 60 seconds**. Every response includes the current limit state:

| Header                  | Description                                     |
| ----------------------- | ----------------------------------------------- |
| `X-RateLimit-Limit`     | Maximum requests allowed in the current window. |
| `X-RateLimit-Remaining` | Requests remaining in the current window.       |
| `X-RateLimit-Reset`     | When the current window resets.                 |

When you exceed your limit, the API returns `429 rate_limit_error` with a `Retry-After` header indicating how long to wait before retrying.

## Versioning

The API is versioned by a major version in the path (`/v1`). Additive changes — new endpoints, new optional fields, new resource types — are considered non-breaking and ship within the current major version. Breaking changes are released under a new major version, so your integration keeps working as we evolve the platform.

## Next steps

<CardGroup cols={2}>
  <Card title="Quickstart" icon="rocket" href="/quickstart">
    Authenticate and fetch your first organization.
  </Card>

  <Card title="Authentication" icon="key" href="/concepts/authentication">
    Manage API keys and understand surface isolation.
  </Card>
</CardGroup>
