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

# Company catalog

> Read and manage company profile metadata and locations.

Company catalog endpoints expose the operational catalog that external systems
need before they create clients, availability searches, or bookings. Outputs are
explicit DTOs. New fields added to internal MongoDB models are not returned by
these endpoints unless the Public API DTO and this page are updated.

These endpoints do not return billing profile IDs, payment connection IDs,
provider payloads, reporting settings, scheduling internals, email sender
settings, media storage objects, change history, coach-only notes, VAT numbers,
company registration numbers, or external reference IDs.

## Scopes

| Scope                  | Allows                                                            |
| :--------------------- | :---------------------------------------------------------------- |
| `company_catalog:read` | Read company profile, facilities, services, and company policies. |
| `locations:read`       | List and read company locations.                                  |
| `locations:write`      | Create, update, and archive locations.                            |

## Rate limits

All resource calls use the standard Public API Bearer-token rate limit. Responses
include the current rate-limit headers when rate limiting is enabled:

| Header                  | Description                               |
| :---------------------- | :---------------------------------------- |
| `X-RateLimit-Limit`     | Maximum requests in the current window.   |
| `X-RateLimit-Remaining` | Requests remaining in the current window. |
| `X-RateLimit-Reset`     | Reset time for the current window.        |
| `Retry-After`           | Seconds to wait after a `429` response.   |

## Company profile

```http theme={null}
GET /public/v1/company-profile
Authorization: Bearer <access_token>
```

Required scope: `company_catalog:read`

Response fields:

| Field                                | Type    | Nullable | Description                            |
| :----------------------------------- | :------ | :------- | :------------------------------------- |
| `data.company.companyId`             | string  | no       | Company ID.                            |
| `data.company.name`                  | string  | no       | Company display name.                  |
| `data.company.slug`                  | string  | no       | Public slug when configured.           |
| `data.company.logoUrl`               | string  | no       | Company logo URL when configured.      |
| `data.company.imageUrl`              | string  | no       | Company image URL when configured.     |
| `data.company.businessType`          | string  | no       | Business type label when configured.   |
| `data.company.email`                 | string  | no       | Public company email.                  |
| `data.company.phoneNumber`           | string  | no       | Public company phone number.           |
| `data.company.about`                 | string  | no       | Public company profile text.           |
| `data.company.location.address`      | string  | no       | Full address string.                   |
| `data.company.location.addressLine1` | string  | no       | Address line 1.                        |
| `data.company.location.addressLine2` | string  | no       | Address line 2 or street number.       |
| `data.company.location.zipCode`      | string  | no       | Postal code.                           |
| `data.company.location.city`         | string  | no       | City.                                  |
| `data.company.location.country`      | string  | no       | Country.                               |
| `data.company.primaryLanguage`       | string  | no       | Primary language code.                 |
| `data.company.secondaryLanguage`     | string  | no       | Secondary language code.               |
| `data.company.timeZone`              | string  | no       | IANA timezone.                         |
| `data.company.timeFormat`            | string  | no       | Company time display format.           |
| `data.company.dateFormat`            | string  | no       | Company date display format.           |
| `data.company.currency`              | string  | no       | ISO currency code when configured.     |
| `data.company.profileVisibility`     | boolean | no       | Whether the company profile is public. |
| `data.company.socialMedia.website`   | string  | no       | Website URL.                           |
| `data.company.socialMedia.instagram` | string  | no       | Instagram URL or handle.               |
| `data.company.socialMedia.facebook`  | string  | no       | Facebook URL or handle.                |
| `data.company.socialMedia.linkedin`  | string  | no       | LinkedIn URL or handle.                |
| `data.company.socialMedia.youtube`   | string  | no       | YouTube URL or handle.                 |
| `data.company.socialMedia.twitter`   | string  | no       | Twitter/X URL or handle.               |
| `data.company.createdAt`             | string  | yes      | Creation timestamp.                    |
| `data.company.updatedAt`             | string  | yes      | Update timestamp.                      |

Omitted: VAT number, company registration number, billing details, payment
provider details, invoice settings, and external reference IDs.

## Facilities and services

```http theme={null}
GET /public/v1/facilities-services
Authorization: Bearer <access_token>
```

Required scope: `company_catalog:read`

Response fields:

| Field                                     | Type   | Nullable | Description                                                     |
| :---------------------------------------- | :----- | :------- | :-------------------------------------------------------------- |
| `data.facilitiesAndServices.facilities[]` | array  | no       | Selected facility keys.                                         |
| `data.facilitiesAndServices.services[]`   | array  | no       | Selected service keys.                                          |
| `data.facilitiesAndServices.source`       | string | no       | `embedded`, `legacy`, or `defaults` depending on stored source. |
| `data.facilitiesAndServices.updatedAt`    | string | yes      | Update timestamp for the selected source.                       |

## Company policies

```http theme={null}
GET /public/v1/company-policies
Authorization: Bearer <access_token>
```

Required scope: `company_catalog:read`

Response fields:

| Field                                | Type   | Nullable | Description                              |
| :----------------------------------- | :----- | :------- | :--------------------------------------- |
| `data.policies.privacy.en.content`   | string | no       | English privacy policy content.          |
| `data.policies.privacy.en.updatedAt` | string | yes      | English privacy policy update timestamp. |
| `data.policies.privacy.nl.content`   | string | no       | Dutch privacy policy content.            |
| `data.policies.privacy.nl.updatedAt` | string | yes      | Dutch privacy policy update timestamp.   |
| `data.policies.terms.en.content`     | string | no       | English terms content.                   |
| `data.policies.terms.en.updatedAt`   | string | yes      | English terms update timestamp.          |
| `data.policies.terms.nl.content`     | string | no       | Dutch terms content.                     |
| `data.policies.terms.nl.updatedAt`   | string | yes      | Dutch terms update timestamp.            |
| `data.policies.updatedAt`            | string | yes      | Policy document update timestamp.        |

## Locations

```http theme={null}
GET /public/v1/locations?page=1&limit=100
POST /public/v1/locations
GET /public/v1/locations/{locationId}
PATCH /public/v1/locations/{locationId}
POST /public/v1/locations/{locationId}/archive
```

Required scopes: `locations:read` for reads, `locations:write` for writes.

List responses include pagination fields:

| Field              | Type    | Nullable | Description                           |
| :----------------- | :------ | :------- | :------------------------------------ |
| `data.page`        | integer | no       | Current page.                         |
| `data.limit`       | integer | no       | Page size after applying the maximum. |
| `data.total`       | integer | no       | Total matching locations.             |
| `data.totalPages`  | integer | no       | Number of pages.                      |
| `data.hasNextPage` | boolean | no       | Whether another page exists.          |
| `data.hasPrevPage` | boolean | no       | Whether a previous page exists.       |
| `data.locations[]` | array   | no       | Location DTOs.                        |

Location DTO fields:

| Field                                            | Type    | Nullable | Description                                                |
| :----------------------------------------------- | :------ | :------- | :--------------------------------------------------------- |
| `locationId`                                     | string  | no       | Location ID.                                               |
| `name`                                           | string  | no       | Location name.                                             |
| `alternateName`                                  | string  | no       | Optional alternate name.                                   |
| `address`                                        | string  | no       | Address label.                                             |
| `primary`                                        | boolean | no       | Whether this is the primary company location.              |
| `coordinates.longitude`                          | number  | yes      | Longitude.                                                 |
| `coordinates.latitude`                           | number  | yes      | Latitude.                                                  |
| `timeZone`                                       | string  | no       | IANA timezone.                                             |
| `type`                                           | string  | no       | `branch`, `outdoor`, `online`, `external`, or `temporary`. |
| `allowsClientAssignment`                         | boolean | no       | Whether clients can be assigned to this location.          |
| `accessZones[].key`                              | string  | no       | Stable zone key.                                           |
| `accessZones[].name`                             | string  | no       | Zone display name.                                         |
| `accessZones[].isActive`                         | boolean | no       | Zone active flag.                                          |
| `facilitiesAndServices.mode`                     | string  | no       | `inherit` or `custom`.                                     |
| `facilitiesAndServices.facilities[]`             | array   | no       | Facility keys.                                             |
| `facilitiesAndServices.services[]`               | array   | no       | Service keys.                                              |
| `profile.visibility`                             | string  | no       | Location profile visibility mode.                          |
| `profile.displayName`                            | string  | no       | Public display name.                                       |
| `profile.description`                            | string  | no       | Public description.                                        |
| `profile.website`                                | string  | no       | Public website.                                            |
| `profile.email`                                  | string  | no       | Public email.                                              |
| `profile.phone`                                  | string  | no       | Public phone number.                                       |
| `profile.socialMedia.instagram`                  | string  | no       | Instagram URL or handle.                                   |
| `profile.socialMedia.facebook`                   | string  | no       | Facebook URL or handle.                                    |
| `profile.socialMedia.linkedin`                   | string  | no       | LinkedIn URL or handle.                                    |
| `profile.socialMedia.youtube`                    | string  | no       | YouTube URL or handle.                                     |
| `profile.socialMedia.twitter`                    | string  | no       | Twitter/X URL or handle.                                   |
| `openingHours.mode`                              | string  | no       | Opening-hours mode.                                        |
| `openingHours.weeklyPattern[].dayOfWeek`         | integer | yes      | Day number, `0` through `6`.                               |
| `openingHours.weeklyPattern[].slots[].startTime` | string  | no       | Local start time, `HH:mm`.                                 |
| `openingHours.weeklyPattern[].slots[].endTime`   | string  | no       | Local end time, `HH:mm`.                                   |
| `openingHours.exceptions[].date`                 | string  | yes      | Exception date timestamp.                                  |
| `openingHours.exceptions[].type`                 | string  | no       | Exception type, such as `closed`.                          |
| `openingHours.exceptions[].slots[].startTime`    | string  | no       | Exception slot start time.                                 |
| `openingHours.exceptions[].slots[].endTime`      | string  | no       | Exception slot end time.                                   |
| `openingHours.exceptions[].reason`               | string  | no       | Public reason text when configured.                        |
| `archived`                                       | boolean | no       | Whether the location is archived.                          |
| `createdAt`                                      | string  | yes      | Creation timestamp.                                        |
| `updatedAt`                                      | string  | yes      | Update timestamp.                                          |

Validation:

| Input                                | Rule                                                                 |
| :----------------------------------- | :------------------------------------------------------------------- |
| `page`                               | Integer, minimum `1`.                                                |
| `limit`                              | Integer, default `100`, maximum `100`.                               |
| `locationId`                         | Must be a valid MongoDB ObjectId.                                    |
| `name`                               | Required on create.                                                  |
| `type`                               | Must be `branch`, `outdoor`, `online`, `external`, or `temporary`.   |
| `coordinates`                        | Must contain numeric longitude and latitude values.                  |
| `accessZones`                        | Must be an array; entries without both `key` and `name` are ignored. |
| `facilitiesAndServices.mode`         | Must be `inherit` or `custom`.                                       |
| `facilitiesAndServices.facilities[]` | Unknown facility keys are ignored.                                   |
| `facilitiesAndServices.services[]`   | Unknown service keys are ignored.                                    |

Archive uses soft deletion and returns the archived DTO. Archived locations are
excluded from list and get responses.

### List locations example

<CodeGroup>
  ```bash cURL theme={null}
  curl -H "Authorization: Bearer $FITSOCIETY_ACCESS_TOKEN" \
    "https://api.fitsociety.io/public/v1/locations?page=1&limit=100"
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch(
    "https://api.fitsociety.io/public/v1/locations?page=1&limit=100",
    {
      headers: {
        Authorization: `Bearer ${process.env.FITSOCIETY_ACCESS_TOKEN}`,
      },
    },
  );

  const body = await response.json();
  console.log(body.data.total, body.data.locations);
  ```

  ```python Python theme={null}
  import os
  import requests

  response = requests.get(
      "https://api.fitsociety.io/public/v1/locations",
      headers={"Authorization": f"Bearer {os.environ['FITSOCIETY_ACCESS_TOKEN']}"},
      params={"page": 1, "limit": 100},
  )
  response.raise_for_status()

  body = response.json()
  print(body["data"]["total"], body["data"]["locations"])
  ```
</CodeGroup>

Response:

```json theme={null}
{
  "data": {
    "page": 1,
    "limit": 100,
    "total": 1,
    "totalPages": 1,
    "hasNextPage": false,
    "hasPrevPage": false,
    "locations": [
      {
        "locationId": "64b64c0f2f5f4c00123456e5",
        "name": "Amsterdam HQ",
        "alternateName": "",
        "address": "Main street 1, 1011AB Amsterdam",
        "primary": true,
        "coordinates": { "longitude": 4.9041, "latitude": 52.3676 },
        "timeZone": "Europe/Amsterdam",
        "type": "branch",
        "allowsClientAssignment": true,
        "archived": false,
        "createdAt": "2026-01-05T09:00:00.000Z",
        "updatedAt": "2026-07-01T09:00:00.000Z"
      }
    ]
  },
  "meta": {
    "requestId": "req_0123456789abcdef",
    "rateLimit": { "limit": 10, "remaining": 9, "resetSeconds": 1 }
  }
}
```

### Create location example

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST "https://api.fitsociety.io/public/v1/locations" \
    -H "Authorization: Bearer $FITSOCIETY_ACCESS_TOKEN" \
    -H "Idempotency-Key: location-create-utrecht-studio-20260823" \
    -H "Content-Type: application/json" \
    -d '{
      "name": "Utrecht studio",
      "address": "Stationsplein 10, 3511ED Utrecht",
      "type": "branch",
      "timeZone": "Europe/Amsterdam",
      "allowsClientAssignment": true,
      "coordinates": { "longitude": 5.1101, "latitude": 52.0894 }
    }'
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch("https://api.fitsociety.io/public/v1/locations", {
    method: "POST",
    headers: {
      Authorization: `Bearer ${process.env.FITSOCIETY_ACCESS_TOKEN}`,
      "Idempotency-Key": "location-create-utrecht-studio-20260823",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      name: "Utrecht studio",
      address: "Stationsplein 10, 3511ED Utrecht",
      type: "branch",
      timeZone: "Europe/Amsterdam",
      allowsClientAssignment: true,
      coordinates: { longitude: 5.1101, latitude: 52.0894 },
    }),
  });

  const body = await response.json();
  if (response.status === 201) {
    console.log("Created location", body.data.location.locationId);
  }
  ```

  ```python Python theme={null}
  import os
  import requests

  response = requests.post(
      "https://api.fitsociety.io/public/v1/locations",
      headers={
          "Authorization": f"Bearer {os.environ['FITSOCIETY_ACCESS_TOKEN']}",
          "Idempotency-Key": "location-create-utrecht-studio-20260823",
      },
      json={
          "name": "Utrecht studio",
          "address": "Stationsplein 10, 3511ED Utrecht",
          "type": "branch",
          "timeZone": "Europe/Amsterdam",
          "allowsClientAssignment": True,
          "coordinates": {"longitude": 5.1101, "latitude": 52.0894},
      },
  )
  response.raise_for_status()

  body = response.json()
  if response.status_code == 201:
      print("Created location", body["data"]["location"]["locationId"])
  ```
</CodeGroup>

Response (`201 Created`):

```json theme={null}
{
  "data": {
    "location": {
      "locationId": "64b64c0f2f5f4c00123456e6",
      "name": "Utrecht studio",
      "alternateName": "",
      "address": "Stationsplein 10, 3511ED Utrecht",
      "primary": false,
      "coordinates": { "longitude": 5.1101, "latitude": 52.0894 },
      "timeZone": "Europe/Amsterdam",
      "type": "branch",
      "allowsClientAssignment": true,
      "archived": false,
      "createdAt": "2026-08-23T10:00:00.000Z",
      "updatedAt": "2026-08-23T10:00:00.000Z"
    }
  },
  "meta": {
    "requestId": "req_0123456789abcdef",
    "rateLimit": { "limit": 10, "remaining": 8, "resetSeconds": 1 }
  }
}
```

### Archive location example

Archive is an action route (`POST .../archive`), not a `DELETE`. Empty request
bodies are accepted; the `Idempotency-Key` header is still required.

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST "https://api.fitsociety.io/public/v1/locations/64b64c0f2f5f4c00123456e6/archive" \
    -H "Authorization: Bearer $FITSOCIETY_ACCESS_TOKEN" \
    -H "Idempotency-Key: location-archive-64b64c0f2f5f4c00123456e6"
  ```

  ```javascript JavaScript theme={null}
  const locationId = "64b64c0f2f5f4c00123456e6";
  const response = await fetch(
    `https://api.fitsociety.io/public/v1/locations/${locationId}/archive`,
    {
      method: "POST",
      headers: {
        Authorization: `Bearer ${process.env.FITSOCIETY_ACCESS_TOKEN}`,
        "Idempotency-Key": `location-archive-${locationId}`,
      },
    },
  );

  const body = await response.json();
  console.log(body.data.location.archived);
  ```

  ```python Python theme={null}
  import os
  import requests

  location_id = "64b64c0f2f5f4c00123456e6"
  response = requests.post(
      f"https://api.fitsociety.io/public/v1/locations/{location_id}/archive",
      headers={
          "Authorization": f"Bearer {os.environ['FITSOCIETY_ACCESS_TOKEN']}",
          "Idempotency-Key": f"location-archive-{location_id}",
      },
  )
  response.raise_for_status()

  body = response.json()
  print(body["data"]["location"]["archived"])
  ```
</CodeGroup>

Response:

```json theme={null}
{
  "data": {
    "location": {
      "locationId": "64b64c0f2f5f4c00123456e6",
      "name": "Utrecht studio",
      "archived": true,
      "updatedAt": "2026-08-23T10:05:00.000Z"
    }
  },
  "meta": {
    "requestId": "req_0123456789abcdef",
    "rateLimit": { "limit": 10, "remaining": 7, "resetSeconds": 1 }
  }
}
```
