Forsid REST API
Ürün, stok, müşteri ve sipariş verilerinizi ERP, muhasebe, pazaryeri ya da kendi yazılımınızla çift yönlü senkronize edin.
https://magazaniz.com/api/v1
Genel bakış
Forsid REST API, mağazanızdaki verilere dış sistemlerden güvenli şekilde erişmenizi sağlar. Her mağazanın kendi API adresi vardır ve istekler mağazanın alan adına yapılır.
Tüm istek ve yanıtlar JSON biçimindedir. Tarihler ISO 8601 biçiminde ve Türkiye saatiyle döner. Tutar alanları iki ondalık basamaklı sayıdır. Her yanıtta meta alanı içinde request_id bulunur, destek talebinde bu değeri paylaşmanız sorunu hızla bulmamızı sağlar.
{
"data": {
"id": 1042,
"sku": "KLK-1042",
"name": "Kablosuz Kulaklık",
"price": 1960.0,
"stock": 24
},
"meta": {
"request_id": "5c3bf4ed-fe66-43ab-8d43-a1dbbf443163",
"server_time": "2026-10-24T09:30:00Z"
}
}
Kimlik doğrulama
API, OAuth 2.0 client credentials akışını kullanır. Client ID ve Client Secret ile token adresine istek atarak bir saat geçerli erişim tokenı alırsınız. Sonraki tüm isteklerde bu tokenı Authorization başlığında gönderirsiniz.
- 1Token alın
Token adresine grant_type, client_id ve client_secret gönderin. Bilgiler JSON gövdede, form gövdesinde ya da Basic Authorization başlığında gönderilebilir.
- 2İstek atın
Dönen access_token değerini Authorization başlığına Bearer önekiyle ekleyin.
- 3Süre dolunca yenileyin
expires_in alanı saniye cinsinden süreyi verir. 401 invalid_token yanıtı aldığınızda yeni token alın.
/oauth/tokengrant_type
metin
zorunlu
client_id
metin
zorunlu
client_secret
metin
zorunlu
scope
metin
curl -X POST https://magazaniz.com/api/v1/oauth/token \
-H "Content-Type: application/json" \
-d '{
"grant_type": "client_credentials",
"client_id": "fsd_...",
"client_secret": "fsk_..."
}'
$response = Http::asJson()->post(
'https://magazaniz.com/api/v1/oauth/token',
[
'grant_type' => 'client_credentials',
'client_id' => 'fsd_...',
'client_secret' => 'fsk_...',
]
);
$token = $response['access_token'];
$products = Http::withToken($token)
->get('https://magazaniz.com/api/v1/products', ['per_page' => 100])
->json('data');
const res = await fetch('https://magazaniz.com/api/v1/oauth/token', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
grant_type: 'client_credentials',
client_id: 'fsd_...',
client_secret: 'fsk_...'
})
});
const { access_token } = await res.json();
const products = await fetch('https://magazaniz.com/api/v1/products?per_page=100', {
headers: { Authorization: `Bearer ${access_token}` }
}).then(r => r.json());
{
"access_token": "fat_9c1e4b...",
"token_type": "Bearer",
"expires_in": 3600,
"scope": "products.read products.write orders.read"
}
İzinler
Her API kullanıcısına panelden sadece ihtiyaç duyduğu alanlarda izin verilir. Yazma izni verilen alanda okuma izni de kendiliğinden açılır. İzni olmayan bir uca istek atıldığında 403 insufficient_scope döner ve eksik izin details.required alanında listelenir.
products.readÜrün, varyant, kategori, marka ve özellik listeleriproducts.writeÜrün ve varyant oluşturma, güncelleme ve silmeinventory.writeToplu stok ve fiyat güncellemecustomers.readMüşteri ve adres okumacustomers.writeMüşteri ve adres oluşturma, güncelleme, adres silmeorders.readSipariş listesi ve detayıorders.writeSipariş durumu, kargo takip bilgisi ve ödeme onayıİzin değişiklikleri anında geçerli olur. Panelden bir izni kaldırdığınızda daha önce alınmış tokenlar da o uca erişemez. IP kısıtlaması tanımlanmışsa listede olmayan adreslerden gelen istekler 403 ip_not_allowed alır.
/me
Tokenın hangi kullanıcıya ait olduğunu ve verilen izinleri döner. Bağlantı testi için kullanabilirsiniz.
curl https://magazaniz.com/api/v1/me \ -H "Authorization: Bearer fat_9c1e4b..."
{
"data": {
"name": "Muhasebe Entegrasyonu",
"client_id": "fsd_b11ff8a360ba3527362154e5",
"scopes": ["orders.read", "orders.write", "products.read"],
"store": {
"name": "Mağaza Adı",
"url": "https://magazaniz.com"
}
}
}
Hatalar
Başarılı istekler 200 ya da 201 döner. Hata durumunda HTTP durum kodu ile birlikte error nesnesi gelir. code alanı makine tarafından okunmak içindir ve değişmez, message alanı Türkçe açıklamadır. Doğrulama hatalarında details alanı her hatalı alanı ayrı ayrı listeler.
invalid_jsonGövde geçerli bir JSON nesnesi değilunauthorizedAuthorization başlığı eksikinvalid_tokenToken geçersiz ya da süresi dolmuşclient_disabledAPI kullanıcısı panelden kapatılmışinsufficient_scopeBu uç için izin yokip_not_allowedİstek izin verilmeyen bir IP adresinden geldinot_foundKayıt ya da uç bulunamadımethod_not_allowedUç bu HTTP yöntemini desteklemiyoralready_paidSiparişin ödemesi zaten onaylıunsupported_media_typeGövde JSON değil, Content-Type application/json olmalıvalidation_failedGönderilen veriler geçersiz, ayrıntı details içinderead_only_productBu ürün türü API ile değiştirilemezinvalid_transitionSipariş bu duruma geçirilemezinvalid_stateİşlem siparişin mevcut durumunda yapılamazlast_variantÜrünün son varyantı silinemezorder_lockedSipariş geçici olarak kilitlirate_limitedDakikalık istek sınırı aşıldıserver_errorBeklenmeyen hata, request_id ile bize bildirinservice_unavailableWeb servis bu mağazada henüz etkin değilToken adresi OAuth 2.0 standardına uygun olarak farklı bir yapı kullanır. Hata durumunda error ve error_description alanları döner, örneğin invalid_client, invalid_scope ya da unsupported_grant_type.
{
"error": {
"code": "validation_failed",
"message": "Gönderilen veriler geçersiz. Standart ürün için price zorunludur.",
"details": {
"price": ["Standart ürün için price zorunludur."],
"variants.1.sku": ["Yeni varyant için sku zorunludur."]
}
},
"meta": {
"request_id": "e7f2dada-92f2-42fa-bc28-0f959bbe07b0",
"server_time": "2026-10-24T09:30:00Z"
}
}
{
"error": "invalid_client",
"error_description": "Kimlik bilgileri geçersiz."
}
Limitler
İstekler API kullanıcısı başına dakikalık olarak sınırlanır. Sınır panelde kullanıcı bazında 60, 120, 300 ya da 600 olarak seçilir, varsayılan 120 istektir. Her yanıtta kalan hakkınız başlıklarda bildirilir. Sınır aşıldığında 429 rate_limited döner ve Retry-After başlığı kaç saniye beklemeniz gerektiğini söyler.
X-RateLimit-Limit
integer
X-RateLimit-Remaining
integer
Retry-After
integer
X-Request-Id
metin
HTTP/1.1 429 Too Many Requests
Retry-After: 42
X-RateLimit-Limit: 120
X-RateLimit-Remaining: 0
{
"error": {
"code": "rate_limited",
"message": "Dakikalık istek sınırı aşıldı.",
"details": { "retry_after": 42 }
}
}
Sayfalama ve senkronizasyon
Tüm liste uçları sayfalı döner ve aşağıdaki ortak parametreleri kabul eder. Sayfalama bilgisi meta.pagination içinde gelir. last_page değerine ulaşana kadar page değerini artırarak tüm kayıtları alabilirsiniz.
page
integer
per_page
integer
updated_since
tarih
created_since
tarih
ids
metin
Değişiklikleri çekmek
- 1İlk senkronizasyon
Tüm kayıtları sayfa sayfa çekin ve ilk yanıttaki meta.server_time değerini saklayın.
- 2Sonraki çalışmalar
updated_since parametresine sakladığınız zamanı vererek sadece değişen kayıtları çekin. Yeni server_time değerini saklayın.
- 3Güvenlik payı
Saat farklarına karşı updated_since değerini birkaç dakika geriden göndermenizi öneririz. Aynı kaydın iki kez gelmesi sorun yaratmaz, id ile eşleştirin.
curl "https://magazaniz.com/api/v1/orders?updated_since=2026-10-24T09:00:00%2B03:00&per_page=100&page=2" \ -H "Authorization: Bearer fat_9c1e4b..."
{
"data": [ ... ],
"meta": {
"request_id": "7d798764-4ae0-4f86-8952-0c620f32a261",
"server_time": "2026-10-24T09:31:12Z",
"pagination": {
"page": 2,
"per_page": 100,
"total": 248,
"last_page": 3
}
}
}
Ürünler
Ürünleri çevirileri, fiyatları, stokları, kategorileri, görselleri ve varyantlarıyla birlikte okuyun. API ile standart ve varyantlı ürünler oluşturulup güncellenebilir. Baskı, tasarım, teklif ve harici ürünler API üzerinden sadece okunur.
Ürünleri listele
/products
products.read
sku
metin
barcode
metin
type
metin
is_active
boolean
category_id
integer
brand_id
integer
q
metin
page
integer
per_page
integer
updated_since
tarih
created_since
tarih
ids
metin
curl "https://magazaniz.com/api/v1/products?category_id=5&is_active=1&per_page=50" \ -H "Authorization: Bearer fat_9c1e4b..."
Ürün detayı
/products/{id}
products.read
Listedeki alanlara ek olarak çevirilerde description ve short_description alanlarını, baskı ürünlerinde print_tiers adet kademelerini döner.
id
integer
type
metin
sku, barcode, product_code
metin
name
metin
translations
dizi
brand
nesne
categories
dizi
price, discount_price
sayı
vat_rate, price_includes_vat
sayı, boolean
stock
integer
dimensions
nesne
images
dizi
variants
dizi
{
"data": {
"id": 10,
"type": "variant",
"sku": "TSHIRT-OVERSIZE",
"barcode": "",
"name": "Oversize Pamuklu Tişört",
"translations": [
{
"locale": "tr",
"name": "Oversize Pamuklu Tişört",
"slug": "oversize-pamuklu-tisort",
"short_description": "%100 pamuk, unisex.",
"description": "<p>%100 pamuk, oversize kesim.</p>",
"meta_title": "Oversize Pamuklu Tişört",
"meta_description": ""
}
],
"brand": { "id": 3, "name": "Forsid Basics" },
"default_category_id": 5,
"categories": [
{ "id": 5, "name": "Tişört", "is_primary": true }
],
"is_active": true,
"is_available_for_order": true,
"price": null,
"discount_price": null,
"vat_rate": 20,
"price_includes_vat": true,
"stock": 24,
"dimensions": { "weight": 0.25, "width": null, "height": null, "depth": null, "desi": null },
"images": [
{ "url": "https://magazaniz.com/storage/products/on.jpg", "is_main": true, "variant_id": null, "position": 0 }
],
"variants": [
{
"id": 13,
"sku": "TSHIRT-OVERSIZE-SIYAH-S",
"barcode": "8690000000013",
"is_active": true,
"is_default": true,
"position": 0,
"price": 790,
"discount_price": 650,
"stock": 12,
"attributes": [
{ "attribute_id": 1, "attribute": "Renk", "value_id": 1, "value": "Siyah" },
{ "attribute_id": 2, "attribute": "Beden", "value_id": 3, "value": "S" }
],
"dimensions": { "weight": null, "width": null, "height": null, "depth": null, "desi": null }
}
],
"created_at": "2026-10-14T12:58:24+03:00",
"updated_at": "2026-10-24T09:12:03+03:00"
}
}
Ürün oluştur
/products
products.write
Standart ürün için price zorunludur. Varyantlı üründe fiyat ve stok ürün seviyesinde gönderilmez, variants listesinde her varyant için ayrı verilir. Başarılı istekte 201 ve oluşan ürünün tam hali döner.
type
metin
zorunlu
sku
metin
zorunlu
name
metin
translations yoksa
description, short_description
HTML
slug, meta_title, meta_description
metin
translations
dizi
barcode, product_code
metin
brand_id
integer
category_ids
dizi
primary_category_id
integer
price
sayı
standartta
discount_price
sayı
vat_rate
sayı
price_includes_vat
boolean
stock
integer
stocks
dizi
images
dizi
variants
dizi
varyantlıda
is_active
boolean
is_available_for_order, is_featured
boolean
min_order_quantity, max_order_quantity
integer
delivery_time
metin
weight, width, height, depth
sayı
curl -X POST https://magazaniz.com/api/v1/products \
-H "Authorization: Bearer fat_9c1e4b..." \
-H "Content-Type: application/json" \
-d '{
"type": "standard",
"sku": "KUPA-SERAMIK-01",
"barcode": "8690000000011",
"name": "Seramik Kupa",
"description": "<p>El yapımı seramik kupa.</p>",
"category_ids": [5, 12],
"brand_id": 3,
"price": 450,
"discount_price": 399.9,
"vat_rate": 20,
"price_includes_vat": true,
"stocks": [
{ "warehouse_id": 1, "quantity": 25 },
{ "warehouse_id": 2, "quantity": 10 }
],
"weight": 0.4,
"width": 10,
"height": 12,
"depth": 10,
"images": [
"https://cdn.ornek.com/kupa-on.jpg",
"https://cdn.ornek.com/kupa-yan.jpg"
]
}'
{
"data": {
"id": 18,
"type": "standard",
"sku": "KUPA-SERAMIK-01",
"name": "Seramik Kupa",
"price": 450,
"discount_price": 399.9,
"vat_rate": 20,
"price_includes_vat": true,
"stock": 35,
"dimensions": { "weight": 0.4, "width": 10, "height": 12, "depth": 10, "desi": 0.4 },
"images": [
{ "url": "https://magazaniz.com/storage/products/api/2026/10/a1b2.jpg", "is_main": true, "variant_id": null, "position": 0 }
]
}
}
Ürün güncelle
/products/{id}
products.write
Sadece gönderdiğiniz alanlar güncellenir, gönderilmeyen alanlar olduğu gibi kalır. Oluşturma ucundaki tüm alanlar kullanılabilir, type değiştirilemez.
- Ad değiştiğinde slug korunur, böylece ürün bağlantısı ve SEO değeri bozulmaz. Yeni slug için slug alanını gönderin.
- category_ids gönderilirse kategoriler bu listeyle değiştirilir, boş dizi tüm kategorileri kaldırır.
- images gönderilirse ürün galerisi bu listeyle değiştirilir. Mevcut görseli korumak için image_id gönderin. Varyant görselleri etkilenmez.
- stock ya da stocks gönderildiğinde stok verilen adede ayarlanır, eklenmez.
- vat_rate ya da price_includes_vat değişikliği ürünün ve tüm varyantlarının fiyatlarına uygulanır.
curl -X PATCH https://magazaniz.com/api/v1/products/18 \
-H "Authorization: Bearer fat_9c1e4b..." \
-H "Content-Type: application/json" \
-d '{
"name": "Seramik Kupa 350 ml",
"price": 500,
"discount_price": null,
"stocks": [{ "warehouse_id": 2, "quantity": 0 }],
"is_featured": true
}'
Ürün sil
/products/{id}
products.write
Ürünü panelden silmekle aynı şekilde siler. Geçmiş siparişlerdeki ürün bilgileri korunur. Sadece standart ve varyantlı ürünler silinebilir.
{
"data": { "id": 18, "deleted": true }
}
Varyantlar ve görseller
Varyantlı ürünlerde her varyant bir özellik kombinasyonudur, örneğin Renk Siyah ve Beden M. Varyantlar ürün oluşturulurken ya da güncellenirken variants listesiyle gönderilir.
Varyant alanları
id
integer
güncellemede
sku
metin
yeni varyantta
barcode
metin
price
sayı
yeni varyantta
discount_price
sayı
stock
integer
stocks
dizi
attributes
dizi
yeni varyantta
images
dizi
is_active
boolean
weight, width, height, depth
sayı
Özellik eşleştirme
- Özellik ve değerler id ile ya da adıyla gönderilebilir. Adla gönderildiğinde büyük küçük harf ve Türkçe karakter farkı gözetilmeden mevcut tanımla eşleşir.
- Eşleşen tanım yoksa özellik ya da değer mağaza dilinde otomatik oluşturulur.
- Bir ürünün tüm varyantları aynı özellikleri kullanmalıdır ve aynı kombinasyon iki kez kullanılamaz.
Güncellemede varyantlar
- id gönderilen varyant güncellenir, id olmayan satır yeni varyant olarak eklenir.
- Listede olmayan varyantlar silinmez. Silmek için varyant silme ucunu kullanın.
- Pasif varyantlar satıştan kalkar ama silinmez.
curl -X POST https://magazaniz.com/api/v1/products \
-H "Authorization: Bearer fat_9c1e4b..." \
-H "Content-Type: application/json" \
-d '{
"type": "variant",
"sku": "SWEAT-BASIC",
"name": "Basic Sweatshirt",
"category_ids": [5],
"vat_rate": 20,
"price_includes_vat": true,
"images": ["https://cdn.ornek.com/sweat-genel.jpg"],
"variants": [
{
"sku": "SWEAT-BASIC-SIYAH-S",
"price": 900,
"discount_price": 790,
"stock": 5,
"attributes": [
{ "attribute": "Renk", "value": "Siyah" },
{ "attribute": "Beden", "value": "S" }
],
"images": ["https://cdn.ornek.com/sweat-siyah.jpg"]
},
{
"sku": "SWEAT-BASIC-SIYAH-M",
"price": 900,
"stock": 7,
"attributes": [
{ "attribute_id": 1, "value_id": 1 },
{ "attribute_id": 2, "value": "M" }
]
}
]
}'
curl -X PATCH https://magazaniz.com/api/v1/products/19 \
-H "Authorization: Bearer fat_9c1e4b..." \
-H "Content-Type: application/json" \
-d '{
"variants": [
{ "id": 30, "discount_price": 850, "stock": 10 },
{
"sku": "SWEAT-BASIC-SIYAH-L",
"price": 950,
"stock": 2,
"attributes": [
{ "attribute": "Renk", "value": "Siyah" },
{ "attribute": "Beden", "value": "L" }
]
}
]
}'
Varyant sil
/products/{id}/variants/{variant_id}
products.write
Varyantı siler ve stoğunu stok hareketleriyle birlikte düşer. Ürünün son varyantı silinemez, ürünü kaldırmak için ürün silme ucunu kullanın. Yanıt olarak ürünün güncel hali döner.
Görseller
- Görseller herkese açık http ya da https adreslerinden indirilip mağazaya kaydedilir, karşı sunucuya bağlı kalınmaz.
- JPG, PNG, WEBP ve GIF desteklenir. Dosya en fazla 10 MB ve 12000 piksel olabilir.
- Herhangi bir görsel indirilemezse istek 422 ile reddedilir ve ürün hiç oluşmaz. Hangi görselin sorunlu olduğu details içinde belirtilir.
- Yerel ağ ve iç adresler güvenlik nedeniyle kabul edilmez.
- Daha önce yüklenmiş bir görseli tekrar indirmeden kullanmak için image_id gönderin.
{
"error": {
"code": "validation_failed",
"message": "Görsel indirilemedi. Sunucu 404 döndü.",
"details": {
"variants.0.images.1.url": ["Görsel indirilemedi. Sunucu 404 döndü."]
}
}
}
Kategori, marka ve özellik
Ürünlere atanabilecek tanımları listeler. Ürün oluştururken ve güncellerken kullanacağınız id değerlerini buradan alırsınız. Üçü de products.read izni ister ve ortak liste parametrelerini kabul eder.
/categories
products.read
Kategoriler üst kategori ve sıra bilgisiyle döner. Ağaç yapısını parent_id ile kurabilirsiniz.
parent_id
integer
/brands
products.read
Markalar id, ad, slug ve web sitesi bilgisiyle döner.
/attributes
products.read
Varyant ve filtre özelliklerini değerleriyle birlikte döner. Renk değerlerinde color alanı renk kodunu içerir.
{
"data": [
{
"id": 5,
"parent_id": null,
"name": "Giyim",
"level": 0,
"position": 1,
"is_active": true,
"translations": [
{ "locale": "tr", "name": "Giyim", "slug": "giyim" }
],
"updated_at": "2026-10-01T10:00:00+03:00"
}
]
}
{
"data": [
{
"id": 1,
"name": "Renk",
"values": [
{ "id": 1, "value": "Siyah", "code": "siyah", "color": "#000000", "position": 1 },
{ "id": 2, "value": "Beyaz", "code": "beyaz", "color": "#ffffff", "position": 2 }
]
}
]
}
Toplu stok ve fiyat
ERP ya da depo yazılımınızdan stok ve fiyatları hızlıca aktarmak için tasarlandı. Tek istekte 200 kaleme kadar güncelleme yapılır. Her kalem bağımsız işlenir, hatalı bir kalem diğerlerini engellemez.
/inventory
inventory.write
variant_id
integer
biri zorunlu
product_id
integer
biri zorunlu
sku
metin
biri zorunlu
barcode
metin
biri zorunlu
stock
integer
warehouse_id
integer
price
sayı
discount_price
sayı
- Eşleştirme sırası variant_id, product_id, sku ve barcode şeklindedir.
- Varyantlı ürünlerde güncelleme varyant bazında yapılır, ana ürün id değeri kabul edilmez.
- Aynı SKU birden fazla kayıtta kullanılıyorsa kalem reddedilir, bu durumda id ile gönderin.
- Baskı ürünlerinin fiyatı adet kademelerinden geldiği için bu uçtan değiştirilemez.
- Sonuçlar gönderdiğiniz sırayla döner, index alanı kalemin sırasını belirtir.
curl -X POST https://magazaniz.com/api/v1/inventory \
-H "Authorization: Bearer fat_9c1e4b..." \
-H "Content-Type: application/json" \
-d '{
"items": [
{ "sku": "SWEAT-BASIC-SIYAH-S", "stock": 9 },
{ "barcode": "8690000000013", "price": 350, "discount_price": 320 },
{ "variant_id": 31, "stock": 4, "warehouse_id": 2 },
{ "sku": "OLMAYAN-SKU", "stock": 1 }
]
}'
{
"data": [
{ "index": 0, "status": "updated", "reference": { "sku": "SWEAT-BASIC-SIYAH-S" }, "product_id": 19, "variant_id": 29, "stock": 9, "price": 900, "discount_price": 790 },
{ "index": 1, "status": "updated", "reference": { "barcode": "8690000000013" }, "product_id": 10, "variant_id": 13, "stock": 12, "price": 350, "discount_price": 320 },
{ "index": 2, "status": "updated", "reference": { "variant_id": 31 }, "product_id": 19, "variant_id": 31, "stock": 4, "price": 950, "discount_price": null },
{ "index": 3, "status": "failed", "reference": { "sku": "OLMAYAN-SKU" }, "error": "Bu sku ile ürün ya da varyant bulunamadı." }
],
"meta": { "updated": 3, "failed": 1 }
}
Müşteriler
Kayıtlı ve misafir müşterileri listeleyin, yeni müşteri açın ve bilgilerini güncelleyin. API ile açılan müşteriye varsayılan olarak davet epostası gönderilmez, isterseniz send_invitation ile gönderebilirsiniz.
Müşterileri listele
/customers
customers.read
email
metin
phone
metin
is_active
boolean
is_guest
boolean
q
metin
page
integer
per_page
integer
updated_since
tarih
created_since
tarih
ids
metin
Müşteri detayı
/customers/{id}
customers.read
Müşteri bilgilerine ek olarak stats alanında sipariş sayısını ve tamamlanan siparişlerin toplam tutarını döner.
{
"data": {
"id": 1,
"first_name": "Ayşe",
"last_name": "Yılmaz",
"email": "ayse@ornek.com",
"phone": "5551112233",
"gender": "female",
"birthday": "1990-05-04",
"is_active": true,
"is_guest": false,
"group": { "id": 1, "name": "Standart" },
"note": null,
"addresses": [ ... ],
"preferred_shipping_address_id": null,
"preferred_billing_address_id": null,
"registered_at": "2026-10-24T03:35:41+03:00",
"created_at": "2026-10-24T03:35:41+03:00",
"updated_at": "2026-10-24T03:37:42+03:00",
"stats": { "orders_count": 4, "total_spent": 5240.5 }
}
}
Müşteri oluştur
/customers
customers.write
first_name, last_name
metin
zorunlu
email
metin
zorunlu
phone
metin
gender
metin
birthday
tarih
is_active
boolean
note
metin
send_invitation
boolean
addresses
dizi
Müşteri güncelle
/customers/{id}
customers.write
Oluşturma ucundaki first_name, last_name, email, phone, gender, birthday, is_active ve note alanlarını kısmi olarak günceller. Adresler bu uçtan değişmez, adres uçlarını kullanın.
curl -X POST https://magazaniz.com/api/v1/customers \
-H "Authorization: Bearer fat_9c1e4b..." \
-H "Content-Type: application/json" \
-d '{
"first_name": "Ayşe",
"last_name": "Yılmaz",
"email": "ayse@ornek.com",
"phone": "5551112233",
"gender": "female",
"addresses": [
{
"label": "Ev",
"contact_name": "Ayşe Yılmaz",
"contact_phone": "5551112233",
"city": "İstanbul",
"district": "Ataşehir",
"address_line1": "Selvili Sk. No 4",
"billing_type": "individual",
"tckn": "11111111110"
}
]
}'
Adresler
Müşterinin teslimat ve fatura adreslerini yönetin. Bireysel adreslerde TC kimlik numarası, kurumsal adreslerde firma adı, vergi dairesi ve vergi numarası tutulur.
/customers/{id}/addresses
customers.write
/customers/{id}/addresses/{address_id}
customers.write
/customers/{id}/addresses/{address_id}
customers.write
address_line1
metin
oluşturmada
city
metin
city_id yoksa
city_id, district_id, country_id
integer
district, neighborhood, postal_code
metin
address_line2
metin
country
metin
label
metin
contact_name, contact_phone, contact_email
metin
billing_type
metin
tckn
metin
company_name, tax_office, tax_number
metin
- İl ve ilçe sadece adla gönderilirse sistemdeki kayıtla otomatik eşleşir ve id değerleri doldurulur. Eşleşme büyük küçük harf ve Türkçe karakter farkına duyarsızdır.
- Güncellemede il değişir ve ilçe gönderilmezse eski ilçe bilgisi temizlenir.
- Silinen adres müşterinin tercih edilen adresiyse tercih kaldırılır.
curl -X POST https://magazaniz.com/api/v1/customers/1/addresses \
-H "Authorization: Bearer fat_9c1e4b..." \
-H "Content-Type: application/json" \
-d '{
"label": "Ofis",
"contact_name": "Ayşe Yılmaz",
"city": "ankara",
"district": "çankaya",
"address_line1": "Atatürk Blv. No 1",
"billing_type": "corporate",
"company_name": "Örnek Teknoloji AŞ",
"tax_office": "Çankaya",
"tax_number": "1234567890"
}'
{
"data": {
"id": 4,
"label": "Ofis",
"contact_name": "Ayşe Yılmaz",
"country": "Türkiye",
"city": "Ankara",
"city_id": 6,
"district": "Çankaya",
"district_id": 79,
"address_line1": "Atatürk Blv. No 1",
"billing_type": "corporate",
"tckn": null,
"company_name": "Örnek Teknoloji AŞ",
"tax_office": "Çankaya",
"tax_number": "1234567890",
"updated_at": "2026-10-24T03:39:43+03:00"
}
}
Siparişler
Siparişleri tutarları, müşteri bilgileri, teslimat ve fatura adresleri, kalemleri ve kargo bilgileriyle birlikte okuyun. Fatura adresi bireysel ya da kurumsal ayrımıyla, TC kimlik ya da vergi bilgileri dolu olarak gelir.
Siparişleri listele
/orders
orders.read
status
metin
payment_status
metin
order_number
metin
customer_id
integer
page
integer
per_page
integer
updated_since
tarih
created_since
tarih
ids
metin
Sipariş detayı
/orders/{id}
orders.read
pendingOnay bekliyorprocessingHazırlanıyorshippedKargoya verildicompletedTamamlandıcancelledİptal edildireturnedİade edildiunpaidÖdenmedipendingÖdeme bekleniyorpaidÖdendifailedÖdeme başarısızrefundedİade edildipartially_refundedKısmi iade{
"data": {
"id": 4,
"order_number": "FS-1003",
"status": "processing",
"status_label": "Hazırlanıyor",
"payment_status": "paid",
"payment_method": "bank",
"paid_at": "2026-10-24T03:05:49+03:00",
"currency": "TRY",
"totals": {
"items_subtotal": 1908.34,
"discounts_total": 381.66,
"shipping_total": 500.0,
"cod_fee": 0.0,
"gift_package_total": 0.0,
"bank_transfer_discount": 0.0,
"tax_total": 305.34,
"grand_total": 2332.0
},
"coupon_code": "DENEME20",
"customer": {
"id": 1,
"is_guest": false,
"name": "Ayşe Yılmaz",
"email": "ayse@ornek.com",
"phone": "5551112233"
},
"shipping_address": {
"name": "Ayşe Yılmaz",
"phone": "5551112233",
"address_line1": "Selvili Sk. No 4",
"address_line2": "",
"neighborhood": "Küçükbakkalköy",
"district": "Ataşehir",
"city": "İstanbul",
"postal_code": "34750",
"country": "Türkiye"
},
"billing_address": {
"name": "Ayşe Yılmaz",
"city": "İstanbul",
"billing_type": "individual",
"tckn": "11111111110",
"company_name": null,
"tax_office": null,
"tax_number": null
},
"items": [
{
"id": 3,
"product_id": 10,
"variant_id": 17,
"sku": "TSHIRT-OVERSIZE-BEYAZ-M",
"barcode": "",
"name": "Oversize Pamuklu Tişört",
"variant": "Beyaz, M",
"product_type": "variant",
"quantity": 1,
"unit_price": 541.67,
"unit_price_incl_tax": 650.0,
"tax_rate": 20,
"discount": 108.33,
"tax": 86.67,
"total": 520.01,
"status": "active",
"customization": "",
"customization_files": [],
"print_details": "",
"design": ""
}
],
"shipment": {
"company": { "id": 1, "name": "Aras Kargo" },
"tracking_number": "ARAS123456",
"tracking_url": "https://kargotakip.araskargo.com.tr/?code=ARAS123456",
"shipped_at": "2026-10-24T14:10:00+03:00",
"delivered_at": null,
"store_pickup": false
},
"gift": { "enabled": false, "note": null },
"customer_note": null,
"placed_at": "2026-10-24T03:00:18+03:00",
"created_at": "2026-10-24T03:00:18+03:00",
"updated_at": "2026-10-24T03:06:10+03:00"
}
}
Durum, kargo ve ödeme
Bu uçlar paneldeki sipariş ekranıyla aynı kuralları ve aynı işlemleri kullanır. Müşteri bildirimleri, stok hareketleri ve fatura entegrasyonu panelde olduğu gibi çalışır. Her işlem siparişin geçmişine API kullanıcısının adıyla kaydedilir.
Sipariş durumunu güncelle
/orders/{id}/status
orders.write
status
metin
zorunlu
cancel_reason
metin
iptal ve iadede
shipping_company_id
integer
kargolamada
tracking_number
metin
entegrasyonsuz kargoda
- Durum sadece bir sonraki adıma ilerler, sırası pending, processing, shipped ve completed şeklindedir.
- İptal ve iade her aşamadan yapılabilir. İptal ya da iade edilmiş sipariş tekrar değiştirilemez.
- Tamamlanmış sipariş sadece iptal ya da iade edilebilir.
- Hazırlanıyor ve tamamlandı adımlarında fatura entegrasyonu ayarlarınıza göre fatura kesilir.
curl -X PATCH https://magazaniz.com/api/v1/orders/4/status \
-H "Authorization: Bearer fat_9c1e4b..." \
-H "Content-Type: application/json" \
-d '{
"status": "shipped",
"shipping_company_id": 1,
"tracking_number": "ARAS123456"
}'
{
"error": {
"code": "invalid_transition",
"message": "Durum sadece bir sonraki adıma güncellenebilir."
}
}
Kargo takip bilgisini güncelle
/orders/{id}/shipment
orders.write
Kargoya verilmiş siparişin takip numarasını ya da takip adresini günceller. En az birini göndermelisiniz.
tracking_number
metin
tracking_url
metin
Ödemeyi onayla
/orders/{id}/mark-paid
orders.write
Havale ve kapıda ödeme siparişlerinde ödemenin alındığını işaretler ve müşteriye ödeme onayı bildirimi gönderir. Ödemesi zaten onaylı siparişte 409 already_paid, iptal ya da iade edilmiş siparişte 422 döner.
payment_reference
metin
curl -X POST https://magazaniz.com/api/v1/orders/7/mark-paid \
-H "Authorization: Bearer fat_9c1e4b..." \
-H "Content-Type: application/json" \
-d '{ "payment_reference": "EFT-2026-10241" }'
Webhook'lar
Webhook'lar mağazada bir olay gerçekleştiğinde entegrasyonunuza anında haber verir. Sipariş, stok ya da ürün değişikliklerini öğrenmek için API'yi sürekli sorgulamanız gerekmez. Adresler Forsid panelinde Web Servis ekranından, ilgili API kullanıcısının içinde tanımlanır. Bir API kullanıcısına en fazla 5 adres eklenebilir ve her adres için hangi olayların gönderileceği ayrı ayrı seçilir.
Olaylar
order.createdYeni sipariş oluştuğunda. İzin orders.readorder.paidSiparişin ödemesi onaylandığında. İzin orders.readorder.status_changedSipariş durumu değiştiğinde, önceki durum previous alanında gelir. İzin orders.readproduct.createdYeni ürün eklendiğinde. İzin products.readproduct.updatedÜrün bilgisi, fiyatı, çevirisi ya da varyantları değiştiğinde. İzin products.readproduct.deletedÜrün silindiğinde. İzin products.readstock.changedMağaza deposundaki stok miktarı değiştiğinde. İzin products.readcustomer.createdYeni müşteri kaydolduğunda. İzin customers.readcustomer.updatedMüşteri bilgileri değiştiğinde. İzin customers.readwebhook.testPanelde Test gönder butonuna basıldığındaBir olay yalnızca API kullanıcısının ilgili okuma izni varsa gönderilir. İzin kaldırılır ya da API kullanıcısı kapatılırsa gönderim de durur.
İstek formatı
Her olay için adresinize JSON gövdeli bir POST isteği gönderilir. data alanı ilgili kaydın API'de dönen halinin aynısıdır, ek bir istek yapmanıza gerek kalmaz. product.deleted olayında sadece id, sku ve barkod gelir. stock.changed olayında ürün, varyant, SKU ve yeni miktar gelir.
X-Forsid-EventOlay adı, örneğin order.paidX-Forsid-Event-IdOlayın benzersiz numarası, gövdedeki id ile aynıdırX-Forsid-DeliveryBu gönderimin numarası, her denemede ve yeniden gönderimde farklıdırX-Forsid-Timestampİsteğin imzalandığı an, Unix saniyesi olarakX-Forsid-Signaturet ve v1 değerlerinden oluşan imzaUser-AgentForsid-Webhooks/1.0İmza doğrulama
Her adresin kendine ait bir imza anahtarı vardır. Anahtar whsec_ ile başlar, panelde sadece oluşturulduğunda ya da yenilendiğinde bir kez gösterilir. Doğrulamak için X-Forsid-Signature başlığındaki t değeri, bir nokta ve ham istek gövdesi birleştirilir, sonuç imza anahtarıyla HMAC SHA256 olarak hesaplanır ve v1 değeriyle sabit zamanlı bir karşılaştırmayla eşleştirilir.
Yanıt ve tekrar deneme
- İsteğe 10 saniye içinde 2xx durum koduyla yanıt verin. İşi kendi kuyruğunuza alıp hemen yanıt vermeniz önerilir.
- 2xx dışındaki yanıtlar ve zaman aşımları başarısız sayılır. Olay 1 dakika, 5 dakika, 30 dakika, 2 saat, 6 saat ve 12 saat sonra yeniden denenir.
- 410 yanıtı verirseniz o olay için tekrar deneme yapılmaz.
- Yönlendirmeler takip edilmez. Adres herkese açık olmalı ve https ile başlamalıdır.
- Art arda 15 olay tüm denemelere rağmen iletilemezse adres otomatik kapatılır. Sorunu giderdikten sonra panelden tekrar açabilirsiniz.
Tekrar eden ve sırasız olaylar
Aynı olay birden fazla kez gelebilir, örneğin yanıtınız zaman aşımına uğradıysa. X-Forsid-Event-Id değerini saklayıp daha önce işlediğiniz olayları atlayın. Olaylar her zaman oluştuğu sırayla gelmeyebilir, data içindeki updated_at alanına göre en güncel kaydı esas alın. Bir kayıt aynı işlem içinde birden fazla kez değişirse tek olay gönderilir ve data alanı kaydın son halini taşır.
Panelde her adres için son gönderimler, gönderilen veri ve sunucunuzun yanıtı görüntülenir. Test gönder ile webhook.test olayı yollanır ve geçmişteki herhangi bir olay yeniden gönderilebilir. Gönderim kayıtları 30 gün saklanır.
POST /forsid/webhook HTTP/1.1 Content-Type: application/json; charset=utf-8 User-Agent: Forsid-Webhooks/1.0 X-Forsid-Event: order.status_changed X-Forsid-Event-Id: evt_3022f8786ba445a78c95e7c899e43966 X-Forsid-Delivery: 6d248b0d-8883-471a-a7d5-5727bac4d4b0 X-Forsid-Timestamp: 1792871827 X-Forsid-Signature: t=1792871827,v1=2ac9fe8cbb47d1d453b6939f0d27372456a42630a925d3ca0c0a0b08e67f698c
{
"id": "evt_3022f8786ba445a78c95e7c899e43966",
"type": "order.status_changed",
"created_at": "2026-10-24T22:57:07+03:00",
"data": {
"id": 1007,
"order_number": "FS-1007",
"status": "shipped",
"status_label": "Kargoya Verildi",
"payment_status": "paid",
"currency": "TRY",
"totals": { "grand_total": 1249.9 }
},
"previous": { "status": "processing" }
}
{
"id": "evt_9b41c0e2d7a84f0e9a3c5d1e2f7a6b80",
"type": "stock.changed",
"created_at": "2026-10-24T23:04:12+03:00",
"data": {
"product_id": 18,
"variant_id": 42,
"sku": "TSH-BLK-M",
"barcode": "8690000000421",
"quantity": 7,
"warehouse_id": 1,
"updated_at": "2026-10-24T23:04:12+03:00"
},
"previous": { "quantity": 8 }
}
$payload = $request->getContent();
$header = (string) $request->header('X-Forsid-Signature', '');
$secret = config('services.forsid.webhook_secret');
parse_str(str_replace(',', '&', $header), $parts);
$timestamp = (int) ($parts['t'] ?? 0);
$expected = hash_hmac('sha256', $timestamp . '.' . $payload, $secret);
if (abs(time() - $timestamp) > 300 || ! hash_equals($expected, (string) ($parts['v1'] ?? ''))) {
abort(400);
}
$event = json_decode($payload, true);
if ($event['type'] === 'order.paid') {
ProcessForsidOrder::dispatch($event['data']['id']);
}
return response()->noContent();
import crypto from 'node:crypto';
import express from 'express';
const app = express();
app.post('/forsid/webhook', express.raw({ type: 'application/json' }), (req, res) => {
const header = req.get('X-Forsid-Signature') || '';
const parts = Object.fromEntries(header.split(',').map(p => p.split('=')));
const timestamp = Number(parts.t || 0);
const expected = crypto
.createHmac('sha256', process.env.FORSID_WEBHOOK_SECRET)
.update(`${timestamp}.${req.body}`)
.digest('hex');
const valid = typeof parts.v1 === 'string'
&& parts.v1.length === expected.length
&& crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(parts.v1));
if (!valid || Math.abs(Date.now() / 1000 - timestamp) > 300) {
return res.sendStatus(400);
}
const event = JSON.parse(req.body);
queue.add(event);
res.sendStatus(204);
});
import hashlib, hmac, json, os, time
from flask import Flask, request, abort
app = Flask(__name__)
SECRET = os.environ['FORSID_WEBHOOK_SECRET'].encode()
@app.post('/forsid/webhook')
def forsid_webhook():
payload = request.get_data()
header = request.headers.get('X-Forsid-Signature', '')
parts = dict(p.split('=', 1) for p in header.split(',') if '=' in p)
timestamp = int(parts.get('t', 0))
expected = hmac.new(SECRET, f'{timestamp}.'.encode() + payload, hashlib.sha256).hexdigest()
if abs(time.time() - timestamp) > 300 or not hmac.compare_digest(expected, parts.get('v1', '')):
abort(400)
event = json.loads(payload)
return '', 204
Depolar ve kargo firmaları
Stok güncellemede kullanılacak depo id değerlerini ve sipariş kargolamada kullanılacak kargo firması id değerlerini verir. Bu uçlar herhangi bir izin gerektirmez, geçerli bir token yeterlidir.
/warehouses
is_default alanı stok gönderiminde depo belirtilmediğinde kullanılan depoyu gösterir.
/shipping-companies
has_integration true olan firmalarda kargo kaydı ve takip numarası entegrasyon üzerinden otomatik oluşur.
{
"data": [
{ "id": 1, "code": "MRZ-8L6G", "name": "E Ticaret Depo", "is_default": true, "is_active": true },
{ "id": 2, "code": "IST-DC01", "name": "Perakende Depo", "is_default": false, "is_active": true }
]
}
{
"data": [
{ "id": 1, "name": "Aras Kargo", "code": "ARAS", "has_integration": false },
{ "id": 2, "name": "Yurtiçi Kargo", "code": "YURTICI", "has_integration": true }
]
}
Yakında
Aşağıdaki özellikler sonraki sürümlerde eklenecek. API sürüm 1 içinde yapılan değişiklikler geriye uyumludur, mevcut alanlar kaldırılmaz ya da anlamı değiştirilmez, sadece yeni alan ve uç eklenir.