Preskočiť na hlavný obsah
← Home page

Public API

REST API (version v1) for your business website, an AI receptionist, Zapier, Make and other integrations. Responses are JSON with an ok field; on error also error. The full description of all paths and fields is in OpenAPI 3.1.

📄 OpenAPI 3.1 (JSON)🔔 Webhooks🔑 Create API key

1. Authenticating with a key

Every request must include the header Authorization: Bearer rk_live_…. You create the key in the dashboard → API keys. The full key is shown only once — store it in environment variables or a password manager; we keep only its fingerprint. A key belongs to one business, so the business is not specified in requests.

curl "https://app.terminuj.com/api/v1/services" \
  -H "Authorization: Bearer rk_live_XXXXXXXXXXXXXXXXXXXXXXXX"

2. Key scopes

When creating a key, you choose its scopes — give it only those the integration really needs.

ScopePaths (/api/v1/…)
booking:readGET /bookings, GET /bookings/{id}, GET /time-off
booking:writePOST /bookings, PATCH /bookings/{id} (cancel, reschedule, confirm), POST /time-off, DELETE /time-off/{id}
customer:readGET /customers
service:readGET /services, GET /availability
webhook:manageGET/POST /webhooks, GET/DELETE /webhooks/{id}, GET /webhooks/{id}/deliveries

3. Most common uses

Available slots

For each day, returns whether the business is open and the free times after subtracting bookings, time off and service breaks; at the earliest 2 h from now. from = day as YYYY-MM-DD (default today), days 1–62 (default 28), optionally staff = a specific staff member. The time zone is Europe/Bratislava.

curl "https://app.terminuj.com/api/v1/availability?service=<id-sluzby>&from=2026-06-15&days=7" \
  -H "Authorization: Bearer rk_live_XXXXXXXXXXXXXXXXXXXXXXXX"

Create a booking

startAt in UTC with Z at the end (12:00Z = 14:00 in summer in Bratislava). The customer’s email is required; without it only with "channel": "telefon" (appointment taken by phone — name and phone are enough). Send appointments from the public form on your website with "channel": "web"; if the business requires consent to start the service before the withdrawal period ends, add "serviceStartConsent": true according to the checkbox the customer ticked (otherwise 422 consent_required). Optionally preferredStaffId, customer.notes and locale (sk | en | cs | hu | de | es — the language of API messages and of further messages to the customer about this booking; defaults to the business language). Sending the same service and time with the same email again within 10 minutes returns the same booking (double click, network outage).

For bookings made via the API, Terminuj does not send the confirmation email to the customer — your integration sends the confirmation. The owner is notified according to the business settings. The booking counts towards the plan’s monthly total.

curl -X POST "https://app.terminuj.com/api/v1/bookings" \
  -H "Authorization: Bearer rk_live_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
    "serviceId": "<id-sluzby>",
    "startAt": "2026-06-15T12:00:00Z",
    "customer": {
      "fullName": "Jana Nováková",
      "email": "jana@example.com",
      "phone": "+421900123456"
    }
  }'

Cancel, reschedule or confirm a booking

One path, depending on the action field: {"action": "cancel", "reason": "…"}, {"action": "reschedule", "startAt": "…Z"} or {"action": "confirm"} (only an appointment awaiting a deposit). On cancellation the customer receives an email; on rescheduling and confirmation, if the business has confirmation emails turned on.

curl -X PATCH "https://app.terminuj.com/api/v1/bookings/<id-rezervacie>" \
  -H "Authorization: Bearer rk_live_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{ "action": "cancel", "reason": "Zákazník neprišiel" }'

Search customers

search looks in the name, email and phone.

curl "https://app.terminuj.com/api/v1/customers?search=jana&limit=10" \
  -H "Authorization: Bearer rk_live_XXXXXXXXXXXXXXXXXXXXXXXX"

Other paths (list of bookings with the from/to/status/createdFrom filter, services, blocking time with /time-off, webhooks) are described in OpenAPI.

4. Pagination

Lists accept the parameters ?limit=25&cursor=<id>. Default 25, at most 100 per page (bookings, customers, webhook deliveries); services default 50, at most 200. The response contains { pagination: { nextCursor, hasMore, limit } }.

# First page
curl "https://app.terminuj.com/api/v1/bookings?limit=25" -H "Authorization: Bearer rk_live_…"

# Next page (nextCursor from the previous response)
curl "https://app.terminuj.com/api/v1/bookings?limit=25&cursor=<nextCursor>" -H "Authorization: Bearer rk_live_…"

5. Rate limit

The limit is counted per key in a sliding window of 1 minute:

  • Reading (booking:read, customer:read, service:read): 600 requests per minute
  • Writing (booking:write, webhook:manage): 60 requests per minute

When exceeded, you get 429 rate_limit_exceeded with the Retry-After header (in how many seconds to try again) and the retryAfterSeconds field. The X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset headers are sent with the rejection.

6. Error codes

HTTPerrorMeaning
401missing_or_invalid_authorizationThe Authorization header is missing or the key is not in the form rk_live_ + 24 characters
401invalid_api_keyNo such key exists
401api_key_revokedThe key was revoked in the dashboard
401api_key_expiredThe key has expired (expiresAt)
402trial_endedThe business’s trial has ended — 14 days after sign-up (resetAt = end of the trial); new bookings only after choosing a plan
402monthly_limit_exceededThe business has used up the monthly number of bookings of its partner plan (used, limit, resetAt)
403insufficient_scopeThe key does not have the required scope (required, have)
403manual_requires_app“manual: true” may only be sent by a signed-in person from the Terminuj app, not by an API key
404not_foundThe booking, time off or webhook does not exist in this business (also service_not_found)
409slot_conflictThe slot has been taken in the meantime; when creating, suggestedAlternatives are included
409already_cancelledThe booking status does not allow the change (also already_completed, cannot_cancel, not_reschedulable, already_confirmed, cannot_confirm)
422invalid_bodyThe request body does not match the schema — details in detail
422consent_requiredThe business requires consent to start the service before the withdrawal period ends and serviceStartConsent: true is missing
422start_in_pastThe start is in the past (also outside_working_hours = outside opening hours)
429rate_limit_exceededThe key’s rate limit was exceeded — see section 5
429daily_cap_reachedThe business has reached its daily cap of public bookings (last 24 h) — writing with a key counts the same as the form

7. Webhooks

If you want Terminuj to notify you itself about a new, cancelled or rescheduled booking, see /docs/webhooks — HMAC SHA-256 signature, retries after 1 min, 5 min, 30 min and 2 h, code samples.

Webhooks can also be managed via the API: GET/POST /api/v1/webhooks, GET/DELETE /api/v1/webhooks/{id} and GET /api/v1/webhooks/{id}/deliveries (delivery log).

8. Support

Bug or feature request: podpora@terminuj.com.