◆ BayirCommunityAPI Referansı v1Markdown indirPanele giriş

Pazaryeri Merkezi — API Referansı (v1) #

Temel adres: https://app.bayircommunity.com/api/v1 Kimlik doğrulama: X-Api-Key: bc_live_… başlığı (veya Authorization: Bearer bc_live_…). Gövde: JSON (Content-Type: application/json). Yanıt: JSON, her zaman success alanı içerir. Hata biçimi: {"success":false,"error":"validation|not_found|action_failed|marketplace_error|rate_limited|unauthorized","message":"…"}. Limit: üye başına dakikada 300 istek (429 + Retry-After).

Bu API, üyelerin kendi e-ticaret yazılımı, WooCommerce ve Shopify eklentileri tarafından aynı şekilde kullanılır; pazaryerine özgü hiçbir alan yoktur — tüm pazaryerleri tek biçime çevrilir.

Modüller: Katalog (ürün/stok/fiyat) · Ürün açma (pazaryerinde listeleme) · Siparişler · Sipariş işlemleri · Kargo (Yurtiçi Kargo gönderisi, takip) · İrsaliye (PDF/HTML) · Fatura (Logo İşbaşı e-Fatura/e-Arşiv, PDF yükleme, e-posta) · İadeler (stok kararı) · Raflama (depo yerleşimi: raflar, fiziksel stok, toplama, hareketler — hesap başına açılıp kapanır) · Sorular · Finans · Bildirimler · Stok olayları (çift yönlü) · Profil · Sistem.


Sistem #

Uç noktaAçıklama
GET /statusHesap, bağlantı listesi, kuyruk sayaçları, sürüm
GET /marketplacesDesteklenen pazaryerleri; her biri için capabilities (stock, price, orders, questions, answer, products, returns) ve order_actions (accept, pack, ship, invoice, cancel, deliver, cargo_change)
GET /connectionsÜyenin bağlantıları (id, marketplace, label, status, last_error, ayarlar)
POST /connections/{id}/testPazaryeri kimlik bilgilerini doğrular
POST /sync/nowKuyruğu beklemeden işletir (yanıt döndükten sonra arka planda)
GET /batchesPazaryerine yapılan gönderim partileri ve sonuçları
GET /dashboardPanel özeti: counts{products, queued_updates, link_errors, orders_24h, orders_open, orders_unprinted, orders_unchecked, orders_shipped, orders_cost_missing, returns_open, returns_restock_pending, returns_restock_oldest_days, returns_restock_overdue, returns_restock_web, questions_waiting, questions_unread (v1.26.0: okunmamış gelen mesaj), unacked_events} (v1.23.11: returns_restock_* = stok kararı bekleyen iade sayısı, en eskisinin kaç gündür beklediği, 2 günü geçen, kararı web sitesinde verilen web iadesi), finance_month, last_30_days{revenue, orders, by_day[]}, connections[]
GET /logs?channel=&level=&connection_id=&since=&q=&page=&size=Hareket kayıtları (panel › Hareketler). Kanallar: orders, poll, push, cargo, invoice, webhook, api, connection, match …
GET /order-items?applied=&connection_id=&since=&page=&size=Sipariş kalemleri ve stok düşüm izi (stock_applied: 0 yok, 1 düşüldü, 2 iade edildi)
GET /api-keys · POST /api-keys · PUT /api-keys/{id} · DELETE /api-keys/{id}Ek API anahtarları: POST {label, channel, rate_per_minute} → key (bir kez gösterilir); PUT {is_active, label, rate_per_minute}

Pazaryeri bağlantıları (tam yönetim) #

Panel › Pazaryerleri'nde yapılan her şey. Kimlik alanları pazaryerine göre değişir: GET /marketplaces → credential_fields[] {name, label, required, type}, extra_settings{}, default_settings{}, sku_index (v1.23.3; kod eşleme dizini olan pazaryerlerinde {label, unit, help, confirm}, yoksa null — "yenile" düğmesi buna göre gösterilir). GET /connections listesindeki her bağlantıda da sku_index: {label, unit, help, confirm, built_at, count, complete, error, error_at, missing_cached} (son tarama zamanı, taranan kod sayısı, tarama tam mı, dizin kurulamadıysa hata metni, "pazaryerinde bulunamadı" önbelleğindeki kod sayısı) ya da null.

Hepsiburada stok kodu (v1.23.3): Hepsiburada stok kodlarını (merchantSku) BÜYÜK HARFE çevirerek kaydeder ("Küçük harf olarak gönderilen merchantSku bilgisi büyük harfe dönüştürülerek … kaydedilmektedir"). Eşleşmedeki kod kataloğunuzdaki gibi kalır (ör. ynck-diger-288-soft-beyaz); stok ve fiyat Hepsiburada'daki yazımla (YNCK-DIGER-288-SOFT-BEYAZ, Türkçe büyük harfle …DİGER… de olabilir) gönderilir. Kodun karşılığı listing listesinden (GET /listings/merchantid/{mid}) kurulan dizinden bulunur; dizin settings.code_index_ttl saat (varsayılan 6) geçerlidir, yeni kod az ise tek tek (merchantSkuList) aranır. Hepsiburada'da listing'i olmayan kod gönderilmez, eşleşmeye "Listing bulunamadı: … Stok kodlarını yenile" yazılır ve settings.code_miss_ttl dakika (varsayılan 30) yeniden sorulmaz. Listing listesi okunamazsa gönderim durmaz: kod büyük harfe çevrilip gönderilir.

Pazarama / PttAVM kodunda tire (v1.23.4): bu pazaryerleri koddaki "-" işaretini kabul etmiyor: satıcı panelinde girilen ynck-diger-288-soft-beyaz "-" işaretinden sonrası silinerek ynck olarak kaydedilebiliyor. Çözüm: ürünün pazaryerindeki kodunu tiresiz yazın (YNCKDIGER288SOFTBEYAZ); kodlar sade anahtarla (harf / rakam dışı karakterler atılmış, harf duyarsız) eşleşir, katalogdaki kodunuz değişmez. Sade anahtar yalnız tam eşleşme yoksa ve iki tarafta da tek karşılığı varken kullanılır (belirsizse "bulunamadı" denir, yanlış ürüne stok yazılmaz). Pazarama'da dizin GET /product/products (onaylı + onaysız), PttAVM'de StokKontrolListesi (Barkod, UrunKodu, Gtin) ile kurulur; ikisinde de settings.code_index_ttl (saat, varsayılan 6) ve settings.code_miss_ttl (dakika, varsayılan 60) vardır. Bulunamayan kodun hata metni ve sku-index sonucu tiresiz kod önerisini verir; pazaryerinde kodu yalnız ilk parçadan oluşan ürün varsa (ynck) bu da yazılır. Kodu zaten kesilmiş ürünler match ile ürün adından eşlenebilir (by_name[]). Siparişlerde ve iadelerde gelen tiresiz kodlar da sade anahtarla ürüne bağlanır. PttAVM ek ayarları: settings.cargo_profile_id (ürün açarken kargo profili), settings.vat_rate (varsayılan KDV %, 20).

PttAVM yeni API (v1.23.12): PttAVM token tabanlı kimlik doğrulamayı zorunlu yaptı. Bağlantı kimlik alanları: credentials.api_key ve credentials.token (ikisi zorunlu; PttAVM satıcı paneli › Hesap Yönetimi › Entegrasyon Bilgileri) — girilince bağlantı https://integration-api.pttavm.com REST API'sini kullanır. username / password / shop_id isteğe bağlıdır (yalnız eski SOAP servisi; API Key + Token girilmemiş eski bağlantılar). PATCH /connections/{id} ile {"credentials": {"api_key": "…", "token": "…"}} gönderip POST /connections/{id}/test ile deneyin. Yeni API'de kod dizini GET products/search + toplu barkod araması (products/get-by-barcodes) ile kurulur; stok / fiyat partisi remote_id = PttAVM takip numarası (trackingId). GET /marketplaces → credential_fields yeni alanları (etiket, zorunluluk, help) verir.

Uç noktaAçıklama
POST /connections{"marketplace":"trendyol","label":"Mağazam","credentials":{"seller_id":"…","api_key":"…","api_secret":"…"},"environment":"prod","settings":{…}} → kaydeder, ürünleri eşler (auto_link), bağlantıyı test eder. Yanıt: connection (detay), test {ok, message}. Zorunlu kimlik alanı eksikse 422 (message alan adını söyler).
GET /connections/{id}Detay: settings{sync_stock, sync_price, sync_orders, sync_questions, sync_returns, deduct_stock, auto_accept, auto_link, identifier (sku|barcode), stock_buffer, max_stock, price_mode (same|percent|fixed), price_value, base_url, cargo_cost_default, orders_history_days, hook_lax, extra{}} — komisyon oranı ayarı yoktur, komisyon her siparişte pazaryerinin bildirdiği tutardır, credentials[] {name, label, required, set} (değerler asla dönmez), capabilities, order_actions, stats{links, queued, errors, orders}, inbound_webhook, son hata / son başarılı zamanları
PUT /connections/{id}{"label":…, "environment":"prod|test", "is_active":true, "credentials":{…yalnız dolu gelen alanlar değişir…}, "settings":{…yalnız gönderilen anahtarlar…}}. Gönderim kuralı (stok/fiyat/tampon) değişince eşleşmeler yeniden sıraya alınır (requeued), auto_link açılınca ürünler bağlanır (linked).
DELETE /connections/{id}Bağlantı + eşleşmeler + o bağlantının sipariş/iade/soru kayıtları silinir (katalog ürünleri kalır)
POST /connections/{id}/poll{"what":"orders|returns|questions","days":90} — şimdi çek (işçi meşgulse 409 busy). Kısayollar: POST …/orders, …/returns, …/questions
POST /connections/{id}/historySipariş geçmişini yeniden yükle (işçi her dakika bir parça)
POST /connections/{id}/pushBekleyen stok/fiyat gönderimini şimdi yap (deferred:true = işçi meşgul, birazdan)
POST /connections/{id}/resendTüm aktif eşleşmeleri sıfırdan gönderime al (queued)
POST /connections/{id}/matchPazaryerindeki ürünleri listeleyip katalogla (SKU / barkod) eşleştir: remote, matched, unmatched, unmatched_sample[]; budget_seconds (10–170). v1.23.4: tam eşleşmeyen kod tiresiz / farklı ayraçlı yazımla (sade anahtar: harf ve rakam dışı karakterler atılır, iki tarafta da TEK karşılık şartıyla) ve bu da tutmazsa ürün adıyla (iki tarafta da tek ürün) eşlenir. Ek alanlar: by_compact (sade anahtarla eşlenen sayısı), by_name[] ({code, sku, title, truncated, suggest} — adla eşlenenler, kontrol edilmeli), truncated[] (pazaryerinde kodu "-" işaretinden sonrası silinmiş görünen kodlar), unmatched_sample[].truncated.
POST /connections/{id}/sku-indexKod eşlemesini yenile (Mirakl/Koçtaş: teklif SKU'ları, Pazarama: ürün kodları, Hepsiburada (v1.23.3): listing stok kodları — merchantSku, PttAVM (v1.23.4): barkodlar). Pazaryerindeki kodlar baştan taranıp harf duyarsız dizin kurulur, "bulunamadı" önbelleği silinir, eşleşmeler yeniden gönderime alınır: offers, mapped, missing, missing_codes[], queued, message; Pazarama / PttAVM'de (v1.23.4) ek olarak suggestions ({bizdeki kod: pazaryerine yazılacak tiresiz kod} — bulunamayan kodlar için öneri, ör. ynck-diger-288-soft-beyaz → YNCKDIGER288SOFTBEYAZ) ve truncated ({bizdeki kod: pazaryerindeki kesik kod} — pazaryerinde kodu yalnız ilk parçadan oluşan ürün varsa, ör. ynck). Tiresiz yazılmış kodlar kendiliğinden eşleşir (ör. "812 listing tarandı, 790 kod eşleşti, 22 kod pazaryerinde bulunamadı. Eşleşmeyenler: …"). Dizini olmayan pazaryerinde 422. Panel: bağlantı sayfası → düğme (Hepsiburada'da "Stok kodlarını yenile").
GET /connections/{id}/probe?what=orders|returns|questionsUç nokta teşhisi: rows[] {name, ok, count, error, detail}
GET|PUT /connections/{id}/fees · GET|PUT …/price-rules · GET …/settlements · …/cargo-companies · …/cancel-reasons · …/return-reasons(aşağıdaki bölümler)

Katalog — ürün, stok, fiyat #

POST /stock (takma adlar: /products/stock, /sync/stock, /products/sync) #

Tek istekte 1000 kaleme kadar. Veri anında kaydedilir (202), pazaryerlerine arka planda partiler hâlinde iletilir. SKU yoksa ürün oluşturulur.

{"mode":"auto", "items":[
  {"sku":"KOLTUK-01","barcode":"8680000000001","title":"3'lü Koltuk","stock":12,"price":4599.90,"list_price":5299.90}
]}

Yanıt: {"success":true,"accepted":1,"created":0,"updated":1,"unchanged":0,"skipped":0,"queued_marketplace_updates":4,"errors":[]}

POST /price (takma ad: /sync/price) — sadece fiyat #

{"items":[{"sku":"KOLTUK-01","price":4499.00,"list_price":5299.90}]}

POST /products veya PUT /products — ürün içeriği (toplu) #

Stok/fiyata ek olarak ürün açmada kullanılan içerik alanları. Sadece gönderilen alanlar güncellenir.

{"items":[{
  "sku":"KOLTUK-01","barcode":"8680000000001","title":"3'lü Koltuk Antrasit",
  "description":"<p>Ahşap iskelet…</p>","brand":"Örnek Mobilya","category":"Mobilya > Koltuk",
  "images":["https://…/1.jpg","https://…/2.jpg"],
  "attributes":{"Renk":"Antrasit","Kişi Sayısı":"3"},
  "vat_rate":20,"weight":45.5,"desi":120,
  "parent_sku":"KOLTUK","variant_attrs":{"Renk":"Antrasit"},
  "status":"active","stock":12,"price":4599.90,"list_price":5299.90
}]}

PUT /products/{sku} — tek ürün güncelle (aynı alanlar, items olmadan) #

Fiyat sahipliği: fiyatın kaynağı üyenin kendi sitesidir. POST /products / PUT /products/{sku} ile gelen price / list_price değeri katalogda değişirse, o ürünün aktif pazaryeri eşleşmelerinin tamamı otomatik olarak gönderim sırasına alınır (dirty); böylece sitede yapılan fiyat değişikliği ilk gönderimde bütün pazaryerlerine yansır. Stoğun kaynağı ise SaaS'tır: site stoğu GET /products ve GET /events ile okur.

GET /products?page=1&size=100&q=&updated_since= — katalog listesi #

GET /products/{sku} — ürün detayı #

Yanıtta image (pazaryerinden alınan ana görsel; panelde önbellekten servis edilir) ve marketplaces[] (bağlantı başına): remote_code, pushed_stock, pushed_price, state (ok|sent|queued|rate_limited|error|pending|unknown), error, rate_limit.

Liste ekranları için ek parametreler:

ParametreAçıklama
skus=A,B,CYalnız bu SKU'lar (en fazla 300). İstemcinin ekranındaki ürünlerin durumunu tek istekte almak için
links=1Her ürüne marketplaces[] eklenir (hafif: connection_id, marketplace, connection_label, remote_code, active, state, error, rate_limit, pushed_stock, pushed_price, pushed_at, price_override, list_price_override, check). v1.21.0: pazaryerine özel fiyatlar (price_override, list_price_override) ve istek sınırı bilgisi (rate_limit) bu hafif çıktıya da eklendi; state artık istek sınırında rate_limited döner ve o sırada error boştur (hata değil, sırada).
state=error|queued|rate_limited|ok|mismatch|unlinkedPazaryeri eşleşme durumuna göre süz (unlinked = hiç aktif eşleşmesi yok, mismatch = kontrolde stok/fiyat uyuşmuyor, rate_limited = pazaryeri istek sınırı yüzünden sırada — hata değil)
connection_id=3Yalnız o bağlantıya eşleşmiş ürünler
details=1v1.23.1: her ürüne kartın özet alanları eklenir: cost (KDV dahil maliyet), vat_rate, desi, weight, parcel_count, parent_sku, status (active|passive), content_updated_at. Açıklama / görsel / özellik gelmez (tek ürün ucunda). Bağlı site kendi kataloğunu bununla karşılaştırır, yalnız farklı olanları gönderir.
status=active|passivev1.23.1: ürün durumuna göre süz
cost=missing|setv1.23.1: maliyeti boş / girilmiş ürünler

GET /products/issues?limit=20 — senkron sorunları özeti #

{"counts":{"error":3,"queued":12,"rate_limited":14,"unlinked":5,"mismatch":2,"products":410},"items":[{"sku","title","connection_id","marketplace","connection_label","remote_code","state","error","rate_limit","pushed_stock","pushed_price","pushed_at","check"}]} — hatalı eşleşmeler önce.

Pazaryeri istek sınırı (rate limit) hata değildir. Pazaryeri "şu kadar süre sonra tekrar deneyin" dediğinde kalem state="rate_limited" olur, error boş döner ve rate_limit{until, seconds, minutes, note} alanı ne zaman yeniden denendiğini söyler. Kalemler kuyrukta kalır, süre dolunca en güncel stok/fiyatla tek pakette kendiliğinden gönderilir; kullanıcının bir şey yapması gerekmez. Bekleme payı ve üst sınırı yönetici panelindeki Ayarlar ekranından değiştirilir.

POST /products/{sku}/resend — ürünü yeniden gönderime al #

Gövde isteğe bağlı: {"connection_id":3} (boşsa tüm aktif eşleşmeler). Değerler değişmemiş olsa bile gönderim kuyruğuna alır ve hata kaydını temizler. Yanıt: {"queued":n,"product":{…}}.

Görseller: ürün görselleri pazaryerlerinden otomatik toplanır (sipariş kalemlerindeki görsel alanları + günde bir pazaryeri ürün listesi), sunucuda küçültülerek önbelleğe alınır (storage/cache/img) ve panelde index.php?p=img&u=… adresinden anında servis edilir.

POST /products/{sku}/rename — ürün kodunu (SKU) değiştir (v1.23.1) #

{"sku":"YENI-KOD"} — ürün satırı aynı kalır: stok, raf kayıtları, pazaryeri eşleşmeleri ve sipariş geçmişi bu üründe kalır, yalnız kod değişir. Yeni kod başka bir üründe varsa 409 conflict (conflict_sku) döner — iki ürün birleştirilmez. Yalnız harf büyüklüğü / Türkçe harf farkı varsa (aynı kod sayılır) yazım güncellenir. Yanıt: {"renamed":true,"product":{…}}. Bağlı site, ürünün SKU'su sitede değiştirilince bunu çağırır.

Site yetkili katalog (e-ticaret sitesi 1.11.1): site ürün bilgilerini (ad, barkod, maliyet, KDV, desi, ağırlık, durum, fiyat, varyant) POST /products ile {"create":false,"depo":false,"items":[…]} gövdesiyle gönderir (stok alanı yok — stok ayrı yoldan gider); sitede olmayan ürünleri {"sku":…,"status":"passive"} ile pasife alır (silmez: stok, raf ve pazaryeri eşleşmeleri korunur; status yalnız bilgi amaçlıdır, pazaryeri gönderimini durdurmaz).

POST /products/delete — toplu silme (v1.23.2) #

{"skus":["ESKI-01","ESKI-02"],"ids":[15,16],"skip_linked":true,"dry_run":true}

Ürünleri katalogdan kalıcı olarak siler (tek istekte en çok 2000 kod; skus ve/veya ids). Pazaryerlerindeki ilanlar silinmez.

eşleşme satırı olduğu gibi (pazaryerine özel fiyatıyla) o ürüne geçer ve gönderim sırasına alınır — stok o üründen güncellenmeye devam eder (kodu değişen ürün grubunun eskisi silinirken ilan yenisine geçer). O üründe aynı ilan zaten varsa eşleşme silinir (already).

Yanıt: {"deleted":2,"relinked":1,"unmanaged":1,"skipped":0,"shelf_qty":7,"not_found":["YOK-1"],"dry_run":false, "items":[{"sku":"ESKI-01","title":"…","action":"delete|skip","reason":null,"shelf_qty":0,"links":[{"marketplace":"Hepsiburada","remote_code":"HB-1","to":"YENI-01","result":"moved|already|unmanaged"}]}]}. Boş liste ya da 2000'den fazla kod: 422. Panelde aynısı: Ürünler › seçim kutuları › "Seçilenleri sil" (aramaya uyan tümü de seçilebilir; önce önizleme). Web sitesi (e-ticaret sitesi 1.11.2) "Pazaryeri Merkezi'nden de sil" seçilerek silinen ürünleri bu uçla siler.

POST /products/verify — pazaryeri kontrolü #

{"connection_ids":[3,4]} (boşsa tüm bağlantılar). Pazaryerindeki ürün listesi çekilir, eşleşmiş ürünlerin stok/fiyatı bizimkiyle karşılaştırılır; sonuç GET /products/{sku} çıktısında marketplaces[].check (status: ok|stock|price|both|missing, note, checked_at).

PUT /products/{sku}/prices — pazaryerine özel fiyat #

{"trendyol":{"price":4799.00,"list_price":5299.00},"n11":4699,"3":null}

Anahtar: pazaryeri kodu veya bağlantı id'si; null özel fiyatı kaldırır (genel fiyat + bağlantı fiyat kuralı geçerli olur). POST /stock / POST /products kalemlerinde "marketplace_prices":{"trendyol":4799} ile de gönderilebilir. Ürün çıktısında marketplaces[].price_override görünür. v1.21.0: değerler burada da doğrulanır — negatif / sıfır / sayı olmayan girişler errors[] içinde Türkçe açıklamayla geri döner ve o bağlantı atlanır (eskiden sessizce 0 ₺ yazılıyordu). Tek bir pazaryerini kodu ile birlikte düzenlemek için PUT /products/{sku}/links daha uygundur.

Excel ile toplu ürün #

Panel › Ürünler › "Şablonu indir" (.xlsx) → doldur → yükle. Sütunlar: SKU*, Barkod, Ürün adı, Stok, Satış/Liste fiyatı, Marka, Kategori, KDV, Maliyet, Desi, Koli adedi, Ağırlık, Açıklama, Görsel 1–5, Ana ürün kodu, Varyant: Renk/Beden, Özellikler (Ad=Değer; …), Durum. API: GET /products/template.xlsx (şablon), POST /products/import (multipart file ya da {"file_base64":"…","file_name":"urunler.xlsx"}; xlsx/csv) → rows, parse_errors, result{created, updated, errors}. JSON karşılığı POST /products.

Diğer ürün işlemleri #

Uç noktaAçıklama
DELETE /products/{sku}Ürünü katalogdan siler (eşleşmeleriyle); pazaryerlerindeki ürünler etkilenmez. Toplu silme ve ilan aktarımı için POST /products/delete
POST /products/{sku}/image-pullBağlı pazaryerlerinden görsel arar, ilk bulunanı ürün kartına yazar: image, source, cached, results[] (404: hiçbirinde yok)
POST /products/images/pullGörseli olmayan tüm ürünler için pazaryerlerinden görsel çeker (budget_seconds 10–90; kalanı arka plan işçisi tamamlar)
GET /products/labels · GET /products/labels.pdfÜrün barkod etiketi (A4 sayfa). skus=SKU1,SKU2 (ya da barkod) · count=12 (her üründen kaç etiket, varsayılan 1) · per_page=12|24|40 (A4'e 2/3/4 sütun) · title=1|0 (ürün adı) · price=1|0. Barkod içeriği ürünün barkodu, yoksa SKU (Code-128). HTML yanıtta yazdırma araç çubuğu vardır.
GET /products/{sku}/labels · .pdfTek ürün için aynısı (count, per_page, title, price)
{"connection_id":3,"remote_code":"8680000000001","active":true,"price_override":4799.90,"list_price_override":5299}

remote_code: pazaryerindeki tanımlayıcı (Trendyol/HB/Koçtaş: barkod; N11/Pazarama/Çiçeksepeti/İdefix/PttAVM: stok kodu ya da pazaryeri ürün id'si). Kaydedince eşleşme gönderim kuyruğuna alınır ve önceki hata kaydı temizlenir (state → pending, last_error → boş). active:false verilirse o pazaryerine stok / fiyat gönderilmez.

v1.21.0 — price_override / list_price_override (bu pazaryerine özel satış / liste fiyatı):

GövdedeSonuç
alan hiç yokmevcut özel fiyat korunur (yalnız kod / aktiflik güncellenir)
null ya da ""özel fiyat kaldırılır: genel fiyat + bağlantının fiyat kuralı uygulanır
sayı (4799.90, "4.799,90", "4 799,90 TL")o pazaryerine bu fiyat gönderilir, fiyat kuralı atlanır

Doğrulama (hepsi 422 + error:"validation" + Türkçe message): negatif değer ("… negatif olamaz"), sıfır ("… sıfırdan büyük olmalı"), sayı olmayan değer ("… sayı olmalı: "abc" okunamadı"), sütuna sığmayan değer ("… çok büyük"). Reddedilen istek hiçbir alanı değiştirmez. Değer kabul edilince kalem gönderim sırasına alınır (dirty), böylece yeni fiyat ilk gönderimde pazaryerine gider. Aynı düzenleme toplu biçimde PUT /products/{sku}/prices ile de yapılabilir.

v1.23.8 — Sipariş: "teslim edilemedi" ve iade süreci iade değil #

kargo müşteriye ulaşamadı, gönderi şubede / tekrar dağıtımda) artık status: "shipped", status_label: "Kargoda · teslim edilemedi", yeni alan undelivered: true. Paket satıcıya geri dönünce (Trendyol Returned, Çiçeksepeti "Firmaya İade Edildi") status: "returned".

INCIDENT_OPEN …): status: "delivered", status_label "Teslim edildi · iade sürecinde" / "· iade reddedildi" / "· iade edildi" / "· talep açık". Sipariş düzeyinde stok oynamaz; iade ve stok kararı iade kaydında (/returns).

v1.23.7 — Eşleşme durumu: hangi ürün hangi pazaryerinde eşli / eşleşmemiş / hatalı #

Bağlantı kartındaki "eşli ürün" yalnız bir sayıydı ("Kimisinde 140, kimisinde 139 — aradaki fark hangisi?"). GET /links/matrix her ürünü × her bağlantıyı tek tabloda verir. Panel: Pazaryerleri / Ürünler › 🔀 Eşleşme durumu (?p=coverage); site (e-ticaret sitesi 1.11.7): Pazaryerleri › Eşleşme Durumu. Mantık tek yerde: App\LinkMatrix.

GET /links/matrix — parametreler:

ParametreAçıklama
filterall (varsayılan) · differs — bazı bağlantılarda eşli, bazılarında değil (aradaki fark) · missing — aktif eşleşmesi olmayan · error — pazaryeri hata verdi · waiting — sırada ya da sonuç gelmedi · check — pazaryeri kontrolü uyuşmazlığı
connection_idOdak bağlantı: missing / error / waiting / check yalnız ona bakar (differs her zaman kapsamdaki bütün bağlantılara)
connectionsKapsam (tablonun sütunları): 3,5 — boşsa bütün bağlantılar (durdurulmuşlar dahil)
qSKU, barkod, ürün adı ya da pazaryeri kodu içinde arama (harf duyarsız; % _ joker değildir)
statusactive · passive (ürün durumu; pasif = sitede yok)
page, sizeSayfa; size en çok 500 (varsayılan 100). Son sayfadan büyük sayfa son sayfaya çekilir

Yanıt: connections[] {id, marketplace, marketplace_label, label, name, active, environment, auto_link, identifier, rate_limit, stats}, products_total, filter, connection_id, q, status, counts {all, differs, missing, error, waiting, check} (arama / ürün durumu / odak dikkate alınır), page, size, total, total_pages, labels (durumların Türkçe adları), items[] {id, sku, title, barcode, status, stock, price, image, linked (kaç bağlantıda aktif eşli), connections (kapsamdaki bağlantı sayısı), cells {"<bağlantı id>": hücre}}.

stats (katalogun tamamı üzerinden): products, linked (= kartın "eşli ürün"ü), missing (= products − linked), none (eşleşmesi hiç açılmamış), inactive (pasif eşleşme), error, queued, unknown, check. Aynı sayılar GET /connections/{id} → stats içinde de (links, missing, inactive, none, products, unknown, check).

Hücre: state = none (eşleşme yok) · inactive (pasif — bu pazaryerine gönderilmiyor) · queued · rate_limited · pending · sent · ok · error · unknown; label, code, active, error (pazaryerinin mesajı; hata sonrası yeniden sıraya girmişse "Önceki gönderim hatası: …"), check {status, label, note, at}, queue (v1.23.6 ile aynı), rate_limit, pushed_at, pushed_stock, pushed_price, price_override, list_price_override; none hücresinde suggest (bağlantının kimlik ayarına göre önerilen kod: barkod ya da SKU).

error sayımı: aktif eşleşme + state = error. Kullanıcı "yeniden gönder" dediyse (sırada, hata metni silinmiş) sonuç gelene kadar hatalı sayılmaz; stok / fiyat değiştiği için yeniden sıraya giren (hata metni duruyor) hatalı sayılır.

POST /links/cell — tek hücre: {"sku":"…","connection_id":3,"op":"link|code|activate|deactivate|resend","remote_code":"…"}

opNe yapar
linkEşleşme aç (kod zorunlu), aktif
codeKodu değiştir (gönderim sırasına alınır)
activatePasif eşleşmeyi aktif et (kod verilirse o kodla); eski kontrol notu silinir
deactivatePasife al: bu pazaryerine artık gönderilmez (pazaryerinden silinmez)
resendAktif eşleşmeyi yeniden gönder (hata metni silinir)

Kurallar POST /links/bulk ile aynı (aynı bağlantıda aynı kod iki aktif eşleşmede olamaz → 422 + neden). Yanıt: message, item (ürünün güncel satırı, GET /links/matrix biçiminde), summary.

Excel — GET /links/export.xlsx?filter=missing&connection_id=3 (ürün durumu için status_filter=active|passive, arama q): süzgeçteki ürünler; odak verilirse yalnız o bağlantının sütunları. filter verilmezse eski davranış.

"Ürünleri eşleştir" (POST /connections/{id}/match): pazaryerinin listesinde bulunamadığı için pasife alınan eşleşmelere neden yazılır (check.status = "missing", check.note = "Ürünleri eşleştir (tarih): ürün pazaryerinin ürün listesinde bulunamadı, eşleşme pasife alındı."); yanıtta deactivated (daha önce aktifken pasife alınan ürün sayısı) ve mesajda bu sayı.

v1.23.6 — Sıradaki eşleşmenin nedeni (queue) · sonucu bildirilmeyen kalemin doğrulanması #

queue alanı — GET /products/{sku}, GET /products?links=1 ve GET /products/issues yanıtlarındaki her marketplaces[] / items[] kaleminde. Eşleşme gönderim sırasında değilse null; sıradaysa:

AlanAnlamı
since, minutesKaç dakikadır sırada (dirty_since)
next_tryBağlantının bir sonraki gönderim denemesi (gelecekteyse)
failuresBağlantının art arda başarısız gönderim sayısı
error, error_atGönderim art arda başarısızken bağlantının son hatası; bağlantı durdurulmuşsa "Bu pazaryeri bağlantısı durdurulmuş…"
pausedBağlantı durdurulmuş (is_active = 0)

GET /products/issues: 30 dakikadan uzun sırada bekleyen ve bağlantısı art arda hata alan (ya da durdurulmuş) eşleşmeler de listelenir; error = "Sırada bekliyor — <bağlantının son hatası>".

Sonuç gelmedi (state = "unknown") — pazaryeri partinin sonucunda kalemi anmadıysa. Pazarama'da (parti kimliği tanınmadı, BSK16) artık Pazarama'daki ürün okunur: stok ve satış fiyatı gönderilenle aynıysa kalem ok olur (check.status = "ok", check.note = "Pazarama sonucu bildirmedi; üründe stok … okundu, gönderilenle aynı"). Uyuşmuyorsa parti ilk 5 dakika açık tutulup yeniden bakılır; sonra unknown olur ve error Pazarama'da ne göründüğünü yazar ("Pazarama'da şu an stok 34 / 29.999,00 ₺ görünüyor (gönderilen: …)"), check.status = stock | price | both | missing.

Kod önerisi kaldırıldı — POST /connections/{id}/sku-index yanıtında suggestions artık boş (truncated sürer); POST /connections/{id}/match yanıtında by_name[].suggest boş. GET /links/export.xlsx: "Tiresiz kod" bilgi sütunu yalnız safe=1 ile gelir.

v1.23.5 — Pazaryeri kodları TOPLU (Excel ve JSON) #

Kodları ürün ürün girmek yerine: indir → Excel'de düzenle → yükle (önce önizleme) → uygula. Panel: Ürünler › 📑 Pazaryeri kodları (Excel) (?p=links); site: Pazaryerleri › Kodlar (Excel). Hepsi aynı mantıktan (App\LinkSheet) geçer.

Uç noktaAçıklama
GET /linksTüm eşleşmeler: items[] {sku, title, barcode, connection_id, marketplace, connection_label, remote_code, active, price_override, list_price_override, state, error, status_text, pushed_at}, total. Süzgeç: connection_id, sku; page, size (en çok 5000, varsayılan 1000)
GET /links/export.xlsxExcel: her ürün bir satır, her bağlantı bir sütun ("Pazarama kodu [#3]"). Seçenekler: connections=3,5 (boş = hepsi) · products=all|linked|unlinked|error · prices=1 (özel fiyat + özel liste fiyatı sütunları) · active=1 (Evet/Hayır) · status=1 (gönderim durumu, bilgi) · safe=1|0 (tiresiz kod bilgi sütunu; verilmezse Pazarama / PttAVM varsa açık). İkinci sayfa "Kılavuz".
POST /links/importDüzenlenen dosya: multipart file ya da {"file_base64":"…","file_name":"kodlar.xlsx"} (CSV de olur). "dry_run": true → yalnız önizleme, hiçbir şey yazılmaz. Yanıt: message, summary {rows, new, code, price, active, same, errors, changes}, applied, changes[] {row, sku, connection_id, connection, actions[], old, new}, changes_total, errors[] {row, sku, conn, connection, message}, errors_total, warnings[], columns[], ignored_columns[] (listelerde ilk 1000)
POST /links/bulkJSON: {"items":[{"sku":"…","connection_id":3,"remote_code":"…","price_override":4799.9,"list_price_override":null,"active":true}],"dry_run":false} — alan gönderilmezse değişmez; price_override: null özel fiyatı kaldırır. Yanıt /links/import ile aynı. En çok 20000 kalem

Kurallar: dosyada boş hücre değiştirmez; özel fiyat hücresine - (ya da sil) → özel fiyat kaldırılır; aktif Evet/Hayır. SKU harf duyarsız bulunur. Bir bağlantıda aynı kod iki aktif eşleşmede olamaz (harf duyarsız; dosyanın SON durumuna bakılır, A↔B takası serbest) — çakışan satır uygulanmaz ve sebebi errors[]'da yazar. Kodu değişen eşleşme PUT /products/{sku}/links gibi gönderim sırasına alınır (eski hata / kontrol notu silinir). Eşleşmesi olmayan üründe özel fiyat / aktif için önce kod gerekir. Başlıktaki [#3] bağlantı numarasıdır; silinirse bağlantı adı / pazaryeri adı tek bağlantıya uyuyorsa sütun yine tanınır. Kod hücresi Excel'de sayıya dönmüşse (8.69E+12) satır reddedilir. Uygulamalar Kayıtlar'a (catalog) yazılır; uygulanmayan satırlar uyarı olarak da düşer.

POST /products/import (ürün Excel'i) ve panelin ürün Excel yüklemesi, dosyada aynı düzende pazaryeri sütunları varsa ürünleri ekledikten sonra kodları da eşler (yanıtta links).


Ürün içeriği hakkında #

Bu sürümde pazaryerine ürün açma / içerik güncelleme (kategori, özellik, açıklama gönderimi) kaldırılmıştır; sistem stok, fiyat, sipariş, kargo, fatura ve iade yönetimine odaklanır. Ürün kartındaki içerik alanları (POST /products ile gönderilen başlık, görsel, açıklama…) yalnızca kendi kayıtlarınız / irsaliye için saklanır.


Siparişler #

GET /orders #

Ek filtreler: cost_missing=1 (maliyeti girilmemiş kalemi olan siparişler), pack=unprinted|unchecked|checked (irsaliye basılmamış / paket kontrolü yapılmamış / yapılmış), local_status=carrier_set|delivery_reported|packed|shipped|…, parent_order_id= (bir siparişin ek gönderileri). Sipariş detayında children[] (bağlı manuel gönderiler), parent_order_id, user_fields[] (elle kilitlenmiş alıcı alanları), picked_at / picked_by (raflama: raftan toplandı) ve raflama açıksa pick{state, items[]} + her kalemde locations[] {location, quantity, status} (bkz. Raflama). Parametreler: status (virgülle: new,processing,shipped,delivered,cancelled,returned), marketplace, connection_id, updated_since, since, until (sipariş tarihi), order_number, q (sipariş no/müşteri/takip no/kargo barkodu/paket no), sort=order_date|updated_at, page, size (≤200), include=items.

Değişiklikleri düzenli almak için: GET /orders?updated_since=<son kontrol>&sort=updated_at&include=items.

Sipariş nesnesi:

{"id":15,"marketplace":"trendyol","connection_id":3,"order_number":"123456789","package_number":"98765",
 "status":"processing","status_label":"Hazırlanıyor","marketplace_status":"Picking","local_status":null,
 "order_date":"2026-09-10 14:22:00","customer":"A*** Y***","email":"…","phone":"…",
 "shipping_address":{"name":"…","address":"…","city":"İstanbul","district":"Kadıköy","postal_code":"…"},
 "billing_address":{…},"tax_number":null,"company":null,
 "cargo_company":"Yurtiçi","tracking_number":"…","tracking_url":"…","cargo_barcode":"…",
 "total":4599.90,"currency":"TRY","invoice_number":"","invoice_url":"","invoice_sent_at":null,"shipped_at":null,"local_status":"",
 "parcel_count":2,"desi":12.5,"note":"Kırılacak eşya","cargo_cost":null,"commission":null,"shipment_id":18,
 "shipment":{"id":18,"carrier":"yurtici","cargo_key":"YRK123456789","tracking_number":"1002131026","status":"in_transit",…},
 "items":[{"id":40,"line_id":"555","sku":"KOLTUK-01","catalog_sku":"KOLTUK-01","barcode":"…","name":"…","quantity":1,"unit_price":4599.90,"total":4599.90,"status":"Picking","stock_deducted":true}],
 "first_seen_at":"…","updated_at":"…"}

Takip no ve kargo barkodu (v1.23.3): tracking_number kargo firmasının TAKİP numarasıdır, cargo_barcode paketin KARGO BARKODUdur (etikete basılan kod; Hepsiburada'da "teslimat numarası"). Hepsiburada'da paket listeleri yalnız barkodu verir; takip numarası ve tracking_url paket sorgusundan (GET /packages/merchantid/{mid}/packagenumber/{no} → trackingInfoCode, trackingInfoUrl) kargo firması paketi teslim alınca gelir: işçi kargodaki siparişleri numara gelene kadar 30 dakikada bir sorar (kargoya verilişten 30 gün; teslim edilmiş ama numarası alınmamış sipariş bir kez). Numara gelince işlem geçmişine tracking ("Kargo takip numarası: …") yazılır. Paket bozulursa (Hepsiburada "Unpacked") sipariş "Yeni"ye döner; package_number, cargo_barcode, tracking_number temizlenir. İrsaliyedeki barkod cargo_barcode (yoksa takip no, o da yoksa sipariş no); paket kontrolü (POST /orders/pack-check) kargo barkoduyla da bulur.

Son kargo tarihi ve indirim (v1.26.0):

İdefix kargo profili (v1.26.0): GET /connections/{id}/cargo-companies İdefix satıcı kargo profillerini döner. code = profil id; etikette "İdefix anlaşmalı / kendi anlaşmam / alternatif" yazar.

Yalnız taşıyıcı bildirilen ship (Koçtaş, İdefix, Çiçeksepeti — v1.26.1): yanıtın data alanında pending: true ve status: "CARRIER_SET" gelir; sipariş henüz kargoya verilmemiştir. İstemciler "kargoya verildi" yazmamalı, "taşıyıcı bildirildi" yazmalıdır (panel mesajı: "Taşıyıcı bildirildi. Kargocu paketi okutunca sipariş otomatik 'Kargoda' olur."). Bu durumda webhook olarak order.updated (pending: true) gider; order.shipped yalnız pazaryeri siparişi gerçekten kargoya verilmiş yaptığında (çekim sonrası, source: auto) gider. POST /orders/bulk sonuçlarında aynı bilgi results[].pending (+ results[].note) olarak döner. GET /orders/{id}/actions kayıtlarında label bu aşamayı yansıtır ve phase alanı pending (taşıyıcı bildirildi) · cargo_code (pazaryeri kargo kodu üretti) · shipped (pazaryeri kargoya verildi yaptı) · cancelled (pazaryeri iptal etti) değerlerinden birini taşır. Koçtaş bağlantı ayarı mirakl_ship_mode=now seçilirse eski davranış (OR24 hemen) sürer.

POST /orders/{id}/refresh — durumu pazaryerinden şimdi yenile (v1.23.2) #

Siparişin güncel durumu pazaryerinden okunur ve yazılır (Hepsiburada: sipariş + paket detayı; diğerleri: canlı sipariş taraması). Yanıt: {"changed":true,"from":"processing","to":"shipped","message":"Durum güncellendi: Hazırlanıyor → Kargoda.","warning":null,"order":{…}}. Web / manuel siparişte ve pasif bağlantıda 422. İşlem geçmişine refresh olarak yazılır. Panelde sipariş sayfasındaki "Pazaryerinden yenile". Hepsiburada'da açık siparişlerin durumu ayrıca kendiliğinden de kontrol edilir (45 dakikada bir, sipariş başına).

GET /orders/{id}?raw=1 — detay (+ pazaryerinden gelen ham veri) #

GET /orders/{id}/actions — bu sipariş için yapılmış işlemler (geçmiş) #

Sipariş kalemlerinde v1.23.0'dan itibaren product_id (katalogdaki ürün; ek gönderide kodu değil bunu gönderin), ek gönderide (marketplace=manual) siparişte manual {reason, charge_material, material_cost}.

PUT /orders/{id} — paket bilgisi / maliyet #

parcel_count / desi değişirse pazaryerine de iletilir (Trendyol box-info, Koçtaş ek alanlar); yanıtta box_info (ok, supported, note).

{"parcel_count":2,"desi":12.5,"note":"Kırılacak eşya","cargo_cost":89.90,"commission":null,"local_status":"packed"}

cargo_cost ve commission girilirse finans özetinde bağlantı ayarındaki oranlar yerine bu değerler kullanılır. Sipariş çıktısında komisyon alanları: commission (pazaryerinin bildirdiği tutar; Trendyol kalem oranından hesaplanır, Koçtaş commission_fee + vergiler), commission_rate (%), commission_source (marketplace = pazaryeri bildirdi ya da siparişe elle girildi | none = pazaryeri komisyon göndermedi; tahmin yoktur), commission_estimate (pazaryeri vermediyse bağlantı ayarındaki oranla tahmin), net_estimate (toplam − komisyon − kargo maliyeti).


Sipariş işlemleri #

POST /orders/{id}/{işlem} — Yanıt 200 {"action":"ship","action_id":77,"data":{…},"order":{…}}; pazaryeri kabul etmezse 422 {"error":"action_failed","message":"…"}. Pazaryeri o işlemi desteklemiyorsa mesajda belirtilir. Her işlem order_actions geçmişine yazılır (GET /orders/{id}/actions).

Ortak gövde alanı: items — sadece belirli kalemler için işlem yapılacaksa line_id listesi (boşsa tüm sipariş).

İşlemGövdeAçıklama
accept—Siparişi kabul et (Koçtaş/Mirakl zorunlu; ayar auto_accept açıksa otomatik)
packinvoice_number, parcel_quantity, deciHazırlanıyor / paketle (Trendyol Picking, N11 Picking, HB paket oluşturma, Çiçeksepeti "hazırlanıyor")
shipcargo_company (ad veya kod), tracking_number, tracking_url, shipped_atKargoya verildi + takip no
invoiceurl (veya invoice_url), number, date, pdf_base64Fatura linki / dosyası gönder
cancelreason (GET /connections/{id}/cancel-reasons), note, itemsİptal / tedarik edememe (kalem bazlı). Hepsiburada (v1.23.3): Hepsiburada'nın belgelenmiş neden kodları (83 Ürün tedarik edilemedi — varsayılan, 12 Stok yok, 80 Fiyat hatası, 81 Yanlış barkod, 82 Kargo çıkışı yapılamadı, 89 Tedarik gecikmesi, 85, 43, 58, 106 Diğer); eski 1–4 kodları çevrilir. Yalnız paketlenmemiş kalem iptal edilir (paketliyse önce Hepsiburada panelinden paket bozulur)
deliverreceived_by, delivered_atTeslim edildi (kendi kargonuzla gönderdiyseniz)
cargocargo_companyKargo firması değiştir. Hepsiburada (v1.23.3): seçilen firma, Hepsiburada'nın o paket / kalem için sunduğu değiştirilebilir firmalar listesinden (…/changablecargocompanies) adına göre bulunup kısa adıyla (ShortName) gönderilir; listede yoksa hata metni geçerli seçenekleri sayar. Değişince takip numarası yeniden sorulur

Yardımcı listeler: GET /connections/{id}/cargo-companies, GET /connections/{id}/cancel-reasons, GET /connections/{id}/return-reasons

Hakediş / ödeme hareketleri (pazaryeri finans servisi, şimdilik Pazarama paymentAgreement): GET /connections/{id}/settlements?from=YYYY-MM-DD&to=YYYY-MM-DD → items[]{order_id, order_number, code, amount, commission, coupon, allowance, installments, status, date, transferred_at}, totals{amount, commission, allowance}. Desteklemeyen pazaryerinde 502 marketplace_error. (yanıtta ayrıca supported_actions).

Pazaryeri desteği (resmi API'lerin izin verdiği işlemler) #

Pazaryeriacceptpackshipinvoicecanceldelivercargo
Trendyol—✓✓✓✓—✓
Hepsiburada—✓✓✓✓✓✓
N11—✓—¹✓✓——
Pazarama—✓✓✓✓✓—
Çiçeksepeti—✓✓✓²—³✓—
İdefix—✓✓✓—³——
Koçtaş (Mirakl)✓✓✓✓✓✓⁵—
PttAVM———⁴✓———

¹ N11 API'sinde takip numarası gönderme yok; N11 anlaşmalı kargo etiketiyle çalışır. ² Çiçeksepeti fatura linki değil, fatura e-postası (SendInvoiceMail) kabul eder; invoice işlemi o yolu kullanır. ³ Çiçeksepeti ve İdefix satıcı tarafı iptal API'si sağlamaz (pazaryeri panelinden). ⁴ PttAVM kargo bilgisi PTT paneli/kargo entegrasyonundan gelir; API yalnızca fatura yükleme sunar. ⁵ Koçtaş: ship işleminde cargo_company olarak SELLER (panelde "Satıcı kendi taşır") seçilirse takip numarası zorunlu değildir ("Kendi Aracımız" yazılır), sipariş "Gönderildi" yapılır ve Koçtaş ek alanı shipment-status = Yolda işlenir; deliver işlemi shipment-status = Tamamlandı + delivered-date gönderir (Yurtiçi hareketlerinden otomatik de tetiklenir).


Fatura — e-Fatura / e-Arşiv (Logo İşbaşı) ve PDF #

Sipariş içindeki fatura bilgileriyle (fatura adresi, VKN/TCKN, vergi dairesi — order.billing_address) fatura kesilir. billing_address.district faturaya giden ilçedir (v1.22.1: Hepsiburada'da ilçe town alanından okunur, mahalle adres satırında kalır; eski kayıtlı siparişlerde ham veriden düzeltilir). Logo İşbaşı ilçeyi tanımazsa ("District Not Found") düzeltilmiş fatura ilçesi, sonra teslimat ilçesi birer kez denenir; tutan değer faturanın customer bilgisine yazılır. Müşteri GİB'de e-Fatura mükellefiyse e-Fatura, değilse e-Arşiv düzenlenir; GİB'e gönderilir, PDF alınıp barındırılır, pazaryerine fatura bağlantısı iletilir ve istenirse müşteriye kurumsal şablonla e-postalanır (PDF ekli).

Uç noktaAçıklama
POST /orders/{id}/invoice{"send_email":true,"email":"ozel@adres.com","push":true,"sync":true} → 201 {"invoice":{…}}. sync:false ile kuyruğa alınır (işçi tamamlar)
POST /orders/{id}/invoice/uploadHazır fatura: multipart file (PDF) veya {"pdf_base64":"…"}; number, date, send_email, email, push. Alternatif {"url":"https://…/fatura.pdf"}
GET /orders/{id}/invoiceFatura durumu: status (queued, processing, created, sent, error, cancelled), type (efatura/earsiv/pdf), number, ettn, pdf_url (imzalı, girişsiz), marketplace_sent_at, email_sent_at, error
POST /orders/{id}/invoice/email{"email":"…"} — faturayı (yeniden) e-posta ile gönder
GET /invoices?status=&order_id=&updated_since=&page=&size= · GET /invoices/{id}Fatura listesi / detay
POST /invoices/{id}/cancel · POST /invoices/{id}/retryİptal (e-Arşiv/taslak; ticari e-faturayı alıcı reddeder) · hatalı adımı tekrar dene
GET|PUT /settings/invoicingLogo İşbaşı API bilgileri (isbasi{api_key,username,password,tenant_id}), SMTP (smtp{host,port,secure,user,pass,from_email,from_name}), otomatik kesim (invoicing.auto_create: never|ship|new), auto_push, auto_email, e-posta şablon metinleri. Yanıt: has_isbasi, has_smtp_password ve gizli olmayan isbasi{username,tenant_id,has_api_key,has_password}. Boş gönderilen şifre / anahtar alanı kayıtlı değeri değiştirmez
POST /settings/invoicing/test{"what":"isbasi"} Logo İşbaşı girişini dener · {"what":"smtp","to":"…"} test e-postası gönderir (to boşsa hesap e-postası). Başarısızlıkta 422 + hata metni

Gelen e-Faturalar (Logo İşbaşı gelen kutusu) #

Uç noktaAçıklama
GET /invoices/incoming?days=30&q=&page=&size=Son N günün gelen e-Faturaları (items[], total); İşbaşı tanımlı değilse 400
GET /invoices/incoming/{uuid}/pdfPDF (inline)
POST /invoices/incoming/{uuid}/accept · …/reject{"note": "…"} — GİB yanıtı (kabul / red)

Toplu işlem #

POST /orders/bulk {"ids":[15,16,17],"action":"pack","params":{}} — action: pack, ship (params: cargo_company, tracking_number…), ship_create (params: account_id, parcel_count, desi, phone; sipariş başına ezmek için rows: {"15": {"parcel_count": 2, "desi": 4.5, "phone": "05xx"}}), invoice, deliver, cancel (params: reason), accept. Yanıt: {"done":2,"failed":1,"results":[{"order_id":15,"ok":true},{"order_id":16,"ok":false,"error":"…"}]}.


Manuel gönderi / yedek parça #

POST /orders/manual — pazaryerinden bağımsız bir gönderi kaydı açar (marketplace = "manual", sipariş no M260912-001 biçiminde); isteğe bağlı olarak aynı anda Yurtiçi gönderisi oluşturur. Tipik kullanım: mevcut bir siparişin alıcısına yedek/eksik parça ya da değişim ürünü göndermek.

{"source_order_id": 12, "reason": "Yedek parça", "parcel_count": 2, "desi": 4,
 "items": [{"sku": "KOLTUK-01", "quantity": 1}, {"name": "Menteşe seti", "quantity": 2}],
 "cargo_account_id": 1, "deduct_stock": false, "note": "Kırılgan"}

Sonradan düzeltme (v1.23.0, yalnız manuel gönderi):

Uç noktaAçıklama
POST /orders/{id}/itemsKalem ekle: {"items":[{"name":"Kapak menteşesi","quantity":2,"cost":45},{"product_id":7,"quantity":1,"deduct_stock":true}]} — maliyetiyle eklenen kalem malzeme gider yazımını açar. Yanıt 201: added, warnings, order, profit
DELETE /orders/{id}/items/{item_id}Kalem çıkar; stoktan düşülmüşse stok geri verilir (?restore_stock=0 ile verilmez), raf önerisi silinir. Yanıt: removed, stock_restored, order, profit
PUT /orders/{id} {"charge_material":true,"material_cost":null,"reason":"Hasarlı parça","cargo_cost":120}Malzeme gider yazılsın mı, elle toplam (null = kalem maliyetleri), gönderim sebebi, kargo ücreti. Pazaryeri siparişinde charge_material/material_cost/reason 422 döner
PUT /orders/{id}/items/{item_id} {"cost":150,"mode":"order"}Kalemin birim maliyeti (malzeme toplamı artık gönderi anında donmaz; düzeltme kâra hemen yansır)

Kargo — kendi kargo anlaşmanızla gönderi (Yurtiçi Kargo) #

Pazaryerinin anlaşmalı kargosu yerine kendi Yurtiçi Kargo sözleşmenizle gönderi oluşturursunuz. Kargo anahtarı (prefix + sipariş numarası) irsaliyeye Code128 barkod olarak basılır; kurye barkodu okutunca Yurtiçi sisteminde takip numarası (docId) oluşur. İşçi 30 dakikada bir açık gönderileri sorgular, takip numarasını siparişe yazar ve hesap ayarı auto_notify açıksa pazaryerine "kargoya verildi" bildirimini otomatik yapar.

Uç noktaAçıklama
GET /cargo/carriersDesteklenen kargo firmaları, kimlik alanları ve ayar tanımları
GET /cargo/accountsKargo hesaplarınız
POST /cargo/accounts{"carrier":"yurtici","label":"Ana sözleşme","environment":"prod","credentials":{"username":"…","password":"…"},"settings":{"prefix":"YRK","cargo_count":"1","auto_notify":true}} → 201 + bağlantı testi sonucu
PUT /cargo/accounts/{id}label, environment, active, settings{}, credentials{} (boş bırakılan kimlik alanı değişmez)
DELETE /cargo/accounts/{id}, POST /cargo/accounts/{id}/testSil; bağlantı testi
POST /orders/{id}/shipmentSipariş için gönderi: {"account_id":1,"parcel_count":2,"desi":12.5,"kg":8,"cod_amount":0,"cod_type":"cash","description":"…","cargo_key":"(ops.)"} → 201 {"shipment":{…}}. Alıcı bilgileri siparişten alınır
POST /shipmentsSiparişsiz gönderi (WooCommerce/Shopify/kendi sisteminiz): {"account_id":1,"reference":"WOO-1001","name":"…","address":"…","city":"…","district":"…","phone":"…","email":"…","parcel_count":1,"desi":3,"cod_amount":0}
GET /shipments?status=created,in_transit&order_id=&cargo_key=&updated_since=&page=&size=Gönderiler (durumlar: created, in_transit, delivered, returned, cancelled, error)
GET /shipments/{id}Detay: cargo_key, carrier_key, tracking_number, tracking_url, status, status_text, events[] {date,event,unit,city}, recipient{}. carrier_key: taşıyıcıya gönderilen gerçek anahtar (barkod); hatalı denemede cargo_key tablo tekilliği için #1234 eki alır, carrier_key bozulmaz
POST /shipments/{id}/refreshTaşıyıcıdan anlık sorgu (takip no / hareketler)
POST /shipments/{id}/cancelGönderiyi iptal et (kargo teslim alınmadan)
POST|PUT /shipments/{id}/boxKoli / desi değiştir (v1.13.2): {"parcel_count":3,"desi":18,"kg":0,"description":"","only_record":0}. Yurtiçi SOAP servisi güncelleme sunmadığı için gönderi iptal edilip yeni değerlerle yeniden oluşturulur → yanıt {shipment{…}, recreated:true, warning}; kargo anahtarı ve takip numarası değişir, etiket/irsaliye yeniden basılmalıdır. Gönderi in_transit / delivered / returned ise ya da only_record:1 verilmişse taşıyıcıya dokunulmaz: yalnız sipariş kaydı (koli, desi, kargo maliyeti, irsaliye dağılımı) güncellenir, recreated:false + uyarı döner. Her iki yolda da pazaryeri destekliyorsa yeni koli/desi pazaryerine bildirilir. İptal başarılıysa ama yeniden oluşturma başarısızsa hata metni bunu açıkça söyler (gönderi iptal kalır, Kargo kartından yeniden denenir).

Takip sıklığı (v1.13.2): gönderiler kademeli sorgulanır — ilk 48 saat 5 dakikada bir, sonrasında 30 dakikada bir. Kargo hesabı ayarlarından değiştirilir: track_fast_minutes (5), track_slow_minutes (30), track_fresh_hours (48).


İrsaliye (sevk fişi) #

Uç noktaAçıklama
GET /orders/{id}/packing-slipYazdırmaya hazır HTML (A4): logo, gönderici, fatura bilgileri (firma adı, VKN/TCKN, vergi dairesi), teslimat adresi, ürün görselleri, KDV, toplam, büyük koli sayısı kutusu, kargo barkodu
GET /orders/{id}/packing-slip.pdfPDF (sunucuda wkhtmltopdf varsa; yoksa 501)
GET /orders/{id}/packing-slip?json=1Model + HTML (kendi şablonunuzu basmak için)
Parametrelershow_images=0, show_prices=0, show_barcode=0 bu çıktı için ayarı geçersiz kılar
show_customer=0|1, hidden_show_city=0|1 (v1.26.0)Müşteri bilgilerini bu baskıda gizle / göster (öncelik: istek > anahtar profili > hesap profili > varsayılan açık). Gizliyken ad, firma, adres, telefon, e-posta ve VKN/TCKN irsaliyeye, etiketlere ve json=1 çıktısındaki ship_to / bill_to'ya yazılmaz; fatura kutusunda yalnız "Bireysel / Kurumsal müşteri", teslimat kutusunda "Alıcı bilgileri kargo barkodunda — barkodu okutun" yazar ve barkod her zaman basılır. Siparişin gerçek kargo barkodu yoksa (barkod sipariş numarasına düşüyorsa) bilgiler gizlenmez; modelde customer_hide_skipped:true. Toplu çağrıda sipariş başına items[].show_customer da verilebilir
(biçim verilmezse)Siparişte kayıtlı dağılım basılır (PUT /orders/{id} ile girilen slip_detailed / slip_labels); kaydedilmemişse 1 detaylı + kalan koliler etiket
mode=full|detailed|label|mixed|both, detailed=N, labels=MKoli başına sayfa türü — verilirse kayıtlı dağılımı ezer: full / detailed hepsi detaylı, label hepsi sadece barkod etiketi, mixed ilk koli detaylı kalanı etiket, both her koliye hem detaylı hem etiket; detailed/labels sayı verilirse doğrudan o kadar basılır (örn. 12 koli detailed=3&labels=9). Etiketler A4'e 8 adet, k / N koli numarasıyla
GET /orders/packing-slips?ids=1,2,3&mode=labelBirden çok siparişin irsaliyesi tek belgede: detaylı sayfalar sipariş sırasıyla, tüm etiketler sona toplu. .pdf eki ya da format=pdf ile PDF
POST /orders/packing-slips{"items":[{"id":15,"detailed":3,"labels":9},{"id":16,"mode":"label"}],"format":"pdf"} — sipariş başına farklı sayı
profile=keyİrsaliye, isteği yapan API anahtarının gönderici profili ve logosuyla basılır (sipariş hangi kanaldan gelirse gelsin). Aynı hesaba bağlı her site kendi firma bilgisiyle bassın diye; anahtar profilinde boş bırakılan alanlar hesap profilinden devralınır. Ana anahtarla istenirse hesap profili kullanılır. GET /orders/{id}/packing-slip ve GET /orders/packing-slips için geçerlidir

Barkod içeriği: kendi kargo gönderisi varsa kargo anahtarı, yoksa pazaryeri takip numarası, o da yoksa sipariş numarası. Barkod altındaki etiket siparişin geldiği pazaryerini belirtir: Yurtiçi Kargo Marketplace - Trendyol (takip no varsa ayrıca yazılır). Koli sayısı kadar sayfa üretilir; her sayfada barkodun altında büyük k / N (ör. 2 / 3) yazar — her koliye bir irsaliye yapıştırılır. Gönderici bilgileri, logo ve varsayılan görünüm PUT /profile ile (veya panel › Ayarlar) belirlenir.

GET /profile · PUT /profile #

Hesap profili. Siteye özel profil: ek API anahtarıyla (Panel › API › ek anahtar, ör. kanal woocommerce) GET /profile?scope=key o anahtarın profilini (key{id,label,channel,override,profile}) ve etkin profili (profile) verir; PUT /profile gövdesine "scope":"key" eklenirse yalnız o anahtarın profili yazılır ("clear":true kaldırır). Anahtar profili, o anahtarla açılan web / manuel siparişlerin irsaliyesinde hesap profilini ezer (dolu alanlar); pazaryeri siparişleri her zaman hesap profilini kullanır. Böylece aynı hesaba bağlı birden çok site kendi gönderici bilgisi ve logosuyla irsaliye basar.

{"company":"Örnek Mobilya","address":"…","district":"Konak","city":"İzmir","postal_code":"35160","phone":"…","email":"…","website":"https://…",
 "tax_office":"Konak","tax_number":"1234567890","logo":"data:image/png;base64,…",
 "slip":{"title":"İrsaliye","accent":"#f26522","note":"İade için 14 gün…","show_images":true,"show_prices":true,"show_barcode":true,"show_customer_phone":true,
         "show_customer":true,"hidden_show_city":false},
 "orders":{"ship_warn_hours":24}}

Anahtar profilinde boş bırakılan metin alanları hesap profilinden devralınır (irsaliye başlığı dâhil); onay kutuları her zaman anahtarın değerini kullanır. Yanıt yalnız gönderici / irsaliye alanlarını içerir — SMTP, Logo İşbaşı kimlikleri, bildirim tercihleri dönmez.


Finans #

Uç noktaAçıklama
GET /finance/summary?since=2026-09-01&until=2026-09-30revenue, orders, items, avg_order, cancelled, commission, cargo, expenses, net, by_marketplace[] {marketplace, orders, revenue, commission, cargo, cancelled, net}, by_day[] {date, orders, revenue}, expenses_by_category[] — ayrıntılı alanlar aşağıda "Kârlılık" bölümünde; v1.23.0: checks[] (eksik ayar / veri uyarıları)
GET /finance/orders?since&until&marketplace&filter&q&sort&dir&page&per_pagev1.23.0 Sipariş bazında kârlılık (iade/iptal ve ek gönderiler sonrası). Satır: id, order_number, marketplace, order_date, status, customer, quantity, sale (satış), revenue (iade sonrası ciro), reversed, commission, fees, stopaj, payout, cargo (gidiş), extra_cargo (ek gönderi), return_cargo (iade dönüşü), cogs (satılan), extra_cogs (ek gönderi malzemesi), cogs_lost (hasarlı iade), pretax, vat_payable, tax_due, net, margin, cost_missing, cargo_known, extras, extras_total, reversal, reversal_loss. filter: boş (masrafsız iptaller gizli) · all · loss (net < 0) · cost_missing · extras · returns · cargo_missing. sort: date|pretax|net|margin|revenue|extras_total|cogs, dir: asc|desc. per_page=0 → hepsi (dışa aktarma). Yanıtta totals
GET /finance/products?since&until&marketplace&q&sort&dir&page&per_pagev1.23.0 Ürün bazında kârlılık: product_id, sku, name, image, orders, quantity, returned, return_rate, net_quantity, sale, revenue, commission, fees (kesinti + stopaj), cargo (gidiş + iade dönüşü payı), extras (ek gönderi payı), extras_orders, cogs, pretax, margin, unit_profit, avg_price, unit_cost, cost_missing. Kaleme ait olanlar (satış, iade edilen adet, maliyet, hasarlı iade) kalemden; siparişe ait olanlar (komisyon, kesinti, kargo, ek gönderi) kalemin ciro payıyla dağıtılır — kalemlerin kârı toplamı siparişin kârına eşittir. İptal edilen sipariş adet olarak sayılmaz. sort: pretax|revenue|quantity|margin|returns|extras|unit_profit
GET /finance/extras?since&until&marketplace&filter=cost_missing&q&page&per_pagev1.23.0 Ek gönderiler (yedek parça / eksik parça / değişim): ana siparişin tarihine göre dönemdekiler + bağımsız manuel gönderiler. Satır: id, order_number, date, reason, status, parent {id, order_number, marketplace, order_date, customer}, lines[] {name, sku, product_id, quantity, unit_cost}, cargo, cargo_source, cargo_known, material, charge_material, material_override, cost_missing, total. Yanıtta totals, by_reason[], by_product[] (ana siparişteki ürüne göre — hangi üründe ek gönderi çıkıyor)
GET /finance/monthly?months=12&until=2026-09v1.23.0 Aylık seyir: her ay month, label, orders, revenue, payout, pretax_profit, expenses, operating_profit, tax_total, net, margin, net_margin, returns_loss, extras_total, cost_missing, cancelled
GET /expenses?since=&until=Giderler (vat_rate, vat, recurring_id, period ile); yanıtta categories, vat_defaults
POST /expenses{"date":"2026-09-11","category":"ads","amount":1500,"vat_rate":20,"note":"Eylül reklam","marketplace":"trendyol"} — tutar KDV dahil; vat_rate verilmezse kategori varsayılanı (personel, vergi %0; diğerleri %20). Kategoriler: cargo, commission, ads, packaging, purchase, salary, rent, tax, software, accounting, utilities, vehicle, affiliate (satış ortaklığı — siparişe bağlanmayan), payment (ödeme / POS — siparişe bağlanmayan), other
PUT /expenses/{id} · DELETE /expenses/{id}Düzelt (yalnız verilen alanlar) / sil
PUT /expenses/by-keyv1.23.0 Anahtarlı gider — bağlı sistemin (site) aynı gideri tekrar tekrar güncellemesi için: {"ext_key":"site:affiliate:2026-09","date":"2026-09-28","category":"affiliate","amount":120,"vat_rate":0,"note":"…"}. Aynı ext_key varsa o kayıt güncellenir (200), yoksa eklenir (201, created:true); amount 0 → kayıt silinir (deleted:true). ext_key: harf, rakam, _ . : - (en çok 80). Giderde ext_key alanı. e-ticaret sitesi 1.11.0 siparişe bağlanmayan nakit satış ortaklığı ücretlerini (tıklama başı, elle düzeltme) ay başına bu uçla yazar
GET /expenses/recurring · POST /expenses/recurring · PUT|DELETE /expenses/recurring/{id}v1.23.0 Tekrarlayan giderler: {"category":"rent","amount":10000,"vat_rate":20,"day":1,"start_month":"2026-06","end_month":null,"note":"Depo kirası","marketplace":null,"active":true} — her ay day. gününde gider kaydı yazılır (saatlik iş + finans ekranı açılışı; aynı ay bir kez; yazılmış ayın kaydı silinirse yeniden yazılmaz). Düzeltme yalnız sonraki ayları etkiler; şablon silinince yazılmış kayıtlar kalır. day 1–28

v1.23.0 — işletme giderleri vergiden önce: giderin KDV'si indirilecek KDV'ye, tutarı kâr vergisi matrahına girer (opex, opex_vat, operating_profit = pretax_profit − expenses, tax_total = vat_payable + tax_due, net = operating_profit − vat_payable − tax_due). Pazaryeri seçilmiş gider (ör. reklam) by_marketplace[] satırında da o pazaryerinden düşülür (expenses). Ek gönderiler özet alanları: extras_count, extras_total, extras_cost_missing, extra_cargo, extra_cogs; ayrıca cargo_unknown (kargo maliyeti bilinmeyen sipariş), loss_orders, returns_count, cancels_count.

Komisyon = sipariş tutarı × bağlantı ayarındaki oran (veya siparişe PUT /orders/{id} ile girilen commission); kargo = siparişe girilen cargo_cost › gönderi maliyeti › bağlantı ayarındaki ortalama; iptal/iade siparişler ciroya dahil edilmez.


İadeler (iade / değişim / iptal talepleri) #

Talepler her bağlantı için periyodik çekilir (sync_returns ayarı).

GET /returns #

Parametreler: status (requested,review,approved,rejected,in_transit,received,completed,cancelled), type (return|change|cancel), marketplace, updated_since, order_number, return_code (v1.27.0: iade kodu, ör. YRKN000002), page, size, include=items.

GET /returns/{id}?raw=1 — detay (kalemler, neden, müşteri, kargo) #

items[]: id, line_id, order_line_id, order_item_id, product_id, catalog_sku (v1.23.3: bağlı katalog ürününün kodu — pazaryeri iade satırında kendi kodunu verebilir, ör. Hepsiburada HBV…), name, sku, barcode, image, quantity, amount, reason, status, restock_qty (karara bağlanan adet), restocked_ok (stoğa giren adet), restock_remaining (karar bekleyen adet), restock_state ('' bekliyor · partial · ok · damaged · mixed · none (v1.23.11: stok değişmesin)), restock_note, restocked_at. v1.23.11: raflama açıksa karar bekleyen kalemde suggestion (önerilen raf: {code, location_id, reason, label, quantity, alternatives[]} — bkz. Raflama › Ürün nerede?); iadede restock_due_at (stok kararının beklenmeye başladığı an), restock_pending ("Stok kararı bekleyen" listesinde mi), restock_age_days (kaç gündür). Pazaryeri iade satırında ürün vermese bile (Koçtaş, Hepsiburada, Trendyol çoğu zaman sadece sipariş kalem kimliği verir) kalem sipariş kaleminden tamamlanır: ad, SKU, barkod, katalog ürünü, görsel.

POST /returns/{id}/{karar} — approve | reject | receive | pending #

Gövde: {"reason":"…","note":"…","items":["line_id"],"days":3,"restock":"yes|no"}. Yanıt {"decision":"approve","data":{…},"return":{…}}. restock: ürün elinize ulaşınca stoğa eklensin mi (yes sağlam / no hasarlı). Verilmezse ürün geri geldiğinde (received/completed) return.restock boş kalır ve panelde "stoğa girsin mi?" sorulur.

POST /returns/{id}/receive — "Teslim aldım" (v1.26.0). Gövde (hepsi isteğe bağlı): {"restock":"yes|no","notify":true|false,"message":"…","by":"Depo"}.

(verilmezse bağlantı ayarı "İade teslim alınınca Koçtaş operatörüne mesaj gönder", varsayılan açık) sipariş üzerinden operatöre mesaj yazılır: varsa siparişin operatörlü görüşmesine (M12), yoksa yeni sipariş görüşmesi (OR43) → receipt_sync: "message_sent", receipt_ref: "M12:{thread}/{message}". message boşsa bağlantı ayarındaki şablon ({siparis_no}, {urun}, {adet}, {tarih}) doldurulur; return.receipt_message önceden doldurulmuş metni verir.

Yanıt: {"ok":true,"decision":"receive","receipt_sync":"sent|message_sent|local|failed","note":"…","error":null|"…","data":{…},"return":{…}}. publicReturn yeni alanlar: received_at, received_by, receipt_sync, receipt_error, receipt_ref, receipt_message, can_notify.

POST /returns/{id}/restock — kalem bazlı, adetli stok kararı #

{"items":[{"id":12,"quantity":2,"state":"ok","note":"2'si sağlam"},{"id":12,"quantity":1,"state":"damaged"},{"line_id":"ci-9","state":"skip"}],"note":"…"}

state: ok → adet kadar katalog stoğuna eklenir ve tüm pazaryerlerine yayılır (olay kaynağı {pazaryeri}_iade); damaged → stoğa girmez, işaretlenir; none (v1.23.11) → stok ve raf değişmez, kalem kapanır (ürün elinize geçmedi — kayıp kargo, ürünsüz para iadesi — ya da stok daha önce elle düzeltildi; "hasarlı" sayılmaz); skip → sonra. Tanınmayan state artık ok sayılmaz: 422 (v1.23.11). Raflama açıksa location (kalemde ya da üstte): raf kodu, RAFSIZ ya da auto (v1.23.11: ürünün önerilen rafı — durduğu raf → bu siparişte toplandığı raf → en son rafı → çeşit / kategori rafı; hiçbiri yoksa rafsız). Sağlam ürün o rafa fiziksel giriş yapar (return_in hareketi, stock.moved olayı). location boşsa ürünün sipariş için toplandığı raf, o da yoksa RAFSIZ kullanılır; yanıttaki items[].location nereye alındığını söyler. quantity verilmezse kalemin kalan adedi; kalanı aşan adet kırpılır; kısmi girişler birikir (restock_qty, restocked_ok). items verilmezse {"state":"ok"|"damaged"} tüm kalemlere uygulanır (eski {"restock":true|false} de kabul edilir). Sipariş iptalinde stok zaten geri verilmiş kaleme (order_items.applied = 2) tekrar eklenmez, uyarı döner; siparişe bağsız kalem önce siparişin kalemine bağlanmaya çalışılır (sipariş numarası + SKU/barkod). Yanıt: {"restocked":2,"done":true|false,"items":[{"id","sku","product_id","state","quantity","restocked","warning"}],"return":{…}}. Kapı (panel ile aynı): stok kararı zaten verilmiş (restocked_at dolu) ya da durumu approved / in_transit / received / completed olmayan iadede istek action_failed (422) ile reddedilir; message Türkçe gerekçedir ("Bu iade "Reddedildi" durumunda — ürün geri gelmeden stoğa alınamaz…"). İstisna: sipariş kalemi bulunamayan type = cancel kayıtlar (karar sahibinin). type = cancel kayıtlarda (ürün müşteriye gitmemiş iptal) stok sipariş kaleminden geri verilir: iptal kesinleşince bağlı sipariş kalemi bulunursa kalem hemen iptal edilir ve stok bir kez geri gelir (kayıt restock: no ile kapanır); sipariş bulunamazsa kayıt açık kalır ve panelde "İptal — sipariş kalemi bulunamadı, stok kararı sizde" diye sorulur. Onaylandı'da kalan (pazaryerinin "ürün ulaştı" demediği) iadeler onaydan 3 gün sonra "stoğa girsin mi?" listesine düşer.

GET /returns/pending-restock?limit=200 — stok kararı bekleyen iadeler (v1.23.11) #

Ürünü geri gelmiş (received / completed, cancel kayıtlarda karar sahibine kalan) ya da onaylanıp 3 gün geçmiş, stok kararı verilmemiş iadeler, en eskiden (restock_due_at). Yanıt: summary{count, web, total, overdue, oldest_days, oldest_at} (count: kararı burada verilecek pazaryeri iadeleri; overdue: 2 günü geçen; web: kararı web sitesinde verilen web iadesi), returns_open (onay / ret bekleyen talep sayısı), items[]: GET /returns/{id} biçiminde iade + kalemler (kalemde suggestion) ve due_since, age_days, pending_note (neden soruluyor), site_managed (web iadesi), can_restock, actions[] (hızlı karar: ok, damaged, none; web iadesinde yalnız none). ?summary=1: yalnız summary ve returns_open (menü sayısı / uyarı için hafif çağrı).

POST /returns/restock-bulk — hızlı / toplu stok kararı (v1.23.11) #

{"ids":[12,13],"state":"ok","location":"auto","note":""}

Seçilen iadelerin kalan bütün kalemlerine tek karar: state ok | damaged | none; location auto (varsayılan; kalem başına önerilen raf) | RAFSIZ | raf kodu. Her iade restock ucunun kapısından geçer (kararı verilmiş / ürünü gelmemiş iade atlanır, gerekçesiyle). Katalogda karşılığı olmayan kalemde ok reddedilir (stok eklenmeden kapanırdı); kalem bilgisi olmayan iade yalnız none ile kapanır; web sitesi iadesinde yalnız none (kararı sitenin teslim alma ekranında verilir). Yanıt: {"done":1,"failed":1,"restocked":2,"results":[{"id":12,"ok":true,"label":"Trendyol #…","error":null,"restocked":2,"done":true,"items":[…]},{"id":13,"ok":false,"error":"…"}],"summary":{…}}.

POST /orders/{id}/reactivate — iptalden çıkarma #

Web sitesi iptal edilmiş siparişi yeniden aktif ederse çağrılır. İptal edilmiş kalemler açılır, iptalde geri verilen stok tekrar düşülür (olay kaynağı {kanal}_yeniden), sipariş processing olur. İkinci çağrı ve iptal edilmemiş siparişte no-op (data.reactivated: 0). Yanıt: {"action":"reactivate","data":{"reactivated":1,"deducted":2,"note":"…"},"order":{…}}.

PazaryeriTalep listesiOnayRetTeslim aldım
Trendyol (claims)✓✓✓ (itiraz + dosya)—
Hepsiburada (claims)✓✓✓✓ (ön onay)
N11 (ReturnService)✓✓✓✓ (beklet)
Pazarama (refund)✓✓✓—
Çiçeksepeti (cancel evaluation)✓✓✓—
İdefix (claim)✓✓——
Koçtaş (RT + OR11 refund/iptal/şikâyet)✓✓ (yalnız RT)✓ (yalnız RT)✓ (v1.26.0: RT25; operatör yönetiyorsa / rf: inc: kaydıysa operatöre mesaj)
PttAVM————

İade kodları — Yurtiçi'de otomatik takip (v1.27.0; ortak sıra v1.28.0) #

Web sitesi iade onaylayınca müşteriye bir iade kodu verir (YRKN000002, YRKN000003, … — sıra sitede artar). Müşteri paketi Yurtiçi şubesinden gönderirken kargo fişine / gönderi referansına "Sabit Cari 990148039 - YRKN000002" yazdırır (adres yok: alıcı Yurtiçi'de bu sabit cari hesabınızdır). Pazaryeri Merkezi Yurtiçi'nin müşteri rapor servisini (WsReportWithReferenceServices) periyodik tarar, kodu taşıyan gönderiyi bulur, takip numarasını / bağlantısını / durumu çeker ve iadeye yazar. Ayrıntılı tasarım: IADE-KODU.md; Yurtiçi servis notları: api-ref/yurtici-rapor.md.

Önkoşul: Kargo sayfasında Yurtiçi hesabı + panel › İade kodları sayfasında izleme açık, kod ön eki (varsayılan YRKN) ve sabit cari numarası girili. Hesap yoksa kod yine iadede durur; izleme açılınca eski kodlar kendiliğinden kayıt defterine alınır.

UçAçıklama
POST /returns (+ return_code)Site iadeyi bildirirken kodu da yollar. Kod returns.return_code'a yazılır ve izlemeye alınır. Yanıt/okumada: return_code, tracking_number, tracking_url, cargo_status (in_transit · delivered …), cargo_status_text, cargo_delivered_at.
GET /returns?return_code=YRKN000002Koda göre iade.
GET /return-codesİzlenen kodlar. Süzgeç: state (waiting,transit,delivered,cancelled,stopped,expired), linked=1|0, source (site,wp,api,manual,scan; virgülle çoklu), q (kod, takip numarası ve not), updated_since, page, size. 1.28.0: her item'da bağlı iade özeti return_ref{id,number,order_number,marketplace,status,customer} ve note.
POST /return-codes{"code":"YRKN000001","return_id":12,"lookup":true,"source":"manual","note":"…","claim":false} — kodu izlemeye al / iadeye bağla / Yurtiçi'de hemen ara. 1.28.0: source (site|wp|api|manual, varsayılan api) ve note (≤250 karakter) kodu ekleyen kanalı yazar; claim:true → kod zaten kayıtlıysa, iadeye bağlı değilse ve kaynağı belirsizse (scan|manual|api) kaynak / not isteyen kanala geçer (WordPress'in elle verilmiş kodu bir talebe bağlaması) ve ortak sıra o numaranın ötesine ilerler. Yanıt: found, item, diag[] (adım adım tanılama), near[], bind_error. Sitenin başka kod verdiği web iadesine farklı kod bağlanamaz → 409 conflict.
POST /return-codes/allocatev1.28.0 — ORTAK SIRADAN sıradaki kodu verir ve kayıt defterine yazar: {"source":"site|wp|api","note":"WordPress · IADE2611070001 · sipariş #1001","return_id":0,"floor":0}. Site ve WordPress aynı Yurtiçi carisini kullandığı için kod buradan alınır; iki kanal aynı numarayı veremez (benzersiz dizin + çakışmada sonraki numara). Aynı return_id yeniden sorarsa mevcut kod döner (idempotent, created:false, HTTP 200); yeni kod 201. floor istemcinin bildiği alt sınırdır. Numara: max(ayardaki "Sıradaki numara", floor, site / WordPress / API'nin verdiği en yüksek numara + 1); Yurtiçi'de keşfedilen ve elle yazılan kodlar sırayı atlatmaz, ama dolu numaralar atlanır. Yanıt: {code, created, item, config{prefix,digits,cari,next}}. Etkin Yurtiçi hesabı / açık izleme yoksa 422 action_failed; return_id bulunamazsa 404.
GET /return-codes/configv1.28.0 — Site / WordPress için ortak ayar özeti (ağa çıkmaz): ready, enabled, prefix, digits, cari, cari_list[], cari_source (settings | account = ayarda boşsa Yurtiçi hesabının kendi müşteri numarası), next, next_number, account{id,label,environment}, reason.
GET /return-codes/{code}Tek kod + bağlı iade. {code} esnek yazılabilir (yrkn2, YRKN2, YRKN000002 aynı kodu bulur).
POST /return-codes/{code}/refreshYurtiçi'de şimdi ara (tanılamalı).
POST /return-codes/{code}/stop · /resumeİzlemeyi durdur / yeniden başlat (60 günü aşıp hiç görülmeyen kod expired olur; resume süreyi sıfırlar).
DELETE /return-codes/{code}Kaydı sil (iadedeki kod alanı kalır).
POST /return-codes/scanİzleme açık hesapları şimdi tara.

item alanları: code, state, state_label, tracking_number, tracking_url, parcel_count, parcels[{tracking_number, tracking_url, status, status_text, created_at, delivered_at}], status_text, cargo_status, cargo_status_label, seen_at, delivered_at, last_check_at, checks, last_error, return_id, source (site|wp|api|manual|scan), note, return_ref, sender_hint (kısaltılmış), sender_city, match_field.

Webhook: takip no / durum değişince bağlı iade için return.updated (reason: "return_code") gider; yalnız değişiklikte, döngü olmaz. Bildirim olayı: return.cargo (bildirim türü ayarlanabilir). Gizlilik: Yurtiçi'den gelen alıcı / gönderici adı, adres ve telefon saklanmaz; tanılama örneklerinde de görünmez (gönderici adı yalnız kısaltılmış ipucu).


Raflama — depo yerleşimi (raflar, fiziksel stok, toplama) #

Hesap başına açılıp kapanan özellik (PUT /settings/features {"shelves": true} ya da Ayarlar › Özellikler). Kapalıyken hiçbir davranış değişmez; /locations, /stock/* ve /orders/{id}/pick uçları 400 feature_disabled döner.

İki stok kavramı

NedirNe zaman değişir
Satılabilir stok (stock)Pazaryerlerine gönderilen adet (GET /products, POST /stock)Sipariş gelince düşer, iptal / iade ile geri gelir; mal girişi / sarf / kayıp / sayım ile değişir
Fiziksel stok (shelves.physical)Raflardaki adetlerin toplamı; RAFSIZ = henüz rafa yerleşmemiş kovaSipariş toplanınca (pick) düşer; mal girişi, transfer, sarf, kayıp, sayım, iade girişi ile değişir

fiziksel − toplanmayı bekleyen = satılabilir beklenir; difference alanı sapmayı verir. v1.22.1'den beri toplanmayı bekleyenin yalnız satılabilirden düşülmüş kısmı sayılır (pending_deducted; stoktan düşülmemiş geçmiş / "düşüm kapalı" sipariş kaleminin adedi zaten satılabilirin içindedir): difference = physical − pending_deducted − stock. Depoda olan her ürün satışa açıktır (v1.22.1): satılabilir stok yazımları depo kaydını da taşır (POST /stock › depo), sapma ürün sayfasındaki "Depodakini satışa aç" / "Satılabilir doğru → depo kaydını düzelt" ile tek tıkla kapatılır. Özellik açıldığında raf kaydı olmayan ürünlerin satılabilir stoğu RAFSIZ olarak yazılır (init hareketi); yeni ürünlerde de ilk stok rafsız başlar.

Sipariş akışı: sipariş gelir → kataloğa bağlı her kaleme raf önerisi yazılır (items[].locations, status: suggested; strateji: most en çok stoklu raf, least en az stoklu, code raf sırası; rafın müsait adedi = raf stoğu − diğer açık siparişlerin önerileri; raflar yetmezse RAFSIZ) → irsaliyede görselin altına raf adresleri basılır (R00-001 ×1, R00-002 ×2) → depo toplar ve toplama onaylanır (POST /orders/{id}/pick; önerilen raftan ya da başka raftan, kısmi olabilir) → o rafın fiziksel stoğu düşer (pick hareketi). Paket kontrolde barkod okutulunca (POST /orders/pack-check) ve kargoya verildiğinde toplanmamışsa öneri otomatik uygulanır (ayarlar shelves_pick_on_check, shelves_auto_pick). Toplanmamış kalem iptal edilirse öneri silinir (raf değişmez); toplanmış kalem kargoya verilmeden iptal edilirse ürün alındığı rafa geri yazılır (cancel_restore; raf silinmişse RAFSIZ); kargoya verilmiş siparişin ürünü iade akışıyla döner: "stoğa girsin mi?" sorulur, sağlam adet POST /returns/{id}/restock ile seçilen rafa girer (return_in; raf verilmezse ürünün toplandığı raf, o da yoksa RAFSIZ).

Ayarlar #

Uç noktaAçıklama
GET /settings/featuresfeatures{shelves, shelves_strategy (most|least|code), shelves_auto_pick, shelves_pick_on_check, zero_on_reject, shelves_stock_sync}, strategies. shelves_stock_sync (v1.22.1, varsayılan açık): satılabilir stok yazımı depo kaydını da taşır.
PUT /settings/featuresAynı alanlar (yalnız gönderilenler değişir). Raflama ilk açılışta initialized{products, orders} döner. zero_on_reject: panel / API'den "İptal / tedarik edememe" (POST /orders/{id}/cancel) yapıldığında o ürünlerin satılabilir stoğu 0 yapılır ve tüm pazaryerlerine 0 gönderilir (olay red_sifirla, tip reset); müşteri / pazaryeri iptallerinde uygulanmaz.

Raflar #

Uç noktaAçıklama
GET /locations?active=1items[] {id, code, name, zone, note, is_active, sort, stats{products, quantity, pending_pick}}; unassigned: "RAFSIZ"
POST /locationsTek: {"code":"R00-001","name":"Depo A · 1. koridor","zone":"A","note":"","sort":10,"is_active":true} → location. Toplu: {"codes":["R00-001","R00-002"],"zone":"A"} → created, skipped[] (zaten var), errors[]. Kod: harf/rakamla başlar, A-Z 0-9 - _ . /, ≤40; küçük harf büyütülür, boşluk - olur; RAFSIZ ayrılmıştır.
GET /locations/{id|kod}Raf + stock[] {product_id, sku, barcode, title, quantity, pending_pick, available, sellable}
GET /locations/{id|kod}/stockYalnız içerik
PUT /locations/{id|kod}{"code","name","zone","note","sort","is_active"} (pasif raf öneriye girmez, stoğu görünür)
DELETE /locations/{id|kod}?move_to=RAFSIZ|R00-002Rafta stok varsa move_to zorunlu (içerik taşınır: transfer hareketi); yanıt moved. Bekleyen öneriler RAFSIZa düşer ve yeniden hesaplanır.

Raf stokları #

Uç noktaAçıklama
POST /stock/sync-physicalv1.22.1: depo (fiziksel) kaydını satılabilire eşitler — {"sku":"…","note":"…","expected_difference":4} ya da {"items":[…]}. Ürün kilitli, göreli hareketler (adjust, sellable_after: null, ref: "stok-yazimi-depo"). expected_difference (fiziksel − düşülmüş toplanacak − satılabilir) farklıysa changed: true, yazılmaz. Yanıt: {done, failed, results[{sku, ok, changed, difference, moved, left, before, after, movements[], product}]}
GET /stock/locations?sku=|product_id=Tek ürünün dökümü: product{sku, sellable, physical, unassigned, pending_pick, pending_deducted, difference, locations[] {location_id, code, name, quantity, pending_pick, available, is_active}}
GET /stock/locations?location=R00-001Raf içeriği
GET /stock/locations?unassigned=1&page=&size=Ürün × raf satırları (unassigned=1: yalnız RAFSIZ kovasındakiler) — "rafsız ürünleri filtreleyip raf tespit et". v1.23.11: her satırda barcode, title, image, unassigned, physical, shelves (ürünün şu anki rafları); &suggest=1 ile suggestion (önerilen raf)
GET /products?unassigned=1 · ?shelf=R00-001 · ?noshelf=1Katalog listesinde raf filtreleri; raflama açıkken her üründe shelves{physical, unassigned, pending_pick, pending_deducted, locations[] {code, quantity}} (detayda tam döküm + difference)
GET /stock/summarylocations, shelved_quantity, unassigned_quantity, unassigned_products, pending_pick, negative_rows

Hareketler #

Uç noktaAçıklama
POST /stock/movementsTek hareket ya da {"items":[…], "by":"Ali"} (≤500). Alanlar: type, sku (SKU ya da barkod) veya product_id, quantity, location / from_location / to_location (raf kodu ya da id; boş / RAFSIZ = rafsız), note, ref, allow_negative, sellable (varsayılan true). Yanıt — tek hareket: movements[], product{…döküm…} (201; reddedilirse 422 + message). Çok hareket (items): {"done":2,"failed":1,"results":[{"index":0,"ok":true,"error":null,"movements":[…],"product":{…}},…]} — index gönderilen sıradır; en az biri işlendiyse 201, hiçbiri işlenmediyse 422 (satır sebepleri yine results'ta). İstemci her satırın sonucunu results[index]'ten okumalıdır; aynı ürün birden çok satırda olabilir. Yetersiz raf stoğunda 422 ("R00-001 rafında yalnız 2 adet var (istenen 5) — önce Sayım yapın"). Raf adedi hiçbir koşulda eksiye düşmez: allow_negative artık eksiye düşürmez (v1.13.1), rafta gerçekten daha fazla varsa type=adjust (sayım) ile doğru adet girilir.
GET /stock/movements?sku=&product_id=&location=&type=receipt,pick&order_id=&since=&after_id=&limit=100items[] {id, sku, location, type, type_label, delta, quantity_after (rafta kalan), physical_after, sellable_after, group_id (transferin iki yüzü), ref_type (order|return|manual), ref_id, ref (sipariş no), order_item_id, note, by, source, created_at}, last_id (artımlı okuma: after_id)
typeEtkiNe zaman
receipt+ fiziksel (location), + satılabilirMal girişi (rafsız ya da doğrudan rafa)
assignRAFSIZ → to_locationRafsız ürünü rafa yerleştirme. Hedef raf to_location ile verilir; boşsa location kullanılır (hedef rafsız olamaz). from_location boşsa RAFSIZ varsayılır.
transferfrom_location → to_locationRaflar arası (iki hareket satırı, aynı group_id)
consume / loss− fiziksel (location zorunlu: hangi raftan), − satılabilirSarf, kayıp / fire
adjustrafın adedi = quantity; fark satılabilir stoğa da yansırSayım düzeltmesi
return_in+ fiziksel, + satılabilirİade / geri gelen ürün girişi (iade akışında POST /returns/{id}/restock location ile otomatik)
pick / unpick− / + fiziksel (satılabilir değişmez; sipariş zaten düşmüştü)Sipariş toplama / geri alma (/orders/{id}/pick)
cancel_restore+ alındığı raf (raf silinmişse RAFSIZ)Toplanmış kalem kargoya verilmeden iptal edildi
init+ RAFSIZÖzellik açılışı / yeni ürün ilk stoğu

Satılabilir stoğu değiştiren hareketler (receipt, consume, loss, adjust, return_in) ayrıca GET /events'e (type: movement, kaynak mal_girisi | sarf | kayip | sayim | raf_iade) düşer ve tüm pazaryerlerine yeni stok gönderilir. Her hareket stock.moved webhook olayı üretir.

Ürün nerede? · raf önerisi (v1.23.11) #

Uç noktaAçıklama
GET /stock/where?code=Kod / barkod (ya da adın bir kısmı) ile ürün: product{id, sku, barcode, title, image, sellable, physical, unassigned, pending_pick, difference, locations[] {location_id, code, name, zone, quantity, pending_pick, available, is_active}, last_movement{type, type_label, delta, location, created_at}}, suggestion. Tam eşleşme yoksa 404 + candidates[] {sku, barcode, title, image, sellable} (en çok 8; tek aday varsa doğrudan o ürün döner).
GET /stock/suggest?skus=A,B,CToplu raf önerisi (en çok 200): items{ "A": {code, location_id, reason, label, quantity} | null }

suggestion = ürünün konacağı rafın önerisi (mal girişi, iade girişi, rafsızdan yerleştirme): {code, location_id, reason, label, quantity, alternatives[]}. Sıra (reason): same_shelf ürünün stoklu durduğu raf (birden çoksa en çok adetli) → picked_shelf (iade kalemi) bu siparişte toplandığı raf → previous_shelf en son durduğu raf → variant aynı modelin (parent_sku) diğer çeşitlerinin rafı → category aynı kategorinin en yoğun rafı → none (code: null). Yalnız aktif raflar önerilir; label Türkçe gerekçedir.

Sipariş toplama #

Uç noktaAçıklama
GET /orders/{id}/pickpick{state: none|suggested|partial|picked, state_label, picked_at, picked_by, items[] {item_id, location, location_id, quantity, status: suggested|picked}}
POST /orders/{id}/pick{} → önerilen dağılım aynen uygulanır. {"items":[{"id":40 | "line_id":"555","location":"R00-002","quantity":2}],"by":"Ali","force":false} → belirtilen raflardan (önerilenden farklı olabilir; kısmi olabilir, kalan için öneri yenilenir). Raf stoğu yetersizse 422 (force:true ile raf eksiye düşer — sayım gerekir). Yanıt picked, state, warnings[], items[] {item_id, sku, location, quantity, shelf_after}, pick{…}; tüm kalemler toplanınca orders.picked_at / picked_by dolar, işlem geçmişine pick yazılır.
POST /orders/{id}/pick/suggestÖneriyi raf stoklarına göre yeniden hesapla
POST /orders/{id}/unpickToplamayı geri al (ürünler aynı raflara geri, öneri yenilenir)
POST /orders/pack-check {"code":"…","by":"Ali","pick":true}Paket kontrol; raflama açıksa pick (varsayılan: ayar) ile öneri "toplandı" sayılır → yanıtta pick{ok, picked, state, items[]}
GET /orders/{id}/packing-slipİrsaliyede kalem görselinin altında raf adresleri (✓ toplandı, Rafsız = raf belirsiz)

Raf ekranı (raf okut → ürün okut → adet gir → işlem) #

Depocunun raf ekranı: raf etiketi okutulur, rafın içindekiler listelenir, ürün okutulur ve adet girilip dört işlemden biri seçilir. Panelde Raflar, WooCommerce eklentisinde Pazaryeri Merkezi › Raflar bu uçları kullanır.

Uç noktaAçıklama
GET /stock/shelf?location=R00-001Raf + içindekiler: location{id, code, name, …}, items[] {product_id, sku, barcode, title, image, quantity, pending_pick, available, sellable}, totals{products, quantity}. location=RAFSIZ rafsız kovasını verir.
GET /stock/shelf/product?location=R00-001&code=868…Okutulan ürün: product{id, sku, barcode, title, image, on_shelf (bu rafta), unassigned (rafsız), physical, sellable, pending_pick (sipariş bekleyen), difference, locations[] (v1.23.11: ürünün bütün rafları), suggestion (önerilen raf)}
POST /stock/shelf{"location":"R00-001","code":"868…","quantity":3,"op":"put|receipt|remove|count|move|return_in","as":"loss","to_location":"R00-002","note":"","by":"Ali","allow_negative":false}. op: put = rafsız stoğu bu rafa yerleştir (satılabilir değişmez) · receipt = mal girişi (+ fiziksel, + satılabilir) · remove = çıkar (sarf; as:"loss" ile kayıp/fire) · count = sayım (rafın yeni adedi) · move = to_location rafına taşı · return_in = iade girişi. Yanıt: movements[], product{…döküm…}, shelf{…GET /stock/shelf…}, undo[] (geri alma için hareket id'leri), message. Raf stoğu yetmezse 422 + insufficient — raf eksiye düşmez (v1.13.1); rafta gerçekten daha fazla varsa op:"count" (sayım) ile doğru adet girilir.
POST /stock/shelf/undo{"movements":[56,57],"by":"Ali"} → son işlemin tersini yazar (aynı rafa geri). Transferin tek yüzü verilse de iki satır birden döner; aynı hareket ikinci kez geri alınamaz (ref_type='undo', ref_id=<hareket>). Yanıt {undone, movements[], product, shelf}.

Raf stoğu değiştiğinde (yerleştirme, mal girişi, transfer, sayım, iade girişi) o ürünü bekleyen açık siparişlerin rafsız kalmış raf önerileri kendiliğinden yeniden hesaplanır: rafsızken satılan ürün sonradan raflanınca sipariş yeni rafa bağlanır. Gerçek bir rafa bağlanmış öneriye dokunulmaz.

Depodan toplama (sipariş seçmeden — raf okut, ürün okut, adet gir) #

Depocunun ekranı: sipariş seçilmez. Okutulan adet, o ürünü bekleyen açık siparişlere en eskiden yeniye (FIFO) dağıtılır. Panelde Toplama menüsü, WooCommerce eklentisinde Pazaryeri Merkezi › Toplama bu uçları kullanır.

Uç noktaAçıklama
GET /stock/pick/queue?location=&code=&limit=100Toplanacaklar: items[] {product_id, sku, barcode, title, image, need (bekleyen adet), orders (kaç sipariş), oldest_order_date, shelves[] {location_id, code, name, quantity}}, total_need. location=R00-001 verilirse yalnız o rafta stoğu olanlar; code= verilirse tek ürün (SKU / barkod).
POST /stock/pick{"location":"R00-001","code":"8680000000013","quantity":2,"by":"Ali","force":false} → {picked, left (girilen adetten dağıtılamayan), need_after, product{…}, location{…}, rows[] {id, order_id, order_number, marketplace, item_id, quantity, shelf_after}, orders[], warnings[]}. Raf stoğu yetersizse 422 insufficient + on_shelf — raf eksiye düşmez (v1.13.1; force kaldırıldı): önce sayım yapılır. Kısmi toplama serbesttir: 2 adet bekleniyorken 1 girerseniz 1'i düşer, kalan ihtiyaç kuyrukta kalır. Tüm kalemleri toplanan sipariş picked olur.
POST /stock/pick/undo{"rows":[12,13],"by":"Ali"} → son işlemin satırlarını geri alır: adet aynı rafa geri yazılır, öneri yenilenir, sipariş picked işareti kalkar. Yanıt {undone, rows[], orders[]}.

POST /stock/pick her satır için pick hareketi (GET /stock/movements?type=pick), geri alma unpick hareketi yazar; ikisi de stock.moved webhook'u üretir.


Web sitesi siparişleri (marketplace=web) #

Kendi e-ticaret sitenizden (WooCommerce, OpenCart, Shopify eklentisi ya da özel yazılım) gelen siparişler pazaryeri gibi kaydedilir; paketleme, kargo, irsaliye, fatura, iade işlemlerinin tamamı panelden/API'den yapılır ve webhook ile sitenize geri bildirilir.

Uç noktaAçıklama
POST /orders/web{"external_id":"WC-1001","channel":"woocommerce","customer":"Ad Soyad","email":"","phone":"","address":"","city":"","district":"","bill_name":"","bill_company":"","bill_address":"","bill_city":"","bill_district":"","tax_number":"","tax_office":"","items":[{"sku":"KOLTUK-01","quantity":1,"price":4599.9},{"name":"Katalog dışı ürün","quantity":1,"price":99}],"total":4698.9,"currency":"TRY","payment_method":"kredi kartı","shipping_method":"Yurtiçi","order_date":"2026-09-12 10:00:00","note":"","deduct_stock":true,"cargo_account_id":null} → order (standart sipariş nesnesi: marketplace=web, order_number=external_id, channel, external_id, payment_method, shipping_method). Aynı external_id tekrar gelirse duplicate:true ile mevcut sipariş döner (eklenti tekrar deneyebilir). channel verilmezse API anahtarının kanalı yazılır.
GET /orders?marketplace=webWeb siparişleri (status, updated_since, q filtreleri aynı)
POST /orders/{id}/pack|ship|deliver|cancel|invoice, POST /orders/{id}/ship_createYerel işlemler: ship {"tracking_number":"","cargo_name":"Yurtiçi Kargo","tracking_url":""}; sonuç sitenize order.shipped vb. webhook'la gider

Sipariş ek maliyetleri ve gelirleri (v1.23.0 — web sitesinin bildiği kâr kalemleri) #

Siparişin kârına giren ama sipariş / pazaryeri verisinde olmayan tutarlar. Kaynak (source, ör. site) başına tutulur; kaynak her gönderdiğinde o kaynağın satırları tamamen yenilenir (listede olmayan tür silinir). Tutarlar KDV dahil; vat_rate > 0 ise içindeki KDV indirilecek KDV'ye (maliyette) ya da satış KDV'sine (gelirde) girer.

kindKâr hesabında
paymentÖdeme altyapısı komisyonu (iyzico / PayTR / Shopier / kapıda ödemede kargonun tahsilat bedeli). Kesinti kalemi olur (fee_lines[] içinde key:"payment_fee", keep:true, note); hakedişten (payout) önce düşülür. Bu satır varsa — 0 tutarlı olsa da (havale: komisyonsuz; kapıda ödeme henüz tahsil edilmedi) — web kanalının "Sanal POS / ödeme komisyonu" oran kalemi o siparişe uygulanmaz. İade / iptal ters kaydı bu satıra dokunmaz (ödeme kuruluşu komisyonu iade etmez; kaynak isterse 0 gönderir)
affiliateSatış ortaklığı komisyonu (nakit ödenen / ödenecek kısmı) — hakedişten sonra, vergi öncesi kârdan düşülür (other_costs, other_lines[])
marketing, other …Diğer sipariş maliyetleri — ortaklık gibi
shipping_incomeMüşteriden alınan kargo ücreti — ciroya eklenir (gross, sale_vat; income_lines[]). Web siparişinde kalemler yalnız ürünleri taşır: sipariş toplamı = kalemler + bu gelirler
fee_incomeKapıda ödeme bedeli (müşteriden) — ciroya eklenir
Uç noktaAçıklama
GET /orders/{id}/costscosts[] {id, kind, label, amount, vat_rate, vat, note, meta, source, updated_at}, kinds
PUT /orders/{id}/costs{"source":"site","external_id":"YK2609281234","costs":[{"kind":"payment","label":"Ödeme komisyonu","amount":43.82,"vat_rate":0,"note":"iyzico · iyzico'nun bildirdiği tutar"},{"kind":"affiliate","amount":85,"note":"ORTAK1"},{"kind":"shipping_income","amount":50,"vat_rate":20}]} → costs, changed, profit. costs:[] → kaynağın satırları silinir. Aynı tür iki kez → toplanır. external_id verilirse siparişin numarasıyla (external_id / order_number / remote_id, büyük-küçük harf duyarsız) eşleşmezse 409 mismatch — hiçbir şey yazılmaz
POST /orders/costsToplu (en çok 500): {"source":"site","orders":[{"order_id":12,"external_id":"YK2609281234","costs":[…]},{"external_id":"YK2609285678","costs":[…]}]} → updated, changed, missing[], errors[] {index, order_id, code, error}. Yalnız external_id verilirse sipariş numarasıyla bulunur (önce web siparişi). Kimlik + numara birlikte verilir ve eşleşmezse o satır yazılmaz, errors[] içinde code:"mismatch" — site eski bir kurulumun / başka hesabın sipariş kimliğini saklıyorsa (Pazaryeri Merkezi yeniden kuruldu) başka bir siparişin maliyetleri ezilmez

Dönem raporunda (GET /finance/summary): other_costs, other_costs_vat, other_costs_by_kind[] {kind, label, amount, vat, count}, income_by_kind[] {kind, label, amount, count} (iade / iptal payı düşülmüş), fee_lines[] içinde "Ödeme komisyonu (web sitesi)". Sipariş kârlılığında (/finance/orders) satırda payment_fee, other_costs; ürün kârlılığında ek maliyet kalemlere ciro payıyla dağıtılır.

Siparişi platformdan silme (iptal DEĞİL) #

DELETE /orders/{id}?purge=1 — sipariş hiç gelmemiş gibi silinir; pazaryerine hiçbir bildirim gönderilmez (iptal isteği yok). Yeniden test için ve yanlış düşen kayıtları temizlemek için.

Giden webhook'lar (sitenize POST) #

Uç noktaAçıklama
GET /webhooksUç noktalar (secret dahil)
POST /webhooks{"url":"https://siteniz.com/bayir-hook","events":["order.created","order.updated","order.shipped","order.delivered","order.cancelled","return.created","return.updated","question.created","invoice.created","stock.low","stock.changed","stock.moved","order.deleted","order.late_cancel"],"label":"Sitem","secret":"isteğe bağlı"} (events boş = tüm olaylar). stock.moved: raflama hareketi (mal girişi, yerleştirme, transfer, toplama, sarf, kayıp, sayım, iade girişi) — data{movement{…}, product{id, sku, sellable, physical}}. order.deleted: sipariş platformdan silindi (v1.13.1). order.late_cancel (v1.13.2): sipariş iptal / iade edildi ama kargo çoktan yola çıkmıştı, gönderi iptal edilemedi — data{order{…}, shipment{cargo_key, tracking_number, status}}; paketi durdurmak için kargo firmasıyla görüşülmelidir
PUT /webhooks/{id}{"url","events","label","is_active","secret"}
DELETE /webhooks/{id}Sil
POST /webhooks/{id}/testping olayı hemen gönderilir, sonuç döner
GET /webhooks/{id}/deliveries?limit=50Teslimat geçmişi (status: pending|sent|failed|skipped, attempts, last_code, last_error, next_at)
POST /webhooks/deliveries/{id}/retryTeslimatı yeniden kuyruğa al

Teslimat: POST {url} gövde {"event":"order.created","created_at":"…","account_id":1,"data":{"order_id":12,"order_number":"WC-1001","marketplace":"web","order":{…tam sipariş, items dahil…}}}; başlıklar Content-Type: application/json, X-Bayir-Event, X-Bayir-Delivery (teslimat id), X-Bayir-Signature: sha256=HMAC_SHA256(gövde, secret), User-Agent: {Marka}-Webhook/2.0 (marka adı Yönetim › Marka ve kimlik ekranından). 2xx dışı yanıt ya da zaman aşımında 60 sn, 5 dk, 15 dk, 1 sa, 2 sa, 6 sa, 12 sa, 24 sa sonra yeniden denenir (8 deneme); 50 ardışık hatada uç nokta pasife alınır. Aynı teslimat id tekrar gelebilir → sitenizde idempotent işleyin.

PHP doğrulama örneği:

$body = file_get_contents('php://input');
$sig  = $_SERVER['HTTP_X_BAYIR_SIGNATURE'] ?? '';
if (!hash_equals('sha256=' . hash_hmac('sha256', $body, $secret), $sig)) { http_response_code(401); exit; }
$evt = json_decode($body, true); // $evt['event'], $evt['data']['order']
http_response_code(200);

Hesap kullanıcıları ve roller #

Uç noktaAçıklama
GET /account/membersitems[] {id,email,name,role,role_label,is_active,last_login_at}, roles (rol → etiket), descriptions
POST /account/members{"email":"","password":"(≥8)","name":"","role":"admin|muhasebe|depo|destek|viewer"} → id
PUT /account/members/{id}{"role","name","is_active","password"}
DELETE /account/members/{id}Sil

Roller panel içindir; API anahtarları her zaman hesap sahibi yetkisiyle çalışır. Ek anahtarlar API sayfasından (kanal etiketiyle) üretilir.

Kârlılık: kesintiler, ürün maliyeti, desi tarifesi #

Uç noktaAçıklama
GET /orders/{id} → profit, GET /orders/{id}/profitKâr dökümü, tüm tutarlar KDV dahil: gross, sale_vat, commission (KDV hariç), commission_vat (komisyon tutarının İÇİNDEN ayrılan KDV — üstüne eklenmez), commission_incl (= pazaryerinin bildirdiği tutar) (+commission_source, commission_rate), fee_lines[] {key,label,amount,vat,total,refund,keep,note}, fees, fees_vat, fees_incl, stopaj, payout (hesaba geçecek), cargo, cargo_vat, cargo_source (table|manual|shipment|default), cogs, cogs_vat, cost_missing_qty, pretax_profit (vergi öncesi), deductible_vat, vat_payable, tax_base, tax_rate, profit_tax, tax_due (stopaj mahsuplu), profit (vergi sonrası net), margin, reversals[] (revenue_reversed, commission_refunded, fees_refunded, fees_kept, cargo_refunded, return_cargo, cogs_restocked, cogs_lost, pending_qty, pretax_impact, profit_impact), reversal_share, reversal_loss, final_figures, final_payout, final_pretax_profit, final_profit, other_costs, other_costs_vat, other_lines[] {kind,label,amount,vat,vat_rate,note,source}, income_lines[] …. ?profit=0 ile kapatılır.
GET|PUT /settings/tax{"rate":25,"enabled":true,"label":"Kurumlar vergisi"} — kâr vergisi oranı (şahıs: gelir vergisi dilimi). Vergi = (vergi öncesi kâr − ödenecek KDV + stopaj) × oran; stopaj mahsup edilir.
PUT /orders/{id}{"parcel_count":2,"desi":12.5,"slip_detailed":1,"slip_labels":null,"cargo_cost":89.9,"customer":"","phone":"","email":"","address":"","city":"","district":"","note":""} — slip_detailed/slip_labels: irsaliye dağılımı (null = otomatik 1 + kalanı); koli/desi girilince box_source=user olur, pazaryerine bildirilir (yanıtta box_info); çıktıda mp_parcel_count, mp_desi (pazaryerinin bildirdiği), box_source, slip_split — koli/desi girilince kargo maliyeti tarifeden yazılır (yanıtta cargo_cost {cost,source,detail}); cargo_cost elle girilirse tarife ezilmez, null gönderilince tarifeye dönülür; telefon "" ile silinir. Gönderilen alıcı alanları (customer, phone, email, address, city, district) kilitlenir: sonraki pazaryeri çekimleri bunları ezmez (user_fields). Fatura (alıcı) bilgisi (1.29.0): bill_name, bill_company, tax_number (10 hane VKN / 11 hane TCKN), tax_office, bill_address, bill_city, bill_district, bill_phone, bill_email — il + ilçe RESMİ adlara çevrilir ("Amasya Merkez" → Merkez; Logo İşbaşı yalnız resmi adı kabul eder); resmi ilçe değilse 422 (options = ilin resmi ilçeleri; force_address:true olduğu gibi kaydeder); gönderilen alanlar kilitlenir; yanıtta order.invoice_address (faturaya yazılacak geçerli adres, valid, suggest, districts), order.invoice (sipariş detayında faturanın durumu: {id,status,number,error,error_hint} ya da null; error_hint:"bill_address" = hata il / ilçe adından) ve notes
GET /address/provinces, GET /address/districts?city=Amasya&district=Amasya MerkezResmi il listesi; ilin resmi ilçeleri (+ verilen ilçenin resmi karşılığı resolved)
DELETE /orders/{id}Yalnız manuel gönderi (marketplace=manual): açık kargo gönderisi web servisten iptal edilir, düşülen stok geri verilir, kayıt silinir; pazaryerine bildirim yapılmaz. Kargoya verilmiş gönderi silinemez (422). Yanıt: {deleted, shipment_cancelled, stock_restored, parent_order_id}
POST /orders/pack-check{"code":"YRK123","by":"Ahmet"} — paket kontrol: paketteki barkod (kargo anahtarı / sipariş no / paket no / takip no) → sipariş pack_checked_at işaretlenir; irsaliyesi hiç basılmamışsa warnings[] (etiketsiz paket). POST /orders/slip-printed {ids[]} irsaliye basıldı işareti (panelden yazdır/PDF otomatik). Siparişte slip_printed_at, pack_checked_at.
GET|PUT /connections/{id}/feesKesinti kalemleri: {"fees":[{"key":"commission_vat","label":"Komisyon KDV’si","type":"pct_commission","value":20,"vat":0,"refund":true,"enabled":true},{"key":"service_fee","label":"Platform hizmet bedeli","type":"fixed_order","value":10.99,"vat":20,"refund":false},{"key":"stopaj","type":"pct_sale_exvat","value":1}]} ya da {"reset":true} (pazaryeri varsayılanları). Türler: pct_sale (KDV dahil satış %), pct_sale_exvat, pct_commission, fixed_order (sipariş başına ₺ KDV hariç), fixed_item. Yanıtta defaults (2026 güncel değerler) ve types.
GET|PUT /settings/web-feesWeb sitesi / manuel sipariş kesintileri (sanal POS vb.), aynı biçim
GET|PUT /settings/cargo-ratesDesi tarifesi: {"rows":[{"min":1,"max":10,"price":350},{"min":11,"max":30,"price":550},{"min":31,"max":0,"price":900}],"mode":"per_parcel|total","extra_parcel":0,"default_desi":0,"return_multiplier":1,"vat_included":true,"vat_rate":20} — max 0 = sınırsız; per_parcel: toplam desi kolilere bölünüp her koli tarifelenir; total: toplam desiye tek ücret + ek koli bedeli. Yanıtta examples.
POST /products / PUT /products/{sku} {"cost":2800}Ürün maliyeti (KDV dahil); ""/null kaldırır. GET /products çıktısında cost; sipariş kalemlerinde cost, vat_rate (sipariş anındaki anlık kayıt)
PUT /returns/{id}{"return_cargo_cost":120,"note":""} — dönüş kargo bedeli (boş = tarife × çarpan)
PUT /orders/{id}/items/{item_id}{"cost":600,"mode":"fill|order|product","vat_rate":20} — kalem maliyeti (KDV dahil). fill (varsayılan): ürün kartında maliyet boşsa oraya da yazar; product: her zaman günceller; order: yalnız bu sipariş; cost:null kaldırır. Yanıt: item, product_updated, profit
POST /orders/manual {"source_order_id":12,"cargo_cost":120,"items":[{"name":"Menteşe","quantity":2,"cost":45}],…}Ek gönderi: kargo (elle ya da desi tarifesi) + malzeme (kalemlerin birim maliyeti; yoksa katalog; material_cost elle toplam) ana siparişin kârından düşülür; GET /orders/{id}/profit → extras[] {order_id, order_number, reason, date, status, cargo, cargo_source, cargo_known, material, charge_material, material_override, cost_missing, items, lines[], total}, extra_cargo, extra_cogs; ek gönderide maliyeti girilmemiş kalem ana siparişin cost_missing_qty değerine de eklenir
GET /finance/summary?since&untilKDV dahil dönem raporu: revenue, sale_vat, net_sales, commission, commission_vat, commission_incl, fees, fees_vat, fees_incl, stopaj, payout, cargo (gidiş + iade dönüşü), cargo_vat, return_cargo, cogs, cogs_vat, cogs_lost, cancelled, returns_loss (iade/iptal kaybı), returns_impact, pretax_profit, deductible_vat, vat_payable, tax_base, profit_tax, tax_due, profit (vergi sonrası, giderler dahil), expenses, expenses_vat, operating_profit / pretax_net (= pretax_profit − expenses), tax_total, net (= operating_profit − vat_payable − tax_due; v1.23.0 öncesinde giderler vergiden sonra düşülüyordu), extras_count, extras_total, extra_cargo, extra_cogs, cargo_unknown, cost_missing, pending_restock, fee_lines[], expenses_by_category[] {category, label, amount, vat, count}, tax, checks[]; by_marketplace[] aynı kırılım; tam iade/iptal edilen siparişler orders ve revenue'ya girmez

Kâr formülü (KDV dahil): payout = gross − commission_incl − fees_incl − stopaj → pretax_profit = payout − other − cargo − cogs (v1.23.0: other = sipariş ek maliyetleri, ör. satış ortaklığı; gross web siparişinde müşteriden alınan kargo ücreti ve kapıda ödeme bedelini de içerir) → (dönem raporunda) operating_profit = pretax_profit − opex → vat_payable = sale_vat − (commission_vat + fees_vat + other_vat + cargo_vat + cogs_vat + opex_vat) → profit_tax = max(0, operating_profit − vat_payable + stopaj) × oran → profit = operating_profit − vat_payable − (profit_tax − stopaj). Siparişte opex 0'dır. İade: ciro/KDV geri, komisyon (+KDV) + refund işaretli kalemler + stopaj geri, gidiş + dönüş kargosu maliyet, stoğa giren ürün gider değil, hasarlı ürün maliyeti gider; iptalde her şey geri (sonuç 0).

Hız sınırı #

Her API anahtarı için dakikalık limit (varsayılan 300, API sayfasından anahtar başına ayarlanır); yanıtta X-RateLimit-Limit, aşımda 429 + Retry-After. Pazaryeri tarafına giden istekler bağlantı başına pencerelenir (ör. Trendyol 40 istek / 10 sn) — limit dolunca istek reddedilmez, kısa süre bekletilir.

Kural bazlı fiyatlama #

Uç noktaAçıklama
GET /connections/{id}/price-rulesbase_rule {price_mode, price_value}, rules[] (+summary)
PUT /connections/{id}/price-rules{"rules":[{"name":"Koltuklar","match":"category","value":"Koltuk","percent":18,"fixed":0,"round":"90","list_percent":0,"disabled":false},{"match":"price_between","min":0,"max":500,"percent":25,"round":"99"},{"match":"all","percent":10}]} — sıra = öncelik; ilk eşleşen kural uygulanır, hiçbiri eşleşmezse genel kural (price_mode/price_value). match: all, category (içeren), brand (tam), sku_prefix (SKU/barkod başlangıcı), sku_contains (SKU/ürün adı içeren), price_between (min–max, max 0 = sınırsız). round: none, int (yukarı tam sayı), 90, 99. list_percent > 0 ise ürünün liste fiyatı yoksa satış × (1+%) liste fiyatı olarak gönderilir. Pazaryerine özel fiyat (PUT /products/{sku}/prices) girildiyse kurallar atlanır. Kaydedince eşleşmeler yeniden gönderime alınır.

Gelen webhook'lar (pazaryeri → biz) #

Uç noktaAçıklama
GET /connections/{id}/inbound-webhookenabled, url, secret, basic_user (HB), last_received_at, count, recent[]
POST /connections/{id}/inbound-webhook{"reset":false,"register":true,"lax":false,"unregister":false} — adres/anahtar üretir; register Trendyol'a kaydeder (registered {ok,error,id}); lax başlık doğrulamasını kapatır (yalnız URL token'ı); unregister Trendyol'daki eski kayıtları siler
DELETE /connections/{id}/inbound-webhookKapatır; ?unregister=1 (ya da gövdede) Trendyol'daki kayıtları da siler (unregistered {items[], deleted})

Adres {base}/hook/trendyol/{token} ya da {base}/hook/hepsiburada/{token}; Hepsiburada adresi Basic auth (kullanıcı = token, şifre = secret) ile HB destek ekibine "base URL" olarak verilir.

Bildirimler #

Uç noktaAçıklama
GET /settings/notifications · PUT /settings/notificationsBildirim tercihleri: types{} ve preferences{order.new: true, …}; PUT gövdesi {"order.new": false, …}
GET /settings/stock-webhook · PUT /settings/stock-webhookEski tip stok olayı webhook'u (tek adres): {"url": "https://…", "regenerate_secret": true} → url, secret (yeni entegrasyonlar için /webhooks kullanın)
GET /notifications?limit=50unread, items[] {id,type,title,body,url,read,data,created_at} — türler: order.new, order.status, return.new, return.restock (v1.23.11: stok kararı hatırlatması, günde en fazla bir, 09–21; url İadeler › Stok kararı bekleyen), question.new, cargo.tracking, cargo.delivered, invoice.error
POST /notifications/read {"id":12} (id yoksa tümü)Okundu işaretle

Tarayıcı push bildirimleri panelden (zil menüsü) açılır; olaylar ayrıca GET /orders?updated_since= ve webhook ile izlenebilir.


Müşteri soruları #

Uç noktaAçıklama
GET /questions?status=waiting|answered|closed|all&unread=1&from=operator|customer&page=&size=total, items[] — id, marketplace, remote_id, product_name, product_code, question, customer, answer, status, answer_state, answer_error, answer_to, asked_at, expires_at, answered_at, unread, read_at, reply_needed, last_from, last_in_at + görüşme alanları (aşağıda). v1.26.0: unread=1 okunmamış gelen mesajlar, from=operator son mesajı Koçtaş operatörü yazmış görüşmeler; bu süzgeçlerle status varsayılanı all olur. Sıralama son gelen mesaja göre
POST /questions/{id}/answer {"text":"…","to":"customer|operator|both"}Cevap sıraya alınır, işçi pazaryerine iletir (answer_state: queued → sent ya da failed; answer_error: pazaryerinin hata metni, Türkçe açıklamasıyla). to yalnızca Koçtaş (Mirakl) için; boşsa son mesajı yazan taraf seçilir (v1.23.10). Cevaplamak soruyu okundu yapar. 409 already_answered / question_closed: tek cevaplı pazaryerinde (Trendyol, Hepsiburada, N11, İdefix, Çiçeksepeti) soru zaten cevaplanmış / kapanmışsa ikinci cevap gönderilmez (Koçtaş görüşmelerinde koruma yok)
POST /questions/{id}/readv1.26.0: soru / görüşme okundu ({"ok":true,"read_at":"…"}) — okunmamış sayacından (GET /dashboard → questions_unread) düşer. id bizim numaramız ya da ?marketplace= ile pazaryeri kimliği

Okunmamış mesajlar (v1.26.0): her yeni GELEN mesaj (müşteri ya da Koçtaş operatörü — cevap gereksin gerekmesin, operatörün "bilgi" notu dahil) last_in_at yazar, read_at boşalır (unread: true), question.new bildirimi + question.created webhook'u üretir. reply_needed (yalnız Koçtaş): pazaryeri mağaza cevabı bekliyor mu (false = bilgi notu; status o zaman answered kalır, soru "Cevap bekleyen"de değil "Okunmamış" / "Koçtaş operatörü"nde görünür). last_from: son mesajı kim yazdı (customer | operator | shop). Diğer pazaryerlerinde yeni soru last_in_at = asked_at ile okunmamış başlar.

Pazaryerinde zaten cevaplanmış (v1.26.0): answer_state: "remote" — soru pazaryerinde (panel / uygulama / başka araç) cevaplanmıştı; pazaryerinin cevabı answera çekildi, answered_at pazaryerinin tarihi, answer_error boş. Hata değildir; gri not olarak gösterin. Bizim gönderemediğimiz metin Kayıtlar'da (answers kanalı) durur. Cevap gönderimi "zaten cevaplandı" hatası alınca (Trendyol business.rule.question.has.already.answered) ya da işçinin uzlaştırma adımı (takılı / 13 günden eski bekleyen sorular, 6 saatte bir, tek soru sorgusu: Trendyol GET …/questions/{id}, İdefix GET …/question/{id}, N11 GetProductQuestionDetail) pazaryerinin durumunu alır. Süresi dolan / reddedilen sorular status: closed olur.

Çiçeksepeti sipariş sohbetleri (v1.26.0): Çiçeksepeti'nin "satıcıya sor" sipariş soruları (GET /api/v1/chats) da soru listesine gelir: remote_id = oc:{chatId}, product_name = "Sipariş #… · ürün adı", customer = "Müşteri" ya da "Çiçeksepeti müşteri temsilcisi" (chatType 2). Görüşme alanları Koçtaş'taki gibi doludur (from, order_number/order_id, messages[], reply_to, recipients); cevap POST /questions/{id}/answer {"text":…} ile sohbete mesaj olarak gider (dosya eki henüz desteklenmez). Sohbet kapanmışsa (isActive=false) kayıt closed olur. Çiçeksepeti ürün sorusunda cevap türü: to=customer → cevap yalnız soran müşteriye gider, sitede yayınlanmaz (Çiçeksepeti branchActionId 2, alt tür "Diğer"); to boş → soru ve cevap sitede yayınlanır (1). "Uygunsuz içerik" (3) ve "başka satıcıya ait soru" (4) işlemleri Çiçeksepeti satıcı panelinden yapılır.

Koçtaş (Mirakl) görüşmeleri (v1.23.10): Koçtaş'ta "soru" bir görüşmedir — müşteri ve Koçtaş operatörü aynı konuya defalarca yazabilir. Konu başına tek kayıt vardır: question son gelen (müşteri / operatör) mesaj, answer mağazanın son mesajı. Görüşmeye yeni mesaj gelince kayıt yeniden status: waiting olur (önceki cevabımız gönderilmişse answer_state sıfırlanır) ve question.new bildirimi / question.created webhook'u yeniden gelir (followup: true). Ek alanlar (diğer pazaryerlerinde null / boş):

AlanAçıklama
fromSon gelen mesajı kim yazdı: operator (Koçtaş ekibi) | customer
customer_visibleSon gelen mesaj müşteriye görünüyor mu — operatörün yalnız mağazaya yazdığı not için false ("Müşteriye görünmez")
order_number, order_idSipariş görüşmesiyse pazaryeri sipariş numarası ve bu hesaptaki sipariş kaydı (varsa)
reply_toVarsayılan cevap alıcısı: son mesajı yazan (operator | customer)
recipientsCevap verilebilecek taraflar (konunun katılımcıları). Müşterinin katılımcı olmadığı operatör konusunda yalnız ["operator"]; müşteriye gönderim Koçtaş'ta reddedilir
messages[]Konuşma, eskiden yeniye (son 30): {from: customer|operator|shop, name, to[], customer_visible, body, date, attachments}. Gönderdiğimiz cevap, sorular yeniden çekilmeden konuşmaya eklenir
answer_toSon cevabımızın gerçekte gittiği taraf: customer | operator | both

Bildirim / webhook verisi (question.new → question.created): marketplace, question, product, question_id + Koçtaş'ta from, order_number, customer_visible, yeni mesajda followup: true. Bildirim başlığı: "Koçtaş operatör mesajı · #sipariş", "Koçtaş müşteriden yeni mesaj", "Koçtaş yeni müşteri sorusu".

Soru desteği: Trendyol, Hepsiburada, N11, Çiçeksepeti, İdefix, Koçtaş (Mirakl mesajları). Pazarama ve PttAVM API'lerinde soru uç noktası yoktur.


Stok olayları (çift yönlü senkron) #

Pazaryerinde sipariş oluşunca stok düşülür, diğer pazaryerlerine yeni stok gönderilir ve üyeye olay üretilir.

Uç noktaAçıklama
GET /events?after_id=0&unacked=1&limit=200events[] {id,type,source,sku,delta,stock_after,marketplace,order_number,acked,created_at}, last_id, has_more. type: order (pazaryeri / web siparişi düşümü) · cancel (iptal → stok geri) · return (iade girişi) · movement (raflama: mal_girisi, sarf, kayip, sayim, raf_iade) · reset (red_sifirla: tedarik edememe iptalinde stok sıfırlandı) · adjust (site: sitenizin stock_delta ile gönderdiği fark; onaylı gelir, order_number = gönderdiğiniz ref). marketplace alanı ham kaynağı verir (trendyol, trendyol_iptal, sarf …)
POST /events/ack {"up_to_id":123} veya {"ids":[…]}Sitenizde stoğu işledikten sonra onay

Webhook alternatifi: Ayarlar › Webhook adresi. Olaylar X-Bayir-Signature: sha256=HMAC-SHA256(gövde, gizli anahtar) ile POST edilir; 2xx yanıt onay sayılır, başarısızlar artan aralıklarla yeniden denenir.

Satılabilir stoğu değiştiren her şey buradan akar: sipariş düşümleri, iptal / iade geri girişleri, raflama hareketleri (mal girişi, sarf, kayıp, sayım) ve "red → stok sıfırlama". Fiziksel (raf) hareketlerinin tamamı ise GET /stock/movements ve stock.moved webhook olayında.


WordPress eklentisi güncellemesi #

WooCommerce eklentisi kendi güncellemesini bu iki uçtan alır; WordPress'in Eklentiler sayfasında "Güncelleme var" uyarısı çıkar ve tek tıkla kurulur. Paketi WordPress.org değil, bu sunucu dağıtır.

GET /plugin/wordpress — yayındaki sürüm #

{"success":true,"plugin":{
  "slug":"bayir-pazaryeri","name":"Pazaryeri Merkezi","available":true,
  "version":"1.9.1","requires":"6.0","tested":"6.7","requires_php":"7.4","requires_wc":"7.0",
  "download_url":"https://app.bayircommunity.com/api/v1/plugin/wordpress/download",
  "changelog":"* ...","released_at":"2026-09-19 23:03:21",
  "sha256":"60db37d3…","size":375055,
  "homepage":"https://app.bayircommunity.com/docs","author":"Platformunuzun adı"}}

Yayında sürüm yoksa available:false ve version:"0.0.0" döner (kurulu her sürüm bundan büyüktür, yani güncelleme uyarısı çıkmaz).

GET /plugin/wordpress/download — paketi indir #

Content-Type: application/zip, Content-Disposition: attachment; filename="bayir-pazaryeri-1.9.1.zip", X-Checksum-SHA256 ve X-Plugin-Version başlıklarıyla döner. API anahtarı zorunludur; anahtarsız istek 401 alır. Sunucu, dosyayı göndermeden önce SHA-256 özetini yeniden hesaplar; tutmazsa 409 (corrupt_package) döner. Her başarılı indirme sayaca işlenir.

Her iki uç da salt okuma olduğu için aboneliği bitmiş hesaplarda da çalışır: güvenlik yaması kimseye kapatılmaz (yazma işlemleri zaten 402 ile kilitlidir).

Sürümleri panelden yönetirsiniz: Yönetim › WordPress eklentisi (?p=wpplugin).


Eski eklenti uyumluluğu #

/{pazaryeri}/status, /{pazaryeri}/sync/stock, /{pazaryeri}/questions, /{pazaryeri}/orders, /{pazaryeri}/returns (trendyol, hepsiburada, n11, pazarama, ciceksepeti, idefix, koctas, pttavm).


Entegrasyon örnekleri #

Kendi e-ticaret yazılımı (PHP) #

$api = fn(string $m, string $p, array $b = []) => json_decode(file_get_contents('https://app.bayircommunity.com/api/v1' . $p, false, stream_context_create(['http' => [
    'method' => $m, 'header' => "X-Api-Key: bc_live_XXX\r\nContent-Type: application/json\r\n", 'content' => $b ? json_encode($b) : null, 'ignore_errors' => true]])), true);

$api('POST', '/stock', ['items' => [['sku' => 'KOLTUK-01', 'stock' => 12, 'price' => 4599.90]]]);
$new = $api('GET', '/orders?status=new&include=items');
$api('POST', '/orders/15/shipment', ['account_id' => 1, 'parcel_count' => 2]);   // kendi Yurtiçi hesabınızla gönderi
file_put_contents('irsaliye.pdf', file_get_contents('https://app.bayircommunity.com/api/v1/orders/15/packing-slip.pdf', false, stream_context_create(['http' => ['header' => "X-Api-Key: bc_live_XXX\r\n"]])));
$api('POST', '/orders/16/ship', ['cargo_company' => 'Yurtiçi', 'tracking_number' => '1234567890']); // pazaryeri anlaşmalı kargo
$ev = $api('GET', '/events?unacked=1');           // pazaryeri satışlarını kendi stoğunuza uygulayın
$api('POST', '/events/ack', ['up_to_id' => $ev['last_id']]);

WooCommerce eklentisi (hazır): Pazaryeri Merkezi #

bayir-pazaryeri.zip — WordPress › Eklentiler › Yeni ekle › Eklenti yükle. Kurulunca Pazaryeri Merkezi › Ayarlar'a API anahtarı girilir; eklenti bağlantıyı test eder, webhook'u kaydeder (POST /webhooks tüm olaylar + PUT /settings/stock-webhook) ve ilk senkronu başlatır. v1.5.1: Sipariş kutusunda "Siparişi platformdan sil" (iptal değil — pazaryerine bildirilmez; stok ve raf adedi geri yüklenir, WooCommerce siparişi çöpe taşınır, isteğe bağlı "bir daha çekilmesin"). Raf ekranlarında "yine de düş" kaldırıldı (raf eksiye düşmez; yetersizse Sayım önerilir) ve eksiye düşmüş kayıtlar için Sıfırla düğmesi. Sipariş listesinde Trendyol "Onay bekliyor — işlem yapmayın" uyarısı.

v1.5.0: Raflar sayfası Toplama ile aynı mantıkta yeniden yazıldı (telefon için): raf okut → ürün okut → adet gir → Rafa koy / Mal girişi / Çıkar / Sayım; rafın içindekiler görselli listede, satırdan ürün seçme ve başka rafa taşı, her işlemde Geri al. Raf seçicilerinde ve ürün alanında kamera. Toplu stok işlemleri aynı telefon düzenine geçti (büyük alanlar, kamera, raf etiketini okutup raf seçme, satırlar kart görünümü). Düzeltmeler: "Rafa yerleştir" seçilince hedef raf alanının gizlenmesi (hareket hiç işlenmiyordu).

v1.4.0: Toplama ve Paket kontrol ayrı menüler oldu (telefon için tek sütun ekran). Toplama sipariş seçmez: raf okut → ürün okut → adet gir (GET /stock/pick/queue, POST /stock/pick, POST /stock/pick/undo); kısmi toplama, satır satır geri alma, raf seçili kalır. Paket kontrol artık toplama yapmaz (pack-check pick:false; eski davranış Ayarlar › Özellikler'den açılabilir). Sipariş ekranındaki toplama kutusu kaldırıldı, yerine durum rozeti + Toplama bağlantısı kondu. Ürün detayında 🏷 Barkod etiketi: adet + düzen seçip önizleme / yazdırma / PDF (GET /products/{sku}/labels(.pdf)).

v1.3.0: Siparişler sayfası panelin sipariş ekranıyla aynı güçte — kontrol kartları (hazırlanacak, ⚠ etiketi basılmamış, paketi kontrol edilmemiş, maliyeti eksik, kargoda), pazaryeri / tarih / arama / paket kontrol filtreleri, satıra tıklayınca sipariş içeriği (ürünler, kodlar, adet, fiyat, adet başına maliyet), teslimat ve fatura adresi, raftan toplama ve tüm işlem düğmeleri; satır içinde koli / desi ve irsaliye dağılımı (PUT /orders/{id}), barkodla paket kontrol (POST /orders/pack-check). Ürünler sayfasında pazaryerine özel kod / fiyat düzenleme (PUT /products/{sku}/links, PUT /products/{sku}/prices, POST /products/{sku}/resend). Paket kontrol, toplu stok işlemleri ve aramalarda kamerayla barkod okuma (harici kütüphane yok; BarcodeDetector yoksa yerleşik EAN-13 / EAN-8 / UPC-A / Code-128 çözücüsü). İrsaliyeler profile=key ile basılır: her site kendi logosuyla.

v1.1.0'dan itibaren panelde ne varsa eklentide de var ve hiçbir form sayfayı yenilemez (AJAX): Ayarlar sekmeleri — Bağlantı, Senkron, Siparişler & müşteriler, Gönderici & irsaliye (siteye özel profil + "WooCommerce'den doldur" + ortam kütüphanesinden logo), Kesintiler & vergi (/settings/tax, /settings/web-fees, /connections/{id}/fees), Kargo & desi (/settings/cargo-rates, /cargo/carriers, /cargo/accounts), e-Fatura & e-posta (/settings/invoicing + test düğmeleri), Özellikler & bildirimler, Webhook; ayrı sayfalar — Pazaryerleri (bağlantı ekle/düzenle/test/çek/teşhis/sil), Faturalar (/invoices, tekrar dene / iptal / e-postala + fatura kesilmemiş siparişlere toplu e-Fatura), Kargo gönderileri (/shipments, sorgula / iptal), Siparişler (toplu e-Fatura, toplu irsaliye, paketle, kargo gönderisi, teslim — POST /orders/bulk, GET /orders/packing-slips) ve WooCommerce sipariş listesi toplu işlemleri. Bu API'nin tamamını kullanır: ürün / stok / fiyat / içerik gönderimi (POST /products, WooCommerce'te stok değişince anında), pazaryeri siparişlerini WooCommerce siparişi olarak kaydetme (GET /orders, webhook), müşteri kaydı (isteğe bağlı, pazaryeri adıyla), sipariş işlemleri (paketle / kargo bildir / teslim / iptal / fatura / gönderi / irsaliye / paket kontrol / raftan toplama), site siparişlerini POST /orders/web ile gönderme, stok olayları (GET /events + POST /events/ack, stock.changed), raflama (raflar, mal girişi, rafa yerleştirme, transfer, sarf, kayıp, sayım, iade girişi; ürün sayfasında raf dağılımı ve tüm hareket geçmişi), iadeler (karar + kalem bazlı stoğa alma, raf seçimli), sorular (cevaplama), finans (dönem özeti, sipariş kârlılığı, giderler — WordPress veritabanında saklanır). Kurulum adımları eklenti içindeki KURULUM.md dosyasındadır.

Kendi eklentiniz (OpenCart / Shopify / özel yazılım) #

Eklenti tarafında yapılacaklar: ürün/stok değişince POST /stock (veya POST /products); sitede sipariş oluşunca POST /orders/web (external_id = site sipariş no); sipariş durumu/takip numarası için sitenin bir adresine giden webhook (POST /webhooks → order.shipped, order.delivered, order.cancelled) ya da periyodik GET /orders?updated_since=; pazaryeri satışlarının site stoğuna yansıması için GET /events → mağaza stoğu güncelleme → POST /events/ack (ya da stock.changed webhook'u). Her eklenti için API sayfasından kanal etiketli ayrı anahtar üretin.

© 2026 BayirCommunity Pazaryeri Merkezi · Entegratör ve alt yapı: Bayır Community