Skip to content

Create an appointment

Request

Creates an appointment for a client with a Team Member at a chosen start time.

  • A client is optional. Pass client_id of an existing client, an inline client object resolved attach-only by normalized phone without clients:write, or neither for a clientless appointment.

  • With a client the 201 response carries visit_id > 0; a clientless appointment has visit_id: null. Payment and visit operations are keyed by appointment_id, not visit_id.

  • Slot conflicts are checked server-side: if a parallel request takes the slot first, the call fails with 409 slot_taken — pick a new slot from availability and retry with a new Idempotency-Key.

  • Requires Idempotency-Key; a retry of the same request returns the original result instead of recording a duplicate appointment.

  • For a package service, pass components[{package_component_id, team_member_id}] from availability; the 201 response returns all created appointments plus their shared visit_id.

  • Inline client resolution does not reveal whether a client was found or created.

Security
OAuth2(Required scopes: appointments:create) or RestrictedKey
Path
location_idintegerrequired

Identifier of the Location. Verified against the credential on every call — a Location the credential cannot access responds with 404.

Headers
Idempotency-Keystring, <= 255 charactersrequired

Client-generated unique key for this logical request (UUID recommended). A retry with the same key and body returns the original result; the same key with a different body fails with 409 idempotency_key_reused. Keys are retained at least 24 hours and are scoped to credential, Location, and operation; after expiry the value may be reused for a new logical request.

Bodyapplication/jsonrequired
team_member_idintegerrequired
service_idsArray of integers, non-emptyrequired
starts_atstring, (date-time)required

RFC 3339 with the Location's local UTC offset (take it from availability).

client_idinteger

An existing client of the Location.

clientobject(AppointmentInlineClient)

Inline client for createAppointment: attach-only resolver links an existing client by normalized phone without changing the client record, or creates a new client when none exists. It never restores a deleted client and the response does not reveal whether the client was found or created. No clients:write scope is required.

resource_instance_idsArray of integers

Required by services that occupy a resource (listResources).

duration_secondsinteger

Optional override; defaults to the sum of service durations.

commentstring
componentsArray of objects(AppointmentPackageComponentCreate)

For package services, selected Team Member per package component.

curl -i -X POST \
  'https://developer.alteg.io/_mock/en/b2b-v3/openapi/locations/{location_id}/appointments' \
  -H 'Authorization: Bearer <YOUR_TOKEN_HERE>' \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: string' \
  -d '{
    "client_id": 789,
    "team_member_id": 321,
    "service_ids": [
      100
    ],
    "starts_at": "2026-07-24T11:30:00+01:00"
  }'

Responses

The created appointment.

Headers
RateLimit-Remaininginteger, (int32), >= 0

Requests left in the most constrained policy window that applies to this request.

RateLimit-Resetinteger, (int32), >= 0

On 429, seconds until the most constrained policy frees up; it equals Retry-After there. On a successful response it reports the length of that policy's window rather than the time left in the current one, so treat it as the window size, not as a countdown — the counter to pace against is RateLimit-Remaining.

RateLimit-Policystring

Most constrained policy applied to the request, as <limit>;w=<window in seconds>.

Example:"10;w=60"
Locationstring

URL of the created resource.

ETagstring

Version tag of the returned resource. Send it back in If-Match on the next PATCH or DELETE.

X-Request-Idstring

Request identifier for support and log correlation.

Bodyapplication/json
One of:

A scheduled appointment. visit_id remains a response field and can be null; payment and visit operations are keyed by appointment_id.

idintegerread-onlyrequired
objectstringread-onlyrequired
Value:"appointment"
location_idintegerread-onlyrequired
team_member_idintegerrequired
service_idsArray of integersrequired
statusstring(AppointmentStatus)required

Status of an appointment. waiting — scheduled, not yet confirmed; confirmed — confirmed by the client; arrived — the client attended (terminal "done" state); no_show — the client did not attend; cancelled — cancelled via the cancel command (never set through the status command).

Enum:"waiting""confirmed""arrived""no_show""cancelled"
starts_atstring, (date-time)required

RFC 3339 with the Location's local UTC offset.

duration_secondsintegerrequired
client_idinteger or null

null only on appointments without a client.

visit_idinteger or nullread-only

Billing visit of this appointment.

resource_instance_idsArray of integers

Resource instances occupied by the appointment.

ends_atstring, (date-time)read-only

RFC 3339 with the Location's local UTC offset.

is_paidbooleanread-only

Whether the visit of this appointment is fully paid.

commentstring or null
cancelled_atstring or null, (date-time)read-only

UTC; set by the cancel command.

cancellation_reasonstring or nullread-only
clientobject(Client)read-only

Present only when requested with expand[]=client; PII rules apply.

team_memberobject(TeamMember)read-only

Present only when requested with expand[]=team_member.

created_atstring, (date-time)read-only

UTC.

updated_atstring, (date-time)read-only

UTC.

Response
{ "id": 12345, "object": "appointment", "location_id": 4321, "client_id": 789, "visit_id": 5001, "team_member_id": 321, "service_ids": [ 100 ], "resource_instance_ids": [], "status": "waiting", "starts_at": "2026-07-24T11:30:00+01:00", "ends_at": "2026-07-24T12:30:00+01:00", "duration_seconds": 3600, "is_paid": false, "comment": null, "cancelled_at": null, "cancellation_reason": null, "created_at": "2026-07-20T09:57:15Z", "updated_at": "2026-07-20T09:57:15Z" }