API Uçları — Genel Bakış

Eklentinin Restomenum'dan veri okuduğu / işlem yaptığı HTTP uçları. Etkileşimler (event, action, iframe) yalnızca bir id taşır; dolu veriyi bu API'lerden çekersiniz. Liste zamanla genişler.

Ortak kurallar

GET {RESTOMENUM_BASE}/plugin-api/<kaynak>/<aksiyon>
Authorization: Bearer <apiKey>     // kurulumdaki (OAuth exchange) install API key

{RESTOMENUM_BASE} ortama göre değişir — geliştirmede sandbox, canlıda production:

OrtamBase URL
Dev / Sandboxhttps://sandbox.plugins.restomenum.app
Productionhttps://plugins.restomenum.app
  • Base: tüm uçlar {RESTOMENUM_BASE}/plugin-api/… altında (yukarıdaki tablo).
  • Auth: Authorization: Bearer <apiKey> — token exchange'te alınan install API key. apiKey üç parçalıdır: serverId.pluginId.secret (secret = 32-byte hex). Sunucu, secret'ı saklı apiKeyHash ile SHA-256 timing-safe karşılaştırır. Kurulum aktif değilse (enabled + connected + billing) çağrı 401 alır.
  • Scope: her uç kendi scope'unu ister; eksikse plugin.scope.denied.
  • PII: customer alanları customers:read + consent ile dolu gelir; yoksa webhook ile aynı kuralla kırpılır.

Yanıt zarfı

// başarı — OKUMA ve YAZMA aynı zarfı kullanır: veri `data` altında
{ "success": true, "data": { … } }

// hata — aynı zarf; `status` HTTP kodunun gövde içindeki kopyasıdır
{ "success": false, "status": 400, "message": "<kod>" }
⚠️ DÜZELTME — okuma ve yazma zarfı AYRI DEĞİL. Bu sayfa (ve SDK) bir dönem "yazma uçları düz { ok: true, … } gövde döner, data yoktur" diyordu; bu YANLIŞTI. Yazma uçları da okuma zarfını kullanır: { success: true, data: { … } }. ok platformun modül-içi dönüş alanıdır ve HTTP sınırına hiç çıkmaz — yanıtta arama. Eski nota göre kod yazdıysan response.data'yı koşulsuz oku.
Yazma uçlarının data şekilleri (koddan teyitli)
POST /packets/create          → data: { packetId, docNo, docNoDate, businessDate }
POST /packets/update          → data: { packetId, updated }
POST /packets/update-orders   → data: { packetId, total }
POST /packets/update-payments → data: { packetId, paid, replayed }
POST /tables/create           → data: { tableId, docNo, docNoDate, total, paid }
POST /tables/update-orders    → data: { tableId, total }
POST /tables/update-payments  → data: { tableId, paid, replayed }
packets/update-payments — gerçek yakalanmış gövde (dev)
{ "success": true, "data": { "packetId": "e2e-append-packet", "paid": 340, "replayed": false } }
⚠️ packets/create yanıtındaki alan packetId'dir. Bu sayfa ve SDK bir dönem uuid diyordu — yanlıştı: platformun iç modelinde kimlik uuid diye taşınır ama dış sözleşmeye packetId adıyla çıkar. result.uuid okuyan kod her zaman undefined alır ve create → update-payments zincirinde kimliği bulamaz.
Dönen tutar otoriterdir: gönderdiğin fiyat yok sayılır, fiyat katalogdan okunur, kuver masanın kendi oranıyla yeniden enjekte edilir ve total sunucuda hesaplanır. paid > total olacak bir yazma reddedilir.
Hiçbir uç bir hesabı kapatamaz — paid == total olsa bile. Kapanış, iptal ve silme yalnız çekirdek/personel akışındadır; eklenti oluşturur ve alan günceller.

Yanıt REST-uyumlu HTTP status taşır: başarı 200; hata not-found 404, doğrulama 400, scope/sahiplik 403, çakışma 409, rate limit 429, auth 401. Gövde her durumda { success, message } (message = makine-okur kod). Tam liste: Hata Kodları.

Uçlar

MethodUçAçıklamaScope
GET/plugin-api/packets/getPaket detayı (dolu order: ürünler, müşteri, adres, toplam + ödeme kırılımı payments[]). Satırlarda lineId + metadata ({key,value,by} dizisi; by = yazar damgası), satış düzeyinde type (null = bilinmiyor).orders:read
GET/plugin-api/packets/openAçık paket/delivery hesapları (özet): packetId, kanal, tutar, ürün adedi. Detay: packets/get?packetId=.orders:read
POST/plugin-api/packets/createYeni paket/sipariş oluştur (yazma ucu). Sepet ürün id'leriyle; fiyat Restomenum kaydından. Satır opsiyonel taxRate (0-100) taşıyabilir — ürünün oranını ezer ve satırda dondurulur. Sepet ve ödeme satırı opsiyonel lineId + metadata ({key,value} DİZİSİ, map değil); satış düzeyinde opsiyonel type (dine_in|takeaway|delivery). idempotencyKey ile retry-güvenli. Ayrı write limit (20/dk).orders:write
POST/plugin-api/packets/updatePaketin sınırlı alanlarını güncelle (allowlist: status[label]/type/note/paymentNote/customer.address|phone). type değişimi eski→yeni loglanır. Kapanış/iptal tetiklemez.orders:write
POST/plugin-api/packets/update-ordersPaket kalemlerini (cart) DEĞİŞTİR (full replace). total ürün kaydından yeniden hesaplanır; satır opsiyonel taxRate (0-100) + lineId/metadata taşıyabilir (lineId full-replace’te kimliği KORUR — ama yalnız HER istekte yeniden beyan edilirse; metadata {key,value} dizisidir). paid > yeni total → reddedilir (success:false).orders:write
POST/plugin-api/packets/update-paymentsPaket ödemelerini yaz. Scope: payments:write (YÜKSEK YETKİ) VEYA orders:write (bu yol için DEPRECATED). mode:"replace" (VARSAYILAN, full replace) veya mode:"append" (mevcutlara dokunmadan ekle; lineId ZORUNLU, yanıtta replayed — 🧪 YALNIZ sandbox; production'da YOK ve planlanmıyor). paid yeniden hesaplanır (price>0). Satır opsiyonel lineId + metadata ({key,value} dizisi) taşıyabilir (id = ödeme YÖNTEMİ id'si, satır kimliği değil; kimliği her istekte yeniden beyan et). paid > total → reddedilir (success:false). update-orders ile eş zamanlı çağırma.payments:write
GET/plugin-api/tables/getMasa detayı (dolu order). orders[] + ödeme kırılımı payments[] packets/get ile aynı satır şekli (lineId + metadata {key,value,by} dizisi dahil); type daima dine_in (türetilir). Kimlik masaya özel (tableId/tableName/desing — packetId değil). table.close gate target.id ile çekilir.orders:read
GET/plugin-api/tables/layoutMasa yerleşimi (floor plan): bölümler + masa adları. Ücret/grid alanları dönmez. Masa = bölüm+ad.orders:read
GET/plugin-api/tables/openAçık masa hesapları (özet): tableId, tutar (total/paid/indirim), ürün adedi. Detay: tables/get?id=.orders:read
POST/plugin-api/tables/createDine-in masa AÇ (QR self-order / kiosk). tableId layout'tan gelmeli (uydurulamaz); açık masada 409; kuver otomatik; cart boş olabilir, satır opsiyonel taxRate (0-100) + lineId/metadata ({key,value} dizisi) taşıyabilir; opsiyonel payments[] (<=20) ile masa AÇILIRKEN tahsilat da yazılır (yanıtta paid). type alanı YOK (masa zaten dine_in). table.created tetikler. Kapatma/silme yetkisi yok.orders:write
POST/plugin-api/tables/update-ordersMasa kalemlerini DEĞİŞTİR (full replace). total kuver dahil yeniden hesap; satır opsiyonel taxRate (0-100) + lineId/metadata taşıyabilir (kimliği HER istekte yeniden beyan et; metadata {key,value} dizisi); timer ürün desteklenmez.orders:write
POST/plugin-api/tables/update-paymentsMasa ödemelerini yaz. Scope: payments:write (YÜKSEK YETKİ) VEYA orders:write (bu yol için DEPRECATED). expectedUuid verilirse oturum kapısı: masanın o anki uuid'si ile tutmazsa 409 session_changed ve hiçbir şey yazılmaz (gecikmeli yazan entegrasyonlar için pratikte zorunlu). mode:"replace" (VARSAYILAN, full replace) veya mode:"append" (mevcutlara dokunmadan ekle; lineId ZORUNLU — 🧪 YALNIZ sandbox; production'da YOK ve planlanmıyor). Satır opsiyonel lineId + metadata ({key,value} dizisi) taşıyabilir. Ödeme doğrulaması packets ile birebir (unknown_payment_method).payments:write
POST/plugin-api/payments/statusÖdeme terminali SAĞLAYICISI tahsilat sonucunu/ilerlemesini bildirir. status küçük harf: sent_to_terminal · processing · approved · declined · cancelled · reversed. approved ve reversed'da payload.approvedAmountMinor ZORUNLU (tutarsız onaydan satır yazılamaz; aşarsa 409 amountExceedsRequested). recorded:false = bayat/sırasız event, HATA DEĞİL → retry ETME. Ucun adresini komuttaki payload.callbackUrls.status'tan al, koda gömme. ⚠️ Jenerik /capabilities/payment.terminal/status 404 döner ve bu KASITLIDIR (jenerik invoke yolu 25 sn sonra yeniden denerdi = kartttan ikinci çekim). Kova cap:payment.terminal, 600/dk.capability:payment.terminal:provide
GET/plugin-api/payments/{paymentId}⚠️ YALNIZ DEV — production'a dağıtılmadı (prod'da 401 döner ve bu "uç yok" demektir, "yetkin yok" değil). Sağlayıcının CİHAZDAKİ uygulaması tahsil edilecek tutarı + (TR) kalem dökümünü çeker. ⚠️ Kimlik CİHAZ OTURUM JWT'si (/v1/connectors/session), install API key DEĞİL. GET = ACK: çekince deneme ACCEPTED olur ve 60 sn servis penceresi başlar (sonrası 409 amountWindowClosed; pencere içinde idempotent). Tutarlar ONDALIK (Exponent yok) → Math.round(x*100), kesme YASAK. TR'de SaleItem var, EU'da yok; ItemsScope:"fullSale" iken RequestedAmount kısmi olabilir. 404 hem "yok" hem "senin cihazın değil" demektir (oracle koruması).capability:payment.terminal:provide
POST/plugin-api/payments/{paymentId}/result⚠️ YALNIZ DEV — production'a dağıtılmadı. Sağlayıcının CİHAZDAKİ uygulaması tahsilat sonucunu bildirir. Kimlik: cihaz oturum JWT'si (GET ucuyla aynı). Gövde: nexo SaleToPOIResponse'ın TAMAMI — kasaya senkron dönenle AYNI nesne (iki ayrı şekil üretme, ıraksarlar). recorded:false HATA DEĞİL (bayat/tekrar, at-least-once) → retry etme. Kesin sonuç DEĞİŞTİRİLEMEZ (409 conflictingResult + alarm). ⚠️ Tanınmayan ErrorCondition "reddedildi" SAYILMAZ: kesin ret yalnız Refusal/InvalidCard/WrongPIN/PaymentRestriction, kesin iptal Cancel/Aborted, kalanı BELİRSİZ — yanlış "declined" kasiyeri yeni denemeye iter ve ikinci kez kart çekilir. Ham PAN → 400 invalidCardLast4 (kırpılmaz, ihlal görünür kalsın). İlerleme bildirimi EventNotification ile ve YALNIZ platforma gider.capability:payment.terminal:provide
POST/plugin-api/connectors/codeYeni bir ödeme cihazı için KAYIT KODU üretir. Kodu üreten eklenti, o kodla kaydolan cihazın SAHİBİ olur — sahiplik zinciri buradan başlar. ELEVATED: kod üretmek, restorana gerçek tahsilat yapacak yeni bir cihazın bağlanmasına izin vermektir.terminals:write
GET/plugin-api/connectors/listBu eklentinin SAHİP OLDUĞU cihazları listeler. Aynı restorandaki başka sağlayıcıların cihazları listede YER ALMAZ.terminals:read
POST/plugin-api/connectors/revokeCihazı devre dışı bırakır (çalışan bir terminali durdurur). Yalnız KENDİ cihazınız; başkasınınki 404 "bulunamadı" döner — "senin değil" DEĞİL, çünkü o yanıt diğer sağlayıcının cihaz kimliklerini taramaya izin verirdi.terminals:write
GET/plugin-api/products/getÜrün detayı (id ile). fiyat, KDV, görsel, barkod, stok, seçenek/choice ağacı. cost/recete dönmez.products:read
GET/plugin-api/products/listTüm ürün kataloğu (aktif+pasif). Max 2000 (aşılırsa truncated+total). cost/recete dönmez.products:read
GET/plugin-api/categories/listTüm ürün kategorileri (aktif+pasif). id, title, image, color, rank. Ürün category ile eşleşir. Max 500.products:read
GET/plugin-api/categories/get?id=Tek kategori detayı (id ile). Şekil categories/list öğesiyle aynı. category.* event id'sini zenginleştir.products:read
GET/plugin-api/payment-methods/listTanımlı ödeme yöntemleri (Nakit/Kredi Kartı…): id, title, description, cash, noreport. users dönmez.payment_methods:read
GET/plugin-api/ingredients/listMalzeme/stok kataloğu (envanter): id, title, unit, stock, alert, tax. ort(maliyet)/stocks/storages dönmez.ingredients:read
GET/plugin-api/customers/listMüşteri kataloğu (CRM/sadakat) — cursor pagination (after/nextCursor, max 500). name/phone/address (PII) + total (finansal) yalnız consent ile; yoksa {id,region}.customers:read
GET/plugin-api/customers/get?customerId=Müşteri detayı (id ile). {id,region} + name/phone/address (PII) + total (finansal) yalnız consent ile. Şekil customers/list öğesiyle aynı.customers:read
GET/plugin-api/users/getPersonel (kullanıcı) listesi [{ id, name }] — name yalnız PII consent ile. Max 200, cache'le. pincode/yetki/e-posta/mesai dönmez.users:read
POST/plugin-api/products/{create,update,delete}Ürün katalog yazma. Sahiplik: yalnız kendi oluşturduğunu düzenler/siler. category var olmalı; cost/stock/image yazılamaz.products:write
POST/plugin-api/categories/{create,update,delete}Kategori katalog yazma (products:write; ayrı scope yok). delete: kategori boş olmalı (categoryNotEmpty).products:write
POST/plugin-api/payment-methods/{create,update,delete}Ödeme yöntemi tanımı yazma. Sahiplik kontrollü. Personel ataması panelden (API'de yazılamaz).payment_methods:write
POST/plugin-api/ingredients/{create,update,delete}Malzeme/stok kartı yazma. Sahiplik kontrollü. stock/ort yazılamaz; yeni kart stok 0.ingredients:write
POST/plugin-api/purchases/createTek-seferlik (IAP) satın alma başlat. Stripe Checkout URL üretir; tenant UI'da öder. Gross kuruş [min,max]; idempotencyKey ile retry-güvenli. Ayrı write kovası.purchases:write
GET/plugin-api/purchases/get?purchaseId=IAP satın alma durumu (authoritative). status/type/productKey/amount/currency/zaman damgaları. net/developerShare/Stripe ID gibi finansal alanlar sızmaz.purchases:read
GET/plugin-api/purchases/listKendi IAP satın almaları — en yeni önce, limit max 100. Yalnız çağıran install'ın (serverId+pluginId) kayıtları; başka eklenti/tenant görünmez.purchases:read
POST/plugin-api/messaging/sendEklentiler-arası: tenant'ın bağladığı mesaj sağlayıcısı (WhatsApp/SMS eklentisi) üzerinden müşteriye mesaj isteği. to yalnız {customerId} (ham PII yasak); idempotencyKey zorunlu; accepted ≠ delivered. Ayrı messaging kovası (60/dk).messaging:send
POST/plugin-api/messaging/statusEklentiler-arası (sağlayıcı): teslim durumu raporu (DLR — sent/delivered/read/failed). Platform yalnız istek sahibi tüketiciye hedefli messaging.message.status event'i teslim eder; aynı raporun tekrarı idempotent.messaging:provide
POST/plugin-api/capabilities/{cap}/invokeJENERİK eklentiler-arası yetenek çağrısı (Faz 4). cap = katalog yeteneği (messaging.send, notify.staff, invoice.issue). Tüketici, tenant'ın bağladığı sağlayıcıya ilgili payload'ı yollar; idempotencyKey zorunlu. messaging.send eski /messaging/send ucuyla aynı sonuç.capability:{cap}:consume
POST/plugin-api/capabilities/{cap}/statusJENERİK sağlayıcı asenkron durum raporu (yalnız async-status'lu capability'ler: messaging.send, invoice.issue). Platform yalnız istek sahibi tüketiciye hedefli status event'i teslim eder.capability:{cap}:provide
Bu liste büyür — yeni uçlar zamanla eklenir; her uç kendi detay sayfasıyla burada listelenir.

OpenAPI spec'i (makine-okunur)

Tüm uçlar + webhook sözleşmeleri (event/lifecycle zarfları, imza header'ları, gerçek örnek payload'lar) OpenAPI 3.1 olarak yayınlanır — bu sayfayı besleyen tek-kaynak kataloglardan build sırasında üretilir, dokümanla asla sapmaz:

  • İnteraktif dene: API Referansı (try-it konsolu) — uçları tarayıcıda keşfet + dev-store apiKey'inle gerçek istek at.
  • Ham spec: /openapi.json — operasyonlar gerekli scope'u x-required-scope, yayın durumunu x-status (live|soon) ile taşır; alan tabloları için her operasyonun externalDocs'u detay sayfasına gider.
  • Postman / Insomnia / Bruno: /openapi.json'u Import et — koleksiyon otomatik oluşur (uç + örnek + auth).
  • Typed SDK üret:
    # OpenAPI Generator (çok dilli)
    npx @openapitools/openapi-generator-cli generate \
      -i https://dev.restomenum.com/openapi.json -g typescript-fetch -o ./sdk
    
    # veya orval (TS, React Query)
    npx orval --input https://dev.restomenum.com/openapi.json --output ./sdk/client.ts

AI ajanları için ayrıca: /llms.txt ve changelog RSS (/changelog.xml). Sürüm/uyumluluk politikası: Versiyonlama & Deprecation.