Geliştiriciler

Webhook'lar

Bir sipariş ilerlediği ya da bir ilan değiştiği anda sunucunuza bir olay POST ederiz; böylece hiç sorgulamanız gerekmez. İmzalı, yaklaşık bir gün boyunca yeniden denenen ve API'nin her rotasında aynı.
Bu sayfada
  1. 1Uç nokta kurun
  2. 2Olay
  3. 3Olaylar
  4. 4İmzalar
  5. 5Bir teslimatı doğrulayın
  6. 6Yeniden denemeler ve sıra

Uç nokta kurun

  1. Sunucunuza ham gövdeyi okuyan ve 10 saniye içinde 2xx yanıtı veren bir https rotası ekleyin. İşi yanıt verdikten sonra yapın.
  2. Uç noktayı API ile oluşturun ya da ekibimizden isteyin. Döndürdüğü whsec_ gizli anahtarını saklayın: yalnızca bir kez gösterilir.
  3. Her isteği doğrulayın (aşağıda), ardından olay id'sine göre tekilleştirin.
  4. İşlediğiniz her tür için kendinize bir test olayı gönderin.

Olay

Her olayın zarfı aynıdır. data, türün kendi alanlarını içerir.

idstring
evt_ ile başlar. Her yeniden denemede ve webhook-id başlığında aynıdır.
typestring
Aşağıdaki olaylardan biri.
api_versionstring
data'nın yazıldığı sürüm: uç noktanızınki.
created_atstring
Ne zaman olduğu; bu, onu almanızdan önce olabilir.
testboolean
Test olayları için true.
dataobject
Tam nesneyi çekmek için id'ler ve neyin değiştiği.
Bir teslimat
POST /hooks/ninjabuy HTTP/1.1
Host: acme-goods.com
Content-Type: application/json
User-Agent: NinjaBuy-Webhooks/1.0
webhook-id: evt_4m2x
webhook-timestamp: 1793685600
webhook-signature: v1,K5oZfzN95Z9UVu1EsfQmfVNQhnkZ2pj9o9NDN/H/pI4=

{
  "id": "evt_4m2x",
  "type": "order.shipped",
  "api_version": "2026-11",
  "created_at": "2026-11-03T06:00:00Z",
  "test": false,
  "data": {
    "order": "ord_3n7q",
    "external_id": "1012",
    "shipment": "shp_5r8w",
    "carrier": "YunExpress",
    "tracking_number": "YT2630812345678",
    "tracking_url": "https://t.17track.net/en#nums=YT2630812345678",
    "shipping_charged": { "amount": "134.52", "currency": "CNY" },
    "pushed_to_channel": true
  }
}

Olaylar

order.created

Shopify mağazanızdan ya da API'den bize bir sipariş ulaştı. Ödenmiş ya da awaiting_payment.

order.created
{
  "id": "evt_1a7c",
  "type": "order.created",
  "api_version": "2026-11",
  "created_at": "2026-11-01T09:14:02Z",
  "test": false,
  "data": {
    "order": "ord_3n7q",
    "external_id": "1012",
    "source": "shopify",
    "status": "buying",
    "payment_status": "paid",
    "lines": [
      {
        "line": "lin_9a2c",
        "variant": "var_41hz",
        "sku": "5187209554",
        "quantity": 1
      }
    ]
  }
}

order.paid

Bir sipariş bakiyenizden ödendi. Bakiye yüklemesi bekleyen siparişler için de tetiklenir.

order.paid
{
  "id": "evt_1a9f",
  "type": "order.paid",
  "api_version": "2026-11",
  "created_at": "2026-11-01T11:02:40Z",
  "test": false,
  "data": {
    "order": "ord_3n8a",
    "external_id": "1013",
    "amount": { "amount": "57.00", "currency": "CNY" },
    "paid_from": "balance",
    "was_awaiting_payment": true
  }
}

order.bought

Satıcıya ödeme yaptık. Satırlar depomuza ulaşana kadar with_seller durumundadır.

order.bought
{
  "id": "evt_2c4e",
  "type": "order.bought",
  "api_version": "2026-11",
  "created_at": "2026-11-01T13:30:05Z",
  "test": false,
  "data": {
    "order": "ord_3n7q",
    "external_id": "1012",
    "lines": [
      {
        "line": "lin_9a2c",
        "sku": "5187209554",
        "quantity": 1,
        "status": "with_seller"
      }
    ]
  }
}

order.checked

Ürünler depomuzda, kontrol edildi ve fotoğraflandı. Sırada paketleme var.

order.checked
{
  "id": "evt_9w1c",
  "type": "order.checked",
  "api_version": "2026-11",
  "created_at": "2026-11-02T03:20:11Z",
  "test": false,
  "data": {
    "order": "ord_3n7q",
    "external_id": "1012",
    "fulfillment_order": "fo_7k2m",
    "lines": [
      {
        "line": "lin_9a2c",
        "qc": "passed",
        "photos": [
          "https://media.ninjabuy.com/qc/ord_3n7q/1.webp",
          "https://media.ninjabuy.com/qc/ord_3n7q/2.webp"
        ]
      }
    ]
  }
}

order.shipped

Bir paket takip numarasıyla yola çıktı; kargo ücreti kesinleşti. Siparişin geldiği mağazada da takip bilgisi var.

order.shipped
{
  "id": "evt_4m2x",
  "type": "order.shipped",
  "api_version": "2026-11",
  "created_at": "2026-11-03T06:00:00Z",
  "test": false,
  "data": {
    "order": "ord_3n7q",
    "external_id": "1012",
    "shipment": "shp_5r8w",
    "carrier": "YunExpress",
    "tracking_number": "YT2630812345678",
    "tracking_url": "https://t.17track.net/en#nums=YT2630812345678",
    "shipping_charged": { "amount": "134.52", "currency": "CNY" },
    "pushed_to_channel": true
  }
}

product.cost_changed

Bir satıcı fiyatı değiştirdi ve senkronizasyon kuralınızın yaptığı: fiyat güncelleme, duraklatma ya da bildirim.

product.cost_changed
{
  "id": "evt_8q0d",
  "type": "product.cost_changed",
  "api_version": "2026-11",
  "created_at": "2026-11-04T02:10:00Z",
  "test": false,
  "data": {
    "product": "prd_1x0a",
    "variant": "var_2b7k",
    "sku": "4410923871",
    "cost": {
      "from": { "amount": "42.00", "currency": "CNY" },
      "to": { "amount": "48.00", "currency": "CNY" }
    },
    "action": "repriced",
    "price": {
      "from": { "amount": "18.99", "currency": "USD" },
      "to": { "amount": "20.99", "currency": "USD" }
    },
    "rule": "rule_default"
  }
}

product.out_of_stock

Satıcının bir varyantı tükendi ve rafınızda hiç yok: kanallarınızda 0 yapıyoruz.

product.out_of_stock
{
  "id": "evt_2b9n",
  "type": "product.out_of_stock",
  "api_version": "2026-11",
  "created_at": "2026-11-04T02:11:30Z",
  "test": false,
  "data": {
    "product": "prd_8f2k",
    "variant": "var_41j0",
    "sku": "5187209555",
    "warehouse_on_hand": 0,
    "channels_updated": [
      {
        "channel": "shopify",
        "shop": "acme-goods.myshopify.com",
        "available": 0
      }
    ]
  }
}

qc.issue

Kontrolümüz bir üründe sorun buldu: yanlış renk ya da beden, hasar, eksik parça. respond_by'a kadar seçim yapın; yanıt gelmezse bekletir ve size yazarız.

qc.issue
{
  "id": "evt_6c3h",
  "type": "qc.issue",
  "api_version": "2026-11",
  "created_at": "2026-11-02T03:20:11Z",
  "test": false,
  "data": {
    "order": "ord_3n7q",
    "external_id": "1012",
    "fulfillment_order": "fo_7k2m",
    "line": "lin_9a2c",
    "sku": "5187209554",
    "issue": "wrong_color",
    "note": "Received grey, ordered black.",
    "photos": ["https://media.ninjabuy.com/qc/ord_3n7q/3.webp"],
    "choices": ["ship_anyway", "exchange", "refund"],
    "respond_by": "2026-11-05T03:20:11Z"
  }
}

İmzalar

Teslimatlar Standard Webhooks yöntemiyle imzalanır; böylece zaten kullanıyor olabileceğiniz bir kütüphane onları doğrular. Her teslimatla üç başlık gelir:

BaşlıkNe içerir
webhook-idOlay id'si.
webhook-timestampBu denemeyi ne zaman gönderdiğimiz, Unix saniyesi cinsinden.
webhook-signaturev1, ardından virgül ve gizli anahtarınızla id.timestamp.body'nin base64 HMAC-SHA256 değeri. Yenileme sırasında boşlukla ayrılmış iki tane.

Anahtar, whsec_ sonrasındaki gizli değerinizin base64 ile çözülmüş hâlidir. Ham gövdeyi tam geldiği gibi imzalayın; ele geçirilmiş bir isteğin yeniden oynatılamaması için beş dakikadan fazla sapan zaman damgasını reddedin.

Bir teslimatı doğrulayın

standardwebhooks kütüphanesiyle ya da kendi yazacağınız birkaç satırla:

// npm install standardwebhooks express
import express from "express"
import { Webhook } from "standardwebhooks"

const webhook = new Webhook(process.env.NINJABUY_WEBHOOK_SECRET) // whsec_...
const app = express()

// The raw body: a parsed and re-serialised body no longer matches.
app.post("/hooks/ninjabuy", express.raw({ type: "application/json" }), (req, res) => {
  let event
  try {
    event = webhook.verify(req.body.toString("utf8"), req.headers)
  } catch {
    return res.sendStatus(400)
  }
  res.sendStatus(204) // answer first, then do the work
  queue.push(event) // deduplicate on event.id: a retry repeats it
})

Yeniden denemeler ve sıra

10 saniye içinde 2xx dışındaki her şey başarısızlıktır ve her seferinde aynı webhook-id, yeni bir zaman damgası ve imzayla yeniden deneriz:

DenemeBir öncekinden sonra
1Hemen
25 saniye
35 dakika
430 dakika
52 saat
65 saat
710 saat
810 saat, son deneme
  • Son denemeden sonra teslimat başarısız olur. Teslimat listesinden yeniden gönderin.
  • Beş gün boyunca tüm teslimatları başarısız olan bir uç nokta, size e-posta gönderildikten sonra devre dışı bırakılır. Yeniden etkinleştirmek, son üç günde kaçırdıklarını gönderir.
  • Olaylar iki kez ve sırasız gelebilir. id'ye göre tekilleştirin; sıra önemliyse nesneyi çekin ve olayınkine değil onun durumuna güvenin.