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

# Organizations

> Manage organizations and their locations via the Chataigne API: list, retrieve, update, and create locations.

An **organization** is the top-level account object. It owns one or more [locations](/location-organization-management/locations) (restaurants) and is the entity your API key is scoped to.

<Note>
  Every API key (prefix `ch_org_`) is bound to exactly one organization. Endpoints under `/v1/organizations` therefore operate on **your** organization. The Admin API (`/admin/v1`, keys prefixed `ch_admin_`) can manage organizations across accounts.
</Note>

## The organization object

<ResponseField name="id" type="string">
  Unique identifier, prefixed `org_`.
</ResponseField>

<ResponseField name="object" type="string">
  Always `organization`.
</ResponseField>

<ResponseField name="name" type="string">
  Human-readable name of the organization.
</ResponseField>

<ResponseField name="location_ids" type="string[]">
  All location IDs (`loc_…`) belonging to this organization.
</ResponseField>

<ResponseField name="active_location_ids" type="string[]">
  Subset of `location_ids` that are currently active.
</ResponseField>

<ResponseField name="created_at" type="string">
  ISO 8601 UTC timestamp of creation.
</ResponseField>

<ResponseField name="updated_at" type="string">
  ISO 8601 UTC timestamp of the last update.
</ResponseField>

<ResponseField name="locations" type="location[]" optional>
  The expanded [location](/location-organization-management/locations) objects. Returned only when you request `expand[]=locations`.
</ResponseField>

```json The organization object theme={null}
{
  "id": "org_8f2k1d9a",
  "object": "organization",
  "name": "Trattoria Group",
  "location_ids": ["loc_7c3b1e", "loc_9a4f2d"],
  "active_location_ids": ["loc_7c3b1e"],
  "created_at": "2025-01-12T09:30:00Z",
  "updated_at": "2025-04-03T14:22:10Z"
}
```

### Expanding locations

Pass `expand[]=locations` on retrieve endpoints to inline full location objects under the `locations` field instead of receiving only `location_ids`.

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

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

***

## List organizations

```
GET /v1/organizations
```

Returns organizations accessible to your API key. With an organization key this list contains the single organization the key is scoped to.

**Auth:** organization API key (`ch_org_…`). Admin keys are rejected with `403`.

### Query parameters

<ParamField query="limit" type="integer" default="10">
  Page size, between `1` and `100`.
</ParamField>

<ParamField query="starting_after" type="string">
  Cursor: return results after this object ID. Mutually exclusive with `ending_before`.
</ParamField>

<ParamField query="ending_before" type="string">
  Cursor: return results before this object ID. Mutually exclusive with `starting_after`.
</ParamField>

<ParamField query="created_after" type="string">
  Only return organizations created at or after this ISO 8601 timestamp.
</ParamField>

<ParamField query="created_before" type="string">
  Only return organizations created at or before this ISO 8601 timestamp.
</ParamField>

<ParamField query="updated_after" type="string">
  Only return organizations updated at or after this ISO 8601 timestamp.
</ParamField>

<ParamField query="updated_before" type="string">
  Only return organizations updated at or before this ISO 8601 timestamp.
</ParamField>

<ParamField query="expand[]" type="string">
  Expand related fields on each item, e.g. `expand[]=locations`.
</ParamField>

### Request

<CodeGroup>
  ```bash curl theme={null}
  curl "https://server.chataigne.ai/v1/organizations?limit=10" \
    -H "x-api-key: ch_org_live_xxx"
  ```

  ```js Node theme={null}
  const res = await fetch("https://server.chataigne.ai/v1/organizations?limit=10", {
    headers: { "x-api-key": "ch_org_live_xxx" },
  });
  const { data } = await res.json();
  ```
</CodeGroup>

### Response

```json 200 OK theme={null}
{
  "object": "list",
  "data": [
    {
      "id": "org_8f2k1d9a",
      "object": "organization",
      "name": "Trattoria Group",
      "location_ids": ["loc_7c3b1e", "loc_9a4f2d"],
      "active_location_ids": ["loc_7c3b1e"],
      "created_at": "2025-01-12T09:30:00Z",
      "updated_at": "2025-04-03T14:22:10Z"
    }
  ],
  "has_more": false,
  "url": "/v1/organizations"
}
```

### Error example

```json 401 Unauthorized theme={null}
{
  "error": {
    "type": "authentication_error",
    "code": "missing_api_key",
    "message": "No API key provided. Pass your key in the x-api-key header.",
    "request_id": "req_1a2b3c4d"
  }
}
```

***

## Retrieve an organization

```
GET /v1/organizations/{organization_id}
```

Retrieves a single organization by ID.

**Auth:** organization API key. The key must be scoped to the requested organization, otherwise a `not_found_error` (`404`) is returned.

### Path parameters

<ParamField path="organization_id" type="string" required>
  The organization ID, e.g. `org_8f2k1d9a`.
</ParamField>

### Query parameters

<ParamField query="expand[]" type="string">
  Expand related fields, e.g. `expand[]=locations`.
</ParamField>

### Request

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

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

### Response

```json 200 OK theme={null}
{
  "id": "org_8f2k1d9a",
  "object": "organization",
  "name": "Trattoria Group",
  "location_ids": ["loc_7c3b1e", "loc_9a4f2d"],
  "active_location_ids": ["loc_7c3b1e"],
  "created_at": "2025-01-12T09:30:00Z",
  "updated_at": "2025-04-03T14:22:10Z",
  "locations": [
    {
      "id": "loc_7c3b1e",
      "object": "location",
      "organization_id": "org_8f2k1d9a",
      "name": "Trattoria Lausanne",
      "currency": "CHF",
      "country": "CH",
      "timezone": "Europe/Zurich",
      "default_language": "fr",
      "address": {
        "line1": "Rue de Bourg 12",
        "line2": null,
        "postal_code": "1003",
        "city": "Lausanne",
        "country": "CH",
        "latitude": 46.5197,
        "longitude": 6.6323
      },
      "created_at": "2025-01-12T09:31:00Z",
      "updated_at": "2025-03-20T11:05:00Z"
    }
  ]
}
```

### Error example

```json 404 Not Found theme={null}
{
  "error": {
    "type": "not_found_error",
    "code": "resource_missing",
    "message": "No organization found with id 'org_unknown'.",
    "param": "organization_id",
    "request_id": "req_5e6f7g8h"
  }
}
```

***

## Update an organization

```
PATCH /v1/organizations/{organization_id}
```

Updates the organization identified by `{organization_id}` (which your API key must have access to). Only the fields you supply are changed.

**Auth:** organization API key.

### Body parameters

<ParamField body="name" type="string">
  New name for the organization.
</ParamField>

<Note>
  `location_ids`, `active_location_ids`, and all timestamps are managed by Chataigne and cannot be set directly. To add a location, use [Create a location](#create-a-location).
</Note>

### Request

<CodeGroup>
  ```bash curl theme={null}
  curl -X PATCH "https://server.chataigne.ai/v1/organizations/org_8f2k1d9a" \
    -H "x-api-key: ch_org_live_xxx" \
    -H "Content-Type: application/json" \
    -d '{ "name": "Trattoria Group SA" }'
  ```

  ```js Node theme={null}
  const res = await fetch("https://server.chataigne.ai/v1/organizations/org_8f2k1d9a", {
    method: "PATCH",
    headers: {
      "x-api-key": "ch_org_live_xxx",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ name: "Trattoria Group SA" }),
  });
  const organization = await res.json();
  ```
</CodeGroup>

### Response

```json 200 OK theme={null}
{
  "id": "org_8f2k1d9a",
  "object": "organization",
  "name": "Trattoria Group SA",
  "location_ids": ["loc_7c3b1e", "loc_9a4f2d"],
  "active_location_ids": ["loc_7c3b1e"],
  "created_at": "2025-01-12T09:30:00Z",
  "updated_at": "2025-05-29T08:14:00Z"
}
```

### Error example

```json 400 Bad Request theme={null}
{
  "error": {
    "type": "invalid_request_error",
    "code": "parameter_invalid_empty",
    "message": "The 'name' field must be a non-empty string.",
    "param": "name",
    "request_id": "req_9i0j1k2l"
  }
}
```

***

## List an organization's locations

```
GET /v1/organizations/{organization_id}/locations
```

Lists the [locations](/location-organization-management/locations) belonging to an organization. Supports the standard cursor pagination and timestamp filters.

**Auth:** organization API key scoped to the organization.

### Path parameters

<ParamField path="organization_id" type="string" required>
  The organization ID, e.g. `org_8f2k1d9a`.
</ParamField>

### Query parameters

<ParamField query="limit" type="integer" default="10">
  Page size, between `1` and `100`.
</ParamField>

<ParamField query="starting_after" type="string">
  Cursor: return results after this location ID. Mutually exclusive with `ending_before`.
</ParamField>

<ParamField query="ending_before" type="string">
  Cursor: return results before this location ID. Mutually exclusive with `starting_after`.
</ParamField>

<ParamField query="created_after" type="string">
  Only locations created at or after this ISO 8601 timestamp.
</ParamField>

<ParamField query="created_before" type="string">
  Only locations created at or before this ISO 8601 timestamp.
</ParamField>

<ParamField query="updated_after" type="string">
  Only locations updated at or after this ISO 8601 timestamp.
</ParamField>

<ParamField query="updated_before" type="string">
  Only locations updated at or before this ISO 8601 timestamp.
</ParamField>

### Request

<CodeGroup>
  ```bash curl theme={null}
  curl "https://server.chataigne.ai/v1/organizations/org_8f2k1d9a/locations?limit=2" \
    -H "x-api-key: ch_org_live_xxx"
  ```

  ```js Node theme={null}
  const res = await fetch(
    "https://server.chataigne.ai/v1/organizations/org_8f2k1d9a/locations?limit=2",
    { headers: { "x-api-key": "ch_org_live_xxx" } },
  );
  const { data, has_more } = await res.json();
  ```
</CodeGroup>

### Response

```json 200 OK theme={null}
{
  "object": "list",
  "data": [
    {
      "id": "loc_7c3b1e",
      "object": "location",
      "organization_id": "org_8f2k1d9a",
      "name": "Trattoria Lausanne",
      "currency": "CHF",
      "country": "CH",
      "timezone": "Europe/Zurich",
      "default_language": "fr",
      "address": {
        "line1": "Rue de Bourg 12",
        "line2": null,
        "postal_code": "1003",
        "city": "Lausanne",
        "country": "CH",
        "latitude": 46.5197,
        "longitude": 6.6323
      },
      "created_at": "2025-01-12T09:31:00Z",
      "updated_at": "2025-03-20T11:05:00Z"
    },
    {
      "id": "loc_9a4f2d",
      "object": "location",
      "organization_id": "org_8f2k1d9a",
      "name": "Trattoria Geneva",
      "currency": "CHF",
      "country": "CH",
      "timezone": "Europe/Zurich",
      "default_language": "fr",
      "address": null,
      "created_at": "2025-02-01T10:00:00Z",
      "updated_at": "2025-02-01T10:00:00Z"
    }
  ],
  "has_more": false,
  "url": "/v1/organizations/org_8f2k1d9a/locations"
}
```

<Note>
  Paginate by passing the last item's `id` as `starting_after` until `has_more` is `false`.
</Note>

### Error example

```json 403 Forbidden theme={null}
{
  "error": {
    "type": "authorization_error",
    "code": "key_type_not_allowed",
    "message": "Admin API keys cannot be used on the /v1 surface.",
    "request_id": "req_3m4n5o6p"
  }
}
```

***

## Create a location

```
POST /v1/organizations/{organization_id}/locations
```

Creates a new [location](/location-organization-management/locations) under the organization.

**Auth:** organization API key scoped to the organization.

<Warning>
  This endpoint creates a resource, so the **`Idempotency-Key` header is required**. Replaying the same key with the same body returns the original response with `Idempotent-Replayed: true`. The same key with a different body returns an `idempotency_error` (`409`); a concurrent in-flight duplicate returns a `conflict_error` (`409`). Keys are retained for 24 hours.
</Warning>

### Path parameters

<ParamField path="organization_id" type="string" required>
  The organization ID, e.g. `org_8f2k1d9a`.
</ParamField>

### Headers

<ParamField header="Idempotency-Key" type="string" required>
  A unique key for safely retrying the request, e.g. a UUID you generate.
</ParamField>

### Body parameters

<ParamField body="name" type="string" required>
  Display name of the location.
</ParamField>

<ParamField body="currency" type="string" required>
  ISO currency code. One of `CHF`, `EUR`, `GBP`, `BRL`, `USD`, `MXN`.
</ParamField>

<ParamField body="country" type="string" required>
  ISO country code. One of `FR`, `CH`, `GB`, `BR`, `LU`, `MX`, `US`.
</ParamField>

<ParamField body="timezone" type="string" required>
  IANA timezone identifier, e.g. `Europe/Zurich`.
</ParamField>

<ParamField body="default_language" type="string">
  Default language code for the location, e.g. `fr`. Optional — when omitted it is inferred from
  the `country`. Countries without a single default language (e.g. `CH`) require it, and a missing
  value returns a `400 invalid_request_error`.
</ParamField>

<ParamField body="address" type="object">
  Postal address. Set to `null` or omit if unknown.

  <Expandable title="address">
    <ParamField body="line1" type="string" />

    <ParamField body="line2" type="string" />

    <ParamField body="postal_code" type="string" />

    <ParamField body="city" type="string" />

    <ParamField body="country" type="string" />

    <ParamField body="latitude" type="number" />

    <ParamField body="longitude" type="number" />
  </Expandable>
</ParamField>

### Request

<CodeGroup>
  ```bash curl theme={null}
  curl -X POST "https://server.chataigne.ai/v1/organizations/org_8f2k1d9a/locations" \
    -H "x-api-key: ch_org_live_xxx" \
    -H "Content-Type: application/json" \
    -H "Idempotency-Key: 9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d" \
    -d '{
      "name": "Trattoria Montreux",
      "currency": "CHF",
      "country": "CH",
      "timezone": "Europe/Zurich",
      "default_language": "fr",
      "address": {
        "line1": "Grand-Rue 50",
        "postal_code": "1820",
        "city": "Montreux",
        "country": "CH"
      }
    }'
  ```

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

  const res = await fetch(
    "https://server.chataigne.ai/v1/organizations/org_8f2k1d9a/locations",
    {
      method: "POST",
      headers: {
        "x-api-key": "ch_org_live_xxx",
        "Content-Type": "application/json",
        "Idempotency-Key": randomUUID(),
      },
      body: JSON.stringify({
        name: "Trattoria Montreux",
        currency: "CHF",
        country: "CH",
        timezone: "Europe/Zurich",
        default_language: "fr",
        address: {
          line1: "Grand-Rue 50",
          postal_code: "1820",
          city: "Montreux",
          country: "CH",
        },
      }),
    },
  );
  const location = await res.json();
  ```
</CodeGroup>

### Response

```json 201 Created theme={null}
{
  "id": "loc_2e5d8c",
  "object": "location",
  "organization_id": "org_8f2k1d9a",
  "name": "Trattoria Montreux",
  "currency": "CHF",
  "country": "CH",
  "timezone": "Europe/Zurich",
  "default_language": "fr",
  "address": {
    "line1": "Grand-Rue 50",
    "line2": null,
    "postal_code": "1820",
    "city": "Montreux",
    "country": "CH",
    "latitude": null,
    "longitude": null
  },
  "created_at": "2025-05-29T08:20:00Z",
  "updated_at": "2025-05-29T08:20:00Z"
}
```

### Error example

```json 409 Conflict theme={null}
{
  "error": {
    "type": "idempotency_error",
    "code": "idempotency_key_in_use",
    "message": "This Idempotency-Key was already used with a different request body.",
    "request_id": "req_7q8r9s0t"
  }
}
```

***

## Errors

All errors return an HTTP status with a body shaped as:

```json theme={null}
{
  "error": {
    "type": "invalid_request_error",
    "code": "parameter_missing",
    "message": "A required parameter is missing.",
    "param": "name",
    "request_id": "req_abc123"
  }
}
```

| Type                    | HTTP | When it happens                                                              |
| ----------------------- | ---- | ---------------------------------------------------------------------------- |
| `invalid_request_error` | 400  | Malformed request or invalid parameter.                                      |
| `authentication_error`  | 401  | Missing API key.                                                             |
| `authorization_error`   | 403  | Wrong key type for the surface (admin key on `/v1`, org key on `/admin/v1`). |
| `not_found_error`       | 404  | Organization or location not found / not accessible to the key.              |
| `conflict_error`        | 409  | Concurrent in-flight duplicate of an idempotent request.                     |
| `idempotency_error`     | 409  | Same `Idempotency-Key` reused with a different body.                         |
| `rate_limit_error`      | 429  | Per-key, per-surface rate limit exceeded. Honor `Retry-After`.               |
| `api_error`             | 500  | Unexpected server error.                                                     |

<Note>
  Every response carries an `X-Request-Id` header, mirrored in error bodies as `error.request_id`. You may echo your own with the `x-request-id` header. Include it when contacting support. Rate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`) are present on every response.
</Note>

## Related resources

<Card title="Locations" href="/location-organization-management/locations" icon="store">
  Retrieve and update locations, settings, opening hours, and special closings.
</Card>
