An availability is one block of time on one day in which a practitioner offers appointments of one availability type. Free slots are what is left of the availabilities after appointments are booked; see Free 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.
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). 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.

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

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

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

{
  "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 apply as on creation.

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.

Questions? Contact us at support@meetone.io.