Geliştirici / APIAPI Temelleri

API Temelleri

Bu sayfa, HummyTummy’nin tüm REST yüzeyinde geçerli olan ortak kuralları açıklar: taban URL, kimlik doğrulama realm’leri, şube kapsamı, hata biçimi ve rate-limit’ler. Partner Display ve Webhook sayfaları bu kuralların üzerine kurulur.

Taban URL ve global ön ek

Tüm uçlar /api global ön eki altındadır.

https://hummytummy.com/api

Yani bir uç v1/webhooks/subscriptions olarak tanımlandığında tam yol https://hummytummy.com/api/v1/webhooks/subscriptions olur. Bu dokümandaki her örnek tam yolu gösterir.

Para birimi tüm tutarlar için TRY’dir. Self-servis ödeme PayTR üzerinden yürür ve yalnızca TR/TRY desteklenir.

Kimlik gerçeklikleri (auth realms)

HummyTummy dört ayrı kimlik realm’i tanır. Her uç bunlardan tam olarak birini bekler; yanlış realm 401 döner.

1. Personel JWT — Authorization: Bearer <jwt>

Dashboard / yönetim API’sinin ana kimliği. Giriş yapan personel kullanıcısının JWT’sidir. Partner API anahtarlarını ve webhook aboneliklerini bu realm yönetir (ADMIN rolü gerekir).

Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
⚠️

Erişim/yenileme token’ları kasıtlı olarak localStorage’da tutulmaz; yenileme token’ı httpOnly çerezdedir. Sunucu-sunucu entegrasyonlarında JWT yerine Partner API anahtarı kullanın (aşağıda).

2. Müşteri oturumu — QR menü oturum token’ı

QR menüden gelen misafirin oturum token’ı. Misafir sipariş ve self-pay akışlarını yetkilendirir. Partner ekranları bu kimliği doğrudan kullanmaz; bunun yerine ekran token’ı arka planda bir müşteri oturumuna (orderingSessionId) bağlanır.

3. Partner anahtarı — X-Partner-Key + X-Partner-Secret

Bir partner backend’in ekran token’ı üretmek/yenilemek/iptal etmek için kullandığı makine kimliği. Anahtar restoran ADMIN’i tarafından üretilir; keyId (pk_live_…, loglanması güvenli) + bir kez gösterilen secret’tan oluşur.

X-Partner-Key:    pk_live_xxxxx
X-Partner-Secret: pk_live_secret_xxxxx

Ayrıntı: Partner Display API.

4. Ekran token’ı — Authorization: Screen <token>

Bir cihazın (tablet/ekran) /v1/display/* uçlarını çağırırken sunduğu kısa ömürlü, kapsamlı token. Token <uuidv7>.<secret> biçimindedir; cihaz API secret’ını asla taşımaz.

Authorization: Screen 0190a1b2-c3d4-... .Hk9...

Şube kapsamı — X-Branch-Id

HummyTummi çok şubeli bir sistemdir. Şubeye-bağlı (branch-scoped) her uç, hangi şube bağlamında çalıştığını belirten bir X-Branch-Id başlığı bekler.

X-Branch-Id: <branch-uuid>
⚠️

Şubeye-bağlı bir uca X-Branch-Id olmadan istek atarsanız 400 alırsınız. Buna karşılık tenant-seviyesi uçlar (örn. webhook abonelikleri /v1/webhooks/subscriptions, partner anahtarları /v1/partner/api-keys) bu başlığı beklemez — şube kapsamını atlarlar. Partner ekranları için şube/tenant bilgisi token’ın içinden gelir; gövdede veya başlıkta gönderilmez.

Hata zarfı

Tüm hatalar standart bir zarf içinde döner:

{
  "statusCode": 401,
  "message": "Invalid email or password",
  "error": "INVALID_CREDENTIALS",
  "errorCode": "INVALID_CREDENTIALS",
  "timestamp": "2026-06-23T08:30:00.000Z",
  "path": "/api/v1/auth/login",
  "requestId": "1718500000000-ab12cd34e"
}
AlanTipAçıklama
statusCodenumberHTTP durum kodu
messagestring | string[]Kullanıcıya dönük mesaj; doğrulama hatalarında dizi olabilir
errorstringİnsan/kategori etiketi (örn. Bad Request, Forbidden); bazen yerelleştirilir
errorCodestring?Makine-okunur, kararlı kod. Yalnızca fırlatan istisna eklediğinde bulunur; PII içermez ve her ortamda döner
timestampstringISO-8601 istek zamanı
pathstringİstek yolu
requestIdstringİzleme için istek kimliği

details ve stack alanları yalnızca development ortamında doldurulur; production’da görünmezler.

İstemci tarafında errorCode üzerinden dallanın, message üzerinden değil — message yerelleştirilebilir, errorCode kararlıdır. errorCode yalnızca fırlatan istisna eklediğinde bulunur; birçok sıradan hata (istek-doğrulama 400’leri, düz 403/404’ler, 429 hız sınırı) yalnızca standart bir error etiketiyle, errorCode olmadan döner. Bugün görebileceğiniz kodlar: INVALID_CREDENTIALS (401), RESOURCE_NOT_FOUND (404), RESOURCE_ALREADY_EXISTS (409). İş-kuralı hatalarında error, errorCode ile aynıdır; framework hatalarında error kategori etiketidir (örn. Forbidden, Bad Request).

Sık karşılaşılan durum kodları

KodAnlamı
400Geçersiz girdi / eksik X-Branch-Id / doğrulama hatası
401Kimlik yok, geçersiz ya da süresi dolmuş token
403Yetki yok, eksik scope ya da plan özelliği kapalı
404Kaynak bulunamadı
409Çakışma (örn. eşzamanlı güncelleme çatışması — yeniden denenebilir)
429Rate limit aşıldı

Veritabanı kaynaklı bazı durumlar otomatik eşlenir: eşzamanlı güncelleme çatışması (409 ConcurrentUpdate, yeniden denenebilir), benzersizlik ihlali (409), aralık/uzunluk taşması (400 ValueOutOfRange).

Sayfalama

Listeleme uçları, ofset tabanlı sayfalamada page ve limit sorgu parametrelerini kullanır; toplam kayıt sayısı X-Total-Count yanıt başlığında döner (CORS’ta açıkça expose edilir).

GET /api/...?page=2&limit=50
X-Total-Count: 137

Tüm liste uçları sayfalamayı zorlamaz; bazıları (örn. partner anahtar listesi, webhook abonelik listesi) tüm satırları döner. İlgili uç sayfası, davranışı belirtir.

Idempotency

Para hareketi içeren uçlar (checkout/ödeme rayı) tekrar-güvenlidir: aynı isteğin iki kez ulaşması ikinci bir tahsilat yaratmaz. Webhook alımı tarafında da aynı olay aynı id ile iki kez gelebilir (en-az-bir-kez teslim) — alıcı tarafta id üzerinden dedup yapın. Ayrıntı Webhook’lar sayfasında.

Rate-limit katmanları

Rate limit, global throttler ile üç katmanda uygulanır:

KatmanPencereLimit
short1 sn10 istek
medium10 sn50 istek
long60 sn100 istek

Bazı makine uçları kendi sıkı limitlerini ekler — örneğin ekran token’ı üretimi (POST /v1/partner/screen-sessions) 60 sn’de 60, self-pay intent (/v1/display/pay-intent) 60 sn’de 5 ile sınırlıdır.

Anahtara/ekran token’ına göre sayım: rate limit bucket’ı yalnızca IP’ye değil, prensibe (partner anahtarı veya ekran token’ı) göre de bölünür. Böylece tek bir NAT IP’sinin arkasındaki çok sayıda tablet birbirini boğmaz. Yine de her prensip kendi kaynak IP’si altında sayılır, böylece sahte prensip üreterek IP limitinden kaçılamaz.

Limit aşıldığında standart bir 429 döner (düz hız-sınırı yanıtı — errorCode eklenmez); Retry-After başlığına saygı gösterin.

Hızlı örnek

# Şubeye-bağlı bir uç (personel JWT + şube kapsamı)
curl https://hummytummy.com/api/v1/orders \
  -H "Authorization: Bearer $JWT" \
  -H "X-Branch-Id: $BRANCH_ID"