SUBSCRIPTION_INACTIVE) — dane pozostają nienaruszone.
Szybki start
Sprawdź, czy token działa:
curl -H "Authorization: Bearer TWOJ_TOKEN" \
https://vouchermarket.pl/api/v1/me
W odpowiedzi dostaniesz dane firmy, plan i uprawnienia tokenu:
{
"success": true,
"data": {
"company": { "uuid": "…", "display_name": "Salon Luna", "city": "Wrocław" },
"plan": { "name": "Pro", "slug": "pro" },
"token": { "name": "Integracja GabinetOnline", "abilities": ["vouchers:read","codes:redeem"] }
}
}
Uwierzytelnianie
Każde zapytanie wymaga nagłówka Authorization: Bearer <token>.
Token generujesz w panelu — przy tworzeniu wybierasz, co ma móc robić. Token widać
tylko raz, w momencie utworzenia; potem przechowujemy wyłącznie jego skrót.
Dostępne uprawnienia:
| Uprawnienie | Co odblokowuje |
|---|---|
| vouchers:read | Lista i szczegóły Twoich voucherów |
| orders:read | Zamówienia i historia realizacji |
| codes:read | Sprawdzenie statusu kodu przed realizacją |
| codes:redeem | Realizacja kodu |
Token jest zawsze związany z jedną firmą — nie trzeba (i nie da się) przekazywać
company_id w zapytaniu. Każda odpowiedź zawiera wyłącznie Twoje dane.
Konwencje i limity
- Sukces:
{"success": true, "data": …} - Błąd:
{"success": false, "error": {"code": "…", "message": "…"}} - Daty w ISO 8601, kwoty jako liczby, waluta w osobnym polu.
- Listy są stronicowane:
?page=i?per_page=(maks. 100, domyślnie 25). Metadane w polumeta. - Limit: 120 zapytań na minutę. Po przekroczeniu HTTP 429.
Kody błędów, które warto obsłużyć:
| Kod | HTTP | Znaczenie |
|---|---|---|
| MISSING_TOKEN | 401 | Brak nagłówka Authorization |
| INVALID_TOKEN | 401 | Token nieznany lub odwołany |
| TOKEN_EXPIRED | 401 | Token po dacie ważności |
| SUBSCRIPTION_INACTIVE | 402 | Abonament nieopłacony |
| PLAN_WITHOUT_API | 403 | Plan inny niż Pro |
| INSUFFICIENT_SCOPE | 403 | Token bez wymaganego uprawnienia |
| NOT_FOUND | 404 | Zasób nie istnieje lub nie należy do firmy |
| ALREADY_USED / EXPIRED / CANCELED | 409 | Kod nie nadaje się do realizacji |
Endpointy
| Endpoint | Uprawnienie | Opis |
|---|---|---|
| GET/api/v1/me | — | Firma, plan, uprawnienia tokenu |
| GET/api/v1/vouchers | vouchers:read | Lista voucherów. Filtry: published, q |
| GET/api/v1/vouchers/{uuid} | vouchers:read | Szczegóły vouchera |
| GET/api/v1/orders | orders:read | Zamówienia. Filtry: payment_status, from, to |
| GET/api/v1/orders/{uuid} | orders:read | Zamówienie wraz z kodami |
| GET/api/v1/redemptions | orders:read | Historia realizacji |
| GET/api/v1/codes/{code} | codes:read | Status kodu przed realizacją |
| POST/api/v1/codes/{code}/redeem | codes:redeem | Realizacja kodu |
Realizacja vouchera
Najpierw sprawdź kod — dowiesz się, czy nadaje się do realizacji i ile na nim zostało:
curl -H "Authorization: Bearer TWOJ_TOKEN" \
https://vouchermarket.pl/api/v1/codes/LUNA-9F3K-220
{
"success": true,
"data": {
"code": "LUNA-9F3K-220",
"status": "active",
"can_redeem": true,
"voucher_name": "Masaż relaksacyjny 90 min",
"face_value": 220.0,
"remaining_value": 220.0,
"sessions_total": null,
"expires_at": "2027-10-26T12:00:00+02:00"
}
}
Następnie zrealizuj. Dla voucherów kwotowych możesz rozliczyć część wartości:
curl -X POST \
-H "Authorization: Bearer TWOJ_TOKEN" \
-H "Content-Type: application/json" \
-d '{"amount": 150, "note": "Wizyta 26.10"}' \
https://vouchermarket.pl/api/v1/codes/LUNA-9F3K-220/redeem
{
"success": true,
"message": "Voucher zrealizowany pomyślnie.",
"amount_used": 150.0,
"remaining_value": 70.0,
"new_status": "partially_used"
}
amount —
każda realizacja odejmuje jedno wejście. Pole remaining_value
dotyczy wyłącznie voucherów kwotowych.
Webhooki
Zamiast odpytywać API w pętli, podaj adres, na który mamy wysyłać zdarzenia. Konfigurujesz go w panelu: adres musi używać HTTPS, wybierasz listę zdarzeń i dostajesz sekret do weryfikacji podpisu.
Każde zadanie przychodzi jako POST z nagłówkami:
| Nagłówek | Zawartość |
|---|---|
| X-VM-Event | Nazwa zdarzenia, np. order.paid |
| X-VM-Delivery | UUID dostawy — ten sam przy ponowieniach, użyj go do idempotencji |
| X-VM-Timestamp | Czas uniksowy podpisania |
| X-VM-Signature | sha256=<HMAC> |
Ponowienia: odpowiedz kodem 2xx, żeby potwierdzić odbiór. Przy innym kodzie lub braku odpowiedzi ponawiamy do 5 razy z odstępami 1 min, 5 min, 15 min, 1 h i 3 h. Po 20 kolejnych nieudanych dostawach endpoint jest automatycznie wyłączany — zobaczysz to w panelu i włączysz go z powrotem jednym kliknięciem.
Idempotencja: ta sama dostawa może przyjść więcej niż raz (np. gdy
Twoja odpowiedź nie dotarła). Zapamiętuj X-VM-Delivery
i pomijaj powtórzenia.
Weryfikacja podpisu
Podpisujemy <timestamp>.<surowe ciało żądania>
algorytmem HMAC-SHA256 Twoim sekretem. Porównaj wynik metodą odporną na pomiar czasu
i odrzuć żądania starsze niż kilka minut:
// PHP $raw = file_get_contents('php://input'); $timestamp = $_SERVER['HTTP_X_VM_TIMESTAMP'] ?? ''; $signature = $_SERVER['HTTP_X_VM_SIGNATURE'] ?? ''; // odrzuć stare żądania (ochrona przed powtórzeniem) if (abs(time() - (int) $timestamp) > 300) { http_response_code(400); exit; } $expected = 'sha256=' . hash_hmac('sha256', $timestamp . '.' . $raw, $SEKRET); if (!hash_equals($expected, $signature)) { http_response_code(401); exit; } $event = json_decode($raw, true); // … obsłuż $event['event'] i $event['data'] http_response_code(200);
Zdarzenia
Każde żądanie ma tę samą kopertę:
{
"event": "order.paid",
"created_at": "2026-10-26T13:45:02+02:00",
"data": { … }
}
order.paid — voucher sprzedany i opłacony
Wysyłane raz, przy faktycznym przejściu zamówienia na status opłacony. Powtórzone powiadomienie od operatora płatności nie generuje drugiego zdarzenia.
"data": {
"order_uuid": "…",
"order_number": "VM/2026/000420",
"voucher_name": "Masaż relaksacyjny 90 min",
"code": "LUNA-9F3K-220",
"customer_email": "klient@example.com",
"recipient_name": "Anna",
"total": 220.0,
"company_payout": 211.2,
"currency": "PLN",
"payment_method": "stripe",
"paid_at": "2026-10-26T13:45:02+02:00"
}
code.redeemed — voucher zrealizowany
Wysyłane zarówno przy realizacji w panelu, jak i przez API. Pole status mówi, czy voucher został wykorzystany w całości.
"data": {
"code": "LUNA-9F3K-220",
"voucher_name": "Masaż relaksacyjny 90 min",
"method": "qr",
"amount_used": 150.0,
"remaining_value": 70.0,
"sessions_total": null,
"sessions_used": 1,
"status": "partially_used",
"redeemed_at": "2026-10-26T14:02:11+02:00"
}
order.refunded — zwrot zamówienia
Wysyłane po zatwierdzeniu zwrotu i unieważnieniu kodu.
"data": {
"order_uuid": "…",
"order_number": "VM/2026/000420",
"voucher_name": "Masaż relaksacyjny 90 min",
"total": 220.0,
"currency": "PLN",
"reason": "Rezygnacja klienta",
"refunded_at": "2026-10-27T09:12:00+02:00"
}
voucher.published — zmiana w katalogu
Jedno zdarzenie dla publikacji i wycofania — rozróżniasz je po polu is_published.
"data": {
"voucher_uuid": "…",
"name": "Masaż relaksacyjny 90 min",
"slug": "masaz-relaksacyjny-90-min-salon-luna-wroclaw",
"type": "service",
"price": 220.0,
"currency": "PLN",
"is_published": true,
"published_at": "2026-10-26T10:00:00+02:00"
}
Potrzebujesz czegoś, czego tu nie ma?
Napisz, z czym integrujesz — rozwijamy API pod realne zastosowania.
Napisz do nas