Ana İçeriğe Atla

Geliştirici dokümanı

Kataloğunuzu kendi sisteminize bağlayın

REST API ile ürün, stok ve fiyatlarınızı ERP veya muhasebe yazılımınızdan güncelleyin; yeni siparişleri imzalı webhook'larla anında alın.

Başlangıç

  1. Firma panelinde API ve Webhook sayfasını açın.
  2. Anahtara bir ad verin (ör. “ERP entegrasyonu”) ve yalnızca gereken yetkileri seçin.
  3. Oluşan 360k_live_… anahtarını hemen kopyalayın. Anahtarın tamamı yalnızca bir kez gösterilir; sistemde yalnızca özeti saklanır.
  4. İsteklerinizi aşağıdaki adrese gönderin. Tüm istek ve yanıtlar JSON ve UTF-8'dir.

Temel adres

https://api.360katalog.com/api/v1

API sunucudan sunucuya kullanım içindir. Anahtarınızı tarayıcıda çalışan koda, mobil uygulamaya veya herkese açık bir depoya koymayın. Bir anahtar sızdıysa panelden iptal edip yenisini oluşturun; iptal anında geçerli olur.

Kimlik doğrulama ve yetkiler

Her istekte anahtarı Authorization başlığında Bearer olarak gönderin. Anahtar hangi firmaya aitse yalnızca o firmanın verisine erişir.

Örnek istek

curl https://api.360katalog.com/api/v1/products.php?per_page=2 \
  -H "Authorization: Bearer 360k_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
YetkiNe sağlar
products:readÜrünleri ve kategorileri okuma
products:writeÜrün ekleme/güncelleme, toplu stok ve fiyat (products:read dahil)
orders:readSiparişleri kalemleriyle birlikte okuma
orders:writeSipariş durumu, kargo firması ve takip kodu güncelleme (orders:read dahil)
customers:readMüşterileri (bayileri) ve cari bakiyelerini okuma

Yanıt biçimi, sayfalama ve tarihler

Başarılı yanıtlar data alanında döner; listelerde meta sayfa bilgisini taşır. Hatalarda HTTP durum kodu ile birlikte error.code (makinece okunur) ve error.message (Türkçe açıklama) gelir.

Listelerde page (1'den başlar) ve per_page parametrelerini kullanın. Tarihler ISO 8601 biçiminde ve UTC'dir (2026-10-29T14:36:25Z). updated_since gibi tarih parametrelerine saat dilimi vermezseniz UTC kabul edilir; Unix zaman damgası da gönderebilirsiniz. Tutarlar ondalık sayıdır; sipariş toplamları Türk lirasıdır (TL), döviz kalemlerin kendi para birimi by_currency içinde ayrıca verilir.

Liste yanıtı

{
  "data": [
    {
      "id": 3229,
      "sku": "KLM-0012",
      "name": "Kalem Seti 12'li",
      "description": null,
      "price": 110.0,
      "currency": "TL",
      "retail_price": 149.9,
      "cost_price": null,
      "price_lists": { "g_bayi": 95.0 },
      "stock": 45,
      "category": "Kırtasiye",
      "brand": null,
      "image_url": null,
      "images": [],
      "is_visible": true,
      "created_at": "2026-10-29T14:36:25Z",
      "updated_at": "2026-10-29T15:02:11Z"
    }
  ],
  "meta": { "page": 1, "per_page": 2, "total": 1, "total_pages": 1 }
}

Hata yanıtı (HTTP 403)

{
  "error": {
    "code": "insufficient_scope",
    "message": "Bu işlem için anahtarın 'orders:write' yetkisi olmalı.",
    "details": { "required_scope": "orders:write" }
  }
}

Ürünler

GET/products.phpproducts:read

Ürün listesi. Parametreler: page, per_page (en fazla 200, varsayılan 50), updated_since, skus (virgülle en fazla 200 stok kodu), category. Tek ürün için ?id= veya ?sku= kullanın. updated_since verildiğinde sonuçlar eskiden yeniye sıralanır; son gördüğünüz updated_at değerini bir sonraki eşitlemede kullanabilirsiniz.

# Son eşitlemeden bu yana değişen ürünler (eskiden yeniye)
curl "https://api.360katalog.com/api/v1/products.php?updated_since=2026-10-29T00:00:00Z&per_page=200&page=1" \
  -H "Authorization: Bearer $API_KEY"

# Tek ürün (id veya stok kodu ile)
curl "https://api.360katalog.com/api/v1/products.php?sku=KLM-0012" -H "Authorization: Bearer $API_KEY"

# Birden fazla stok kodu, kategoriye göre
curl "https://api.360katalog.com/api/v1/products.php?skus=KLM-0012,KLM-0024&category=Kırtasiye" -H "Authorization: Bearer $API_KEY"

price ana satış fiyatıdır; price_lists fiyat listesi kimliğine göre özel fiyatları içerir (değer bir sayı veya { "price": 10, "currency": "USD" } olabilir).

POST/products.phpproducts:write

Stok koduna (sku) göre ekle veya güncelle. Tek ürün nesnesi ya da {"products": [...]} ile en fazla 500 ürün gönderebilirsiniz. Mevcut üründe yalnızca gönderdiğiniz alanlar değişir; yeni üründe name ve price zorunludur. Alanlar: name, description, price, currency (TL, USD, EUR), retail_price, cost_price, price_lists, stock, category, brand, image_url, images, is_visible. Bir kalemde hata varsa hiçbir ürün değişmez ve tüm hatalar listelenir. Yeni ürünler paketinizin ürün sınırını aşarsa plan_limit_exceeded döner.

İstek

curl -X POST https://api.360katalog.com/api/v1/products.php \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "products": [
      { "sku": "KLM-0012", "stock": 40 },
      { "sku": "KLM-0024", "name": "Kalem Seti 24'lü", "price": 18.5,
        "currency": "USD", "stock": 120, "category": "Kırtasiye",
        "price_lists": { "g_bayi": 16.0 } }
    ]
  }'

Yanıt

{
  "data": [
    { "sku": "KLM-0012", "id": 3229, "action": "updated" },
    { "sku": "KLM-0024", "id": 3230, "action": "created" }
  ],
  "meta": { "created": 1, "updated": 1, "unchanged": 0 }
}
PATCH/products.phpproducts:write

Toplu stok ve fiyat güncelleme. Her kalem sku veya id ile ürünü belirtir ve stock, price, retail_price alanlarından en az birini içerir. Tek istekte en fazla 1.000 kalem. Bulunamayan ürünler not_found içinde döner, diğerleri güncellenir.

curl -X PATCH https://api.360katalog.com/api/v1/products.php \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "items": [
        { "sku": "KLM-0012", "stock": 45, "price": 110 },
        { "id": 3230, "stock": 0 }
      ] }'

# Yanıt
{ "data": { "updated": 2, "unchanged": 0, "not_found": [] } }

Siparişler

GET/orders.phporders:read

Siparişler kalemleri ve müşteri bilgisiyle döner, son değişene göre sıralanır. Parametreler: page, per_page (en fazla 100, varsayılan 25), status (virgülle birden fazla), updated_since, customer_id. Tek sipariş için ?id= veya ?order_number=.

Durumlar: pending, pending_finance, processing, shipped, completed, sent_to_bizimhesap, cancelled.

İstek

# Yeni siparişler
curl "https://api.360katalog.com/api/v1/orders.php?status=pending,pending_finance&per_page=50" \
  -H "Authorization: Bearer $API_KEY"

# Belirli bir tarihten sonra değişen siparişler
curl "https://api.360katalog.com/api/v1/orders.php?updated_since=2026-10-29T08:00:00Z" -H "Authorization: Bearer $API_KEY"

# Tek sipariş
curl "https://api.360katalog.com/api/v1/orders.php?order_number=SIP-DEMO-186562" -H "Authorization: Bearer $API_KEY"

Sipariş nesnesi

{
  "id": 14,
  "order_number": "SIP-DEMO-186562",
  "status": "pending",
  "status_label": "Beklemede",
  "customer": {
    "id": 11, "name": "Örnek Bayi", "phone": "0500 000 00 00", "email": null,
    "city": "Antalya", "district": "Manavgat", "address": null,
    "tax_number": null, "tax_office": null, "price_list": "g_bayi"
  },
  "items": [
    { "id": 18, "product_id": 3229, "sku": "KLM-0012", "name": "Kalem Seti 12'li",
      "quantity": 2, "unit_price": 110.0, "currency": "TL", "line_total": 220.0 },
    { "id": 19, "product_id": 3230, "sku": "KLM-0024", "name": "Kalem Seti 24'lü",
      "quantity": 1, "unit_price": 18.5, "currency": "USD", "line_total": 18.5 }
  ],
  "totals": {
    "subtotal": 1139.44, "discount": 0.0, "delivery_fee": 0.0, "total": 1139.44,
    "currency": "TL",
    "by_currency": { "TL": 220.0, "USD": 18.5 },
    "exchange_rates": { "USD": 49.6997, "EUR": 55.4243 }
  },
  "applied_campaigns": [],
  "delivery_zone": null,
  "payment_method": null,
  "customer_note": "Hafta içi teslim",
  "firm_note": null,
  "shipping_company": null,
  "tracking_code": null,
  "bizimhesap_ref_id": null,
  "created_at": "2026-10-29T14:36:44Z",
  "updated_at": "2026-10-29T14:36:44Z"
}
PATCH/orders.php?id={id}orders:write

Sipariş durumunu, kargo firmasını ve takip kodunu günceller; note durum geçmişine yazılır. Durum değişikliği panelden yapılanla aynı sonuçları doğurur: iptalde stoklar iade edilir ve cari borç sıfırlanır, iptalden geri alınca stok yeniden düşülür ve borç geri yazılır. Değişiklik durum geçmişine kaydedilir ve ilgili webhook olayları gönderilir.

curl -X PATCH "https://api.360katalog.com/api/v1/orders.php?id=14" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "status": "shipped", "shipping_company": "Yurtiçi Kargo",
        "tracking_code": "TR123456789", "note": "ERP sevk kaydı" }'

Müşteriler

GET/customers.phpcustomers:read

Bayi listesi. Parametreler: page, per_page (en fazla 200), q (ad, telefon, e-posta veya vergi no), created_since. Tek müşteri için ?id=. balance cari bakiyedir (borç eksi alacak, TL). Bayi katalog şifreleri API'de hiçbir zaman döndürülmez.

curl "https://api.360katalog.com/api/v1/customers.php?q=manavgat&per_page=100" -H "Authorization: Bearer $API_KEY"

{
  "data": [
    { "id": 11, "name": "Örnek Bayi", "email": null, "phone": "0500 000 00 00",
      "customer_type": "Standart", "status": "active", "price_list": "g_bayi",
      "tax_number": null, "tax_office": null, "address": null,
      "city": "Antalya", "district": "Manavgat",
      "risk_limit": 50000.0, "risk_action": "warn", "balance": 1139.44,
      "created_at": "2026-10-29T14:30:02Z" }
  ],
  "meta": { "page": 1, "per_page": 100, "total": 1, "total_pages": 1 }
}

Kategoriler

GET/categories.phpproducts:read

Tüm kategoriler. parent_id ile ağaç kurabilirsiniz. Ürünlerdeki category alanı kategori adını taşır.

curl https://api.360katalog.com/api/v1/categories.php -H "Authorization: Bearer $API_KEY"

{
  "data": [
    { "id": 4, "name": "Kırtasiye", "parent_id": null, "image_url": null, "created_at": "2026-06-28T05:02:14Z" },
    { "id": 9, "name": "Kalemler", "parent_id": 4, "image_url": null, "created_at": "2026-06-28T05:03:40Z" }
  ],
  "meta": { "total": 2 }
}

Webhook

Panelde bir https adresi ve dinlemek istediğiniz olayları seçerek webhook ekleyin. Olay olduğunda adresinize imzalı bir POST isteği gönderilir. İmza anahtarı (whsec_…) yalnızca oluştururken gösterilir; panelden yenileyebilirsiniz.

OlayNe zamandata içeriği
order.createdBayi katalogdan sipariş verdiğinde.order
order.status_changedSipariş durumu panelden veya API ile değiştiğinde.order, previous_status, source
order.updatedSipariş panelden düzenlendiğinde (kalem, kargo bilgisi, firma notu) veya API ile kargo bilgisi girildiğinde.order, changes, source
product.updatedÜrün API ile eklendiğinde veya stok/fiyatı API ile güncellendiğinde.action, product
quote.acceptedBayi teklif linkinden teklifi kabul ettiğinde. Teklif siparişe dönüşünce ayrıca order.created gönderilir.quote_id, quote_number, note

Sipariş olaylarındaki order nesnesi, GET /orders.php yanıtındakiyle aynıdır. source değişikliğin nereden geldiğini gösterir (panel veya api). Panelden “Test gönder” ile ping olayı yollayıp entegrasyonunuzu deneyebilirsiniz.

Örnek istek

POST /360katalog/webhook HTTP/1.1
Content-Type: application/json
User-Agent: 360Katalog-Webhooks/1.0
X-360Katalog-Event: order.status_changed
X-360Katalog-Event-Id: evt_c840b3a75eb8b507720c454f
X-360Katalog-Delivery: 12
X-360Katalog-Timestamp: 1793284690
X-360Katalog-Signature: sha256=5d1c0e...

{
  "id": "evt_c840b3a75eb8b507720c454f",
  "event": "order.status_changed",
  "created_at": "2026-10-29T14:38:10Z",
  "firm_id": 4,
  "data": {
    "order": { "id": 14, "order_number": "SIP-DEMO-186562", "status": "processing", "...": "..." },
    "previous_status": "pending",
    "source": "panel"
  }
}
  • Adresiniz 3 saniye içinde 2xx durum koduyla yanıt vermelidir. Ağır işleri kuyruğa alıp hemen yanıt verin.
  • Başarısız teslimatlar 1 dk, 5 dk, 30 dk, 2 sa ve 6 sa sonra yeniden denenir (toplam 6 deneme).
  • Aynı olay birden fazla kez gelebilir. Tekrarları id (X-360Katalog-Event-Id) ile ayıklayın.
  • Üst üste 50 başarısız denemeden sonra webhook otomatik durdurulur; panelden yeniden etkinleştirebilirsiniz.
  • Her webhook için son 100 teslimat, gönderilen içerik ve aldığınız yanıtla birlikte panelde görünür ve tek tıkla yeniden gönderilebilir.
  • Yönlendirmeler (3xx) izlenmez; yerel veya özel ağ adreslerine gönderim yapılmaz.

İmza doğrulama

İmza, X-360Katalog-Timestamp değeri, bir nokta ve ham istek gövdesi birleştirilerek webhook anahtarınızla HMAC-SHA256 hesaplanır ve X-360Katalog-Signature: sha256=<hex> olarak gönderilir. Karşılaştırmayı sabit süreli yapın ve 5 dakikadan eski zaman damgalarını reddedin.

PHP

<?php
$secret    = getenv('KATALOG_WEBHOOK_SECRET'); // whsec_...
$body      = file_get_contents('php://input'); // ham gövde, json_decode'dan ÖNCE
$timestamp = $_SERVER['HTTP_X_360KATALOG_TIMESTAMP'] ?? '';
$signature = $_SERVER['HTTP_X_360KATALOG_SIGNATURE'] ?? '';

$expected = 'sha256=' . hash_hmac('sha256', $timestamp . '.' . $body, $secret);

if (!hash_equals($expected, $signature) || abs(time() - (int)$timestamp) > 300) {
    http_response_code(401);
    exit('invalid signature');
}

$event = json_decode($body, true);
// Aynı olay birden fazla gelebilir: $event['id'] ile tekrarları ayıklayın.
if ($event['event'] === 'order.created') {
    // $event['data']['order'] ...
}
http_response_code(200);
echo 'ok';

Node.js (Express)

import express from "express";
import crypto from "node:crypto";

const app = express();
const SECRET = process.env.KATALOG_WEBHOOK_SECRET; // whsec_...

// İmza ham gövde üzerinden hesaplanır: express.json() yerine raw kullanın
app.post("/360katalog/webhook", express.raw({ type: "application/json" }), (req, res) => {
  const timestamp = req.get("X-360Katalog-Timestamp") || "";
  const signature = req.get("X-360Katalog-Signature") || "";
  const expected = "sha256=" + crypto
    .createHmac("sha256", SECRET)
    .update(timestamp + "." + req.body.toString("utf8"))
    .digest("hex");

  const valid = signature.length === expected.length &&
    crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected));
  if (!valid || Math.abs(Date.now() / 1000 - Number(timestamp)) > 300) {
    return res.status(401).send("invalid signature");
  }

  const event = JSON.parse(req.body.toString("utf8"));
  // event.id ile tekrarları ayıklayın, işi kuyruğa alıp hemen 200 dönün
  res.status(200).send("ok");
});

app.listen(3000);

Hız sınırı

Her anahtar dakikada en fazla 120 istek yapabilir. Her yanıtta kalan hakkınız başlıklarda gelir. Sınır aşıldığında HTTP 429 ve Retry-After (saniye) döner. Çok sayıda ürünü tek tek göndermek yerine toplu uçları (POST ile 500, PATCH ile 1.000 kalem) kullanın.

Yanıt başlıkları

X-RateLimit-Limit: 120
X-RateLimit-Remaining: 87
X-RateLimit-Reset: 1793284560

Hata kodları

HTTPcodeAçıklama
400invalid_jsonGövde geçerli bir JSON nesnesi değil.
400invalid_parameterSorgu parametresi geçersiz (ör. tarih biçimi, durum adı).
401unauthorizedAnahtar eksik, hatalı veya iptal edilmiş.
403insufficient_scopeAnahtarın bu işlem için yetkisi yok. details.required_scope gereken yetkiyi söyler.
403firm_inactiveFirma hesabı askıda veya paket süresi dolmuş.
403plan_limit_exceededYeni ürünler paketinizin ürün sınırını aşıyor.
404not_foundKayıt bulunamadı (veya başka bir firmaya ait).
405method_not_allowedUç nokta bu HTTP metodunu desteklemiyor.
422validation_failedAlan doğrulaması başarısız. details her hatalı kalemi index, sku, field ve message ile listeler. Hiçbir değişiklik yapılmaz.
422too_many_itemsTek istekteki kalem sayısı sınırı aşıldı.
422unprocessableİşlem yapılamadı (ör. iptalden geri alırken stok yetersiz).
429rate_limitedDakikalık istek sınırı aşıldı. Retry-After başlığı kadar bekleyin.
500internal_errorBeklenmeyen sunucu hatası. İsteği daha sonra tekrar deneyin.

Entegrasyon için yardım mı gerekiyor?

Hesabınızı açın, panelden ilk API anahtarınızı oluşturun. Sorularınız için bize WhatsApp'tan veya iletişim formundan yazın.