Dokumentasi pengembang

REST API TapTime

Baca dan perbarui reservasi meja serta janji temu, baca pesanan dan kartu loyalitas, jajaki umpan peristiwa yang terurut, dan terima webhook bertanda tangan — dari CRM, kasir, gudang data atau platform otomatisasi Anda sendiri. Halaman ini adalah referensi lengkapnya; panduan pelacakan konversi menjelaskan mengapa Anda memakainya.

URL dasarhttps://api.tapti.me AuthBearer token FormatJSON Mengapa memakainya

Setiap permintaan memerlukan kunci API perusahaan (Integrasi → Webhook & API di panel) yang dikirim sebagai Authorization: Bearer tt_live_…. Respons dan kesalahan berbentuk JSON.

Reservasi terkonfirmasi yang berubah sejak sebuah tanggal
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

GET /v1/company Baca-saja atau baca-tulis

Ambil perusahaan saat ini

Perusahaan pemilik kunci itu, dan apa yang bisa dilakukan kunci itu sendiri.

GET /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.

ParameterTypeArti
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.
GET /v1/company/appointments Baca-saja atau baca-tulis

Daftar janji temu

Bentuk dan filter yang sama seperti reservasi, untuk modul Janji Temu.

ParameterTypeArti
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.
GET /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.

GET /v1/company/appointments/{id} Baca-saja atau baca-tulis

Ambil satu janji temu

Satu janji temu, bentuk dan aturan yang sama seperti pencarian reservasi.

POST /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": "..."}.

ParameterTypeArti
status string, required Salah satu dari: pending, confirmed, seated, completed, no_show, cancelled (canceled dan canceled_by_venue juga diterima).
POST /v1/company/appointments/{id}/status Hanya baca-tulis

Ubah status sebuah janji temu

Sama seperti endpoint reservasi, tanpa status seated.

ParameterTypeArti
status string, required Salah satu dari: pending, confirmed, completed, no_show, cancelled (canceled dan canceled_by_venue juga diterima).
GET /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.

ParameterTypeArti
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.
GET /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.

ParameterTypeArti
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.
GET /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.

GET /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.

GET /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.

ParameterTypeArti
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.
GET /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.

ParameterTypeArti
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.
GET /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.

POST /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.

ParameterTypeArti
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.
DELETE /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.

GET /v1/company/reservations/4821 → data
{
  "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.

GET /v1/company/orders/9170 → data
{
  "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.

GET /v1/company/loyalty/cards → data[0]
{
  "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 peristiwaArti
booking.requestedSeorang tamu meminta pemesanan yang menunggu konfirmasi Anda.
booking.confirmedSebuah pemesanan dikonfirmasi — langsung confirmed, atau dikonfirmasi kemudian oleh staf.
booking.cancelledDibatalkan oleh tamu atau tempat usaha; statusnya menyebutkan yang mana.
booking.no_showTamunya tidak datang.
booking.completedKunjungannya sudah selesai.
order.placedPesanan 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.paidPesanan mana pun yang sudah dilunasi, termasuk penjualan yang dicatat di kasir.
loyalty.member_joinedSeorang pelanggan mendapat stempel pertamanya pada sebuah program.
loyalty.stamp_addedSebuah stempel ditambahkan ke kartu.
loyalty.reward_issuedSebuah kartu selesai dan hadiahnya diterbitkan.
loyalty.reward_redeemedSebuah hadiah sudah diserahkan.
Tetap sinkron dengan umpan peristiwa
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.

HeaderArti
TapTime-EventJenis peristiwanya, mis. booking.confirmed.
TapTime-Event-IdId tetap untuk peristiwa itu — pakai untuk menghapus duplikat pengiriman ulang.
TapTime-DeliveryId dari upaya pengiriman spesifik ini.
TapTime-Signaturet=<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.
POST · application/json · booking.confirmed
{
  "id": "evt_9f3c2a7e1b",
  "type": "booking.confirmed",
  "createdAt": "2026-09-12T19:02:11+03:00",
  "test": false,
  "data": { "booking": { "kind": "reservation", "id": 4821, "status": "confirmed", "…": "…" } }
}
Verifikasi tanda tangan (Node.js)
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.
Langganan sebuah URL untuk pesanan baru
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.

URL postback dengan placeholder · GET atau POST
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>" }.

StatuskesalahanArti
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.
Butuh kunci?

Akses API, webhook serta integrasi otomatisasi dan obrolan sudah termasuk dalam setiap modul — tanpa biaya tambahan, tanpa paket pengembang terpisah.

Mulai uji coba gratis