products/create · update · delete ✓ CanlıÜrün kataloğunu yazar (oluştur/güncelle/sil). Alan adları products/get okuma şekliyle birebir simetriktir. Sahiplik, idempotency, hata ve echo kuralları tüm katalog yazma uçlarında ortaktır.
← API Uçları · Scope: products:write.
POST /plugin-api/products/create
{
"title": "Margherita Pizza", // ZORUNLU (2..200)
"price": 185.5, // ZORUNLU (>= 0)
"category": "a0-0c", // ZORUNLU — VAR OLAN kategori id'si (categories/list)
"tax": 10, // ops — KDV % (0..100)
"active": true, // ops (default true)
"barcode": "8690000000001", // ops (<=64)
"barcodeType": "EAN13", // ops (<=32)
"languages": { "en": { "title": "Margherita" } }, // ops (<=30 dil)
"options": [ // ops (<=20 grup)
{ "title": "Boyut", "min": 1, "max": 1, "multiple": false,
"choices": [ { "title": "Orta", "price": 0 }, { "title": "Büyük", "price": 25 } ] }
],
"idempotencyKey": "prod-9af2..." // ops AMA ÖNERİLİR
}category var olmalı: geçersiz id → plugin.catalog.categoryNotFound (orphan ürün panel/QR'da görünmez).cost, recete, stock, image, rank ve web-store alanları — işletme-içidir; gönderilirse reddedilir (kütle-atama koruması).options.choices[].price = seçim ek ücreti; grup/seçim id'leri sunucu üretir.POST /plugin-api/products/update
{
"id": "79-06", // ZORUNLU — ürün id'si
"price": 199.9 // + en az 1 yazılabilir alan (create ile aynı küme)
}{ id } + en az 1 yazılabilir alan (create ile aynı küme).options gönderirseniz tam değiştirme (replace) — mevcut gruplar silinir.plugin.catalog.notOwned.POST /plugin-api/products/delete
{ "id": "79-06" }
// 200 → { "success": true, "data": { "id": "79-06", "deleted": true } }Ürünün görselleri de temizlenir. Sahiplik kontrollü (notOwned).
Okuma ucuyla (products/get) aynı kanonik obje: { id, title, category, price, tax, active, image, barcode, barcodeType, stock, languages, options[] }.
create ile oluşturduğunuz her kayıt eklentinize damgalanır (sahiplik).update ve delete yalnız KENDİ oluşturduğunuz kayıtlarda çalışır — işletmenin veya başka eklentinin kaydını düzenleyemez/silemezsiniz → plugin.catalog.notOwned. (Slack chat.delete deseni.)id ile kendi tarafınızda takip edin; okuma uçları sahiplik bilgisi döndürmez.Tüm create uçları: idempotencyKey (≤128 char, önerilir) → retry'da duplicate yazmaz, ilk başarılı yanıtı aynen döner (24sa pencere; eklenti+tenant+entity başına). Eşzamanlı 2. istek işlenirken → plugin.catalog.duplicateInProgress (kısa bekle, aynı key ile tekrar dene). update/delete doğal idempotenttir (silinmiş kayda tekrar delete → plugin.catalog.notFound).
Hatalar HTTP 200 + { success:false, message } (rate limit 429 hariç).
| message | Anlam |
|---|---|
| joi doğrulama mesajı | Eksik/yanlış tip alan veya tanımsız alan (kütle-atama engeli) |
| plugin.scope.denied | Gerekli yazma scope'u (products:write) onaylı değil |
| plugin.catalog.notFound | id ile kayıt bulunamadı |
| plugin.catalog.notOwned | Kayıt sizin eklentinizce oluşturulmamış (update/delete reddi) |
| plugin.catalog.categoryNotFound | Üründe verilen category id'si yok |
| plugin.catalog.duplicateInProgress | Aynı idempotencyKey ile eşzamanlı 2. istek |
| plugin.rateLimited | Ortak write kovası aşıldı (HTTP 429; varsayılan 20/dk — Limitler) |
Her başarılı yazma ilgili kanonik event'i tetikler (product.*).
id'yi saklayıp event data.id ile eşleyin. Event data'sı bu uçların yanıt data'sıyla aynı şekildedir.