BrasnarHub · за разработчици
Базов адрес: https://brasnarhub.com/api/v1 · Формат: JSON (UTF-8) · Часова зона: Europe/Sofia · Суми: цели евроцентове (2550 = €25.50).
Машинно четима спецификация: OpenAPI 3 (openapi.yaml).
Клиенти получават токен от POST /auth/token и го пращат като Authorization: Bearer <token>.
Салони създават API ключове в панела → „API ключове“ (план ENTERPRISE). Всеки ключ има права:
bookings:read — Четене на резервацииbookings:write — Създаване и промяна на резервацииclients:read — Четене на клиенти| Метод | Адрес | Описание |
|---|---|---|
| GET | /api/v1/salons | Списък с публикувани салони. Филтри: city, district, category, q, per_page, page. |
| GET | /api/v1/salons/{slug} | Салон с активните услуги и бръснари. |
| GET | /api/v1/salons/{slug}/availability | Свободни часове за ден: service_ids[] (задължително), barber (slug или id), date (ГГГГ-ММ-ДД). |
| GET | /api/v1/barbers/free-now | „Свободни СЕГА“ — бръснари със свободен час в следващите 2 часа. city, limit (1–20). |
| Метод | Адрес | Описание |
|---|---|---|
| POST | /api/v1/auth/token | Вход: email, password, device_name → token. Ограничено до 5 опита/мин. |
| DELETE | /api/v1/auth/token | Анулира текущия токен. |
| POST | /api/v1/bookings | Нова резервация: salon, service_ids[], barber, starts_at (ISO 8601), name, phone, email, notes. ?src=own за собствен линк на салона. |
| GET | /api/v1/me/bookings | Моите резервации: status, upcoming=1, per_page, page. |
| POST | /api/v1/bookings/{code}/cancel | Отказ от резервация (reason). Спазва срока за отказ на салона. |
| Метод | Адрес | Описание |
|---|---|---|
| GET | /api/v1/salon/bookings | Резервации за период: from, to (ГГГГ-ММ-ДД, до 92 дни), status, barber. Право: bookings:read. |
| POST | /api/v1/salon/bookings | Резервация от салона (източник „по телефона“): service_ids[], barber, starts_at, client{name, phone, email, notes, salon_client_id}. Право: bookings:write. |
| PATCH | /api/v1/salon/bookings/{code} | action: complete | no_show | cancel | reschedule (+ starts_at, reason). Право: bookings:write. |
| GET | /api/v1/salon/clients | Клиентска база: q, per_page, page. Право: clients:read. |
curl -X POST https://brasnarhub.com/api/v1/bookings \
-H "Authorization: Bearer $TOKEN" -H "Accept: application/json" -H "Content-Type: application/json" \
-d '{"salon":"barbershop-sofia","service_ids":[12],"barber":"ivan-petrov","starts_at":"2026-09-18T10:30:00+03:00","phone":"0888123456"}'
Списъците връщат data, links и meta (current_page, last_page, per_page, total). Параметри: page, per_page (до 100).
Всички грешки имат един и същ формат. Съобщенията са на български и могат да се покажат на потребителя.
{
"error": {
"code": "booking_failed",
"message": "Този час току-що беше зает. Избери друг свободен час.",
"details": {}
}
}
| HTTP | code | Кога |
|---|---|---|
| 401 | unauthenticated | Липсващ, невалиден или изтекъл токен / API ключ. |
| 403 | plan_required, insufficient_ability | Планът на салона не включва API или ключът няма нужното право. |
| 404 | not_found | Салон, бръснар, услуга или резервация не са намерени. |
| 422 | validation_failed, booking_failed, invalid_credentials… | Невалидни данни или нарушено правило (напр. зает час). |
| 429 | too_many_requests | Превишен лимит. Виж хедъра Retry-After. |
Публични: 60 заявки/мин на IP · Вход: 5/мин · Клиенти: 120/мин · Салонни ключове: 300/мин.
Салонът добавя URL адреси в „API ключове“ → „Уебхукове“. При събитие изпращаме POST с JSON тяло. Неуспешните доставки (не-2xx или таймаут) се повтарят след 1, 5, 15, 60 и 240 минути; всеки опит се записва в дневника.
booking.created — Нова резервацияbooking.cancelled — Отказана резервацияbooking.rescheduled — Преместена резервацияbooking.completed — Завършена резервацияХедъри: X-BrasnarHub-Event, X-BrasnarHub-Delivery (uuid), X-BrasnarHub-Event-Id и Idempotency-Key (еднакви за всички адреси и повторни опити на едно събитие — използвай ги за дедупликация; също event_id в тялото), X-BrasnarHub-Timestamp, X-BrasnarHub-Signature: sha256=<hex>.
Подписът е HMAC-SHA256 на "{timestamp}.{сурово тяло}" с тайния ключ на адреса. Проверка (PHP):
$expected = 'sha256=' . hash_hmac('sha256', $_SERVER['HTTP_X_BRASNARHUB_TIMESTAMP'] . '.' . file_get_contents('php://input'), $secret);
if (! hash_equals($expected, $_SERVER['HTTP_X_BRASNARHUB_SIGNATURE']) || abs(time() - (int) $_SERVER['HTTP_X_BRASNARHUB_TIMESTAMP']) > 300) {
http_response_code(400); exit;
}