Setiap permintaan memerlukan kunci API perusahaan (Integrasi → Webhook & API di panel) yang dikirim sebagai Authorization: Bearer tt_live_…. Respons dan kesalahan berbentuk JSON.
curl "https://api.tapti.me/v1/company/reservations?status=confirmed&updatedSince=2026-09-01T00:00:00Z" \
-H "Authorization: Bearer tt_live_…"
Autentikasi
Setiap permintaan membawa kunci API perusahaan sebagai token bearer. Buat satu dari panel — Integrasi → Webhook & API → Kunci REST API — di sana kunci ditampilkan sekali dan disimpan di server hanya sebagai hash SHA-256; kunci yang hilang dicabut dan diganti, bukan dipulihkan. Satu perusahaan bisa memegang hingga 10 kunci aktif.
- Kunci baca-saja bisa memanggil setiap endpoint GET, serta berlangganan dan berhenti berlangganan webhook — sebuah langganan tidak mendorong apa pun yang tidak bisa dibaca kunci itu.
- Kunci baca-tulis juga bisa mem-POST perubahan status pemesanan; kunci baca-saja akan mendapat 403 Forbidden pada rute tersebut.
- Satu kunci milik satu perusahaan — setiap daftar dan pencarian sudah dibatasi padanya, tidak ada parameter companyId.
Batas laju
50 permintaan per menit per kunci, pada jendela geser, dipakai bersama oleh setiap endpoint. Melebihinya mengembalikan 429 Too Many Requests; mundur lalu coba lagi alih-alih menjajaki lebih cepat — atau langganan webhook dan berhenti menjajaki.
Endpoint
/v1/company
Baca-saja atau baca-tulis
Ambil perusahaan saat ini
Perusahaan pemilik kunci itu, dan apa yang bisa dilakukan kunci itu sendiri.
/v1/company/reservations
Baca-saja atau baca-tulis
Daftar reservasi
Reservasi meja untuk perusahaan, waktu mulai terlama dulu — atau, saat updatedSince disetel, yang paling lama diperbarui dulu.
| Parameter | Type | Arti |
|---|---|---|
status |
string | Dipisah koma: pending, confirmed, seated, completed, no_show, cancelled. cancelled mencakup kedua alasan pembatalan. |
branchId |
integer | Batasi ke satu cabang. |
from |
ISO 8601 datetime | Hanya pemesanan yang mulai pada atau setelah waktu ini (UTC jika tidak ada offset). |
to |
ISO 8601 datetime | Hanya pemesanan yang mulai sebelum waktu ini. |
updatedSince |
ISO 8601 datetime | Hanya pemesanan yang berubah sejak waktu ini; mengubah urutan menjadi updatedAt menaik, untuk sinkronisasi. |
limit |
integer | Ukuran halaman, 1–100. Bawaan 50. |
page |
integer | Nomor halaman berbasis 1. Bawaan 1. |
/v1/company/appointments
Baca-saja atau baca-tulis
Daftar janji temu
Bentuk dan filter yang sama seperti reservasi, untuk modul Janji Temu.
| Parameter | Type | Arti |
|---|---|---|
status |
string | Dipisah koma: pending, confirmed, completed, no_show, cancelled. |
branchId |
integer | Batasi ke satu cabang. |
from |
ISO 8601 datetime | Hanya pemesanan yang mulai pada atau setelah waktu ini. |
to |
ISO 8601 datetime | Hanya pemesanan yang mulai sebelum waktu ini. |
updatedSince |
ISO 8601 datetime | Hanya pemesanan yang berubah sejak waktu ini; diurutkan menurut updatedAt menaik. |
limit |
integer | Ukuran halaman, 1–100. Bawaan 50. |
page |
integer | Nomor halaman berbasis 1. Bawaan 1. |
/v1/company/reservations/{id}
Baca-saja atau baca-tulis
Ambil satu reservasi
Satu reservasi, dalam bentuk yang sama seperti yang dibawa webhook, lengkap dengan atribusinya. 404 bila id-nya bukan milik perusahaan pemilik kunci.
/v1/company/appointments/{id}
Baca-saja atau baca-tulis
Ambil satu janji temu
Satu janji temu, bentuk dan aturan yang sama seperti pencarian reservasi.
/v1/company/reservations/{id}/status
Hanya baca-tulis
Ubah status sebuah reservasi
Konfirmasi, dudukkan, selesaikan, tandai tidak datang, batalkan atau buka kembali — memicu webhook dan konversi yang sama seperti mengubahnya di papan. Badan JSON: {"status": "..."}.
| Parameter | Type | Arti |
|---|---|---|
status |
string, required | Salah satu dari: pending, confirmed, seated, completed, no_show, cancelled (canceled dan canceled_by_venue juga diterima). |
/v1/company/appointments/{id}/status
Hanya baca-tulis
Ubah status sebuah janji temu
Sama seperti endpoint reservasi, tanpa status seated.
| Parameter | Type | Arti |
|---|---|---|
status |
string, required | Salah satu dari: pending, confirmed, completed, no_show, cancelled (canceled dan canceled_by_venue juga diterima). |
/v1/company/events
Baca-saja atau baca-tulis
Jajaki umpan peristiwa
Setiap peristiwa pemesanan, pesanan dan loyalitas, terlama dulu — umpan yang sama tempat webhook diambil. Kirim kursor terakhir yang Anda lihat sebagai after untuk mengambil hanya yang baru, dan type untuk mengambil hanya jenis tertentu.
| Parameter | Type | Arti |
|---|---|---|
after |
integer cursor | Kursor dari peristiwa terakhir yang Anda proses. Kosongkan untuk mulai dari awal. |
type |
string | Jenis peristiwa atau keluarga yang dipisah koma: booking.confirmed,order.placed, atau order, loyalty.*. Kosongkan untuk semua peristiwa. |
limit |
integer | Ukuran halaman, 1–100. Bawaan 50. |
/v1/company/orders
Baca-saja atau baca-tulis
Daftar pesanan
Pesanan meja, bawa pulang dan pengiriman dari tamu serta setiap penjualan yang dicatat di kasir, terlama dulu — atau, saat paidSince disetel, dalam urutan pembayarannya. Pesanan yang masih menunggu pembayaran di muka tidak disertakan.
| Parameter | Type | Arti |
|---|---|---|
status |
string | Dipisah koma: open, paid. |
source |
string | customer (dibuat oleh tamu) atau staff (dicatat oleh staf). |
fulfilment |
string | Dipisah koma: dine_in, takeaway, delivery. |
branchId |
integer | Batasi ke satu cabang. |
from |
ISO 8601 datetime | Hanya pesanan yang dibuat pada atau setelah waktu ini. |
to |
ISO 8601 datetime | Hanya pesanan yang dibuat sebelum waktu ini. |
paidSince |
ISO 8601 datetime | Hanya pesanan yang dibayar sejak waktu ini; diurutkan menurut paidAt menaik, untuk menyinkronkan penjualan. |
limit |
integer | Ukuran halaman, 1–100. Bawaan 50. |
page |
integer | Nomor halaman berbasis 1. Bawaan 1. |
/v1/company/orders/{id}
Baca-saja atau baca-tulis
Ambil satu pesanan
Satu pesanan lengkap dengan barisnya, totalnya dan atribusinya, dalam bentuk yang dibawa webhook pesanan.
/v1/company/loyalty/programs
Baca-saja atau baca-tulis
Daftar program loyalitas
Setiap program kartu stempel: nama, status, stempel yang dibutuhkan, hadiahnya dan di mana berlakunya.
/v1/company/loyalty/cards
Baca-saja atau baca-tulis
Daftar kartu loyalitas
Kartu para anggota, dalam bentuk objek loyalitas. Anggota yang memenuhi kartunya punya kartu completed dan satu kartu active baru di sampingnya; customer.id adalah anggotanya.
| Parameter | Type | Arti |
|---|---|---|
programId |
integer | Batasi ke satu program. |
customerId |
integer | Batasi ke satu anggota. |
status |
string | Dipisah koma: active, completed. |
updatedSince |
ISO 8601 datetime | Hanya kartu yang distempel atau diselesaikan sejak waktu ini; diurutkan menurut updatedAt menaik. |
limit |
integer | Ukuran halaman, 1–100. Bawaan 50. |
page |
integer | Nomor halaman berbasis 1. Bawaan 1. |
/v1/company/loyalty/rewards
Baca-saja atau baca-tulis
Daftar hadiah loyalitas
Hadiah yang diperoleh dengan menyelesaikan sebuah kartu, lengkap dengan kodenya, masa berlakunya dan apakah sudah ditukarkan.
| Parameter | Type | Arti |
|---|---|---|
programId |
integer | Batasi ke satu program. |
customerId |
integer | Batasi ke satu anggota. |
status |
string | Dipisah koma: issued, redeemed, expired. |
from |
ISO 8601 datetime | Hanya hadiah yang diterbitkan pada atau setelah waktu ini. |
to |
ISO 8601 datetime | Hanya hadiah yang diterbitkan sebelum waktu ini. |
limit |
integer | Ukuran halaman, 1–100. Bawaan 50. |
page |
integer | Nomor halaman berbasis 1. Bawaan 1. |
/v1/company/webhooks
Baca-saja atau baca-tulis
Daftar langganan webhook
Langganan yang dibuat kunci ini. Webhook yang ditambahkan lewat panel tidak tercantum di sini.
/v1/company/webhooks
Baca-saja atau baca-tulis
Langganan sebuah webhook
Mulai mengirim peristiwa ke sebuah URL — yang dipanggil aplikasi platform otomatisasi saat pengguna mengaktifkan sebuah pemicu. Mengembalikan langganan dan rahasia penanda tangannya, sekali saja. Badan JSON: {"url": "…", "events": ["order.placed"]}; format Zapier {"target_url": "…", "event": "…"} juga diterima.
| Parameter | Type | Arti |
|---|---|---|
url |
string, required | Alamat https tujuan pengiriman (target_url juga diterima). |
events |
array of strings, required | Jenis peristiwa, keluarga seperti order.* atau loyalty, atau * untuk semuanya (event juga diterima, untuk satu jenis). |
description |
string | Nama yang ditampilkan di panel. Bawaannya adalah nama platform dan nama kuncinya. |
/v1/company/webhooks/{id}
Baca-saja atau baca-tulis
Berhenti berlangganan sebuah webhook
Berhenti mengirim ke langganan yang dibuat kunci ini. Mengembalikan 204. Mencabut kuncinya juga menghapus semua langganannya.
Objek pemesanan
Reservasi dan janji temu keluar dalam satu bentuk bersama: kind, id, status, source, guestInitiated, startsAt/endsAt/timezone (zona cabangnya sendiri), currency, company, branch, guest, attribution, conversionId, createdAt/updatedAt — ditambah partySize dan table untuk reservasi, service dan specialist untuk janji temu. Persis itulah yang dikirim sebuah webhook, sehingga penerima yang menangani salah satunya menangani keduanya.
{
"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…" }
}
}
Objek pesanan
Sebuah pesanan keluar dalam satu bentuk di mana pun Anda menemuinya — REST API, webhook pesanan, umpan peristiwa: kind ("order"), id, number (nomor tiket yang diteriakkan staf), status (open atau paid), source (customer atau staff), guestInitiated, fulfilment, table, label, deliveryAddress, note, currency, timezone, company, branch, customer (anggota loyalitas, bila staf mengenalinya), items (name, variant, quantity, unitPriceCents, subtotalCents), itemCount, subtotalCents, discountCents, deliveryFeeCents, tipCents, totalCents, valueCents (nilai pesanan tanpa tip — angka yang dilaporkan konversi), paymentMethod, servedBy, conversionId, createdAt, paidAt dan attribution. Uang selalu dalam satuan terkecil.
{
"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…" }
}
}
Objek loyalitas
Setiap peristiwa, kartu dan hadiah loyalitas berbagi satu bentuk: kind ("loyalty"), id (kartunya), timezone, company, branch (tempat kejadiannya, bila ada), program (id, name, stampsRequired, rewardTitle), customer (id, name, phone, locale), card (id, status, stampsCount, stampsRequired, stampsToReward, createdAt), stamp (untuk stempel: source, issuedBy, createdAt) dan reward (untuk hadiah: code, title, status, expiresAt, redeemedAt, redeemedBy), ditambah conversionId, id yang dipakai melaporkan pendaftaran loyalitas.
{
"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…"
}
Umpan peristiwa
Setiap baris berupa { id, cursor, type, createdAt, previousStatus, data }. data memuat subjeknya di bawah kunci yang dinamai awalan peristiwanya: data.booking, data.order atau data.loyalty. Simpan kursor tertinggi yang sudah Anda proses lalu kirim kembali sebagai after — kursor itu tidak pernah melewati atau mengulang baris, jadi aman untuk melanjutkan setelah kegagalan. Abaikan jenis yang tidak Anda tangani: jenis baru bisa ditambahkan.
| Jenis peristiwa | Arti |
|---|---|
booking.requested | Seorang tamu meminta pemesanan yang menunggu konfirmasi Anda. |
booking.confirmed | Sebuah pemesanan dikonfirmasi — langsung confirmed, atau dikonfirmasi kemudian oleh staf. |
booking.cancelled | Dibatalkan oleh tamu atau tempat usaha; statusnya menyebutkan yang mana. |
booking.no_show | Tamunya tidak datang. |
booking.completed | Kunjungannya sudah selesai. |
order.placed | Pesanan seorang tamu sampai ke tempat usaha — dari halaman, kode QR sebuah meja, bawa pulang atau pengiriman; setelah pembayaran bila tempat usaha menagihnya di muka. |
order.paid | Pesanan mana pun yang sudah dilunasi, termasuk penjualan yang dicatat di kasir. |
loyalty.member_joined | Seorang pelanggan mendapat stempel pertamanya pada sebuah program. |
loyalty.stamp_added | Sebuah stempel ditambahkan ke kartu. |
loyalty.reward_issued | Sebuah kartu selesai dan hadiahnya diterbitkan. |
loyalty.reward_redeemed | Sebuah hadiah sudah diserahkan. |
curl "https://api.tapti.me/v1/company/events?after=998&limit=100" \
-H "Authorization: Bearer tt_live_…"
Webhook
Buat sebuah endpoint di Integrasi → Webhook & API — atau hubungkan Zapier, Make, n8n atau Pipedream di Integrasi → Otomatisasi — agar TapTime mem-POST peristiwa JSON bertanda tangan begitu sebuah pemesanan, pesanan atau kartu loyalitas berubah. Anda memilih peristiwanya per endpoint. Satu perusahaan bisa punya hingga 50 webhook, postback, obrolan dan koneksi otomatisasi secara keseluruhan.
| Header | Arti |
|---|---|
TapTime-Event | Jenis peristiwanya, mis. booking.confirmed. |
TapTime-Event-Id | Id tetap untuk peristiwa itu — pakai untuk menghapus duplikat pengiriman ulang. |
TapTime-Delivery | Id dari upaya pengiriman spesifik ini. |
TapTime-Signature | t=<waktu unix>,v1=<HMAC-SHA256 heksa dari "t.rawBody">, ditandatangani dengan rahasia endpoint itu sendiri. |
- Respons 2xx apa pun dianggap terkirim; respons non-2xx atau kehabisan waktu dicoba ulang dengan penundaan bertahap (1m, 5m, 15m, 1j, 3j, 6j, 12j) hingga 8 upaya — 410 menghentikan percobaan ulang.
- Pengalihan tidak diikuti.
- URL-nya harus HTTPS di produksi dan tidak boleh mengarah ke alamat privat atau loopback.
- Pengiriman bersifat minimal sekali: selalu verifikasi tanda tangannya dan hapus duplikat berdasarkan 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));
Langganan webhook
Platform otomatisasi mengaktifkan dan mematikan pemicu lewat API alih-alih meminta pengguna menempel URL (“REST hooks”): POST URL milik platform itu beserta peristiwa yang diinginkannya, simpan id yang dikembalikan, lalu DELETE saat pemicunya dimatikan. Sebuah langganan adalah webhook bertanda tangan biasa — tampil di panel, ditandai dengan kunci yang membuatnya.
- Sebuah kunci hanya melihat dan menghapus langganan yang dibuatnya sendiri; mencabut kuncinya menghapus semuanya.
- Alamat di hooks.zapier.com, make.com dan pipedream.net dikenali dan ditampilkan dengan nama platformnya; alamat https lain menjadi webhook biasa.
- Rahasia penanda tangan dikembalikan sekali, dalam respons POST; pemiliknya bisa menampilkannya lagi di panel.
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"]}'
Postback
Sebuah GET atau POST ke URL pelacak Anda sendiri dengan makro yang sudah diisi, untuk platform yang memakai postback query-string alih-alih webhook JSON. Untuk sebuah pesanan, {value} adalah nilai pesanan tanpa tip dan {order_id} adalah id-nya.
https://tracker.example/postback
?cid={click_id}&event={event}&status={status}
&payout={value}&cur={currency}
Placeholder yang tersedia
{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}
Kesalahan
Setiap kesalahan berupa JSON: { "error": "<kode>", "message": "<terbaca manusia>" }.
| Status | kesalahan | Arti |
|---|---|---|
| 401 | unauthorized |
Header Authorization tidak ada, atau kuncinya tidak valid atau sudah dicabut. |
| 403 | forbidden |
Kunci baca-saja memanggil endpoint tulis (perubahan status). |
| 404 | not_found |
Tidak ada pemesanan dengan id itu yang dimiliki perusahaan pemilik kunci. |
| 409 | conflict |
Perubahan status itu akan menggandakan pemesanan meja atau slotnya; tidak ada yang diubah. |
| 422 | invalid_status |
Nilai status pada badan permintaan bukan salah satu nilai yang diterima untuk jenis pemesanan itu. |
| 422 | invalid_type |
type pada umpan peristiwa tidak menyebut jenis peristiwa atau keluarga mana pun. |
| 422 | invalid_url |
URL langganan bukan alamat https publik. |
| 429 | rate_limited |
Lebih dari 50 permintaan dalam satu menit untuk kunci ini. Perlambat lalu coba lagi. |
Akses API, webhook serta integrasi otomatisasi dan obrolan sudah termasuk dalam setiap modul — tanpa biaya tambahan, tanpa paket pengembang terpisah.
Mulai uji coba gratis