Skip to main content
To let a customer book a service, you read a published Appointment Definition, fetch its availability for a location and date, then create an appointment against the chosen slot. This guide covers that flow and the queries most front ends need. For the model behind it, see the Appointments concept. All endpoints are bearer authenticated and live under https://api.[tenant].getomneo.com/api/v3.

Booking flow

1

List published definitions

GET /api/v3/appointment-definitions?filter[is_published]=1&filter[is_archived]=0
2

Read the definition and its booking questions

GET /api/v3/appointment-definitions/{definitionId}
GET /api/v3/appointment-definitions/{definitionId}/questions
The definition returns its normal and special hours, linked locations, staff, and whether it has a booking questionnaire. The questions endpoint returns the active form slots to render.
3

Fetch availability for a location and date

curl -X POST "https://api.[tenant].getomneo.com/api/v3/appointment-definitions/{definitionId}/available-slots" \
  -H "Authorization: Bearer ${TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
    "location_id": 13,
    "date": "2026-05-11"
  }'
When the definition has requires_staff: true, pass staff_id, and first call available-staff to populate a staff picker. For a calendar view, use available-slots-range with start_date and end_date (capped at 31 days) instead of calling the single-day endpoint repeatedly.
4

Create the appointment

curl -X POST "https://api.[tenant].getomneo.com/api/v3/appointments" \
  -H "Authorization: Bearer ${TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
    "appointment_definition_id": 1,
    "profile_id": "a1b460b2-953f-4587-b4eb-fb0f29b55e02",
    "location_id": 13,
    "scheduled_start_at": "2026-05-11 10:00:00",
    "scheduled_end_at": "2026-05-11 10:30:00",
    "timezone": "Australia/Melbourne",
    "answers": [
      { "questionnaire_question_id": 1, "value": "consultation" }
    ]
  }'
For an instant definition the response status is confirmed. For an approval_required definition it is requested. Times are sent in timezone and stored in UTC. Pass assigned_staff_id when the definition requires staff.
The create response includes the saved answers[], so you can confirm what was captured without a follow-up read.

Fetching a customer’s appointments

There is no profile-scoped appointments sub-resource. Unlike Profile Benefits, which expose /profiles/{profileId}/benefits, appointments are read from the global endpoint with a profile filter:
GET /api/v3/appointments?filter[profile_id]={profileId}
The appointments list is filterable by every stored field, so you can narrow a customer’s appointments without filtering on the front end:
FilterExampleUse
profile_idfilter[profile_id]={profileId}All appointments for one customer.
statusfilter[status]=confirmedOnly confirmed (or requested, arrived, completed, cancelled, no_show, rejected).
appointment_definition_idfilter[appointment_definition_id]=1Appointments for one service.
location_idfilter[location_id]=13Appointments at one location.
assigned_staff_idfilter[assigned_staff_id]={staffId}Appointments for one staff member.
Combine filters with AND logic. For a customer’s upcoming confirmed bookings:
GET /api/v3/appointments?filter[profile_id]={profileId}&filter[status]=confirmed
The list endpoint is paginated. Use page[size] to control the page size and page through meta.pagination like every other Omneo list endpoint.

Listing and filtering definitions

The Appointment Definition list supports these filters:
FilterNotes
id, handle, nameExact match.
is_published, is_archivedPublication state.
booking_typeinstant, approval_required, or walk_in_only.
allow_customer_booking, allow_walk_in, requires_staff, customer_must_select_staff, allow_waitlist, allow_queueBoolean capability flags.
queue_codeWalk-in queue code.
definitionLocations.location_id, definitionLocations.is_activeDefinitions offered at a location.
created_at, updated_atTimestamps.
For example, every published definition bookable at a location:
GET /api/v3/appointment-definitions?filter[is_published]=1&filter[definitionLocations.location_id]=13

Filtering appointments by type

The Appointment Definition is the type. To fetch every appointment of a given type, filter the appointments list by its definition rather than fetching everything and filtering on the front end:
# All appointments for one definition (one "type" of service)
GET /api/v3/appointments?filter[appointment_definition_id]=1

# Narrow to one customer and one type
GET /api/v3/appointments?filter[profile_id]={profileId}&filter[appointment_definition_id]=1
This is the same Definition/Instance filter pattern used elsewhere in the API.
The appointments list filters by definition id only. It does not currently accept the definition handle as a relational filter (filter[appointmentDefinition.handle] is ignored), unlike some other instance endpoints such as Credits, which accept filter[definition.handle]. If you only have a handle, resolve it to an id first:
GET /api/v3/appointment-definitions?filter[handle]=bra-fitting
Then use the returned id in filter[appointment_definition_id]. Adding appointmentDefinition.handle to the appointments filter whitelist is a reasonable enhancement to request from the Omneo team.
There is no separate category or type field on a definition, and meta is not filterable, so the definition id is the way to group appointments by type.

Managing the lifecycle

Update an appointment with PUT /api/v3/appointments/{id}. Sending a status sets the matching timestamp automatically.
# Approve a requested appointment
curl -X PUT "https://api.[tenant].getomneo.com/api/v3/appointments/{id}" \
  -H "Authorization: Bearer ${TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{ "status": "confirmed" }'
ActionBody
Approve{ "status": "confirmed" }
Reject{ "status": "rejected" }
Cancel{ "status": "cancelled" }
Mark arrived, completed, or no-show{ "status": "arrived" } (or completed, no_show)
Reschedule{ "scheduled_start_at": "...", "scheduled_end_at": "...", "timezone": "..." }
Booking answers are captured at creation only. To collect post-visit feedback, create a separate questionnaire and submit it through POST /api/v3/questionnaires/{id}/submissions.

Walk-in queues and waitlists

For walk_in_only definitions, check a customer in to the queue. Omit profile_id for an anonymous walk-in.
POST /api/v3/appointment-queues
When a slot is unavailable and the definition allows it, add the customer to the waitlist, then fulfil it later by creating an appointment and linking it.
POST /api/v3/appointment-waitlists