Umovi integration platform
Booking flow
Recommended sequence
- Resolve the requested service and optional employee with
POST /catalog/resolve. - If the result is ambiguous, ask the user to choose instead of silently taking the first match.
- For caller recognition, use
POST /clients/identifywith an exact phone number. Use/clients/searchonly when your trusted workflow needs full client records. - Call
/slotsfor a known range or/slots/first-availablefor the nearest appointment. - Confirm the selected service, employee and time with the user.
- Create the reservation with a stable
Idempotency-Key. - Subscribe to webhooks for changes made outside your integration.
Caller recognition
All short paths on this page are relative to /integrations/v1/providers/{providerId}.
POST /clients/identify requires clients:identify and accepts { "phone": "+48123456789" }. Send an international E.164 phone number. The response contains only status and providerClientId:
| Status | Result |
|---|---|
MATCHED | Exactly one provider client matched; providerClientId is its UUID. |
NOT_FOUND | No match; providerClientId is null. |
AMBIGUOUS | Multiple matches; providerClientId is null. |
Caller ID is a recognition signal, not proof of identity. Do not use it alone to disclose bookings or authorize changes. Do not choose an arbitrary record after an ambiguous result.
When creating a reservation, supply exactly one of providerClientId or client. Use providerClientId for an existing record within this provider; use client with firstName and at least an email address or phone number for contact-based creation.
Client identity and account claims
Reservation contact data belongs first to the provider. When an integration creates a reservation using an email address or phone number, Umovi creates or reuses a provider-scoped client record. It does not create a global Umovi user or silently link the contact to an existing account.
If that provider client has already been claimed by an authenticated Umovi client, the new reservation remains linked to that account. Otherwise the booking is treated as a guest reservation. Guest email communication contains a secure claim link, so the recipient can create an account or sign in and explicitly attach the provider record and its bookings later.
Do not treat a matching email address as proof that the person submitting the reservation owns an existing Umovi account.
Employee selection and time windows
For a selected employee, send employeeSelectionMode: "SPECIFIC" with employeeId. To let Umovi allocate an eligible available employee atomically, send employeeSelectionMode: "ANY" and omit employeeId. Availability results contain employeeIds; they do not reserve an employee until creation succeeds.
GET /slots accepts inclusive dateFrom/dateTo bounds spanning at most 31 days. Both slot endpoints accept optional local timeFrom/timeTo in HH:mm format and an IANA timezone. An end time must not precede the start time.
GET /slots/first-available also accepts inclusive dateFrom/dateTo, direction: "forward" | "backward" to choose the search direction, and slotPreference: "earliest" | "latest" to choose a slot on the resulting day. Its inDays horizon defaults to 30 and permits 1–90 days. For the last slot on one day, set both date bounds to that day and slotPreference: "latest". No availability returns null date, startsAt and label, with an empty employeeIds array.
Provider-only context
Use internalNote when the provider team needs operational context that must
not be shown to the client. For example, a demo request can include the company
name, website, team size and the questions the sales team should prepare for.
{
"serviceId": "67bb6ca0-b376-40e8-ae99-169db1db6e65",
"employeeId": "65aa7b83-d328-428d-b220-8932f4ce37ca",
"startAt": "2026-09-03T08:30:00.000Z",
"client": {
"firstName": "Anna",
"lastName": "Nowak",
"email": "anna@example.com"
},
"internalNote": "Company: Example Studio\nTeam size: 12\nTopic: migration"
}The field accepts up to 2,000 characters. It is visible only on provider surfaces, is omitted from Integration API reservation reads and is never added to client notifications or the booking conversation. Do not put secrets or authentication data in it.
Idempotency
Generate one key for one logical reservation attempt. When a network timeout leaves the outcome unknown, retry the same request body with the same key.
Idempotency-Key: booking-attempt-7d8f4aKeys must contain 8–180 printable ASCII characters without whitespace. A repeated request with the same key and body returns the original reservation and includes Idempotency-Replayed: true. The reservation is not created again and creation webhooks or audit entries are not duplicated.
Do not reuse a key for a different customer, service or time. Reuse with a different body returns 409 with code IDEMPOTENCY_KEY_REUSED. Validation failures do not consume the key.
An external reservation identifier can be included in the body to make reconciliation easier. When Idempotency-Key is omitted and externalReservationId is present, Umovi derives the idempotency key from that external identifier for the authenticated integration client.
Slot races
Availability is a snapshot. A slot can be taken between lookup and reservation creation. Treat a conflict as an expected business event: fetch availability again and let the user select another time.
Catalog ambiguity
Catalog resolution returns candidates, valid service/employee pairs and a machine-readable state. When it reports an ambiguous service or employee, preserve the candidates and ask a short disambiguation question. Fuzzy matching is a fallback for speech and typing errors, not permission to book a low-confidence result.