# Availabilities endpoints

> Reference for creating, listing, moving and deleting availabilities, the blocks of time in which a practitioner offers an availability type, including atomic daily and weekly repeats.

Source: https://help.meetone.io/developers/scheduling-api/availabilities-endpoints
Last updated: 2026-10-08

---

An availability is one block of time on one day in which a practitioner offers appointments of one [availability type](https://help.meetone.io/developers/scheduling-api/availability-types-endpoints). Free slots are what is left of the availabilities after appointments are booked; see [Free slots and booking](https://help.meetone.io/developers/scheduling-api/availability-slots-and-booking).

## Requirements

- **Appointment booking** must be enabled for the organization. Without it, every endpoint on this page returns `403` with the code `feature_disabled`.
- Instance tokens name the organization with `organization_id` or `organization_external_id` when they create an availability, and may use them as a filter on lists.
- The practitioner must exist in the organization and be a practitioner (`doctor`), or a medical assistant where medical assistants may plan. Any other reference returns `404`.

## The availability object

| Field | Type | Description |
|---|---|---|
| `id` | string (uuid) | MeetOne's ID of the availability. |
| `external_id` | string, nullable | Your key for the availability. Unique within the organization. See [Identifiers](https://help.meetone.io/developers/scheduling-api/identifiers). |
| `doctor` | object | The practitioner: `id`, `external_id`, `first_name`, `last_name`. |
| `availability_type` | object | The type: `id`, `external_id`, `display_name`. |
| `starts_at`, `ends_at` | string (date-time) | The block as ISO 8601 timestamps in `Europe/Berlin`. |
| `date` | string (date) | The day, e.g. `2026-10-12`. |
| `start_time`, `end_time` | string | The times of day as `HH:MM`, e.g. `09:00`. |
| `created_at`, `updated_at` | string (date-time) | Timestamps. |

`date`, `start_time` and `end_time` say the same as `starts_at` and `ends_at`; use whichever is easier for your system.

## Rules

- An availability lies **within one day** in `Europe/Berlin`: `starts_at` and `ends_at` have to fall on the same calendar day (`422`, code `same_day`, attribute `ends_at`), and `ends_at` has to be after `starts_at` (`422`, code `not_after_start_time`, attribute `ends_at`).
- It lies **within the working day** of the organization (settings `planner_day_start_hour` and `planner_day_end_hour`, see [Organizations endpoints](https://help.meetone.io/developers/scheduling-api/organizations-endpoints#settings)). Otherwise `422` with the code `outside_working_hours`.
- It must **not overlap** another availability of the **same type** of the same practitioner (`422`, code `overlaps`, attribute `starts_at`). Availabilities of different types may overlap each other; a booking in one type still takes the practitioner's time away from the others.

## List availabilities

`GET /api/v1/availabilities`

`from` and `to` are required and bound the days to list. The range covers at most 92 days (`to` at most 92 days after `from`); otherwise `422` with the code `invalid` and the attribute `to`.

| Query parameter | Type | Description |
|---|---|---|
| `from` | string (date) | First day, e.g. `2026-10-12`. Required. |
| `to` | string (date) | Last day, inclusive. Required. |
| `doctor_id`, `doctor_external_id` | string | Only this practitioner's availabilities. |
| `availability_type_id`, `availability_type_external_id` | string | Only availabilities of this type. |
| `external_id` | string | Only the availability with this external ID. |
| `organization_id`, `organization_external_id` | string | Instance tokens: only this organization's availabilities. |
| `updated_since` | string (date-time) | Only availabilities changed at or after this time. |
| `page`, `per_page` | integer | Pagination. |

Availabilities are listed by day and start time, unless you use `updated_since`.

```bash
curl "https://acme.meetone.io/api/v1/availabilities?from=2026-10-12&to=2026-10-18&doctor_external_id=staff-12" \
  -H "Authorization: Bearer $TOKEN"
```

## Create an availability

`POST /api/v1/availabilities`

| Field | Type | Required | Description |
|---|---|---|---|
| `doctor_id` or `doctor_external_id` | string | Yes | The practitioner. |
| `availability_type_id` or `availability_type_external_id` | string | Yes | The type. |
| `starts_at`, `ends_at` | string (date-time) | Yes | The block. A time without an offset is read in `Europe/Berlin`. |
| `external_id` | string | No | Your key for the availability. |
| `repeat` | object | No | Creates copies on the following days or weeks. See [Repeat](https://help.meetone.io/developers/scheduling-api/availabilities-endpoints#repeat). |

```bash
curl -X POST "https://acme.meetone.io/api/v1/availabilities" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "doctor_external_id": "staff-12",
    "availability_type_external_id": "first-visit",
    "starts_at": "2026-10-12T09:00:00+02:00",
    "ends_at": "2026-10-12T12:00:00+02:00",
    "external_id": "shift-2026-10-12"
  }'
```

A successful request returns `201 Created`:

```json
{
  "data": {
    "id": "2a8f6d14-95b3-4e0c-87d1-c4b9e3a7f520",
    "external_id": "shift-2026-10-12",
    "doctor": {
      "id": "b7d2e9c4-1a3f-4c58-8e66-2f9a0d7c5b13",
      "external_id": "staff-12",
      "first_name": "Maria",
      "last_name": "Muster"
    },
    "availability_type": {
      "id": "5d9a2f77-c3e1-4b08-8a64-7e1f0c92d3b6",
      "external_id": "first-visit",
      "display_name": "First visit"
    },
    "starts_at": "2026-10-12T09:00:00+02:00",
    "ends_at": "2026-10-12T12:00:00+02:00",
    "date": "2026-10-12",
    "start_time": "09:00",
    "end_time": "12:00",
    "created_at": "2026-10-08T10:00:00+02:00",
    "updated_at": "2026-10-08T10:00:00+02:00"
  }
}
```

> **Note**
>
> Free slots follow a grid that starts at the beginning of the working day and advances by the type's `slot_duration`, and a slot is only offered when it fits completely inside an availability. Align availabilities with that grid: for a type with 30-minute slots, start and end them on the hour or the half hour.

### Repeat

With `repeat`, MeetOne copies the availability to the following days or weeks in one request:

| Field | Type | Description |
|---|---|---|
| `repeat.interval` | string (enum) | `daily` or `weekly`. |
| `repeat.count` | integer | 1 to 52. The number of availabilities **including** the one you send. |

```bash
curl -X POST "https://acme.meetone.io/api/v1/availabilities" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "doctor_external_id": "staff-12",
    "availability_type_external_id": "first-visit",
    "starts_at": "2026-10-12T09:00:00+02:00",
    "ends_at": "2026-10-12T12:00:00+02:00",
    "external_id": "series-2026-10-12",
    "repeat": { "interval": "weekly", "count": 4 }
  }'
```

This creates four availabilities, on 12, 19 and 26 October and 2 November. The response is `201 Created` and `data` is a list of the whole series, with the availability you sent first:

```json
{
  "data": [
    { "id": "2a8f6d14-95b3-4e0c-87d1-c4b9e3a7f520", "external_id": "series-2026-10-12", "date": "2026-10-12", "...": "..." },
    { "id": "7e3b9c51-0d2a-4f68-a1c4-5b8d2e6f9a03", "external_id": null, "date": "2026-10-19", "...": "..." },
    { "id": "d05a1f8e-3b7c-4296-8e4d-1c9a6b2f7e30", "external_id": null, "date": "2026-10-26", "...": "..." },
    { "id": "48c2e7a1-9f5d-4b03-b6e8-0a3d7c1f5b92", "external_id": null, "date": "2026-11-02", "...": "..." }
  ]
}
```

A repeat is **atomic**: either the whole series is created, or nothing is. If any copy would overlap an availability of the same type of the same practitioner, the response is `422` with the code `overlaps` and the attribute `repeat`, and no availability is created, not even the first one. The message names the first date that is taken in ISO 8601 format, for example `2026-10-15`. Unlike the planner in the app, the API never deletes overlapping availabilities for you.

The `external_id` applies to the first availability only, because external IDs must be unique. Copies have `external_id` `null`; set theirs afterwards with `PATCH` if you need them. An unknown `interval` returns `422` (code `inclusion`, attribute `repeat.interval`), and so does a `count` outside 1 to 52 (code `invalid`, attribute `repeat.count`).

## Show an availability

`GET /api/v1/availabilities/{id}` returns the availability in the object shown above, or `404` if it does not exist or belongs to another organization.

## Update an availability

`PATCH /api/v1/availabilities/{id}`

Send only the fields you want to change: `doctor_id`/`doctor_external_id`, `availability_type_id`/`availability_type_external_id` and `external_id`. To move the block, send `starts_at` and `ends_at` together; one without the other returns `422` (`blank`). The same [rules](https://help.meetone.io/developers/scheduling-api/availabilities-endpoints#rules) apply as on creation.

```bash
curl -X PATCH "https://acme.meetone.io/api/v1/availabilities/2a8f6d14-95b3-4e0c-87d1-c4b9e3a7f520" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "starts_at": "2026-10-12T10:00:00+02:00", "ends_at": "2026-10-12T13:00:00+02:00" }'
```

## Delete an availability

`DELETE /api/v1/availabilities/{id}` returns `204 No Content`. Appointments that are already booked inside the availability stay as they are; only the times that were still free disappear from the free slots.

## Related

- [Availability types endpoints](https://help.meetone.io/developers/scheduling-api/availability-types-endpoints)
- [Free slots and booking](https://help.meetone.io/developers/scheduling-api/availability-slots-and-booking)
- [Users endpoints](https://help.meetone.io/developers/scheduling-api/users-endpoints)
- [Errors & pagination](https://help.meetone.io/developers/getting-started/errors-and-pagination)

Questions? Contact us at [support@meetone.io](mailto:support@meetone.io).
