Za programere · plan Premium
API i webhookovi
Povežite web stranicu, CRM, blagajnu ili automatizacije s Table Rushom: čitajte i upisujte rezervacije API ključem, a svaku novu, izmijenjenu ili otkazanu rezervaciju primite kao potpisanu obavijest na svoju adresu.
Autentikacija
Ključ stvara vlasnik u aplikaciji: Postavke → API i webhookovi → Novi ključ. Ključ (tr_ + 40 znakova) prikazuje se samo jednom; u bazi čuvamo samo njegov otisak (SHA-256). Ključ je „samo čitanje" ili „čitanje i pisanje". Opozvani ključ prestaje raditi odmah.
Base URL: https://flfjwaukkpgxywtoudge.supabase.co/functions/v1/api
Header: Authorization: Bearer tr_0123456789abcdef0123456789abcdef01234567
Ključ ne stavljajte u kod koji se izvršava u pregledniku posjetitelja — pozivajte API sa svog poslužitelja.
Rezervacije
Polja u odgovoru: id, name, phone, email, date (YYYY-MM-DD), time (HH:MM), guests, status (pending · confirmed · declined · cancelled), source, note, arrival (arrived · noshow · null), event_id, language, cancelled_by, created_at, updated_at.
GET/v1/reservations
Parametri: from, to (zadano danas → +30 dana, najviše 62 dana), status, limit (do 500, zadano 100), offset.
curl -H "Authorization: Bearer $TR_KEY" \
"$BASE/v1/reservations?from=2026-10-01&to=2026-10-07&status=confirmed"
{ "data": [ { "id": "…", "name": "Ana Horvat", "date": "2026-10-03", "time": "20:00", "guests": 4, "status": "confirmed", … } ],
"limit": 100, "offset": 0 }
GET/v1/reservations/{id}
Jedna rezervacija. Rezervacija drugog restorana uvijek vraća 404.
POST/v1/reservations
Treba ključ s pravom pisanja. Obavezno: name, phone, date, time, guests (1–99). Neobavezno: email, note, status (pending ili confirmed, zadano pending), language (hr/en/de/it). Izvor rezervacije je api.
curl -X POST -H "Authorization: Bearer $TR_KEY" -H "Content-Type: application/json" \
-d '{"name":"Ana Horvat","phone":"+385 91 234 5678","email":"ana@example.com","date":"2026-10-03","time":"20:00","guests":4}' \
"$BASE/v1/reservations" # → 201 + rezervacija
PATCH/v1/reservations/{id}
Mijenjati se smiju (status može biti pending, confirmed, declined ili cancelled — pending ponovno otvara rezervaciju): status, arrival, note, date, time, guests, name, phone, email. Sva ostala polja (npr. kartica ili ulaznice) odbijaju se s UNKNOWN_FIELD. Rezervacija čija kartica ili ulaznice još nisu plaćene ne može se potvrditi (409).
curl -X PATCH -H "Authorization: Bearer $TR_KEY" -H "Content-Type: application/json" \
-d '{"status":"confirmed","note":"stol uz prozor"}' "$BASE/v1/reservations/$ID"
Događanja
GET/v1/events
Nadolazeća događanja: id, title, description, date, time, seats, seats_sold, price_eur, status.
Greške i ograničenja
| HTTP | code | Značenje |
|---|---|---|
| 400 | VALIDATION · UNKNOWN_FIELD | Neispravno ili nedopušteno polje; message kaže koje. |
| 401 | UNAUTHORIZED | Nema ključa, ključ ne postoji ili je opozvan. |
| 403 | SCOPE · PLAN_REQUIRED · READ_ONLY | Ključ samo za čitanje; restoran nije na planu Premium; račun je samo za čitanje (tada rade samo zahtjevi za čitanje). |
| 404 | NOT_FOUND | Nema takve rezervacije u vašem restoranu. |
| 409 | CARD_PENDING · TICKET_PENDING · EVENT_BOOKING · … | Pravilo u bazi odbilo je promjenu. Rezervaciji za događanje API ne mijenja datum, vrijeme ni broj gostiju. |
| 429 | RATE_LIMIT | Više od 120 zahtjeva u minuti po ključu. |
| 500 | INTERNAL | Greška na našoj strani; pokušajte ponovno. |
| 503 | UNAVAILABLE | Brojač zahtjeva trenutačno ne odgovara; pokušajte za nekoliko sekundi. |
{ "error": { "code": "VALIDATION", "message": "guests must be 1–99" } }
Webhookovi
Dodaju se u Postavke → API i webhookovi (do 5 adresa, samo https://, bez IP adresa i lokalnih imena). Uz svaku adresu dobivate tajni ključ (whsec_…) koji se prikazuje samo jednom. Događaji: reservation.created, reservation.updated, reservation.cancelled (i ping kad pošaljete test).
POST https://vasa-stranica.hr/table-rush
Content-Type: application/json
X-TableRush-Event: reservation.created
X-TableRush-Delivery: 5b1f… (isti id kao "id" u tijelu — koristite ga za odbacivanje duplikata)
X-TableRush-Signature: t=1790000000,v1=9f2c…
{ "id": "5b1f…", "type": "reservation.created", "created_at": "2026-10-01T18:02:11Z",
"data": { "id": "…", "name": "Ana Horvat", "date": "2026-10-03", "time": "20:00", "guests": 4, "status": "pending", … } }
- Odgovorite 2xx u 5 sekundi; posao radite poslije.
- Neuspjela slanja ponavljamo nakon 1, 5, 30, 120 i 360 minuta, zatim odustajemo.
- Nakon 20 neuspjeha zaredom adresa se isključuje (vidi se u aplikaciji, uključite je ponovno kad je popravite).
- Redoslijed nije zajamčen — koristite
updated_atiz podataka.
Provjera potpisa
Potpis je HMAC-SHA256 tajnog ključa nad <t>.<sirovo tijelo zahtjeva>, zapisan heksadecimalno. Odbacite zahtjev ako potpis ne odgovara ili je t stariji od 5 minuta.
Node.js
import crypto from 'node:crypto';
function verify(rawBody, header, secret) {
const m = /^t=(\d+),v1=([0-9a-f]{64})$/.exec(header || ''); if (!m) return false;
if (Math.abs(Date.now() / 1000 - Number(m[1])) > 300) return false;
const expected = crypto.createHmac('sha256', secret).update(`${m[1]}.${rawBody}`).digest('hex');
return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(m[2]));
}
PHP
function tr_verify(string $raw, string $header, string $secret): bool {
if (!preg_match('/^t=(\d+),v1=([0-9a-f]{64})$/', $header, $m)) return false;
if (abs(time() - (int)$m[1]) > 300) return false;
return hash_equals(hash_hmac('sha256', $m[1] . '.' . $raw, $secret), $m[2]);
}
Python
import hmac, hashlib, re, time
def verify(raw: bytes, header: str, secret: str) -> bool:
m = re.fullmatch(r"t=(\d+),v1=([0-9a-f]{64})", header or "")
if not m or abs(time.time() - int(m[1])) > 300: return False
exp = hmac.new(secret.encode(), f"{m[1]}.".encode() + raw, hashlib.sha256).hexdigest()
return hmac.compare_digest(exp, m[2])
Pitanja o integraciji: podrska@table-rush.com. API je dio plana Premium.