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

# Changelog

> New features, improvements, and changes to the Chataigne API and Admin API.

The Chataigne API is versioned by a major version in the path (`/v1`, `/admin/v1`). Additive changes — new endpoints, new optional fields, new resource types — are 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.

<Note>
  Watch this page for new releases. Each entry is dated and labeled with the surfaces it affects: the public **Chataigne API** (`/v1`) and the **Admin API** (`/admin/v1`).
</Note>

<Update label="2026-05-01" tags={["v1", "admin/v1"]}>
  ## Initial release

  The first public release of the Chataigne API. This launch ships two API surfaces and the **Location & Organization Management** resource family, along with the platform conventions every endpoint shares.

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

  ### Two surfaces

  | 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 curl theme={null}
    curl https://server.chataigne.ai/v1/organizations \
      -H "x-api-key: ch_org_..."
    ```

    ```javascript Node.js theme={null}
    const res = await fetch("https://server.chataigne.ai/v1/organizations", {
      headers: { "x-api-key": process.env.CHATAIGNE_API_KEY },
    });
    const organizations = await res.json();
    ```
  </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>

  ### Location & Organization Management

  Three core resources and a set of per-location settings sub-resources are available at launch. Every resource carries `id` (opaque, prefixed), `object`, `created_at`, and `updated_at` (ISO 8601 UTC), and all field names use `snake_case`.

  <CardGroup cols={3}>
    <Card title="Organizations" icon="building" href="/location-organization-management/organizations">
      `org_…` — `name`, `location_ids`, `active_location_ids`. Expandable: `locations`.
    </Card>

    <Card title="Locations" icon="store" href="/location-organization-management/locations">
      `loc_…` — `name`, `currency`, `country`, `timezone`, `default_language`, `address`.
    </Card>

    <Card title="Special closings" icon="calendar-xmark" href="/location-organization-management/special-closings">
      `scl_…` — `location_id`, `starts_at`, `ends_at`, `reason`.
    </Card>
  </CardGroup>

  Each location also exposes five independently readable and updatable settings objects: `order_settings`, `opening_hours`, `delivery_settings`, `acceptance_settings`, and `ai_instructions`.

  #### Public endpoints — `/v1`

  | Resource               | Endpoints                                                                                                                                                 |
  | ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
  | Organizations          | `GET` / `PATCH /v1/organizations`, `GET /v1/organizations/{organization_id}`                                                                              |
  | Organization locations | `GET` / `POST /v1/organizations/{organization_id}/locations`                                                                                              |
  | Locations              | `GET` / `PATCH /v1/locations`, `GET /v1/locations/{location_id}`                                                                                          |
  | Order settings         | `GET` / `PATCH /v1/locations/{location_id}/order_settings`                                                                                                |
  | Opening hours          | `GET` / `PUT /v1/locations/{location_id}/opening_hours`                                                                                                   |
  | Delivery settings      | `GET` / `PATCH /v1/locations/{location_id}/delivery_settings`                                                                                             |
  | Acceptance settings    | `GET` / `PATCH /v1/locations/{location_id}/acceptance_settings`                                                                                           |
  | AI instructions        | `GET` / `PATCH /v1/locations/{location_id}/ai_instructions`                                                                                               |
  | Special closings       | `GET` / `POST /v1/locations/{location_id}/special_closings`, `GET` / `PATCH` / `DELETE /v1/locations/{location_id}/special_closings/{special_closing_id}` |

  #### Admin endpoints — `/admin/v1`

  | Resource               | Endpoints                                                                                         |
  | ---------------------- | ------------------------------------------------------------------------------------------------- |
  | Organizations          | `GET` / `POST /admin/v1/organizations`, `GET` / `PATCH /admin/v1/organizations/{organization_id}` |
  | Organization locations | `GET` / `POST /admin/v1/organizations/{organization_id}/locations`                                |
  | Locations              | `GET` / `POST /admin/v1/locations`, `GET` / `PATCH /admin/v1/locations/{location_id}`             |

  #### Provision an organization and a location

  <CodeGroup>
    ```bash curl theme={null}
    # 1. Create an organization (Admin API)
    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"}'

    # 2. Add a location to it
    curl https://server.chataigne.ai/admin/v1/organizations/org_4b7e2f10/locations \
      -H "x-api-key: ch_admin_..." \
      -H "Idempotency-Key: 9a2c4e10-8b71-4f3d-a0c5-1e6f2b7d4c88" \
      -H "Content-Type: application/json" \
      -d '{
        "name": "Pizzeria Centrale — Genève",
        "currency": "CHF",
        "country": "CH",
        "timezone": "Europe/Zurich",
        "default_language": "fr"
      }'
    ```

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

    const headers = {
      "x-api-key": process.env.CHATAIGNE_ADMIN_KEY,
      "Content-Type": "application/json",
    };

    // 1. Create an organization
    const orgRes = await fetch("https://server.chataigne.ai/admin/v1/organizations", {
      method: "POST",
      headers: { ...headers, "Idempotency-Key": randomUUID() },
      body: JSON.stringify({ name: "Pizzeria Centrale" }),
    });
    const organization = await orgRes.json();

    // 2. Add a location to it
    const locRes = await fetch(
      `https://server.chataigne.ai/admin/v1/organizations/${organization.id}/locations`,
      {
        method: "POST",
        headers: { ...headers, "Idempotency-Key": randomUUID() },
        body: JSON.stringify({
          name: "Pizzeria Centrale — Genève",
          currency: "CHF",
          country: "CH",
          timezone: "Europe/Zurich",
          default_language: "fr",
        }),
      }
    );
    const location = await locRes.json();
    ```
  </CodeGroup>

  ```json An organization with an expanded location theme={null}
  {
    "id": "org_4b7e2f10",
    "object": "organization",
    "name": "Pizzeria Centrale",
    "location_ids": ["loc_8f2c1a9d"],
    "active_location_ids": ["loc_8f2c1a9d"],
    "created_at": "2026-05-01T08:00:00Z",
    "updated_at": "2026-05-01T08:05:42Z"
  }
  ```

  ### Platform conventions

  Every endpoint shares the same building blocks from day one.

  <ResponseField name="Cursor pagination" type="lists">
    List endpoints return a `list` object — `{ "object": "list", "data": [...], "has_more": bool, "url": "/v1/..." }` — paginated with `limit` (`1`–`100`, default `10`), `starting_after`, and `ending_before` (the cursor params are mutually exclusive). Lists are ordered by `created_at` by default.
  </ResponseField>

  <ResponseField name="Timestamp filters" type="lists">
    Filter any list with `created_after`, `created_before`, `updated_after`, and `updated_before` (ISO 8601).
  </ResponseField>

  <ResponseField name="Expansion" type="query">
    Inline referenced objects with `expand[]`. For example, `GET /v1/organizations/org_4b7e2f10?expand[]=locations` returns full `location` objects instead of ids.
  </ResponseField>

  <ResponseField name="Idempotency" type="header">
    Resource-creating `POST`s require an `Idempotency-Key` header. Replaying the same key with the same body returns the original response with `Idempotent-Replayed: true`. The same key with a different body returns `409 idempotency_error`; a concurrent in-flight duplicate returns `409 conflict_error`. Keys are retained for **24 hours**.
  </ResponseField>

  <ResponseField name="Request IDs" type="header">
    Every response carries `X-Request-Id`; error bodies mirror it as `error.request_id`. Echo your own correlation id through the `x-request-id` request header.
  </ResponseField>

  <ResponseField name="Rate limits" type="header">
    Applied per key and per surface. Responses include `X-RateLimit-Limit`, `X-RateLimit-Remaining`, and `X-RateLimit-Reset`; a `429 rate_limit_error` adds `Retry-After`.
  </ResponseField>

  #### Error model

  All errors return a standard HTTP status with a structured `error` body.

  ```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"
    }
  }
  ```

  | `error.type`            | HTTP status |
  | ----------------------- | ----------- |
  | `invalid_request_error` | 400         |
  | `authentication_error`  | 401         |
  | `authorization_error`   | 403         |
  | `not_found_error`       | 404         |
  | `conflict_error`        | 409         |
  | `idempotency_error`     | 409         |
  | `rate_limit_error`      | 429         |
  | `api_error`             | 500         |
</Update>
