Послуги
Відкритий API/services/api/v1/
Клієнти, записи, вільні слоти, статуси та історія клієнта. Те саме, що робить кабінет, але для сайту, телеграм-бота чи рецепції.
Доступ
Токен у заголовку. Створюється в налаштуваннях модуля «Послуги» → «API для інтеграцій». На платному тарифі токен робочий, на безкоштовному — sandbox (усі методи працюють, дані живуть 24 години).
Authorization: Bearer <token>
X-API-Key: <token>
Обидва заголовки рівнозначні — достатньо одного.
Ліміти й режими
- Час і дати
- date, time, starts_at і ends_at — місцевий час бізнесу без зсуву: саме так календар і зберігає години, і саме їх бачить клієнт. created_at, updated_at і expires_at — повний ISO 8601 зі зсувом.
- Ліміт запитів
- 60 на годину на кожен токен платного тарифу, 30 — для sandbox. Ліміт налаштовується окремо для кожного токена: якщо інтеграції треба більше, напишіть у підтримку.
- Заголовки залишку
- X-RateLimit-Limit, X-RateLimit-Remaining і X-RateLimit-Reset приходять у кожній відповіді, а при 429 ще й Retry-After — у секундах до скидання вікна.
- Sandbox
- Токен безкоштовного тарифу працює в окремому просторі: він бачить лише створене ним і не може змінити справжні дані кабінету. Створені обʼєкти видаляються через 24 години (поле expires_at у кожній відповіді), не займають час у публічному календарі й не створюють доходів і списань.
- Кілька токенів
- До 5 токенів на платному тарифі — окремий на кожну інтеграцію, щоб відкликати один, не ламаючи решту. На безкоштовному — один sandbox-токен.
Ендпоінти
-
GET
/services/api/v1/clients/Список клієнтів
Клієнти акаунта з пагінацією й пошуком.
Параметри й приклади
Параметри запиту
Параметр Обовʼязковий Опис qні Пошук за імʼям, прізвищем, телефоном або email. is_activeні true або false — лише активні чи лише архівні. limitні Скільки повернути, 1–100. За замовчуванням 50. offsetні Зсув для наступної сторінки. За замовчуванням 0. Відповідь 200
{ "count": 128, "limit": 50, "offset": 0, "results": [ { "id": 41, "first_name": "Оксана", "last_name": "Мельник", "full_name": "Оксана Мельник", "email": "[email protected]", "phone": "+380671234567", "telegram": "@oksana", "notes": "Алергія на аміак", "is_active": true, "sandbox": false, "expires_at": null, "created_at": "2026-08-14T11:02:37+03:00", "updated_at": "2026-09-01T09:15:00+03:00" } ] }Помилки й тіла відповідей
-
401
missing_token{"error": {"code": "missing_token", "message": "Authorization header is missing."}} -
401
invalid_token{"error": {"code": "invalid_token", "message": "Token is invalid or revoked."}} -
403
module_required{"error": {"code": "module_required", "message": "Module is not enabled for this account."}} -
403
plan_required{"error": {"code": "plan_required", "message": "Paid plan required for this token."}} -
429
rate_limit_exceeded{"error": {"code": "rate_limit_exceeded", "message": "Hourly request limit exceeded."}} -
405
method_not_allowed{"error": {"code": "method_not_allowed", "message": "HTTP method is not allowed for this endpoint."}} -
400
invalid_parameter{"error": {"code": "invalid_parameter", "message": "Query parameter is invalid."}}
-
-
POST
/services/api/v1/clients/Створити клієнта
Обовʼязкове лише імʼя — решта полів за наявності.
Параметри й приклади
Поля тіла запиту
Поле Обовʼязкове Опис first_nameтак Імʼя, до 100 символів. last_nameні Прізвище, до 100 символів. emailні Перевіряється на формат. null — прибрати. phoneні До 30 символів, у будь-якому форматі. telegramні До 100 символів. notesні Внутрішня примітка, будь-яка довжина. is_activeні true за замовчуванням. Зірочка означає «одне з двох» — достатньо будь-якого.
Запит
{ "first_name": "Оксана", "last_name": "Мельник", "phone": "+380671234567", "email": "[email protected]", "notes": "Прийшла з Instagram" }Відповідь 201
{ "id": 42, "first_name": "Оксана", "last_name": "Мельник", "full_name": "Оксана Мельник", "email": "[email protected]", "phone": "+380671234567", "telegram": null, "notes": "Прийшла з Instagram", "is_active": true, "sandbox": false, "expires_at": null, "created_at": "2026-09-08T12:41:09+03:00", "updated_at": "2026-09-08T12:41:09+03:00" }Помилки й тіла відповідей
-
401
missing_token{"error": {"code": "missing_token", "message": "Authorization header is missing."}} -
401
invalid_token{"error": {"code": "invalid_token", "message": "Token is invalid or revoked."}} -
403
module_required{"error": {"code": "module_required", "message": "Module is not enabled for this account."}} -
403
plan_required{"error": {"code": "plan_required", "message": "Paid plan required for this token."}} -
429
rate_limit_exceeded{"error": {"code": "rate_limit_exceeded", "message": "Hourly request limit exceeded."}} -
405
method_not_allowed{"error": {"code": "method_not_allowed", "message": "HTTP method is not allowed for this endpoint."}} -
400
invalid_json{"error": {"code": "invalid_json", "message": "Request body is not a valid JSON object."}} -
400
validation_error{ "error": { "code": "validation_error", "message": "Some fields failed validation.", "details": { "first_name": "This field is required and must not be empty.", "email": "Not a valid email address." } } }
-
-
GET
/services/api/v1/clients/<id>/Один клієнт
Той самий обʼєкт, що у списку, за внутрішнім id.
Параметри й приклади
Відповідь 200
{ "id": 42, "first_name": "Оксана", "last_name": "Мельник", "full_name": "Оксана Мельник", "email": "[email protected]", "phone": "+380671234567", "telegram": null, "notes": "Прийшла з Instagram", "is_active": true, "sandbox": false, "expires_at": null, "created_at": "2026-09-08T12:41:09+03:00", "updated_at": "2026-09-08T12:41:09+03:00" }Помилки й тіла відповідей
-
401
missing_token{"error": {"code": "missing_token", "message": "Authorization header is missing."}} -
401
invalid_token{"error": {"code": "invalid_token", "message": "Token is invalid or revoked."}} -
403
module_required{"error": {"code": "module_required", "message": "Module is not enabled for this account."}} -
403
plan_required{"error": {"code": "plan_required", "message": "Paid plan required for this token."}} -
429
rate_limit_exceeded{"error": {"code": "rate_limit_exceeded", "message": "Hourly request limit exceeded."}} -
405
method_not_allowed{"error": {"code": "method_not_allowed", "message": "HTTP method is not allowed for this endpoint."}} -
404
not_found{"error": {"code": "not_found", "message": "Object does not exist."}}
-
-
PATCH
/services/api/v1/clients/<id>/Редагувати клієнта
Часткове оновлення: надсилайте лише ті поля, які змінюються. Порожнє тіло — це 400, а не «нічого не робити».
Параметри й приклади
Поля тіла запиту
Поле Обовʼязкове Опис first_nameні Імʼя, до 100 символів. Порожнім бути не може. last_nameні Прізвище. emailні Формат перевіряється, null прибирає значення. phoneні Телефон, null прибирає значення. telegramні Telegram, null прибирає значення. notesні Примітка. is_activeні Активність клієнта. Зірочка означає «одне з двох» — достатньо будь-якого.
Запит
{ "phone": "+380509998877", "notes": "Просила писати в Telegram" }Відповідь 200
{ "id": 42, "first_name": "Оксана", "last_name": "Мельник", "full_name": "Оксана Мельник", "email": "[email protected]", "phone": "+380509998877", "telegram": null, "notes": "Просила писати в Telegram", "is_active": true, "sandbox": false, "expires_at": null, "created_at": "2026-09-08T12:41:09+03:00", "updated_at": "2026-09-08T13:02:44+03:00" }Помилки й тіла відповідей
-
401
missing_token{"error": {"code": "missing_token", "message": "Authorization header is missing."}} -
401
invalid_token{"error": {"code": "invalid_token", "message": "Token is invalid or revoked."}} -
403
module_required{"error": {"code": "module_required", "message": "Module is not enabled for this account."}} -
403
plan_required{"error": {"code": "plan_required", "message": "Paid plan required for this token."}} -
429
rate_limit_exceeded{"error": {"code": "rate_limit_exceeded", "message": "Hourly request limit exceeded."}} -
405
method_not_allowed{"error": {"code": "method_not_allowed", "message": "HTTP method is not allowed for this endpoint."}} -
404
not_found{"error": {"code": "not_found", "message": "Object does not exist."}} -
400
invalid_json{"error": {"code": "invalid_json", "message": "Request body is not a valid JSON object."}} -
400
validation_error{ "error": { "code": "validation_error", "message": "Some fields failed validation.", "details": { "body": "Provide at least one of: first_name, last_name, email, phone, telegram, notes, is_active." } } }
-
-
POST
/services/api/v1/clients/<id>/status/Змінити статус клієнта
Активний або архівний. Окремий ендпоінт, бо це найчастіша зміна, і плутати її з редагуванням полів не варто.
Параметри й приклади
Поля тіла запиту
Поле Обовʼязкове Опис is_activeтак true — активний, false — в архіві. Зірочка означає «одне з двох» — достатньо будь-якого.
Запит
{ "is_active": false }Відповідь 200
{ "id": 42, "first_name": "Оксана", "last_name": "Мельник", "full_name": "Оксана Мельник", "email": "[email protected]", "phone": "+380509998877", "telegram": null, "notes": "Просила писати в Telegram", "is_active": false, "sandbox": false, "expires_at": null, "created_at": "2026-09-08T12:41:09+03:00", "updated_at": "2026-09-08T13:20:10+03:00" }Помилки й тіла відповідей
-
401
missing_token{"error": {"code": "missing_token", "message": "Authorization header is missing."}} -
401
invalid_token{"error": {"code": "invalid_token", "message": "Token is invalid or revoked."}} -
403
module_required{"error": {"code": "module_required", "message": "Module is not enabled for this account."}} -
403
plan_required{"error": {"code": "plan_required", "message": "Paid plan required for this token."}} -
429
rate_limit_exceeded{"error": {"code": "rate_limit_exceeded", "message": "Hourly request limit exceeded."}} -
405
method_not_allowed{"error": {"code": "method_not_allowed", "message": "HTTP method is not allowed for this endpoint."}} -
404
not_found{"error": {"code": "not_found", "message": "Object does not exist."}} -
400
invalid_json{"error": {"code": "invalid_json", "message": "Request body is not a valid JSON object."}} -
400
validation_error{ "error": { "code": "validation_error", "message": "Some fields failed validation.", "details": { "is_active": "This field is required and must be a boolean." } } }
-
-
GET
/services/api/v1/clients/<id>/history/Історія клієнта
Усі записи клієнта, підсумки й оплати. Оплати беруться з модуля «Облік доходів» — вони створюються з виконаних записів. Немає модуля — список порожній, і це не помилка.
Параметри й приклади
Відповідь 200
{ "client": { "id": 42, "full_name": "Оксана Мельник", "...": "решта полів як у GET клієнта" }, "stats": { "bookings_total": 7, "bookings_completed": 5, "bookings_cancelled": 1, "bookings_upcoming": 1, "revenue_completed": "3400.00", "first_visit": "2026-04-12", "last_visit": "2026-08-30" }, "bookings": [ { "id": 913, "status": "completed", "date": "2026-08-30", "time": "14:00", "starts_at": "2026-08-30T14:00:00", "ends_at": "2026-08-30T15:30:00", "duration_minutes": 90, "notes": null, "client": { "id": 42, "full_name": "Оксана Мельник", "phone": "+380509998877", "email": null }, "service": { "id": 3, "name": "Стрижка", "price": "700.00", "duration_minutes": 90 }, "sandbox": false, "expires_at": null, "created_at": "2026-08-20T10:00:00+03:00", "updated_at": "2026-08-30T15:31:02+03:00" } ], "payments": [ { "id": 55, "booking_id": 913, "date": "2026-08-30", "amount": "700.00", "currency": "UAH", "source": "booking_completed" } ] }Помилки й тіла відповідей
-
401
missing_token{"error": {"code": "missing_token", "message": "Authorization header is missing."}} -
401
invalid_token{"error": {"code": "invalid_token", "message": "Token is invalid or revoked."}} -
403
module_required{"error": {"code": "module_required", "message": "Module is not enabled for this account."}} -
403
plan_required{"error": {"code": "plan_required", "message": "Paid plan required for this token."}} -
429
rate_limit_exceeded{"error": {"code": "rate_limit_exceeded", "message": "Hourly request limit exceeded."}} -
405
method_not_allowed{"error": {"code": "method_not_allowed", "message": "HTTP method is not allowed for this endpoint."}} -
404
not_found{"error": {"code": "not_found", "message": "Object does not exist."}}
-
-
GET
/services/api/v1/services/Список послуг
Потрібен, щоб знати service_id і тривалість: від неї залежить сітка слотів.
Параметри й приклади
Параметри запиту
Параметр Обовʼязковий Опис is_activeні true або false. limitні 1–100, за замовчуванням 50. offsetні Зсув, за замовчуванням 0. Відповідь 200
{ "count": 4, "limit": 50, "offset": 0, "results": [ { "id": 3, "name": "Стрижка", "short_description": "Чоловіча або жіноча", "price": "700.00", "duration_minutes": 90, "is_active": true } ] }Помилки й тіла відповідей
-
401
missing_token{"error": {"code": "missing_token", "message": "Authorization header is missing."}} -
401
invalid_token{"error": {"code": "invalid_token", "message": "Token is invalid or revoked."}} -
403
module_required{"error": {"code": "module_required", "message": "Module is not enabled for this account."}} -
403
plan_required{"error": {"code": "plan_required", "message": "Paid plan required for this token."}} -
429
rate_limit_exceeded{"error": {"code": "rate_limit_exceeded", "message": "Hourly request limit exceeded."}} -
405
method_not_allowed{"error": {"code": "method_not_allowed", "message": "HTTP method is not allowed for this endpoint."}} -
400
invalid_parameter{"error": {"code": "invalid_parameter", "message": "Query parameter is invalid."}}
-
-
GET
/services/api/v1/slots/Вільні часові слоти
Сітка дорівнює тривалості послуги, зайняте виключається за реальним перетином часу, минулі години не показуються. Це та сама функція, що малює пікер у кабінеті, тож API не покаже вільним те, чого не приймає створення запису.
Параметри й приклади
Параметри запиту
Параметр Обовʼязковий Опис service_idтак Послуга, під тривалість якої рахується сітка. dateні YYYY-MM-DD. За замовчуванням — сьогодні. daysні Скільки днів підряд повернути, 1–14. За замовчуванням 1. Відповідь 200
{ "service_id": 3, "duration_minutes": 90, "count": 3, "results": [ { "date": "2026-09-10", "is_working_day": true, "slots": [ { "time": "09:00", "starts_at": "2026-09-10T09:00:00", "ends_at": "2026-09-10T10:30:00" }, { "time": "10:30", "starts_at": "2026-09-10T10:30:00", "ends_at": "2026-09-10T12:00:00" } ] }, { "date": "2026-09-11", "is_working_day": false, "slots": [] } ] }Помилки й тіла відповідей
-
401
missing_token{"error": {"code": "missing_token", "message": "Authorization header is missing."}} -
401
invalid_token{"error": {"code": "invalid_token", "message": "Token is invalid or revoked."}} -
403
module_required{"error": {"code": "module_required", "message": "Module is not enabled for this account."}} -
403
plan_required{"error": {"code": "plan_required", "message": "Paid plan required for this token."}} -
429
rate_limit_exceeded{"error": {"code": "rate_limit_exceeded", "message": "Hourly request limit exceeded."}} -
405
method_not_allowed{"error": {"code": "method_not_allowed", "message": "HTTP method is not allowed for this endpoint."}} -
400
invalid_parameter{"error": {"code": "invalid_parameter", "message": "Query parameter is invalid."}} -
404
not_found{"error": {"code": "not_found", "message": "Object does not exist."}}
-
-
GET
/services/api/v1/bookings/Список записів
Записи з фільтрами за датою, статусом, клієнтом і послугою.
Параметри й приклади
Параметри запиту
Параметр Обовʼязковий Опис date_fromні YYYY-MM-DD, включно. date_toні YYYY-MM-DD, включно. statusні pending, confirmed, cancelled або completed. client_idні Лише записи цього клієнта. service_idні Лише записи на цю послугу. limitні 1–100, за замовчуванням 50. offsetні Зсув, за замовчуванням 0. Відповідь 200
{ "count": 12, "limit": 50, "offset": 0, "results": [ { "id": 913, "status": "confirmed", "date": "2026-09-10", "time": "09:00", "starts_at": "2026-09-10T09:00:00", "ends_at": "2026-09-10T10:30:00", "duration_minutes": 90, "notes": "Просила майстра Ірину", "client": { "id": 42, "full_name": "Оксана Мельник", "phone": "+380509998877", "email": null }, "service": { "id": 3, "name": "Стрижка", "price": "700.00", "duration_minutes": 90 }, "sandbox": false, "expires_at": null, "created_at": "2026-09-08T12:50:00+03:00", "updated_at": "2026-09-08T12:50:00+03:00" } ] }Помилки й тіла відповідей
-
401
missing_token{"error": {"code": "missing_token", "message": "Authorization header is missing."}} -
401
invalid_token{"error": {"code": "invalid_token", "message": "Token is invalid or revoked."}} -
403
module_required{"error": {"code": "module_required", "message": "Module is not enabled for this account."}} -
403
plan_required{"error": {"code": "plan_required", "message": "Paid plan required for this token."}} -
429
rate_limit_exceeded{"error": {"code": "rate_limit_exceeded", "message": "Hourly request limit exceeded."}} -
405
method_not_allowed{"error": {"code": "method_not_allowed", "message": "HTTP method is not allowed for this endpoint."}} -
400
invalid_parameter{"error": {"code": "invalid_parameter", "message": "Query parameter is invalid."}}
-
-
POST
/services/api/v1/bookings/Створити запис
Час перевіряється так само, як у кабінеті: перетин із наявними записами за тривалістю послуги, робочий розклад і «час уже минув». Не пройшло — 409 із людським текстом причини в message.
Параметри й приклади
Поля тіла запиту
Поле Обовʼязкове Опис client_idтак Наявний клієнт цього акаунта. service_idтак Активна послуга цього акаунта. dateтак YYYY-MM-DD. timeтак HH:MM (приймається і HH:MM:SS). notesні Примітка до запису. statusні pending (за замовчуванням), confirmed, cancelled, completed. Зірочка означає «одне з двох» — достатньо будь-якого.
Запит
{ "client_id": 42, "service_id": 3, "date": "2026-09-10", "time": "09:00", "notes": "Просила майстра Ірину", "status": "confirmed" }Відповідь 201
{ "id": 914, "status": "confirmed", "date": "2026-09-10", "time": "09:00", "starts_at": "2026-09-10T09:00:00", "ends_at": "2026-09-10T10:30:00", "duration_minutes": 90, "notes": "Просила майстра Ірину", "client": { "id": 42, "full_name": "Оксана Мельник", "phone": "+380509998877", "email": null }, "service": { "id": 3, "name": "Стрижка", "price": "700.00", "duration_minutes": 90 }, "sandbox": false, "expires_at": null, "created_at": "2026-09-08T13:40:00+03:00", "updated_at": "2026-09-08T13:40:00+03:00" }Помилки й тіла відповідей
-
401
missing_token{"error": {"code": "missing_token", "message": "Authorization header is missing."}} -
401
invalid_token{"error": {"code": "invalid_token", "message": "Token is invalid or revoked."}} -
403
module_required{"error": {"code": "module_required", "message": "Module is not enabled for this account."}} -
403
plan_required{"error": {"code": "plan_required", "message": "Paid plan required for this token."}} -
429
rate_limit_exceeded{"error": {"code": "rate_limit_exceeded", "message": "Hourly request limit exceeded."}} -
405
method_not_allowed{"error": {"code": "method_not_allowed", "message": "HTTP method is not allowed for this endpoint."}} -
400
invalid_json{"error": {"code": "invalid_json", "message": "Request body is not a valid JSON object."}} -
400
validation_error{ "error": { "code": "validation_error", "message": "Some fields failed validation.", "details": { "client_id": "Client with this id does not exist in this account.", "date": "Required, format YYYY-MM-DD." } } } -
409
slot_taken{ "error": { "code": "slot_taken", "message": "Requested time slot is not available.", "details": { "reason": "overlaps_existing_booking" } } }
-
-
GET
/services/api/v1/bookings/<id>/Один запис
Той самий обʼєкт, що у списку, за внутрішнім id.
Параметри й приклади
Відповідь 200
{ "id": 914, "status": "confirmed", "date": "2026-09-10", "time": "09:00", "starts_at": "2026-09-10T09:00:00", "ends_at": "2026-09-10T10:30:00", "duration_minutes": 90, "notes": "Просила майстра Ірину", "client": { "id": 42, "full_name": "Оксана Мельник", "phone": "+380509998877", "email": null }, "service": { "id": 3, "name": "Стрижка", "price": "700.00", "duration_minutes": 90 }, "sandbox": false, "expires_at": null, "created_at": "2026-09-08T13:40:00+03:00", "updated_at": "2026-09-08T13:40:00+03:00" }Помилки й тіла відповідей
-
401
missing_token{"error": {"code": "missing_token", "message": "Authorization header is missing."}} -
401
invalid_token{"error": {"code": "invalid_token", "message": "Token is invalid or revoked."}} -
403
module_required{"error": {"code": "module_required", "message": "Module is not enabled for this account."}} -
403
plan_required{"error": {"code": "plan_required", "message": "Paid plan required for this token."}} -
429
rate_limit_exceeded{"error": {"code": "rate_limit_exceeded", "message": "Hourly request limit exceeded."}} -
405
method_not_allowed{"error": {"code": "method_not_allowed", "message": "HTTP method is not allowed for this endpoint."}} -
404
not_found{"error": {"code": "not_found", "message": "Object does not exist."}}
-
-
PATCH
/services/api/v1/bookings/<id>/Редагувати запис
Перенести на інший час, змінити послугу, клієнта чи примітку. Якщо змінюються дата, час або послуга — час перевіряється заново, але вже без урахування самого цього запису (інакше він конфліктував би сам із собою).
Параметри й приклади
Поля тіла запиту
Поле Обовʼязкове Опис client_idні Інший клієнт цього акаунта. service_idні Інша активна послуга. dateні YYYY-MM-DD. timeні HH:MM. notesні Примітка, null — прибрати. statusні pending, confirmed, cancelled, completed. Зірочка означає «одне з двох» — достатньо будь-якого.
Запит
{ "date": "2026-09-11", "time": "11:00" }Відповідь 200
{ "id": 914, "status": "confirmed", "date": "2026-09-11", "time": "11:00", "starts_at": "2026-09-11T11:00:00", "ends_at": "2026-09-11T12:30:00", "duration_minutes": 90, "notes": "Просила майстра Ірину", "client": { "id": 42, "full_name": "Оксана Мельник", "phone": "+380509998877", "email": null }, "service": { "id": 3, "name": "Стрижка", "price": "700.00", "duration_minutes": 90 }, "sandbox": false, "expires_at": null, "created_at": "2026-09-08T13:40:00+03:00", "updated_at": "2026-09-08T14:05:12+03:00" }Помилки й тіла відповідей
-
401
missing_token{"error": {"code": "missing_token", "message": "Authorization header is missing."}} -
401
invalid_token{"error": {"code": "invalid_token", "message": "Token is invalid or revoked."}} -
403
module_required{"error": {"code": "module_required", "message": "Module is not enabled for this account."}} -
403
plan_required{"error": {"code": "plan_required", "message": "Paid plan required for this token."}} -
429
rate_limit_exceeded{"error": {"code": "rate_limit_exceeded", "message": "Hourly request limit exceeded."}} -
405
method_not_allowed{"error": {"code": "method_not_allowed", "message": "HTTP method is not allowed for this endpoint."}} -
404
not_found{"error": {"code": "not_found", "message": "Object does not exist."}} -
400
invalid_json{"error": {"code": "invalid_json", "message": "Request body is not a valid JSON object."}} -
400
validation_error{ "error": { "code": "validation_error", "message": "Some fields failed validation.", "details": { "body": "Provide at least one of: client_id, service_id, date, time, notes, status." } } } -
409
slot_taken{ "error": { "code": "slot_taken", "message": "Requested time slot is not available.", "details": { "reason": "time_in_the_past" } } }
-
-
POST
/services/api/v1/bookings/<id>/status/Змінити статус запису
Переведення в completed тягне за собою те саме, що й у кабінеті: автоматичний дохід у модулі «Облік доходів» і списання матеріалів в ERP, якщо вони налаштовані. Для sandbox-токена ці наслідки не виконуються — тестовий запис не має рухати справжні гроші й склад.
Параметри й приклади
Поля тіла запиту
Поле Обовʼязкове Опис statusтак pending, confirmed, cancelled або completed. Зірочка означає «одне з двох» — достатньо будь-якого.
Запит
{ "status": "completed" }Відповідь 200
{ "id": 914, "status": "completed", "date": "2026-09-11", "time": "11:00", "starts_at": "2026-09-11T11:00:00", "ends_at": "2026-09-11T12:30:00", "duration_minutes": 90, "notes": "Просила майстра Ірину", "client": { "id": 42, "full_name": "Оксана Мельник", "phone": "+380509998877", "email": null }, "service": { "id": 3, "name": "Стрижка", "price": "700.00", "duration_minutes": 90 }, "sandbox": false, "expires_at": null, "created_at": "2026-09-08T13:40:00+03:00", "updated_at": "2026-09-11T12:31:00+03:00" }Помилки й тіла відповідей
-
401
missing_token{"error": {"code": "missing_token", "message": "Authorization header is missing."}} -
401
invalid_token{"error": {"code": "invalid_token", "message": "Token is invalid or revoked."}} -
403
module_required{"error": {"code": "module_required", "message": "Module is not enabled for this account."}} -
403
plan_required{"error": {"code": "plan_required", "message": "Paid plan required for this token."}} -
429
rate_limit_exceeded{"error": {"code": "rate_limit_exceeded", "message": "Hourly request limit exceeded."}} -
405
method_not_allowed{"error": {"code": "method_not_allowed", "message": "HTTP method is not allowed for this endpoint."}} -
404
not_found{"error": {"code": "not_found", "message": "Object does not exist."}} -
400
invalid_json{"error": {"code": "invalid_json", "message": "Request body is not a valid JSON object."}} -
400
validation_error{ "error": { "code": "validation_error", "message": "Some fields failed validation.", "details": { "status": "This field is required and must be one of: pending, confirmed, cancelled, completed." } } }
-
Усі помилки
Формат один на всі модулі. code стабільний — на нього
і варто перевіряти; message англійською й може бути
уточнений. У details — конкретні поля, якщо помилка
про них. Тіло кожної помилки показане в самому ендпоінті, ось
загальний вигляд:
{
"error": {
"code": "validation_error",
"message": "Some fields failed validation.",
"details": {
"field_name": "What exactly is wrong with this field."
}
}
}
| code | HTTP | message | Коли |
|---|---|---|---|
missing_token |
401 | Authorization header is missing. | Немає ні Authorization: Bearer, ні X-API-Key. |
invalid_token |
401 | Token is invalid or revoked. | Токена не існує або його відкликали в налаштуваннях модуля. |
module_required |
403 | Module is not enabled for this account. | До акаунта не підключено модуль «Послуги». |
plan_required |
403 | Paid plan required for this token. | Токен видано на платному тарифі, а тариф уже не платний. Дані не зникають — але щоб API знову працював, треба або поновити підписку, або створити sandbox-токен. |
rate_limit_exceeded |
429 | Hourly request limit exceeded. | Вичерпано ліміт запитів на годину. Коли вікно скинеться — у заголовках X-RateLimit-Reset і Retry-After. |
method_not_allowed |
405 | HTTP method is not allowed for this endpoint. | Не той HTTP-метод. Дозволені перелічені в заголовку Allow. |
invalid_json |
400 | Request body is not a valid JSON object. | Тіло запиту не розібралось як JSON. |
validation_error |
400 | Some fields failed validation. | Поля не пройшли перевірку. Які саме й що з ними — у details. |
invalid_parameter |
400 | Query parameter is invalid. | Некоректний параметр у query string (дата, id, limit). |
not_found |
404 | Object does not exist. | Обʼєкта немає або він належить іншому акаунту — назовні це одне й те саме, щоб чужі id не можна було перебрати. |
slot_taken |
409 | Requested time slot is not available. | Час зайнятий іншим записом, поза робочим розкладом або вже минув. Причина — у details.reason: time_in_the_past, non_working_day, outside_working_hours або overlaps_existing_booking. |
Вебхуки
Вебхук — це API навпаки: не ви питаєте нас, а ми надсилаємо POST на вашу адресу, коли щось стається. Опитувати /bookings/ раз на хвилину не потрібно.
Куди вставити адресу: Налаштування модуля «Послуги» → «Вебхуки». Там же — секрет для перевірки підпису, кнопка тестової доставки й журнал останніх спроб.
Події
| event | Коли | data |
|---|---|---|
client.created |
Новий клієнт — з кабінету, публічної форми запису або через API. | client |
client.updated |
Змінились дані клієнта або його статус (активний / в архіві). | client |
booking.created |
Новий запис на послугу — з кабінету, публічної сторінки запису або через API. | booking |
booking.updated |
Перенесення на інший час, зміна послуги, клієнта або примітки. | booking |
booking.status_changed |
Окрема подія, бо саме на неї вішають нагадування, відгуки й підрахунок виручки. У changes — старий і новий статус. | booking |
Тіло запиту
{
"event": "booking.status_changed",
"delivery_id": "0f3c1d2e-6f5a-4a1b-9c77-1b2f4e5d6a70",
"created_at": "2026-09-11T12:31:00+03:00",
"sandbox": false,
"changes": {
"status": { "from": "confirmed", "to": "completed" }
},
"data": {
"id": 914,
"status": "completed",
"date": "2026-09-11",
"time": "11:00",
"starts_at": "2026-09-11T11:00:00",
"ends_at": "2026-09-11T12:30:00",
"duration_minutes": 90,
"notes": "Просила майстра Ірину",
"client": { "id": 42, "full_name": "Оксана Мельник", "phone": "+380509998877", "email": null },
"service": { "id": 3, "name": "Стрижка", "price": "700.00", "duration_minutes": 90 },
"sandbox": false,
"expires_at": null,
"created_at": "2026-09-08T13:40:00+03:00",
"updated_at": "2026-09-11T12:31:00+03:00"
}
}
data — той самий обʼєкт, що віддає відповідний ендпоінт API. Другий парсер на ті самі поля писати не треба. changes приходить лише в booking.status_changed.
Заголовки
| Заголовок | Що в ньому |
|---|---|
X-ClearMoney-Event |
Код події — те саме, що в полі event. |
X-ClearMoney-Delivery |
UUID доставки. За ним відсіюйте повтори. |
X-ClearMoney-Timestamp |
Час відправлення, ISO 8601. |
X-ClearMoney-Signature |
sha256=<HMAC-SHA256 сирого тіла запиту з вашим секретом>. |
Перевірка підпису
Підпис рахується від сирого тіла запиту — до будь-якого розбору JSON. Якщо спершу розібрати й серіалізувати назад, підпис не збіжиться через порядок ключів і пробіли.
import hashlib
import hmac
def is_from_clearmoney(request_body: bytes, signature: str, secret: str) -> bool:
expected = "sha256=" + hmac.new(
secret.encode(), request_body, hashlib.sha256
).hexdigest()
# compare_digest, а не ==: побайтове порівняння дає можливість
# підібрати підпис за часом відповіді.
return hmac.compare_digest(expected, signature)
<?php
function is_from_clearmoney($body, $signature, $secret) {
$expected = 'sha256=' . hash_hmac('sha256', $body, $secret);
return hash_equals($expected, $signature);
}
$body = file_get_contents('php://input');
$signature = $_SERVER['HTTP_X_CLEARMONEY_SIGNATURE'] ?? '';
if (!is_from_clearmoney($body, $signature, CLEARMONEY_WEBHOOK_SECRET)) {
http_response_code(401);
exit;
}
http_response_code(200);
Вимоги до вашого боку
- Тільки https
- Ми надсилаємо дані клієнтів — імена, телефони. Посилання на http не приймається, як і адреса у внутрішній мережі.
- Відповідайте 2xx
- Будь-який код 2xx означає «прийняв». Таймаут — 10 секунд: складну обробку робіть після відповіді, а не до неї.
- Ідемпотентність
- Одна подія може прийти двічі — мережа є мережа. Тримайтеся X-ClearMoney-Delivery: той самий UUID означає ту саму подію.
Повтори й відмови
- Коли повторюємо
- Таймаут, обрив зʼєднання, 429 і 5xx. До 5 спроб із наростаючою паузою: хвилина, потім довше, до двох годин.
- Коли не повторюємо
- Решта 4xx — це «надсилаєш не те або не туди». Повтори тут лише марно стукають у ваш сервер.
- Мертва адреса
- 20 невдач підряд — і вебхук вимикається, а в налаштуваннях зʼявляється причина. Інакше інтеграція місяцями «працює», а події нікуди не доходять.
- Sandbox
- Вебхук безкоштовного тарифу отримує лише події sandbox-обʼєктів. У платного в конверті є поле sandbox — за ним тестові події можна відсіяти.
Наявні ендпоінти кабінету
Ці адреси лишились для сторінок кабінету й працюють лише з сесією браузера. Для інтеграцій вони не потрібні — усе те саме є вище під токеном.
-
GET
/services/api/clients/Список клієнтів -
POST
/services/api/clients/create/Створити клієнта -
GET
/services/api/clients/<id>/Один клієнт -
POST
/services/api/clients/<id>/delete/Видалити клієнта
Спільні правила
Гроші рядками, дати ISO 8601, ізоляція даних за токеном, ідемпотентність ingest — однакові для всіх модулів і описані на головній документації.
Інші модулі
- Товари та замовлення Відкритий API
- Облік доходів У планах
Питання по інтеграції — у Telegram або на сторінці підтримки.