Başlangıç
- Firma panelinde API ve Webhook sayfasını açın.
- Anahtara bir ad verin (ör. “ERP entegrasyonu”) ve yalnızca gereken yetkileri seçin.
- Oluşan
360k_live_…anahtarını hemen kopyalayın. Anahtarın tamamı yalnızca bir kez gösterilir; sistemde yalnızca özeti saklanır. - İ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/v1API 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"| Yetki | Ne sağlar |
|---|---|
| products:read | Ürünleri ve kategorileri okuma |
| products:write | Ürün ekleme/güncelleme, toplu stok ve fiyat (products:read dahil) |
| orders:read | Siparişleri kalemleriyle birlikte okuma |
| orders:write | Sipariş durumu, kargo firması ve takip kodu güncelleme (orders:read dahil) |
| customers:read | Müş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
/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).
/products.phpproducts:writeStok 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 }
}/products.phpproducts:writeToplu 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
/orders.phporders:readSipariş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"
}/orders.php?id={id}orders:writeSipariş 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
/customers.phpcustomers:readBayi 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
/categories.phpproducts:readTü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.
| Olay | Ne zaman | data içeriği |
|---|---|---|
| order.created | Bayi katalogdan sipariş verdiğinde. | order |
| order.status_changed | Sipariş durumu panelden veya API ile değiştiğinde. | order, previous_status, source |
| order.updated | Sipariş 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.accepted | Bayi 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: 1793284560Hata kodları
| HTTP | code | Açıklama |
|---|---|---|
| 400 | invalid_json | Gövde geçerli bir JSON nesnesi değil. |
| 400 | invalid_parameter | Sorgu parametresi geçersiz (ör. tarih biçimi, durum adı). |
| 401 | unauthorized | Anahtar eksik, hatalı veya iptal edilmiş. |
| 403 | insufficient_scope | Anahtarın bu işlem için yetkisi yok. details.required_scope gereken yetkiyi söyler. |
| 403 | firm_inactive | Firma hesabı askıda veya paket süresi dolmuş. |
| 403 | plan_limit_exceeded | Yeni ürünler paketinizin ürün sınırını aşıyor. |
| 404 | not_found | Kayıt bulunamadı (veya başka bir firmaya ait). |
| 405 | method_not_allowed | Uç nokta bu HTTP metodunu desteklemiyor. |
| 422 | validation_failed | Alan doğrulaması başarısız. details her hatalı kalemi index, sku, field ve message ile listeler. Hiçbir değişiklik yapılmaz. |
| 422 | too_many_items | Tek istekteki kalem sayısı sınırı aşıldı. |
| 422 | unprocessable | İşlem yapılamadı (ör. iptalden geri alırken stok yetersiz). |
| 429 | rate_limited | Dakikalık istek sınırı aşıldı. Retry-After başlığı kadar bekleyin. |
| 500 | internal_error | Beklenmeyen 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.