Geliştiriciyi etkileyen değişiklikler (yeni uçlar, hook'lar, scope'lar, yetenekler). Yalnızca canlıya alınmış/doğrulanmış özellikler listelenir; planlananlar 'Yakında' altında.
/changelog.xml (RSS 2.0; bot/izleme aracına ekle). AI ajanları için /llms.txt.table.reopened (kapanmış masa geri açıldı) · packet.reopened (kapanmış entegrasyon satışı geri açıldı) · table.closed_deleted/packet.closed_deleted (kapanmış fiş silindi — satış geri gelmez, kestiğin belgenin dayanağı ortadan kalkar). Yalnız table.reopened dinleyen bir eklenti diğer ikisini hiç görmez ve kestiği belge ayakta kalır → karşılaştırma tablosu.entegrasyon alanı doluysa geri açma masa kanalından bildirilmez — table.reopened yayılmaz; packets/{id} yeniden yaratılır ve onCreate trigger'ı packet.reopened yayar. Teslim platformu siparişlerinde geri açmayı görmek için packet.reopened aboneliği şarttır.table.closed akarken table.reopened hiç gelmiyor olabilir → "webhook çalışıyor" gözlemi o tipe abone olduğunu kanıtlamaz. "Event gelmiyor" dediğinde ilk bakacağın yer manifest'inin events[] listesi.sequence: eskiden "numara atlaması olay kaybı değildir" diyorduk. Teknik olarak doğruydu ve tam bu yüzden tehlikeliydi: okuyucuyu boşluğu masum saymaya götürüyordu. Doğrusu: tek başına boşluk kaybın KANITI değildir, ama kaybı DIŞLAMAZ da. Bir olayın sana ulaşmaması platform tarafında da sessiz olabilir.*.closed. Bir satış hattı normalde bir kez kapanır → aynı sequenceScope için ikinci bir kapanış aldıysan ve arada geri alma işlemediysen, o geri alma sana ulaşmamıştır. Belirsiz değil, kesin çıkarım; yanlış alarm üretmez ve defterinde zaten var olan veriyle uygulanır. Sahada beş kayıp geri almanın beşini de ayırt eden sinyal buydu.mode göndermek isteği komple 400'e düşürür ("mode" is not allowed) — eski davranışa düşmez. Production entegrasyonunda bu alanı gönderme; durum değişirse burada duyurulur. Sandbox'ta gerçek HTTP çağrılarıyla uçtan uca doğrulandı — paket ucu 18/18, masa ucu sandbox.plugins.restomenum.app hostname'i üzerinden 9/9; doküman sayfalarındaki yanıt gövdeleri o testlerden yakalanmış gerçek gövdelerdir.mode: "replace" | "append" (packets · tables). Varsayılan "replace" → mode göndermeyen mevcut çağıranın davranışı bit-bit aynı; kırıcı değişiklik yok, sürüm artışı gerekmiyor.paid düşüyordu. Ekleme modunda satırlar mevcutların üzerine eklenir, mevcutlara dokunulmaz.lineId ekleme modunda ZORUNLU — keyfi değil, tekrar gönderim kalkanı. Kimlik göndermeyen satıra platform her çağrıda farklı bir kimlik üretir → ağ hatasındaki retry ikinci satır olarak eklenirdi = çift tahsilat. Kimlik güçlü olmalı (≥8 karakter, saf rakam değil); grandfather affı burada işlemez, çünkü af yalnız dokümanda zaten var olan kimliği bağışlar. Kalıp: pay-<uuid>.replayed. true → aynı lineId ile tekrar gönderim algılandı, yazma yapılmadı, doküman değişmedi ve hiçbir event yayılmadı. Retry sonrası "ödemem zaten kayıtlı" demektir.append_requires_line_id · append_requires_payment_line · append_partial_duplicate · append_replay_amount_mismatch · append_replay_method_mismatch · too_many_payment_lines. append_partial_duplicate bilerek serttir: satırların bir kısmı yazılı bir kısmı yeniyken sessizce yalnız yenileri eklemek, çağıranın hangi satırının geçtiğini bilmediği bir durumda çift tahsilat üretirdi → istek toptan reddedilir, tüm isteği aynı lineId kümesiyle tekrar gönder.replace bu yüzden dokümanı fiilen 20'ye indirir) + ekleme modunda birleşim ≤100. ⚠️ Çekirdek/personel akışları bu uçlardan geçmez ve dokümanı 20'nin üstüne çıkarabilir → böyle bir hesaba replace çağırmak fazlasını siler.*.updated olayını changed:"payment_added" ile yayar, "payment_updated" ile değil — ikincisi "ödeme satırları tam değiştirmeylegüncellendi" demektir ve ekleme modunda onu yaymak aboneye "tüm satırlar değişti, yeniden diff'le" dedirtirdi. replace modu eskisi gibi payment_updated yayar.{ ok:true } gövde" iddiası YANLIŞTI. Doküman ve SDK bir dönem "yazma uçları okuma zarfını kullanmaz, data yoktur" diyordu. Doğrusu: yazma uçları da { success:true, data:{…} } döner; ok platformun modül-içi dönüş alanıdır ve HTTP sınırına hiç çıkmaz. Yedi paket/masa yazma ucunun data şekli artık Genel Bakış'ta teyitli olarak listeli.packets/create alan adı packetId, uuid DEĞİL. Doküman ve SDK tersini söylüyordu. 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. SDK PacketCreateResult tipi düzeltildi.docNoDate ≠ businessDate. Biri numaranın hangi seriden/günden kesildiği, diğeri satışın ait olduğu iş günü (ikisi de YYYY-MM-DD, null olabilir). Çoğu gün aynı görünürler ama gün sınırında ve geri-açmada ayrışırlar — karıştıran entegrasyon raporlamayı yanlış güne yazar. ⚠️ businessDate create yanıtında dolu gelir ama pakete yazılmaz → packets/get ile geri okunamaz; ihtiyacın varsa yanıttan kendi kaydına sakla.status. Hata zarfı { success:false, status, message } — status HTTP kodunun gövde içindeki kopyasıdır (kuyruklanan/loglanan gövdelerde kod kaybolmasın diye)."Yemeksepeti-Kapıda Nakit" dün cash:false görünüyordu, bugün cash:true.CASH/NON_CASH ayrımını ödeme satırları + cash bayrağından türetiyor → imzalanan fişteki ZAHLART_TYP değişiyor: dün NON_CASH damgalanan teslimat ödemeleri bugün CASH damgalanacak. Almanya'da bu yasal bir beyan alanıdır; geçmiş kayıtlarla karşılaştırma yapıyorsanız kırılma noktasını bu tarihe koyun.cashDeclared — hem payment-methods/list kataloğunda hem ödeme satırında. cash bir beyan mı, platformun güvenli varsayımı mı? false → yöntem kaydında nakitlik alanı hiç doğmamış → varsayıma dayalı sınıflandırmayı damgalama, kiracıdan beyan iste.methodId taşıyor (teslimat entegrasyonlarının sözde-yöntemleri) → o satırlarda join edecek hedef yoktur, nakitliği satırdan oku.locale — blocking hook gövdesinin üst seviyesinde (data'nın içinde değil). decision:"deny" döndüğünde message'ınız kasiyerin ekranında görünüyor; o metni bu dile göre yerelleştirin. ⚠️ Opsiyonel, fallback zorunlu — tanınmayan dilde alan hiç gelmez. Ayrıntı: hook sözleşmesi.payment_method.* webhook'unun data'sı katalogla “birebir aynı şekil” değil — description serbest metin olduğu için PII taramasına takılıyor ve müşteri-PII rızası olmayan kurulumlarda gelmiyor.origin.deviceId'yi "doğrulanmış cihaz kimliği — mali atıfta bunu tercih et" diye duyurmuştuk. O yönlendirme geçersizdir ve alan zarftan kaldırıldı: platform origin'i göndermiyor.undefined değil, yanlış kasa kimliği demektir — Almanya'da Z_KASSE_ID DSFinV-K kaydında yasal bir beyandır. Alan yayındayken de zayıf temeldi: deviceId bir hesap kimliğiydi (terminalId değil) ve aynı ortak hesap birden çok tablette aynı değeri taşıyabiliyordu.actor.userId (⚠️ doğrulanmaz, denetim izi olarak yaz); hangi kasa/terminal → senin beyanın (fiscal.de → registerId). Personel/cihaz → kasa eşlemesi eklentinin kendi ayarlarındadır. SDK 3.2.0'da Origin ve WebhookEnvelope.origin @deprecated; eşleyici ve passthrough yerinde bırakıldı — alan bir şekilde gelirse yine de düşmez.lines = satışın sipariş satırları, şekli kapanış gövdesindeki orders[] ile birebir aynı (DSFinV-K satır ayrıntısı). ⚠️ Ya tam ya hiç — kırpılmaz: satış 200 satırı aşarsa liste hiç konmaz, yerine linesOmitted: "too_many_lines" gelir. Alanın yokluğu "satır yok" değildir → boş liste sanıp eksik fiş imzalama; ayrıntı gerekiyorsa tables/get ile çek.docNo satış ömrü boyunca sabit değil: belge numarası her kesilen belgede sayaçtan alınır → geri açılan satış yeniden kapanınca yeni numara gelir. Satış kimliği (uuid) ömür boyu sabittir. Satışı anahtarlamak için uuid kullan; mali tekleme anahtarında docNo + iş günü birlikte kullanılmaya devam eder.reopenedFrom kapanış gövdesinde de tipli: gate gövdesine reopenedFrom ({ saleId, docNo?, closedAt? } — *.reopened ile aynı şekil) eklendi. ⚠️ Garanti edilmez, savunmacı oku: varsa yerine geçen fişe atıf bas ("… nolu belge yerine"), yoksa hiçbir şey değiştirme — yokluğunu "geri açılma yok" sayma. Kesin zincir *.reopened olayındadır.integration/removeOrder dokümanı yazıyordu ama hiçbir olay çıkarmıyordu; artık panelin iptal ucuyla aynı desende packet.updated yayınlıyor. Silinen satır cancels[]'a taşındığı için op: "cancelled"'dır, removed değil — kapsam listesine eklendi.op:"updated" girdisine movedTo + movedQuantity koyar. ⚠️ movedQuantity yalnız düşüş tek anlamlıyken konur: aynı yazımda satıra iptal kaydı da düştüyse adet ayrıştırılamaz → movedTo gelir ama movedQuantity konmaz.title her akışta dolu; sıra tenant ayarı (kuverText) → satıştaki mevcut kuver başlığı → "kuver". Önce alan istekte yoksa undefined olup dokümandan düşüyordu — aynı tenant'ın bir fişinde işletme adı, diğerinde ham kimlik görünüyordu (DSFinV-K ARTIKELTEXT tutarsızlığı). Kuver yalnız masa satışında oluşur.op === 'removed' && removeReason !== 'moved' kısmi devri kaçırır (orada removed hiç gelmez) — sahada tam olarak bu yaşandı ("4 adet iptal edildi"). Doğrusu: adet düşüşü her zaman iptal değildir; updated + movedTo varsa düşüşün movedQuantity kadarı devirdir. SDK'da LineChangeUpdated iki alanı da tanıyor ve yeni shouldReverse(change) yardımcısı dört dalı tek yerde kapatıyor.table.close/packet.close gate gövdesi (⏳) · capability:fiscal.de payload'ı (⏳). Üçü de aynı sözleşme; kırıcı değil, ek okuma maliyeti yok.sequenceScope yeniden kullanılmaz (yalnız kalıcı yazımda üretilir, değeri rastgele) · sequence scope içinde monotondur (yalnız ileri; atlanan numara olabilir, tekrar eden/azalan olmaz). ⚠️ Karşılaştırma daima aynı scope içinde — farklı scope'lar arasında sıra ilişkisi tanımsızdır; hat yeniden başlarsa yeni scope üretilir ve sayaç 1'den başlar.null da gelmez) → o olay için karşılaştırmayı atla; sequence: 0 varsayma.fiscal.de: bugün yalnız sale.type: "packet" kabul ediliyor; "table" ayrı bir hata koduyla reddediliyor → masa satışlarında capability yolu yok, mali blok kapanış gate'i üzerinden taşınır.lineChanges yayın kuralı netleşti: blok changed tipine değil gerçek satır deltasına bağlı; delta boşsa alan hiç konmaz ve ödeme değişimleri delta üretmez.packet.close_aborted yayınlanmaya başladı — table.close_aborted ile birebir aynı sözleşme, ikisi de artık canlı.abortReason sözlüğü (underpaid · overpaid · payment_without_order · total_repaired — dördü de kestiğin fişi storno et), "yalnız gate gerçekten çalıştıysa yayınlanır" koşulu ve sıra kuralı: iptal kapanışın tersi değildir, hat sürer (sequence artmaz) → defterini kapatma.packet.updated ile aynı kanonik şekil + abortReason).lib/closeAborted.mjs'te). SDK tipi: PacketCloseAbortedPayload.*Decimal sonekine geçti: discount → discountDecimal, extra → extraDecimal, lineTotal → lineTotalDecimal. Satır düzeyinde aynı ad iki farklı para ölçeğinde yaşıyordu ve kökteki amountExponent: 2 bu ondalıklara uygulanmıyor → üssü görüp satırdaki discount'ı 100'e bölen entegratör 12,60 ₺ yerine 0,126 ₺ yazardı; mali tüketici satırı imzaladığı için sapma geri alınamazdı. Eski adlar kaldırıldı; amounts minor unit'in tek otoritesi. Kök total/paid/totalDiscount, payments[].amount ve yazma tarafı cart[] değişmedi.packet.status_changed: teslimat statüsü geçişi artık ayrı tip — gövde packet.updated ile aynı + status / previousStatus (bilinmiyorsa null, uydurulmaz). ⚠️ Zarfta actor bulunmaz (Firestore trigger yayınlar) → isOwnEcho daima false. Statü değişmeyen yazımlarda olay çıkmaz.1+2+4+8+16 = 31 sn) bir deploy'u ya da kısa kesintiyi kaldıramıyor, olayı kalıcı olarak düşürüyordu. Artık 20 deneme · 10 sn → 3600 sn (+ 24 saatlik sert tavan). ⚠️ Idempotency artık daha kritik: aynı olay 20 kez gelebilir ve aralarında saatler geçebilir → zarf id'si ile dedup zorunlu. (Şu an yalnız sandbox; production kuyruğu eski ayarda.)tableId ile anahtarlayan bir mali eklentide aynı masanın kayıtları üç ayrı anahtara dağıldı — siparişler table:masa-904'te, fiş table:<uuid>'de. Aynı satışın sipariş kayıtlarıyla fişinin bağı koptu (KassenSichV/DSFinV-K açısından ihlal).tableId/packetId bir adrestir, kimlik değil — tek satış içinde biçim değiştirir: masa-904 → geri açmada masa-904* → kapanışta kapanış kaydının kimliği. uuid ise açılış · düzenleme · kapanış · geri açma boyunca sabittir (ölçüm: 20 masa — her biri iki fazlı — + 13 paket, hepsi 1:1 tek anahtarda).accountKey(data) artık uuid döndürüyor (uuid → saleId → eski dokümanlarda tableId/packetId). Caret bağımlılıkla (^3.0.0) bu sürüm otomatik gelir → store anahtarların değişir: kayıtlarını uuid'ye taşı ya da eski anahtarı kendi tarafında data.tableId ?? data.packetId ile üret.Table/Packet olay yükü tiplerinde uuid artık ilan ediliyor (alan zaten gönderiliyordu, sözleşmede görünmüyordu) · cancelPayments[] eklendi · tableId yorumu "adres/slug — kimlik değil" olarak düzeltildi.actor, origin, sequence, sequenceScope tüketiciye ulaşıyor.table.closed hâlâ kapanış kaydının kimliğini taşıyordu — "artık masa slug'ı" düzeltmesi dev'de yayında ama sandbox'ta gözlenmedi. Hangi davranışta olursan ol uuid doğru anahtardır.lineId artık ayırt edici olmak zorunda: canlıda bir eklenti satır kimliği olarak "1" yazdı. Sözleşme benzersizliği yalnız doküman içinde garanti eder — ama mali tüketici için lineId, "bu satır fişlendi mi?" sorusunun tek yanıtıdır: iki satış aynı kimliği taşıyınca ikisi tek satır sayılır ve ikincisi fişsiz kalır. Uzunluk 8–64 (yeni alt sınır), saf rakam reddedilir ("1", "00000001" → 400); biçim ve rezerve kimlikler (kuver, new) değişmedi. "00000001" sekiz karakterdir ama iki bağımsız sayaç kaçınılmaz olarak aynı değerleri üretir — uzunluk tek başına yetmiyor.packets/create / tables/create uçlarında grandfather yok. Platformun kendi üretimi de kırılmıştı: 1196 satırın 409'u (%34) alt sınırın altındaydı (b1-1829) — üretim artık prefix'i telafi ediyor (b1-1d049). Öneri: anahtarını (uuid, lineId) çiftine çevir.table.closed artık masa slug'ı döndürüyor: aynı satışın akışında tableId iki farklı kavram taşıyordu (table.updated'da masa-901, kapanışta closedTables doküman kimliği). Artık üçü de aynı: table.updated masa-901 · table.closed masa-901 · table.reopened masa-901*. Kapanış kaydına tableId ile ulaşıyorsan kırılırsın → uuid kullan (closedTables/{uuid}); reopenedFrom.saleId ve closed_deleted saleId de artık kapanış olayının uuid'siyle eşleşir. uuid'si olmayan eski satışlarda bu bağ tamamen kapanır (bilinçli kabul). ℹ️ Paket kanalı değişmedi — packet.closed aynen eskisi gibi.quantity, extra, discount dokümandan ham geçiyordu ve alan eksikse payload'dan sessizce düşüyordu. Artık: "10"/"10,50" ayrıştırılır → 10/10.5 (virgül ondalık ayırıcı); boş/çözülemeyen ve eksik alan → extra/discount 0, quantity 1; açık 0 korunur. quantity 1'e düşer çünkü satırın lineTotalDecimal'ı eksik adedi 1 kabul ederek hesaplanır (0 deseydik gövde kendini yalanlardı). Yuvarlama yok — quantity para değildir. Number("") → NaN dalı artık hiç doğmuyor; 4 üretim tenant'ı · 1196 satır taramasında tamamı zaten sayıydı → veri düzeltmesi değil, sözleşme garantisi.moved_out kaldırıldı: yerine removed + removeReason ('moved' | 'deleted'). Eski ad iki farklı olguyu aynı kelimeyle söylüyordu: hedefi belli devir (storno etme — hedef zinciri sürdürüyor) ile izsiz silme (storno et). Tüketici kuralı tek satır: if (op === 'removed' && removeReason !== 'moved') storno(). removeReason çağıranın beyanı değil, movedTo'dan türetilir → hedefsiz bir 'moved' yayınlanması yapısal olarak imkânsızdır.users:read onaylatan eklenti, customers:read hiç istemeden müşterinin adını, telefonunu, adresini ve konumunu alıyordu. Artık CUSTOMER_PII (customers:read, customers:write, messaging:provide, capability:messaging.send:provide) ve USER_PII (users:read) ayrı kapılar. Müşteri verisi okuyorsan manifest'ine customers:read ekle ve yeniden onay al; yoksa customer alanında yalnız { id, region } görürsün.reason adı verilmez: redaction katmanı reason anahtarını serbest-metin PII sayıp her derinlikte siler; alan önce bu adla yazılmıştı ve PII rızası olmayan tipik mali eklentide undefined geliyordu → kural gereği taşınan her satır storno edilirdi. Kök seviyede deleteReason, satır seviyesinde removeReason.orders[]'dan sessizce düşüyor, cancels[]'a hiçbir kayıt yazılmıyordu. Artık void kaydı yazılır ve delta cancelled olarak gelir (kuver satırı türev olduğu için dışlanır; void kaydı plugin:<pluginId> aktör damgası taşır).discount: 0 ile yazılıyor, extra hiç bölünmüyordu → indirimli kalemde storno tutarı fazla, ekstralı kalemde ekstra çift sayılıyordu. 3 adetlik satır (indirim 10 · ekstra 30) 1 adet iptalinde: eski iptal {discount:0, extra:30} + kalan {discount:10, extra:30}; yeni iptal {discount:3.33, extra:10} + kalan {discount:6.67, extra:20} → toplam korunuyor.payOrders satırın tamamı tahsil edilince yeni lineId veriyordu; mali tüketici bunu "sil + ekle" görüp imzaladığı kaydı haksız yere storno ediyordu. Kimlik artık sabit. ⚠️ Kısmi tahsilatta satır hâlâ bölünür ve parçalar yeni kimlik alır (bilinçli olarak ertelendi) — soyu lineChanges'ten izle.cancelPayments[]: iptal edilen tahsilatlar, payments[] ile birebir aynı şekil. Satır void'i yayınlanırken ödeme void'inin yayınlanmaması doğrudan bir asimetriydi. ⚠️ paid aktif ödemelerin toplamıdır — bu liste ona dahil değildir.moved_out geçen kodunu removed + removeReason'a çevir; müşteri verisi okuyorsan customers:read ekleyip yeniden onay al. Tipler SDK 3.0.1+'da.table.close_aborted: gate onayından sonra kapanış düşerse gelir (kalem/ödeme eklendi → underpaid/overpaid/payment_without_order/total_repaired). Kestiğin fişi storno et. ⚠️ İptal kapanışın tersi değildir: satış hattı sürer (sequence artmaz) → defterini kapatma. (⚠️ Güncellendi: packet.close_aborted artık yayınlanıyor — birebir aynı sözleşme.)receiptExtras döndürebilirsin — panel gateToken'ı data.gateTokens[] ile taşır (HMAC imzalı, 120 sn, yalnız gerçek allow). Senkron yol kaldırılmadı. Ayrıca ön koşul kapısı: kapanamayacak hesapta gate hiç çalışmaz → plugin.hook.preconditionFailed.uuid — kalıcı satış kimliği: bir satışın üç doküman kimliği vardı (masa-300 → masa-300* → kapanış UUID'si). uuid ömür boyu sabittir ve kapanış kaydının kimliğidir (⚠️ güncellendi: table.closed'ın tableId'si artık masa slug'ı — bkz.); olaylarda + tables/open · packets/open'da gelir.n+1, hedef n+2 (aynı hat); birleştirmede hedef kendi hattını ilerletir; kısmi taşımada iki hesap da kendi hattını sürdürür.extra ölçümde tamamen sayı çıktı. (⚠️ Güncellendi: extra/discount/quantity artık normalize ediliyor ve sözleşme tip garantisi veriyor — bkz. Üç kırıcı değişiklik.) Taşımada satır kimliği korunur (çakışmada movedFrom.lineId eskiyi taşır). İptal sebebi metni (reasonId → katalog) hâlâ açık madde.table.updated / packet.updated gövdesine data.lineChanges — hangi kalem değişti, ne kadarı iptal edildi, hangi yeni satır hangisinin devamı. Alan opsiyoneldir: yalnız satır düzeyinde bir şey değiştiğinde gelir (ödeme eklenmesinde gelmez) → ?? [] ile oku. Tam sözleşme: Satır deltası (lineChanges); tipler SDK 3.0.1'de.op sözlüğü: created · updated · cancelled · moved_out (⚠️ sonradan kaldırıldı → removed + removeReason; bkz. sözleşme bülteni). deleted bilerek yok: bir satır ya iptal edilir ya devredilir, mali işlemleri zıttır.orders[] tam durumu; blok yoksa/eksikse tam durumdan yakınsa) ve cancelled adet kapsamlıdır (quantity iptal edilen adettir; satır azaltılmış adetle hâlâ aktif olabilir).splitFrom · movedFrom · movedTo — yeniden kimliklenen satırın nereden geldiğini söyler; varsa storno yazma. Şekil *.deleted'takiyle aynı.orders[], changed, zarf, imza ve redaction aynen duruyor. Bugün yapman gereken: hiçbir şey.sequence (satışın kaçıncı durum değişikliği) + sequenceScope (sq_ önekli opak satış hattı). Teslim sıralı değildir; occurredAt bayat snapshot'ı ayırt etmeye yetmez. Beş kural + defter tasarımı: Olay sırası (sequence).(tenantId, sequenceScope) ile anahtarla ve terminal olaydan sonra hemen silme (öneri: 7 gün). Tek slotlu tasarım ve erken silme, satışın dirilmesine yol açar. Numara atlayabilir — olay kaybı değildir; alan yoksa sequence: 0 varsayma.currency + amountExponent, satırda amounts (tamsayı minor unit bileşen kırılımı) ve karışık KDV oranlı satırda perVat[]; options[].vatRate dondurulmuş orandır (null = dondurulmamış). Garantiler ve tuzaklar: Tutarlar (amounts).amountExponent yalnız amounts.* içindir. lineTotalDecimal, total, paid, payments[].amount, options[].price ondalıktır — üssü onlara uygularsan 100 kat sapma. Özet uçlarında (tables/open · packets/open) üs hiç gönderilmez.table.*/packet.* webhook'ları · packets/get · tables/get · blocking hook includeData · customer.order_added. sequence/sequenceScope yalnız webhook zarfında.sequenceVerdict · advanceSequenceCursor · sequenceKey · minorToDecimal · sumLineAmounts · vatBreakdown (+ LineAmounts/VatBucket tipleri) — SDK.webhook / connect /action yolları ve UI sayfalarının ortak origin’i bir kez tanımlanır — her sürümde yeniden girilmez. Sürüm editöründeki “Uç noktalar” kartı bu tek konfigürasyonu düzenler.application_url + redirect_urls), Slack (Request URL), GitHub Apps (Webhook/Callback URL), Stripe (endpoint URL) — hepsi uygulama seviyesinde tutar ve origin/path diye bölmez.set_origins aracı; set_dev_origin geriye dönük ad olarak kaldı; create_version’da webhook_url/connect_url artık opsiyonel (verilmezse eklenti konfigürasyonundan türetilir).options[] alanı artık düz ad dizisi değil, tipli nesne dizisidir: { id, title, price }. Yalnız ada ihtiyacın varsa options.map(o => o.title) yaz.price katalogtan okunur ve satır toplamına platformca dahil edilir — lineTotalDecimal üzerine ayrıca ekleme.table.updated · packet.updated · *.created · *.closed · *.deleted · *.reopened · *.closed_deleted · packet.cancelled · customer.order_added · hook includeData gövdesi · callback servisi · ve iptal listesi cancels[].{ id } (katalog kimliği — en kesin), { title } ya da düz string (eski biçim) ile beyan edersin; mevcut çağrılar çalışmaya devam eder.Invalid option: <ürün>: <neden> (<beyan>): seçenek katalogda yok · başlıkla beyan belirsiz (aynı adlı farklı fiyatlı seçenekler → { id } ile beyan et) · aynı seçenek tekrar beyan edilmiş.OrderOption (okuma) ve CartOptionInput (yazma) tipleri eklendi; CartLine.options ve OrderLine.options bunlara bağlandı.table.closed_deleted ve packet.closed_deleted. Kapanmış bir satışın kaydı silindiğinde düşer. Kapsam: orders:read. Tam sözleşme: Hesap Yaşam Döngüsü.*.deleted ile karıştırmayın — farklı olaylar. *.deleted açık bir hesabın başka hesaba devridir (veri yaşar, sahip değişir); *.closed_deleted ise kapanmış bir satışın yok edilmesidir.*.closed ile kayıt oluşturduysanız (fiş, fatura, ciro satırı) bu olayda onu storno edin. *.reopened'dan farkı: orada satış tekrar açılır ve yeniden kapanınca yeni kayıt gelir; burada satış geri gelmez.{ saleId, channel, status, closedAt, deletedAt, orders[], payments[] } — tableId/packetId yoktur, kimlik saleId'dedir. saleId, kapanış olayının gövdesindeki tableId/packetId ile birebir aynıdır → storno hedefini bununla bulun.orders[] / payments[] tek arşiviniz. Silinmeden önceki tam kayıttır; kayıt silindiği için tables/get / packets/get ile artık çekemezsiniz — gövdeyi saklayın.ClosedSaleDeletedPayload tipi; örnek eklentide iki yeni handler (44/44 event testi).isOwnEcho(envelope, MY_PLUGIN_ID). Atlarsan yaz → olay al → tekrar yaz sonsuz döngüsüne girersin; id dedup'u bunu durdurmaz. Ayrıntı.actor genişledi — ve güven seviyeleri ayrıştı. Önceki kayıt "kişi kimliği taşımaz" diyordu; doğrusu actor.userId (opak personel) ve actor.role (manager|staff) taşınır. ⚠️ Ama doğrulanmazlar: personel kasada PIN ile seçilir, backend bunu doğrulamaz → denetim izi olarak yaz, yetki kararında kullanma. Doğrulanmış tek actor alanı pluginId'dir.origin.deviceId. ⚠️ BU MADDE GERİ ALINDI — alan 19 Ağustos'ta kaldırıldı, platform göndermiyor; "mali atıfta bunu tercih et" yönlendirmesi GEÇERSİZDİR (bkz. en üstteki origin zarftan kaldırıldı kaydı — mali/kasa atfı için actor.userId + kendi registerId beyanın). Kayıt tarihçe için duruyor: alan o gün "oturum açmış cihaz hesabının doğrulanmış token kimliği" diye duyurulmuştu.{ success:true, data:{…} } döner ve packets/create alanı packetId'dir (uuid değil). Aşağıdaki metin tarihsel kayıt olarak duruyor. Yazma yanıt zarfı ayrı: { ok: true, … }. Okuma uçları { success, data } döner, yazma uçları düz gövde — data yoktur. ⚠️ packets/create → { ok, uuid }: alan adı uuid, packetId değil. Dönen tutar otoriterdir (gönderdiğin fiyat yok sayılır, kuver yeniden enjekte edilir); paid > total yazma reddedilir.sidebar.tools ve settings.menu (önceden yalnız sidebar.main).cancels[] okuma yanıtlarında da var — tables/get ve packets/get iptal edilmiş kalemleri döner (reason serbest metin → PII rıza kapısına tabi). open özetleri de genişledi (type; pakette orderCode, entegrasyon, isScheduled, scheduledDate).*.notFound 404 · *.missingParams 400 · plugin.scope.denied 403 · *.duplicateInProgress 409 · *.noProvider 424 · *.providerUnavailable 503 · *.timeout 504 · internal 500.paid == total olsa bile. Kapanış, iptal ve silme yalnız çekirdek/personel akışındadır; eklenti oluşturur ve alan günceller.isOwnEcho, Origin, ActorRole, Actor.userId/role, Table.cancels / Packet.cancels ve yazma yanıtı düzeltmesi (istemci yazma çağrılarında undefined dönüyordu).table.updated · table.reopened · table.deleted · packet.updated · packet.reopened · packet.deleted. Veri kapsamı altısında da orders:read; müşteri alanları ve serbest metin için ek olarak customers:read + rıza. Tam referans: Hesap Yaşam Döngüsü.actor. Değişikliğe kimin sebep olduğunu söyler ({ type: "staff" | "plugin" (+pluginId) | "system" }) ve data'nın dışında, üst seviyede durur — kapsam eksikken data boşaltılır ama aktör bilgisi hassas değildir ve kaybolmaz. Opsiyoneldir: alan yoksa kaynak bilinmiyordur → "personel" varsayma. (⚠️ DÜZELTİLDİ — "kişi kimliği taşımaz" iddiası YANLIŞTI: actor userId + role de taşır — ama bunlar doğrulanmaz; ayrıca zarfta origin.deviceId vardır — ⚠️ o da geri alındı, alan kaldırıldı. Bkz. üstteki "Platform sözleşmesi" ve "origin zarftan kaldırıldı" kayıtları.) Zarf sürümü yine "1".*.updated — satır düzeyinde ayrı olay YOKTUR. Kalem ekleme/düzenleme/iptal, satır indirimi, kuver, ödeme alma ve iptali, masa taşıma/bölme ve ÖKC senkronu hepsi bu tek olayla bildirilir. data.changed hangi işlemin tetiklediğini söyler ama yalnız filtre ipucudur: null olabilir, liste büyüyebilir ve gövde sözleşmesi değere göre değişmez → bilinmeyen değerde olayı yine de işle.*.reopened — bu YENİ BİR SATIŞ DEĞİLDİR. Olay *.created olarak gelseydi kesilen fişin üzerine ikinci bir fiş kesilirdi. Doğru davranış: kapanış kaydını storno et, hesabı tekrar açık say, yeniden kapanınca *.closed ile yeni kayıt kes. Zincir data.reopenedFrom.saleId ile kurulur (kapanış gövdesindeki tableId/packetId ile birebir aynı); null ise hiçbir kaydı storno etme. ⚠️ Geri açılan masa yeni bir kimlik alır (Masa 5 → Masa 5*) — pakette kimlik korunur.*.deleted — devir, kapanış değil. Hesap kapanmadan satırları başka bir hesaba geçti: veri kaybolmaz, sahip değişir. *.closed göndermek taşınan hesabı satış sayıp ciroyu çiftlerdi. Gövde *.updated ile aynı şekil + deleteReason (merged · moved_to_table · moved_to_account) + movedTo { type, id }; movedTo: null ise kaydı kapat ama satırları bağlama. Kısmi devirde bu olay atılmaz → *.updated (changed: "order_moved").data hesabın TAM hâlidir, delta değil. orders[]/payments[] her zaman tam listedir → kendi kopyanı tamamen değiştir. Sıra garanti edilmez: occurredAt karşılaştır, geç gelen eski olayı yok say — kaybolan ya da sırası bozulan tek bir olay kalıcı hasar vermez.isOwnEcho). Bkz. üstteki "Platform sözleşmesi — echo kuralı TERSİNE döndü" kaydı.Actor · ChangedReason · DeleteReason · MovedTo · ReopenedFrom · CancelledLine + altı gövde tipi ve accountKey / isAccountLifecycleEvent yardımcıları. parseEnvelope artık actor'ü açık bir eşleyiciyle doğrular (tanınmayan type → alan düşer).metadata artık { key, value, by } DİZİSİ. Taslakta düz map ({ "tseRef": "TSE-9911" }) olarak anlatılmıştı; nihai şekil dizidir ve geriye uyum yoktur — map gönderen istek 400 metadata must be an array of {key, value} alır. Yanıtta her öğe platformun bastığı bir by yazar damgası taşır (istekte gönderilirse yok sayılır): iki eklenti aynı anahtarı çakışmadan kullanabilir, çağıran yalnız kendi öğelerini değiştirir/siler. Aynı yazar bir anahtarı iki kez yazamaz (400). Anahtar: alfanümerik başlar, A-Za-z0-9_-, ≤64. Ayrıntı: Satır kimliği & metadata.metadata (başka eklentilerinki dahil) onunla gider. İstek reddedilmez (meşru satır silme de bu yola düşer) ama platform kaybı loglar.metadata tenant içi korelasyon verisidir (kiosk yazar, fiskal sağlayıcı okur) → her kanalda orders:read yeterlidir, müşteri-PII rızası gerekmez ve alan push gövdelerinden silinmez. Taslakta "customers:read + rıza yoksa silinir" deniyordu. note, paymentNote ve iptal reason bu kapsamda değildir — rıza kapısında kalır. PII yasağı sözleşme düzeyindedir: platform desen taraması yapmaz (yanlış pozitif meşru bir mali kaydı reddedip satışı durdururdu).value ≤256 karakter · istek başına ≤20 KB (sepet ve ödeme ayrı) · belge geneli birleşme sonrası ≤100 KB (orders + payments + iptaller; seninkiler + korunan yabancı öğeler). Belge aşımının mesajı kırılımlıdır — (yours: X, other plugins: Y); aşım karşı taraftaysa kendi payload'ını küçültmek çözmez.metadata üzerinden sürdür (o satırla birlikte taşınır).kuver. Ödeme satırı her zaman kalıcı bir lineId taşır; göndermezsen platform üretir (pay- önekli). Alanı olmayan satırlarda (panel ödemeleri, eski kayıtlar) okuma ucu lineId: null döner — platform kimlik uydurmaz.docNo) tüketmez. Sepet uçlarında mesaj ihlalin hangi ürün satırında, ödeme uçlarında hangi indekste olduğunu söyler → Hata Kodları.sale.type: "table". fiscal.de invoke artık packet ve table kabul ediyor (v2'de table → 400 saleTypeUnsupported dönüyordu). Kod kalkmadı: tanınmayan tipler ve ileride eklenecek kanallar için ayrıldı.tableId kat planındaki kalıcı masa kimliğidir — masa kapanınca kayıt silinir, aynı masa aynı id ile yeniden açılır; oturumları docNo ayırır. Sağlayıcı tekleme anahtarını yalnız table:<id> olarak kurarsa dünkü oturumun Beleg'i bugünkü satışa replay edilir ve o satış hiç TSE imzası almaz. Masa kanalında anahtara oturum ayracı (docNo + iş günü) ekleyin. packet kanalında bu sorun yoktur (paket id'si işlem-tekil).registerId (ops., ≤64, opak). Platform yorumlamaz, sağlayıcıya olduğu gibi iletir; sağlayıcı bunu kendi kasa kaydına (DSFinV-K Z_KASSE_ID) eşler. Tanınmayan değer imzayı engellemez — varsayılan kasaya düşülür. Gönderilmezse davranış bugünküyle aynıdır.FiscalDeInput.registerId · FiscalDePayload.registerId · FiscalSaleType = "packet" | "table". Eklemeli — mevcut çağrılar aynen çalışır.metadata düz map değil { key, value, by } dizisidir, rıza kapısı kalktı (orders:read yeterli) ve masa taşımada kimlikler korunur. Aşağıdaki maddeler tarihsel kayıttır.lineId (ops.). packets/update-orders ve tables/update-orders sepetin tamamını değiştirdiği için satır kimlikleri her yazımda yeniden üretiliyordu; Almanya'da her satır kayıt anında TSE ile imzalandığından kimlik değişince fiş zinciri kopuyordu. Artık kimliği çağıran taşır, platform korur (Stripe line_item.id deseni). Biçim: 1–64 karakter, alfanümerik başlar, A-Z a-z 0-9 . _ : -; kuver ve new rezerve. Aynı istekte tekrar → 400; iptal edilmiş (void) bir satırın kimliğini yeniden beyan → 409 lineId belongs to a cancelled line. Gönderilmeyene platform üretir ve üretilen kimlikler beyan edilenlerle çakışmaz. Ayrıntı: Satır kimliği & metadata.lineId alır (önceden ödeme kaydının kimliği hiç yoktu). ⚠️ payments[].id satır kimliği değildir — o alan ödeme yönteminin id'sidir ve polimorfiktir; okuma yanıtında lineId (kimlik) ve methodId (yöntem) ayrı döner, id'ye fallback yapılmaz.metadata (ops.). Düz key/value; platform yorumlamaz, okuma yanıtında aynen döner. Değerler string | number | boolean; ≤10 anahtar, string değer ≤256 karakter, istek başına toplam ≤20 KB (sepet ve ödeme ayrı bütçe); iç içe obje / dizi / null → 400. PII yasak: push kanallarının ikisinde de (webhook fan-out'u ve hook çağrısı) alan note ile aynı sınıftadır — customers:read + rıza olmayan eklentiye giden gövdede silinir; okuma uçlarında orders:read ile döner. (DÜZELTİLDİ — nihai sözleşme: metadata düz map değil { key, value, by } dizisidir; rıza kapısı kalktı, her kanalda orders:read yeterlidir ve alan push gövdelerinden silinmez; bütçeler yazar başına 10 öğe / istek başına 20 KB / belge geneli 100 KB.)type (ops.). dine_in | takeaway | delivery; bu bilgi yalnız satışın alındığı yüzeyde doğar, platform türetemez (mali oran DE %19/%7 ve raporlama buna bakar). packets/create opsiyonel alır (whitelist dışı → 400), packets/update ile güncellenebilir (değişim eski→yeni loglanır), tables/create almaz (masa zaten dine_in). Okumada değer veya null ("bilinmiyor" — sessizce bir biçime düşürülmez); masa hesaplarında daima dine_in. deliveryType/restaurantDelivery (kim teslim ediyor) ve fiscal.de sale.type (hangi koleksiyon) ile karıştırmayın → Satış tipi (type).moveTableToTable kapsam dışı); sunucu tarafı heuristik eşleme yok; kimlik korunursa created zamanı her zaman, ready/storages yalnız ürün aynıysa taşınır; lineId içerik değişmezliği garanti etmez (orders:write yetkili çağıran aynı kimliği farklı ürün/fiyatla beyan edebilir). (DÜZELTİLDİ — nihai sözleşmede masa taşıma/birleştirme kimlikleri korur; yalnız hedef masada aynı kimlik varsa ya da satırın bir kısmı taşınırsa yeni kimlik verilir.)taxRate (ops., 0–100). Almanya'da oran ürüne değil siparişe bağlı olabilir (yerinde tüketim %19 / götürü %7); bu bilgi yalnız sipariş yüzeyinde doğar, platform türetemez. Verilirse ürünün oranını ezer ve satırda dondurulur — ürünün oranı sonradan değişse bile geçmiş satışın mali kaydı değişmez. Geçersiz değer 400 döner (sessizce ürüne düşmez); beyanı yapan eklenti satırda taxRateBy ile kaydedilir. Aynı şema dört uçta: packets/create · packets/update-orders · tables/create · tables/update-orders. Fiyat otoritesi değişmedi (kalem fiyat göndermez).amountsPerPaymentType'a girmez; KDV tarafında oranlara ciro payıyla orantılı dağıtılır (en-büyük-kalan yöntemi, kuruş kaybı yok). Oranlar kova kova toplanır, yüksek oran önce. Platform Σ amountsPerVatRate == Σ amountsPerPaymentType dengesini garanti eder: en fazla 2 kuruşluk artık en büyük KDV kovasına emilir, üzeri imza atılmadan reddedilir. Sağlayıcıdaki denge kontrolü artık savunma katmanıdır.saleTypeUnsupported (400) · vatUnresolved (400, details.lines[]) · paymentUnresolved (400, details.payments[]) · saleEmpty / saleUnpaid (400) · amountsInvalid (400). Kaldırılanlar: invalidVatRates · invalidPaymentTypes · invalidReference · invalidReferenceType.sale sıkılaştı: type bu turda yalnız packet (table → 400 saleTypeUnsupported; masa id'si kalıcı olduğu için anahtar oturum-tekil değil). id ≤100 ve doküman id'si olarak kullanılabilir olmalı (/, ., .., __x__ yasak). idempotencyKey parmak izi = receiptType + sale. (DÜZELTİLDİ — masa kanalı sonradan açıldı: type artık packet ve table kabul eder; oturum ayracı sorumluluğu sağlayıcıdadır.)accepted terminal DEĞİL: sonuç taşımaz ve aynı key ile yeni çağrı sağlayıcıya tekrar gider. Replay: aynı key ile ikinci çağrı sağlayıcıya gitmez, saklanan yanıt idempotentReplay: true ile döner — satış bu arada silinmiş olsa bile (varlık kontrolü yalnız yeni isteklerde koşar). Platform retry yapmaz.tse.* yazan eklentinin o tenant'ta fiscal.de'nin bağlı sağlayıcısı olduğu da doğrulanır; değilse öğe sessizce düşer (tek aday varsa davranış değişmez). Yazılmış bir key hiçbir yoldan üzerine yazılamaz.invoke yanıtında: fiscal.de çağrısının sonucu receiptExtras taşır (tse.qr, tse.txNumber = Beleg-Nr, tse.signatureCounter, TSE zamanları). Neden: fişini KENDİ basan eklenti (self-servis kiosk) POS kapanış gate'ini tetikleyemez, packet.closed ise kapanıştan SONRA gelir — müşteri fişini beklerken QR elde edilemiyordu. KassenSichV §6 mali alanların müşteri fişinde bulunmasını ister.signed → blok dolu · ausfall → tek öğe (tse.ausfall, arıza fişte görünür kılınır) · failed → blok taşınmaz (imza atılmamıştır).tse.qr BYTE-KESİN taşınır: kırpma / escape / normalize yok. Kırpılmış QR geçerli görünür ama doğrulanamaz — hiç QR olmamasından kötüdür. Sınırlar, tse.* namespace sahipliği ve verified kuralı kapanış gate'iyle birebir aynı; iki yol da aynı bloğu üretir.tax alanı) ve ödeme kırılımı (payments[] + yöntemin cash bayrağı → CASH/NON_CASH) platform tarafından satış kaydından türetilir ve sağlayıcıya öyle iletilir; gönderilen tutarlar yok sayılır. Neden: mali kayıt POS kaydıyla birebir tutmak zorundadır (AO §146a / DSFinV-K) — tüketici beyanı ile POS kaydı ayrışırsa yanlış Zahlart ve yanlış ciro beyanı doğar. Sağlayıcı tarafında değişiklik yok: alınan payload aynı alanları taşır, yalnız kaynağı platformdur.sale: { type: "packet", id }. Eski serbest metin reference alanı kullanımdan kalktı (@deprecated) — opsiyonel ve tipsiz olduğu için tekleme anahtarı olarak güvenli değildi. Platform sale'in çağıranın işletmesinde var olduğunu doğrular (yoksa 404, 403 değil). Sağlayıcı tekleme anahtarını bundan kurar (fiscalSaleKey → packet:pkt_123) — aynı satışın POS kapanışı ikinci Kassenbeleg kesmez.2.0.0 (kırıcı): FiscalDeInput artık { sale, receiptType?, idempotencyKey }. Yeni: FiscalSaleRef, fiscalSaleKey(), FiscalDeResult.receiptExtras, fiscalResponse(). ⚠️ Jenerik capabilityResponse() yalnız {status, providerMessageId, error} kurar → onunla yanıt üreten sağlayıcı mali bloğu kendi elinde düşürür; replay yanıtlarında da bloğu taşıyın. KDV oranı DSFinV-K listesinden olmalı (19/7/10.7/5.5/0 — oran tahmin edilmez); providerMessageId = Beleg-Nr.@kullanıcıadı handle'ıyla listelenir. Kullanıcı adı global benzersizdir — görünen ad (serbest metin) aynı kalabilir, yayıncı kimliği karışmaz.restomenum, admin, support gibi platform çağrışımlı adlar rezervedir.set_listing: AI geliştirme akışında da aynı öneri verilebilir (display_name / description / icon_url; "" = öneriyi temizle). get_manifest mevcut öneriyi listing alanında gösterir.packet.cancelled: paket sipariş tam iptali. Önerilen scope: orders:read.table.created (canlı): dine-in masa açıldı (müşterisiz açılış; müşteri atanmış açılış packet.created sayılır). Masa taşıma/dönüşümde tetiklenmez. Scope: orders:read.customer.created / customer.updated (canlı): müşteri (CRM) oluşturma/güncelleme — PII, customers:read + consent ile dolu gelir.customers/list + customers/get (canlı): müşteri kataloğu (CRM/sadakat) — {id, region, name, phone, address, total} allowlist; PII consent gate; list cursor pagination (after/nextCursor, max 500). Scope customers:read./plugin-api/* artık doğru HTTP status döner — not-found 404, doğrulama 400, scope/sahiplik 403, çakışma 409 (eskiden hepsi 200). Gövde {success,message} uyumlu kaldı (Hata Kodları).{error, error_description} (invalid_client→401, invalid_grant→400…). Başarı değişmedi (Token Exchange).tables/update-orders + tables/update-payments — packets karşılıkları (full-replace). Kuver otomatik eklenir, timer ürünlü masalar desteklenmez, ödeme doğrulaması packets ile birebir. tableId'yi tables/open'dan al./plugin-api/* yanıtlarında X-RateLimit-Limit/Remaining/Reset; 429'da Retry-After (sn) — backoff yerine buna uy (Limitler).app.uninstalled GDPR sinyali); kayıt tombstone olarak kalır, geri alma taslağa döndürür.POST /plugin-api/packets/create — paket/sipariş oluştur (orders:write canlı). Fiyat sunucuda hesaplanır; idempotencyKey ile retry-güvenli.packet.status.update (statü geçişi öncesi — sahiplik damgalı) ve packet.close (hesap kapanışı öncesi — tenant-genel). Scope'lar: hooks:packet.status, hooks:packet.close.resolve/close + önerilen Desen B (iframe → kendi backend'in, session token ile).decision:"pending" + async resolve: packet.status.update gate'inde senkron pencereye (≤10 sn) sığmayan kararlar için geçişi askıya al → gate-resolve ucuyla sonra allow/deny ver.packets/create.callbackUrl: sahiplik damgası (packet.status.update gate'ini açar) + ileride statü bildirimi hedefi.id'sini tenant'ın gerçek yöntemlerine karşı doğrular (unknown_payment_method); önce payment-methods/list. İndirim satırları muaf.app.installed, subscription.activated/past_due/canceled, app.uninstalled — abone olmadan her bağlı kuruluma gelir.payment-methods/list, ingredients/list, categories/get.version string "1", entegrasyon string kanal kodu.skipped), 72sa sonra kalıcı durur; hacim cap'i aşımında dropped. Sinyaller: delivery.degraded/restored/disabled/throttled lifecycle webhook'ları (canlı).customer.redact (GDPR/KVKK): tenant müşteri silince zorunlu PII-silme webhook'u (PII scope'lu kurulumlara; critical, breaker/cap muaf).subscription.canceled.reason="plugin_now_free" (ücretsize geçişte erişim ücretsiz sürer — deprovision etme); ücretsize geçişte mevcut kurulumlar ücretsiz kalır (grandfather).packet.status_changed event'i: statü değişince sahip eklentiye async (imzalı) webhook bildirim — packets/create'teki callbackUrl'e (yoksa webhookUrl'e) düşecek. Şu an callbackUrl yalnız saklanır.ui:form ve ui:widget scope'ları: manifest'te seçilebilir ama canlı katalogda yok — bildirimsel form/widget motoru yayına girene kadar akmazlar. Diğer tüm scope, event ve yetenekler canlıdır.