Każde żądanie wymaga klucza API firmy (Integracje → Webhooki i API w panelu) przesyłanego jako Authorization: Bearer tt_live_…. Odpowiedzi i błędy są w formacie JSON.
curl "https://api.tapti.me/v1/company/reservations?status=confirmed&updatedSince=2026-09-01T00:00:00Z" \
-H "Authorization: Bearer tt_live_…"
Uwierzytelnianie
Każde żądanie zawiera klucz API firmy jako token typu Bearer. Klucz tworzy się w panelu — Integracje → Webhooki i API → Klucze REST API — gdzie jest wyświetlany jeden raz, a po stronie serwera przechowywany wyłącznie jako skrót SHA-256; utracony klucz się unieważnia i zastępuje nowym, nie da się go odzyskać. Firma może mieć do 10 aktywnych kluczy.
- Klucze tylko do odczytu mogą wywoływać każdy endpoint GET oraz subskrybować i anulować webhooki — subskrypcja nie wysyła niczego, czego klucz nie mógłby już odczytać.
- Klucze do odczytu i zapisu mogą dodatkowo wysyłać żądanie POST zmieniające status rezerwacji; klucz tylko do odczytu otrzymuje na tych ścieżkach 403 Forbidden.
- Klucz należy do jednej firmy — każda lista i każde wyszukiwanie są już do niej zawężone, nie ma parametru companyId.
Limity żądań
50 żądań na minutę na klucz, w oknie przesuwnym, wspólnie dla wszystkich endpointów. Po przekroczeniu zwracany jest kod 429 Too Many Requests; należy odczekać i ponowić żądanie zamiast odpytywać częściej — albo zasubskrybować webhook i przestać odpytywać.
Endpointy
/v1/company
Tylko odczyt lub odczyt i zapis
Pobranie bieżącej firmy
Firma, do której należy klucz, oraz uprawnienia samego klucza.
/v1/company/reservations
Tylko odczyt lub odczyt i zapis
Lista rezerwacji stolików
Rezerwacje stolików firmy, od najwcześniejszego terminu rozpoczęcia — a gdy ustawiono updatedSince, od najdawniej zaktualizowanej.
| Parametr | Typ | Znaczenie |
|---|---|---|
status |
string | Rozdzielone przecinkami: pending, confirmed, seated, completed, no_show, cancelled. cancelled obejmuje oba powody odwołania. |
branchId |
integer | Zawężenie do jednego oddziału. |
from |
ISO 8601 datetime | Tylko rezerwacje rozpoczynające się w tym momencie lub później (UTC, jeśli nie podano przesunięcia). |
to |
ISO 8601 datetime | Tylko rezerwacje rozpoczynające się przed tym momentem. |
updatedSince |
ISO 8601 datetime | Tylko rezerwacje zmienione od tego momentu; przełącza sortowanie na rosnące według updatedAt, na potrzeby synchronizacji. |
limit |
integer | Rozmiar strony, 1–100. Domyślnie 50. |
page |
integer | Numer strony liczony od 1. Domyślnie 1. |
/v1/company/appointments
Tylko odczyt lub odczyt i zapis
Lista wizyt
Ten sam kształt i te same filtry co w rezerwacjach stolików, dla modułu Wizyty.
| Parametr | Typ | Znaczenie |
|---|---|---|
status |
string | Rozdzielone przecinkami: pending, confirmed, completed, no_show, cancelled. |
branchId |
integer | Zawężenie do jednego oddziału. |
from |
ISO 8601 datetime | Tylko rezerwacje rozpoczynające się w tym momencie lub później. |
to |
ISO 8601 datetime | Tylko rezerwacje rozpoczynające się przed tym momentem. |
updatedSince |
ISO 8601 datetime | Tylko rezerwacje zmienione od tego momentu; sortowanie rosnące według updatedAt. |
limit |
integer | Rozmiar strony, 1–100. Domyślnie 50. |
page |
integer | Numer strony liczony od 1. Domyślnie 1. |
/v1/company/reservations/{id}
Tylko odczyt lub odczyt i zapis
Pobranie rezerwacji stolika
Jedna rezerwacja, w tym samym kształcie, w jakim przesyłają ją webhooki, wraz z atrybucją. 404, gdy identyfikator nie należy do firmy klucza.
/v1/company/appointments/{id}
Tylko odczyt lub odczyt i zapis
Pobranie wizyty
Jedna wizyta, z tym samym kształtem i zasadami co przy pobieraniu rezerwacji stolika.
/v1/company/reservations/{id}/status
Tylko odczyt i zapis
Zmiana statusu rezerwacji stolika
Potwierdzenie, posadzenie gości, zakończenie, oznaczenie niestawiennictwa, odwołanie lub ponowne otwarcie — wywołuje te same webhooki i konwersje co zmiana na tablicy. Treść JSON: {"status": "..."}.
| Parametr | Typ | Znaczenie |
|---|---|---|
status |
string, wymagany | Jedna z wartości: pending, confirmed, seated, completed, no_show, cancelled (akceptowane są też canceled i canceled_by_venue). |
/v1/company/appointments/{id}/status
Tylko odczyt i zapis
Zmiana statusu wizyty
Tak samo jak endpoint rezerwacji stolika, bez stanu seated.
| Parametr | Typ | Znaczenie |
|---|---|---|
status |
string, wymagany | Jedna z wartości: pending, confirmed, completed, no_show, cancelled (akceptowane są też canceled i canceled_by_venue). |
/v1/company/events
Tylko odczyt lub odczyt i zapis
Odpytywanie strumienia zdarzeń
Wszystkie zdarzenia dotyczące rezerwacji, zamówień i lojalności, od najstarszego — ten sam strumień, z którego powstają webhooki. Ostatni widziany kursor przekazany jako after zwraca tylko nowe zdarzenia, a type — tylko wybrane rodzaje.
| Parametr | Typ | Znaczenie |
|---|---|---|
after |
integer, kursor | Kursor ostatniego przetworzonego zdarzenia. Bez tego parametru odczyt zaczyna się od początku. |
type |
string | Typy lub rodziny zdarzeń rozdzielone przecinkami: booking.confirmed,order.placed albo order, loyalty.*. Bez tego parametru zwracane są wszystkie zdarzenia. |
limit |
integer | Rozmiar strony, 1–100. Domyślnie 50. |
/v1/company/orders
Tylko odczyt lub odczyt i zapis
Lista zamówień
Zamówienia gości przy stoliku, na wynos i z dostawą oraz każda sprzedaż nabita na kasie, od najstarszego — a gdy ustawiono paidSince, w kolejności opłacenia. Zamówienie wciąż oczekujące na przedpłatę jest pomijane.
| Parametr | Typ | Znaczenie |
|---|---|---|
status |
string | Rozdzielone przecinkami: open, paid. |
source |
string | customer (złożone przez gościa) lub staff (nabite przez personel). |
fulfilment |
string | Rozdzielone przecinkami: dine_in, takeaway, delivery. |
branchId |
integer | Zawężenie do jednego oddziału. |
from |
ISO 8601 datetime | Tylko zamówienia utworzone w tym momencie lub później. |
to |
ISO 8601 datetime | Tylko zamówienia utworzone przed tym momentem. |
paidSince |
ISO 8601 datetime | Tylko zamówienia opłacone od tego momentu; sortowanie rosnące według paidAt, na potrzeby synchronizacji sprzedaży. |
limit |
integer | Rozmiar strony, 1–100. Domyślnie 50. |
page |
integer | Numer strony liczony od 1. Domyślnie 1. |
/v1/company/orders/{id}
Tylko odczyt lub odczyt i zapis
Pobranie zamówienia
Jedno zamówienie z pozycjami, sumami i atrybucją, w kształcie, w jakim przesyłają je webhooki zamówień.
/v1/company/loyalty/programs
Tylko odczyt lub odczyt i zapis
Lista programów lojalnościowych
Wszystkie programy z kartą pieczątek: nazwa, status, wymagana liczba pieczątek, nagroda i miejsce, w którym obowiązuje.
/v1/company/loyalty/cards
Tylko odczyt lub odczyt i zapis
Lista kart lojalnościowych
Karty uczestników w kształcie obiektu lojalnościowego. Uczestnik, który zapełnił kartę, ma ją w stanie completed, a obok nową, aktywną; customer.id to uczestnik.
| Parametr | Typ | Znaczenie |
|---|---|---|
programId |
integer | Zawężenie do jednego programu. |
customerId |
integer | Zawężenie do jednego uczestnika. |
status |
string | Rozdzielone przecinkami: active, completed. |
updatedSince |
ISO 8601 datetime | Tylko karty ostemplowane lub zakończone od tego momentu; sortowanie rosnące według updatedAt. |
limit |
integer | Rozmiar strony, 1–100. Domyślnie 50. |
page |
integer | Numer strony liczony od 1. Domyślnie 1. |
/v1/company/loyalty/rewards
Tylko odczyt lub odczyt i zapis
Lista nagród lojalnościowych
Nagrody zdobyte po zapełnieniu karty, z kodem, terminem ważności i informacją, czy zostały wydane.
| Parametr | Typ | Znaczenie |
|---|---|---|
programId |
integer | Zawężenie do jednego programu. |
customerId |
integer | Zawężenie do jednego uczestnika. |
status |
string | Rozdzielone przecinkami: issued, redeemed, expired. |
from |
ISO 8601 datetime | Tylko nagrody przyznane w tym momencie lub później. |
to |
ISO 8601 datetime | Tylko nagrody przyznane przed tym momentem. |
limit |
integer | Rozmiar strony, 1–100. Domyślnie 50. |
page |
integer | Numer strony liczony od 1. Domyślnie 1. |
/v1/company/webhooks
Tylko odczyt lub odczyt i zapis
Lista subskrypcji webhooków
Subskrypcje utworzone przez ten klucz. Webhooki dodane w panelu nie są tu wymieniane.
/v1/company/webhooks
Tylko odczyt lub odczyt i zapis
Subskrypcja webhooka
Rozpoczyna wysyłanie zdarzeń na adres URL — to wywołuje aplikacja platformy automatyzacji, gdy użytkownik włącza wyzwalacz. Zwraca subskrypcję i jej klucz podpisu, jednorazowo. Treść JSON: {"url": "…", "events": ["order.placed"]}; akceptowany jest też format Zapier {"target_url": "…", "event": "…"}.
| Parametr | Typ | Znaczenie |
|---|---|---|
url |
string, wymagany | Adres https, na który są wysyłane zdarzenia (akceptowany jest też target_url). |
events |
tablica stringów, wymagana | Typy zdarzeń, rodziny takie jak order.* lub loyalty albo * dla wszystkich (akceptowane jest też event, dla jednego). |
description |
string | Nazwa wyświetlana w panelu. Domyślnie nazwa platformy i nazwa klucza. |
/v1/company/webhooks/{id}
Tylko odczyt lub odczyt i zapis
Anulowanie subskrypcji webhooka
Zatrzymuje wysyłanie do subskrypcji utworzonej przez ten klucz. Zwraca 204. Unieważnienie klucza usuwa również wszystkie jego subskrypcje.
Obiekt rezerwacji
Rezerwacja stolika i wizyta mają jeden wspólny kształt: kind, id, status, source, guestInitiated, startsAt/endsAt/timezone (strefa czasowa oddziału), currency, company, branch, guest, attribution, conversionId, createdAt/updatedAt — a do tego partySize i table dla rezerwacji stolika oraz service i specialist dla wizyty. To dokładnie to, co dostarcza webhook, więc odbiorca obsługujący jedno obsługuje oba.
{
"data": {
"kind": "reservation",
"id": 4821,
"status": "confirmed",
"source": "online",
"guestInitiated": true,
"startsAt": "2026-09-12T20:00:00+03:00",
"endsAt": "2026-09-12T21:30:00+03:00",
"timezone": "Asia/Baku",
"currency": "AZN",
"company": { "id": 12, "name": "Cafe Aroma", "slug": "cafe-aroma", "country": "AZ" },
"branch": { "id": 3, "name": "Nizami st." },
"partySize": 4,
"table": { "id": 9, "label": "T3" },
"guest": { "name": "Maria K.", "phone": "…", "email": "…" },
"locale": "en",
"note": null,
"conversionId": "tt3f9c…",
"createdAt": "2026-09-10T08:12:04+00:00",
"updatedAt": "2026-09-12T20:00:03+00:00",
"attribution": { "channel": "widget", "utmSource": "instagram", "gclid": null, "fbclid": "IwAR2…" }
}
}
Obiekt zamówienia
Zamówienie ma jeden kształt, niezależnie od miejsca, w którym się pojawia — REST API, webhooki zamówień, strumień zdarzeń: kind ("order"), id, number (numer wywoływany przez personel), status (open lub paid), source (customer lub staff), guestInitiated, fulfilment, table, label, deliveryAddress, note, currency, timezone, company, branch, customer (uczestnik programu lojalnościowego, jeśli personel go zidentyfikował), items (name, variant, quantity, unitPriceCents, subtotalCents), itemCount, subtotalCents, discountCents, deliveryFeeCents, tipCents, totalCents, valueCents (wartość zamówienia bez napiwku — liczba raportowana w konwersjach), paymentMethod, servedBy, conversionId, createdAt, paidAt i attribution. Kwoty są zawsze w jednostkach podrzędnych waluty (np. groszach).
{
"data": {
"kind": "order",
"id": 9170,
"number": 42,
"status": "paid",
"source": "customer",
"guestInitiated": true,
"fulfilment": "takeaway",
"table": null,
"label": "Ana",
"currency": "EUR",
"branch": { "id": 3, "name": "Vitosha Blvd" },
"customer": { "id": 311, "name": "Ana", "phone": "…" },
"items": [
{ "menuItemId": 88, "name": "Flat white", "variant": "Large",
"quantity": 2, "unitPriceCents": 450, "subtotalCents": 900 }
],
"itemCount": 2,
"subtotalCents": 900,
"discountCents": 0,
"deliveryFeeCents": 0,
"tipCents": 100,
"totalCents": 1000,
"valueCents": 900,
"paymentMethod": "online",
"conversionId": "tt81ad…",
"createdAt": "2026-09-12T12:04:10+03:00",
"paidAt": "2026-09-12T12:05:02+03:00",
"attribution": { "channel": "web", "utmSource": "google", "gclid": "Cj0K…" }
}
}
Obiekt lojalnościowy
Każde zdarzenie lojalnościowe, karta i nagroda mają jeden wspólny kształt: kind ("loyalty"), id (karta), timezone, company, branch (miejsce zdarzenia, jeśli jest), program (id, name, stampsRequired, rewardTitle), customer (id, name, phone, locale), card (id, status, stampsCount, stampsRequired, stampsToReward, createdAt), stamp (dla pieczątki: source, issuedBy, createdAt) i reward (dla nagrody: code, title, status, expiresAt, redeemedAt, redeemedBy), a także conversionId — identyfikator, pod którym raportowane jest dołączenie do programu lojalnościowego.
{
"kind": "loyalty",
"id": 5120,
"program": { "id": 4, "name": "Coffee card", "stampsRequired": 8, "rewardTitle": "Free coffee" },
"customer": { "id": 311, "name": "Ana", "phone": "…", "locale": "bg" },
"card": { "id": 5120, "status": "active", "stampsCount": 5,
"stampsRequired": 8, "stampsToReward": 3 },
"branch": { "id": 3, "name": "Vitosha Blvd" },
"stamp": { "source": "qr_scan", "issuedBy": "Ivan", "createdAt": "…" },
"reward": null,
"conversionId": "tt5c02…"
}
Strumień zdarzeń
Każdy wiersz to { id, cursor, type, createdAt, previousStatus, data }. data zawiera obiekt pod kluczem wskazanym przez prefiks zdarzenia: data.booking, data.order lub data.loyalty. Należy zapisywać najwyższy przetworzony kursor i przekazywać go z powrotem jako after — nigdy nie pomija ani nie powtarza wiersza, więc można bezpiecznie wznowić pracę po awarii. Nieobsługiwane typy należy ignorować: mogą pojawiać się nowe.
| Typ zdarzenia | Znaczenie |
|---|---|
booking.requested | Gość poprosił o rezerwację, która czeka na potwierdzenie przez lokal. |
booking.confirmed | Rezerwacja została potwierdzona — od razu przy utworzeniu lub później przez personel. |
booking.cancelled | Odwołana przez gościa lub lokal; wskazuje to pole status. |
booking.no_show | Gość się nie pojawił. |
booking.completed | Wizyta dobiegła końca. |
order.placed | Zamówienie gościa dotarło do lokalu — ze strony, z kodu QR przy stoliku, na wynos lub z dostawą; po płatności, jeśli lokal pobiera ją z góry. |
order.paid | Dowolne zamówienie zostało rozliczone, w tym sprzedaż nabita na kasie. |
loyalty.member_joined | Klient otrzymał pierwszą pieczątkę w programie. |
loyalty.stamp_added | Do karty dodano pieczątkę. |
loyalty.reward_issued | Karta została zapełniona i przyznano nagrodę. |
loyalty.reward_redeemed | Nagroda została wydana. |
curl "https://api.tapti.me/v1/company/events?after=998&limit=100" \
-H "Authorization: Bearer tt_live_…"
Webhooki
Wystarczy utworzyć endpoint w sekcji Integracje → Webhooki i API — lub podłączyć Zapier, Make, n8n albo Pipedream w sekcji Integracje → Automatyzacja — a TapTime wyśle żądanie POST z podpisanym zdarzeniem JSON w chwili, gdy zmieni się rezerwacja, zamówienie lub karta lojalnościowa. Zdarzenia wybiera się dla każdego endpointu osobno. Firma może mieć łącznie do 50 webhooków, postbacków, czatów i połączeń z platformami automatyzacji.
| Nagłówek | Znaczenie |
|---|---|
TapTime-Event | Typ zdarzenia, np. booking.confirmed. |
TapTime-Event-Id | Stały identyfikator zdarzenia — służy do usuwania duplikatów przy ponownym doręczeniu. |
TapTime-Delivery | Identyfikator tej konkretnej próby doręczenia. |
TapTime-Signature | t=<czas unix>,v1=<szesnastkowy HMAC-SHA256 z "t.rawBody">, podpisany własnym kluczem tajnym endpointu. |
- Każda odpowiedź 2xx oznacza doręczenie; odpowiedź inna niż 2xx lub przekroczenie czasu skutkuje ponowieniem z rosnącymi odstępami (1m, 5m, 15m, 1h, 3h, 6h, 12h), maksymalnie 8 prób — odpowiedź 410 kończy ponawianie.
- Przekierowania nie są obsługiwane.
- W środowisku produkcyjnym adres URL musi używać HTTPS i nie może wskazywać na adres prywatny ani pętli zwrotnej.
- Doręczenie odbywa się co najmniej raz: zawsze należy weryfikować podpis i usuwać duplikaty według TapTime-Event-Id.
{
"id": "evt_9f3c2a7e1b",
"type": "booking.confirmed",
"createdAt": "2026-09-12T19:02:11+03:00",
"test": false,
"data": { "booking": { "kind": "reservation", "id": 4821, "status": "confirmed", "…": "…" } }
}
const [t, v1] = req.headers["taptime-signature"]
.split(",").map(part => part.split("=")[1]);
const expected = crypto
.createHmac("sha256", process.env.TAPTIME_WEBHOOK_SECRET)
.update(`${t}.${rawBody}`)
.digest("hex");
const valid = crypto.timingSafeEqual(
Buffer.from(expected), Buffer.from(v1));
Subskrypcje webhooków
Platformy automatyzacji włączają i wyłączają wyzwalacze przez API, zamiast prosić użytkownika o wklejenie adresu URL („REST hooks”): wysyłają żądanie POST z własnym adresem URL platformy i żądanymi zdarzeniami, zachowują zwrócony identyfikator i wysyłają DELETE po wyłączeniu wyzwalacza. Subskrypcja to zwykły podpisany webhook — widoczny w panelu i oznaczony kluczem, który go utworzył.
- Klucz widzi i usuwa wyłącznie utworzone przez siebie subskrypcje; unieważnienie klucza usuwa je wszystkie.
- Adresy w domenach hooks.zapier.com, make.com i pipedream.net są rozpoznawane i wyświetlane z nazwą platformy; każdy inny adres https to zwykły webhook.
- Klucz podpisu jest zwracany jeden raz, w odpowiedzi na żądanie POST; właściciel może go ponownie wyświetlić w panelu.
curl -X POST "https://api.tapti.me/v1/company/webhooks" \
-H "Authorization: Bearer tt_live_…" -H "Content-Type: application/json" \
-d '{"url": "https://hooks.zapier.com/hooks/catch/123/abc/", "events": ["order.placed"]}'
Postbacki
Żądanie GET lub POST na własny adres URL trackera z wypełnionymi makrami — dla platform, które obsługują postbacki w parametrach zapytania zamiast webhooków JSON. W przypadku zamówienia {value} to wartość zamówienia bez napiwku, a {order_id} — jego identyfikator.
https://tracker.example/postback
?cid={click_id}&event={event}&status={status}
&payout={value}&cur={currency}
Dostępne makra
{event}{event_id}{status}{booking_id}{booking_type}{order_id}{customer_id}{conversion_id}{value}{currency}{party_size}{branch_id}{timestamp}{utm_source}{utm_medium}{utm_campaign}{utm_term}{utm_content}{gclid}{fbclid}{msclkid}{ttclid}{click_id}
Błędy
Każdy błąd jest zwracany w formacie JSON: { "error": "<kod>", "message": "<opis czytelny dla człowieka>" }.
| Status | błąd | Znaczenie |
|---|---|---|
| 401 | unauthorized |
Brak nagłówka Authorization albo klucz jest nieprawidłowy lub unieważniony. |
| 403 | forbidden |
Klucz tylko do odczytu wywołał endpoint zapisu (zmianę statusu). |
| 404 | not_found |
Żadna rezerwacja o tym identyfikatorze nie należy do firmy klucza. |
| 409 | conflict |
Zmiana statusu spowodowałaby podwójną rezerwację stolika lub terminu; niczego nie zmieniono. |
| 422 | invalid_status |
Wartość status w treści żądania nie należy do wartości akceptowanych dla danego typu rezerwacji. |
| 422 | invalid_type |
Parametr type strumienia zdarzeń nie wskazuje żadnego typu ani rodziny zdarzeń. |
| 422 | invalid_url |
Adres URL subskrypcji nie jest publicznym adresem https. |
| 429 | rate_limited |
Ponad 50 żądań na minutę dla tego klucza. Należy zwolnić i ponowić żądanie. |
Dostęp do API, webhooki oraz integracje z platformami automatyzacji i czatami są w cenie każdego modułu — bez dodatkowych opłat i bez osobnego planu dla programistów.
Rozpocznij bezpłatny okres próbny