Sipariş ve teslimat aktarımı
MarkdownSipariş ve teslimat bilgisinin sunucu anahtarıyla Sayproof'a gönderilmesi.
Sayproof yorum yazma hakkını ve davetleri siparişlere dayanarak oluşturur. Bu nedenle mağaza sisteminizin siparişleri ve teslimatları Sayproof’a göndermesi gerekir. Aktarım sunucudan sunucuya yapılır ve her istek sunucu anahtarıyla gönderilir; böylece bilginin gerçekten sizden geldiği doğrulanır.
Gönderim zamanı
Bölüm başlığı “Gönderim zamanı”- Sipariş oluşturulduğunda ve ödeme durumu değiştiğinde (ödendi, iade edildi, iptal edildi).
- Bir sipariş satırı kargoya verildiğinde, teslim edildiğinde, iade ya da iptal edildiğinde.
Aynı siparişin yeniden gönderilmesi güvenlidir: sipariş güncellenir, kopyası oluşmaz. En basit yöntem, her değişiklikte siparişin tamamını yeniden göndermektir.
Davet gönderilebilmesi ve yorum yazılabilmesi için sipariş satırının teslim edilmiş, siparişin ödenmiş olması gerekir. Teslimattan sonra Sayproof, Davet gönderimi ekranındaki bekleme süresi (varsayılan 2 gün) dolduğunda daveti gönderir.
Endpoint’ler
Bölüm başlığı “Endpoint’ler”| Endpoint | İşlev |
|---|---|
POST /v1/ingest/orders |
Siparişleri ve sipariş satırlarını kaydeder ya da günceller |
POST /v1/ingest/deliveries |
Sipariş satırlarının teslimat durumlarını bildirir |
Adresler panelde Entegrasyon › Sipariş aktarımı sekmesinin Mağazadan gönderim bölümündeki Siparişleri ve teslimatları gönderin kartında Kurulumda kullanılacak değerler listesinde Siparişler ve Teslimatlar satırlarında yer alır; aynı listede Kanal kodu da bulunur.
Sunucu anahtarı
Bölüm başlığı “Sunucu anahtarı”Her istek sunucu anahtarını Authorization header’ında taşır:
| Header | Değer |
|---|---|
Authorization |
Bearer <sunucu-anahtarı> |
Content-Type |
application/json |
Kurallar:
- Sunucu anahtarı Kanallar › Anahtarlar sekmesindeki Sunucu anahtarları kartında ya da kanal kurulum sihirbazının Anahtarlar adımında oluşturulur. SSR için kullandığınız anahtarla aynı anahtar olabilir.
- Anahtarın sipariş gönderme (
orders) izni olmalıdır. Panelden oluşturulan sunucu anahtarları bu izni kendiliğinden taşır. - Anahtar yalnızca sunucuda tutulur; tarayıcıya ya da sayfa koduna konmaz.
- Siparişin kanalı body’deki
channelalanından belirlenir.
Node.js
Bölüm başlığı “Node.js”export async function sendOrders(orders) { const answer = await fetch(`${process.env.SAYPROOF_BASE}/v1/ingest/orders`, { method: "POST", headers: { "Content-Type": "application/json", Authorization: `Bearer ${process.env.SAYPROOF_SERVER_KEY}`, }, body: JSON.stringify({ channel: "web", orders }), }); if (!answer.ok) throw new Error(`sayproof_ingest_${answer.status}: ${await answer.text()}`); return answer.json();}Python
Bölüm başlığı “Python”import jsonimport os
import requests
def send_orders(orders): body = json.dumps({"channel": "web", "orders": orders}, ensure_ascii=False).encode("utf-8") answer = requests.post( f"{os.environ['SAYPROOF_BASE']}/v1/ingest/orders", data=body, headers={ "Content-Type": "application/json", "Authorization": f"Bearer {os.environ['SAYPROOF_SERVER_KEY']}", }, timeout=10, ) answer.raise_for_status() return answer.json()function sayproof_send_orders(array $orders): array{ $body = json_encode(['channel' => 'web', 'orders' => $orders], JSON_UNESCAPED_UNICODE); $curl = curl_init(getenv('SAYPROOF_BASE') . '/v1/ingest/orders'); curl_setopt_array($curl, [ CURLOPT_POST => true, CURLOPT_POSTFIELDS => $body, CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 10, CURLOPT_HTTPHEADER => [ 'Content-Type: application/json', 'Authorization: Bearer ' . getenv('SAYPROOF_SERVER_KEY'), ], ]); $answer = curl_exec($curl); $status = curl_getinfo($curl, CURLINFO_RESPONSE_CODE); curl_close($curl); if ($answer === false || $status !== 200) { throw new RuntimeException('sayproof_ingest_' . $status); } return json_decode($answer, true);}Komut satırı
Bölüm başlığı “Komut satırı”curl -X POST "$SAYPROOF_BASE/v1/ingest/orders" \ -H "Content-Type: application/json" \ -H "Authorization: Bearer $SAYPROOF_SERVER_KEY" \ --data '{"channel":"web","orders":[]}'İmzalı gönderim isteğe bağlıdır. İsteklerini sunucu anahtarı yerine ortak bir şifreyle imzalamak isteyen ekipler için Kanallar › Anahtarlar sekmesinin altındaki Gelişmiş: imzalı gönderim şifreleri bölümünde İmzalı gönderim şifresi oluşturulur. İstekte Authorization: Bearer header’ı varsa Sayproof sunucu anahtarını, yoksa imzayı denetler. İmzalı her istek üç header taşır:
| Header | Değer |
|---|---|
X-Sayproof-Secret |
İmzalı gönderim şifresinin kimliği: İmzalı gönderim şifreleri tablosunun Şifre kimliği sütunu. Şifrenin adı gönderilmez. |
X-Sayproof-Timestamp |
İsteğin zamanı; saat dilimi içeren ISO 8601 biçiminde: 2026-09-28T07:30:00Z ya da 2026-09-28T10:30:00+03:00 |
X-Sayproof-Signature |
hex(HMAC-SHA256(şifre, zaman + "." + body)) |
Kurallar:
- İmza, gönderilen byte’ların kendisi üzerinden hesaplanır. İmzaladıktan sonra JSON’u yeniden biçimlendirmeyin ve boşluk eklemeyin.
- İstek zamanı Sayproof’un saatinden en fazla 5 dakika farklı olabilir; sunucunuzun saati senkronize olmalıdır.
- Saat dilimi içermeyen zaman değerleri (
2026-09-28T10:30:00) reddedilir. - Şifrenin kendisi hiçbir istekte gönderilmez; yalnızca imzayı hesaplamak için kullanılır.
import { createHmac } from "node:crypto";
export async function sendOrdersSigned(orders) { const body = JSON.stringify({ channel: "web", orders }); const timestamp = new Date().toISOString(); const signature = createHmac("sha256", process.env.SAYPROOF_INGEST_SECRET) .update(`${timestamp}.${body}`) .digest("hex"); const answer = await fetch(`${process.env.SAYPROOF_BASE}/v1/ingest/orders`, { method: "POST", headers: { "Content-Type": "application/json", "X-Sayproof-Secret": process.env.SAYPROOF_INGEST_SECRET_ID, "X-Sayproof-Timestamp": timestamp, "X-Sayproof-Signature": signature, }, body, }); if (!answer.ok) throw new Error(`sayproof_ingest_${answer.status}: ${await answer.text()}`); return answer.json();}Sipariş verisi
Bölüm başlığı “Sipariş verisi”Tek bir sipariş ya da en fazla 100 siparişten oluşan bir liste gönderilebilir:
{ "channel": "web", "orders": [ { "external_id": "ORD-1001", "payment_state": "paid", "market": "TR", "language": "tr", "placed_at": "2026-09-25T10:00:00+03:00", "customer_email": "ayse@ornek.com", "customer_key": "musteri-4821", "items": [ { "line_reference": "1", "variant_key": "URUN-38", "group_key": "URUN", "title": "Koşu ayakkabısı", "quantity": 1, "fulfilment_state": "delivered", "delivered_at": "2026-09-27T09:00:00+03:00" } ] } ]}| Alan | Zorunlu | Açıklama |
|---|---|---|
channel |
Hayır | Kanal kodu (en fazla 32 karakter). Body’nin en üstünde verilirse istekteki tüm siparişlere, siparişin içinde verilirse yalnızca o siparişe uygulanır; ikisi birden verilmişse siparişteki değer geçerlidir. Hiçbiri verilmezse siparişin mevcut kanalı korunur. |
external_id |
Evet | Sipariş numarası (en fazla 128 karakter). Müşterinin sipariş doğrulamasında gireceği numaradır; büyük/küçük harfe duyarlıdır. |
payment_state |
Evet | pending, paid, partially_refunded, refunded, voided. Yorum ve davet için paid ya da partially_refunded gerekir. |
market |
Hayır | Pazar kodu; örneğin TR. Belirtilmezse kanalın pazarı kullanılır. Kanalın pazarından farklı bir pazar gönderilirse sipariş reddedilir (market_channel_mismatch: <pazar>). |
language |
Hayır | tr ya da en. Belirtilmezse kanalın dili kullanılır. |
placed_at |
Evet | Sipariş zamanı; saat dilimiyle birlikte. |
customer_email |
Hayır | Siparişteki e-posta adresi (en fazla 254 karakter). Davet bu adrese gönderilir; sipariş doğrulamasında ve oturum açmış müşteri sorgusunda bu adres kullanılır. Adres gönderilmezse davet gönderilmez. |
customer_key |
Hayır | Müşterinin sizin sisteminizdeki kimliği (en fazla 128 karakter). Günlük davet sınırı ve seri gönderim kontrolü bu kimliğe göre, kimlik yoksa e-posta adresine göre uygulanır. |
customer_phone |
Hayır | Siparişteki telefon numarası (en fazla 32 karakter); alan kabul edilir. Numara WhatsApp ile davet için kullanılacak. WhatsApp ile davet v2 sürümüyle gelene kadar telefon numarası saklanmaz. Sonra numara uluslararası biçimde saklanacak (+905321112233); ülke kodu olmayan numara kanalın pazarına göre tamamlanacak (Türkiye pazarında 0532 111 22 33 → +905321112233), tamamlanamayan numara saklanmayacak. |
items[] |
Evet | Sipariş satırları. |
Siparişteki e-posta adresi, telefon ve müşteri numarası, yorum yazma süresi bitince ya da müşterinin KVKK silme talebiyle takma değere çevrilir; aynı sipariş sonradan yeniden gönderilse de bu alanlar geri yazılmaz, sipariş aynı kayda işlenir. Ayrıntılar için: Saklama süreleri.
Sipariş satırı alanları:
| Alan | Zorunlu | Açıklama |
|---|---|---|
line_reference |
Evet | Satırın sipariş içindeki kimliği (en fazla 128 karakter). Her satır için bir yorum yazılabilir. |
variant_key |
Evet | Ürün kodu (en fazla 128 karakter). Sayfadaki container’ın data-review-product değeriyle aynı olmalıdır. |
group_key |
Hayır | Ürün grubu kodu (en fazla 128 karakter). Grup düzeyinde yorum gösterimi için gereklidir. |
catalog_id |
Hayır | Ürünün katalogdaki kimliği (en fazla 128 karakter). |
title |
Hayır | Ürün adı (en fazla 300 karakter). Yorum formunda gösterilir. |
quantity |
Hayır | Adet; varsayılan 1. |
fulfilment_state |
Hayır | placed (varsayılan), preparing, shipped, in_transit, delivered, cancelled, returned. |
delivered_at |
Hayır | Teslim zamanı. delivered durumundaki satırlarda gönderilmesi önerilir. Daha önce iade ya da iptal edilmiş bir satır delivered_at olmadan yeniden delivered durumuyla gelirse bu durum yok sayılır; satır gerçekten yeniden teslim edildiyse teslim zamanını gönderin. |
Durum alanları yalnızca yukarıdaki değerleri kabul eder; kendi sisteminizdeki durum adlarını gönderirken bu değerlere dönüştürün.
Sipariş verisinde delivered, returned ya da cancelled durumuyla gelen satırlar için Sayproof bir teslimat kaydı oluşturur; bu durumda teslimat endpoint’ine ayrıca istek göndermeniz gerekmez.
İade ve iptal bilgisi yorumdan sonra da önemlidir. Siparişin ödemesi refunded ya da voided durumuna geçtiğinde ya da bir satır returned olarak bildirildiğinde, o siparişe ya da satıra daha önce yazılmış yorumların satın alma kanıtına “Yorumdan sonra iade edildi” işareti düşer ve otomatik kontroller yeniden çalışır. Alışveriş deneyimi davetiyle yazılmış yorumlar zaten iptal ya da iade sonrasında yazıldığı için bu işareti almaz. İptal ya da iade edilen ve henüz yorumlanmamış satırlar için alışveriş deneyimi daveti oluşturulur; bkz. Davetler ve e-postalar.
{ "accepted": 1, "orders": [{ "external_id": "ORD-1001", "id": "…" }] }Liste bütün olarak işlenir: siparişlerden biri reddedilirse aynı istekteki diğer siparişler de kaydedilmez. Hata yanıtındaki kod, sorunlu alanı belirtir.
Teslimat verisi
Bölüm başlığı “Teslimat verisi”Sipariş verisiyle birlikte gönderilmeyen teslimat değişiklikleri için:
{ "deliveries": [ { "external_id": "ORD-1001", "line_reference": "1", "state": "delivered", "observed_at": "2026-09-27T09:00:00+03:00", "source": "carrier" } ]}| Alan | Zorunlu | Açıklama |
|---|---|---|
external_id, line_reference |
Evet | Hangi siparişin hangi satırı olduğu. |
state |
Evet | Sipariş satırıyla aynı değerler. |
observed_at |
Evet | Durumun gözlendiği zaman; saat dilimiyle birlikte. |
source |
Hayır | platform (varsayılan), carrier, manual, estimated. |
confidence |
Hayır | verified (varsayılan) ya da estimated. |
detail |
Hayır | Kabul edilir ama saklanmaz; teslim alan kişinin adı ya da adres gibi bilgi göndermeyin. |
Tahmine dayalı bilgi (estimated kaynak ya da güven değeri) kanıt sayılmaz; “kargo 3 günde teslim eder” gibi bir tahmin davet ya da yorum hakkı oluşturmaz. Tahmine dayalı bir delivered bilgisi satırın durumunu da belirlemez: kayıtlı kalır ancak daha önce ya da sonra gelen doğrulanmış teslimat bilgisini gizlemez. Yalnızca gerçekleştiği doğrulanan teslimat bilgisini gönderin.
Tanınmayan satırlar isteğin başarısız olmasına neden olmaz; yanıttaki unknown listesinde döner:
{ "accepted": 1, "unknown": [{ "external_id": "ORD-9", "line": "2" }] }Hatalar
Bölüm başlığı “Hatalar”| Yanıt | Anlamı |
|---|---|
401 refused / unknown_key |
Sunucu anahtarı tanınmıyor. Biçimi hatalı anahtarda ayrıntı malformed_key olur. Anahtarın tamamının Bearer önekinden sonra gönderildiğini kontrol edin. |
401 refused / revoked_key |
Sunucu anahtarı iptal edilmiş. Yeni bir sunucu anahtarı oluşturun. |
403 refused / scope_missing |
Anahtarın sipariş gönderme (orders) izni yok. |
401 signature_refused / signature_mismatch |
İmzalı gönderimde imza eşleşmiyor. Body’nin imzalandıktan sonra değişip değişmediğini ve doğru şifrenin kullanıldığını kontrol edin. |
401 signature_refused / timestamp_outside_window |
Zaman farkı 5 dakikadan fazla. Sunucu saatini senkronize edin. |
401 signature_refused / timestamp_invalid |
Zaman değeri okunamadı ya da saat dilimi içermiyor. |
401 signature_refused / secret_unknown |
Şifre kimliği tanınmıyor ya da şifre iptal edilmiş. Özel amaçlı şifreler (bildirim adresi, e-posta teslim bildirimi) sipariş aktarımını imzalayamaz. İstekte Authorization: Bearer header’ı yoksa istek imzalı gönderim sayıldığı için de bu yanıt döner. |
400 invalid / field_missing: <alan> |
Zorunlu bir alan eksik. field_invalid ve field_too_long biçim ve uzunluk hatalarını bildirir. |
400 invalid / market_without_policy: <pazar> |
Bu pazar için tanımlı kural yok. |
400 invalid / status_unmapped: …/<değer> |
Durum değeri tanınmıyor. Yukarıdaki değerlerden birini gönderin. |
400 invalid / channel_unknown |
Kanal kodu yanlış ya da kanal kapalı. |
400 invalid / market_channel_mismatch: <pazar> |
Siparişin pazarı, siparişin bağlandığı kanalın pazarıyla aynı değil. |
400 invalid / batch_too_large: 100 |
Tek istekte 100’den fazla sipariş gönderildi. |
429 rate_limited |
Sunucu anahtarı ya da şifre başına 5 dakikada 600 istek sınırı aşıldı. |
Bağlantı denemesi
Bölüm başlığı “Bağlantı denemesi”Paneldeki Entegrasyon › Sipariş aktarımı sekmesinin Mağazadan gönderim bölümündeki Bağlantıyı dene işlemi, mağaza sisteminizin göndereceği veriyi kaydetmeden sınar. Formda yalnızca Ne gönderilecek? (Sipariş ya da Teslimat) seçilir ve Gönderilecek içerik girilir; anahtar ya da şifre istenmez. Sonuç, verinin kabul edilip edilmediğini ve kaç kaydın kabul edileceğini gösterir; hiçbir kayıt oluşturulmaz.
Aynı kartta Son gelen siparişler satırı seçilen kanala gelen siparişleri sayar. Sipariş aktarımı durumu (tüm kanallar) bölümündeki son 7 günün istek sayıları ve Son istekler listesi ise bütün kanalları kapsar.