# Ingest API

> Sipariş, teslimat ve e-posta olaylarını Sayproof'a gönderen sunucu endpoint'lerinin özeti.

Kaynak: /tr/reference/ingest-api/

Bu endpoint'lere istek sunucudan sunucuya gönderilir. Ayrıntılı açıklama ve dil bazında örnek kodlar için: [Sipariş ve teslimat aktarımı](/tr/integrate/orders.md), [E-posta teslim bildirimleri](/tr/integrate/email-events.md).

## Kimlik doğrulama

| Endpoint | Yöntem |
|---|---|
| `/v1/ingest/orders`, `/v1/ingest/deliveries` | `Authorization: Bearer <sunucu-anahtarı>`; anahtarın sipariş gönderme (`orders`) izni olmalıdır. İsteğe bağlı olarak imzalı gönderim şifresiyle imza da kullanılabilir. |
| `/v1/mail-events/generic` | E-posta teslim bildirimi şifresiyle imza |

İstekte `Authorization: Bearer` header'ı varsa sunucu anahtarı denetlenir; yoksa aşağıdaki imza header'ları aranır.

## İmza

| Header | Değer |
|---|---|
| `X-Sayproof-Secret` | Şifre kimliği (panelde şifre tablosunun **Şifre kimliği** sütunu; şifrenin adı değil) |
| `X-Sayproof-Timestamp` | Saat dilimini içeren ISO 8601 zaman değeri; Sayproof'un saatinden en fazla ±5 dakika farklı olabilir |
| `X-Sayproof-Signature` | `hex(HMAC-SHA256(şifre, zaman + "." + body))` |

İmza, gönderilen byte'ların kendisi üzerinden hesaplanır.

## Endpoint'ler

| Endpoint | Body | Yanıt |
|---|---|---|
| `POST /v1/ingest/orders` | Tek bir sipariş ya da `{"channel", "orders": […]}` (en fazla 100 sipariş) | `{"accepted", "orders": [{"external_id", "id"}]}` |
| `POST /v1/ingest/deliveries` | Tek bir teslimat ya da `{"deliveries": […]}` (en fazla 100 kayıt) | `{"accepted", "unknown": [{"external_id", "line"}]}` |
| `POST /v1/mail-events/generic` | Tek bir olay ya da `{"events": […]}` (en fazla 500 olay) | `{"accepted", "matched", "duplicates", "ignored", "opted_out"}` |

E-posta hizmetlerine özel endpoint'lerde (`/v1/mail-events/ses`, `sendgrid`, `postmark`, `mailgun`) imza yerine adreste markaya özel bir erişim kodu bulunur; bu adresler panelde gösterilir.

## Davranış

- **Sipariş listesi bütün olarak işlenir.** Siparişlerden biri reddedilirse aynı istekteki diğer siparişler de kaydedilmez.
- **`channel` body'nin en üstünde, her siparişte ya da ikisinde birden verilebilir**; ikisi birden verilmişse siparişteki değer geçerlidir. Siparişin pazarı kanalın pazarıyla aynı olmalıdır; değilse istek `400 invalid / market_channel_mismatch: <pazar>` yanıtı alır.
- `external_id`, `line_reference`, `variant_key`, `group_key`, `catalog_id` ve `customer_key` en fazla 128 karakter olabilir.
- **Aynı sipariş yeniden gönderildiğinde güncellenir**, kopyası oluşturulmaz. Sonraki gönderimde yer almayan sipariş satırları silinmez. Müşteri bilgileri takma değere çevrilmiş bir sipariş yeniden gönderilirse `customer_email`, `customer_phone` ve `customer_key` geri yazılmaz.
- **Teslimat listesinde tanınmayan satırlar isteğin başarısız olmasına neden olmaz**; yanıttaki `unknown` listesinde döner. Tanınmayan bir durum değeri ise isteğin tamamının geri alınmasına neden olur.
- **Aynı teslimat bilgisi** (aynı satır, durum, kaynak ve zaman) ikinci kez kaydedilmez.
- **Tahmine dayalı bir `delivered` bilgisi** satırın durumunu belirlemez ve doğrulanmış teslimat bilgisini gizlemez.
- **İade ya da iptal edilmiş bir satır** sipariş verisinde `delivered_at` olmadan yeniden `delivered` olarak gelirse bu durum yok sayılır.
- **Ödeme `refunded` ya da `voided` durumuna geçtiğinde** ya da satır `returned` olarak bildirildiğinde, daha önce yazılmış ürün yorumlarının kanıtına "Yorumdan sonra iade edildi" işareti düşer ve otomatik kontroller yeniden çalışır; süreç deneyimi yorumları bu işareti almaz.
- **Aynı e-posta olayı** (aynı `event_id`) ikinci kez işlenmez.

## Değer listeleri

| Alan | Değerler |
|---|---|
| `payment_state` | `pending`, `paid`, `partially_refunded`, `refunded`, `voided` |
| `fulfilment_state`, `state` | `placed`, `preparing`, `shipped`, `in_transit`, `delivered`, `cancelled`, `returned` |
| `source` | `platform`, `carrier`, `manual`, `estimated` |
| `confidence` | `verified`, `estimated` |
| E-posta olayı `type` | `delivered`, `deferred`, `bounced`, `complained`, `opened`, `unsubscribed` |

Hata kodları için: [Hata kodları › Aktarım](/tr/reference/errors.md#aktarim).

## Örnek: ortak istek fonksiyonu

Sipariş ve teslimat endpoint'lerine istek sunucu anahtarıyla, e-posta olaylarına E-posta teslim bildirimi şifresiyle imzalanarak gönderilir. Aşağıdaki yardımcı fonksiyon ikisini de karşılar: sunucu anahtarı verilirse `Authorization` header'ını, şifre verilirse imza header'larını ekler.

```js
import { createHmac } from "node:crypto";

export async function sayproofPost(path, payload, auth) {
  const body = JSON.stringify(payload);
  const headers = { "Content-Type": "application/json" };
  if (auth.serverKey) {
    headers.Authorization = `Bearer ${auth.serverKey}`;
  } else {
    const timestamp = new Date().toISOString();
    headers["X-Sayproof-Secret"] = auth.secretId;
    headers["X-Sayproof-Timestamp"] = timestamp;
    headers["X-Sayproof-Signature"] = createHmac("sha256", auth.secret).update(`${timestamp}.${body}`).digest("hex");
  }
  const answer = await fetch(`${process.env.SAYPROOF_BASE}${path}`, {
    method: "POST",
    headers,
    body,
    signal: AbortSignal.timeout(10000),
  });
  const result = await answer.json().catch(() => ({}));
  if (!answer.ok) throw new Error(`${answer.status} ${result.error ?? ""} ${result.detail ?? ""}`.trim());
  return result;
}

await sayproofPost(
  "/v1/ingest/deliveries",
  {
    deliveries: [
      { external_id: "ORD-1001", line_reference: "1", state: "delivered", observed_at: "2026-09-27T09:00:00+03:00", source: "carrier" },
    ],
  },
  { serverKey: process.env.SAYPROOF_SERVER_KEY }
);
```
