Ürün Yazma — 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.

products/create

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).
  • Yazamadığınız alanlar: 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.

products/update

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.
  • Sahiplik: ürünü siz oluşturmadıysanız plugin.catalog.notOwned.

products/delete

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).

Yanıt şekli (create/update)

Okuma ucuyla (products/get) aynı kanonik obje: { id, title, category, price, tax, active, image, barcode, barcodeType, stock, languages, options[] }.

Sahiplik modeli (ZORUNLU kural)

  • 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.)
  • İşletme personeli panelden sizin kayıtlarınızı da düzenleyip silebilir (tam yetki). Personel düzenlemesi sahiplik damgasını korur — kayıt "sizin" kalır.
  • Hangi kayıtların size ait olduğunu create yanıtındaki id ile kendi tarafınızda takip edin; okuma uçları sahiplik bilgisi döndürmez.

Idempotency

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).

Hata mesajları

Hatalar HTTP 200 + { success:false, message } (rate limit 429 hariç).

messageAnlam
joi doğrulama mesajıEksik/yanlış tip alan veya tanımsız alan (kütle-atama engeli)
plugin.scope.deniedGerekli yazma scope'u (products:write) onaylı değil
plugin.catalog.notFoundid ile kayıt bulunamadı
plugin.catalog.notOwnedKayıt sizin eklentinizce oluşturulmamış (update/delete reddi)
plugin.catalog.categoryNotFoundÜründe verilen category id'si yok
plugin.catalog.duplicateInProgressAynı idempotencyKey ile eşzamanlı 2. istek
plugin.rateLimitedOrtak write kovası aşıldı (HTTP 429; varsayılan 20/dk — Limitler)

Webhook etkileşimi (echo dahil)

Her başarılı yazma ilgili kanonik event'i tetikler (product.*).

Event abone tüm eklentilere gider — çağrıyı yapan eklenti dahil (echo; Shopify/Stripe davranışı). Kendi yazmanızı ayırt etmek için create yanıtındaki id'yi saklayıp event data.id ile eşleyin. Event data'sı bu uçların yanıt data'sıyla aynı şekildedir.