<!-- Source: https://docs.infraio.xyz/tr/api-reference/authentication -->
<!-- Last updated: 2026-10-04 -->

# Kimlik doğrulama

InfraIO Pay'in farklı auth modelleriyle **iki API yüzeyi** vardır. Kimin
çağırdığına uyanı seçin:

| Yüzey | Yol öneki | Hedef kitle | Auth |
| --- | --- | --- | --- |
| **Satıcı B2B** | `/b2b/v1/*` | Sunucunuz | HMAC-SHA256 istek imzalama |
| **Panel** | Satıcı paneli tarafından kullanılır | Satıcı paneli için tarayıcı oturumları | Bearer JWT |

Bu sayfa **B2B** yüzeyini kapsar; bir API anahtar çifti ile sunucunuzdan
çağırdığınız yüzey. Panel yüzeyi InfraIO Pay satıcı paneli tarafından
kullanılır ve herkese açık bir entegrasyon yüzeyi değildir.

İsteklerde her zaman `/b2b` öneki dahil tam yolu gönderin ve aynı yolu
imzalayın (aşağıya bakın).

## Uç noktalar

| Ortam | Temel URL |
| --- | --- |
| Test | `https://api-dev.infraio.xyz` |
| Canlı | `https://api.infraio.xyz` |

Aynı URL deseni — ortam, URL ile değil, **anahtar öneki** ile kontrol
edilir (`pk_test_…` vs `pk_live_…`).

## Anahtar çifti

Satıcı panelinden iki değer alırsınız (**Geliştiriciler → API anahtarları
→ + Anahtar ekle**):

- **Publishable key** (`pk_test_…` veya `pk_live_…`) — hesabınızı
  tanımlar. `X-Client-ID` olarak gönderilir. Tarayıcı paketinize gömmek
  güvenlidir (SDK bunu zaten yapar).
- **Secret key** (`sk_test_…` veya `sk_live_…`) — HMAC imzalama anahtarı.
  Yalnızca sunucu. Bir veritabanı şifresi gibi davranın.

> **Important:**
>
> Bir secret key bir tarayıcı paketine, git deposuna, log satırına veya
> paylaşılan sohbete düşerse — panelden **hemen iptal edin**.
> İptal anlıktır, çakışma penceresi yoktur. Yeni bir anahtar verin ve
> yeniden dağıtın.

## Bir isteği imzalama

`/b2b/v1/*`'a yapılan her çağrı üç başlık taşır:

```http
X-Client-ID:  pk_live_70d0becbd7a53047b0dfe88a960d10ad
X-Timestamp:  1715990400
X-Signature:  9a8b7c6d…             (hex HMAC-SHA256)
```

İmza bir kanonik dize üzerinde hesaplanır:

```
METHOD + "\n" + PATH + "\n" + TIMESTAMP + "\n" + BODY
```

- `METHOD` — büyük harf HTTP fiili (`POST`, `GET`, …).
- `PATH` — host olmadan ve **query string olmadan**, `/b2b` öneki
  **dahil** istek yolu (örn. `/b2b/v1/checkout-sessions/quick`). Önek
  mevcut olmalıdır. Query parametreleri imzalanmaz — bir
  `GET …?cursor=…&limit=20` için yalnızca yolu imzalayın, `?…` kısmını
  değil.
- `TIMESTAMP` — unix saniye, ondalık string olarak (örn. `"1715990400"`),
  `X-Timestamp` ile tam olarak eşleşmelidir.
- `BODY` — ham istek gövdesi baytları. `GET`/`DELETE` için boş string.

**Secret** anahtarla HMAC-SHA256 ile imzalayın, çıktı **hex**:

**Node / TS**

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

function sign({ method, path, body, secret }: {
  method: string; path: string; body: string; secret: string;
}) {
  const timestamp = Math.floor(Date.now() / 1000).toString();
  const input = [method.toUpperCase(), path, timestamp, body].join("\n");
  const signature = createHmac("sha256", secret).update(input).digest("hex");
  return { timestamp, signature };
}
```

**Go**

```go
package infraio

import (
    "crypto/hmac"
    "crypto/sha256"
    "encoding/hex"
    "strconv"
    "time"
)

func Sign(method, path, body, secret string) (timestamp, signature string) {
    timestamp = strconv.FormatInt(time.Now().Unix(), 10)
    input := method + "\n" + path + "\n" + timestamp + "\n" + body
    mac := hmac.New(sha256.New, []byte(secret))
    mac.Write([]byte(input))
    return timestamp, hex.EncodeToString(mac.Sum(nil))
}
```

**Python**

```python
import hmac, hashlib, time

def sign(method: str, path: str, body: str, secret: str):
    timestamp = str(int(time.time()))
    input_ = f"{method}\n{path}\n{timestamp}\n{body}"
    signature = hmac.new(
        secret.encode(), input_.encode(), hashlib.sha256
    ).hexdigest()
    return timestamp, signature
```

## Neden HMAC, Bearer değil?

Bir çıplak Bearer-token API'si, her istekte tek secret'ınızı tel
üzerinden gönderir. Bir TLS-sonlandırılmış proxy logu yakalayan herkes
hesabınızın anahtarlarını alır. HMAC imzalama, secret'ın asla
seyahat etmediği anlamına gelir — yalnızca türetilmiş imzası, ki bu da
tek kullanımlıktır (o tam isteğe + o tam dakikaya bağlı).

Ödünleşim: her çağrı için bir imza hesaplarsınız. Henüz bir sunucu SDK'sı
yok, ancak yukarıdaki yardımcı dil başına yaklaşık 15 satırdır.

## Timestamp toleransı

Tolerans **±5 dakikadır** (300 saniye). Bu pencerenin dışındaki bir
istek `401 invalid_signature` ile reddedilir. İki sonuç:

1. **Sunucu saatinizi NTP ile senkronize edin.** Kaymış saatli uzun süre
   çalışan bir cron aralıklı olarak başarısız olur.
2. **İmzaları önceden hesaplayıp kuyruğa almayın.** Bir istek bir yeniden
   deneme kuyruğunda >5 dakika oturursa, imzasının süresi dolar.

## Anahtar scope'ları

Secret anahtarlar şu scope demetlerinden bir veya daha fazlasını taşır:

| Scope | Kullanım amacı |
| --- | --- |
| `read` | Siparişleri, oturumları, iadeleri listele/oku |
| `write_order` | Checkout oturumları, siparişler oluştur |
| `write_refund` | İadeler ver, iade-talep token'ları üret |
| `webhook_manage` | Webhook uç noktalarını oluştur/güncelle/sil |

Panel varsayılan olarak bir "tam erişim" anahtarı verir (dört scope da).
Entegrasyonun ihtiyaç duyduğu scope'ları işaretleyerek
**Geliştiriciler → API anahtarları → + Anahtar ekle** üzerinden kısıtlı
scope'lu bir anahtar üretebilirsiniz.

> **Warning:**
>
> **Scope'lar henüz uygulanmıyor.** Scope'lar anahtarda kaydedilir ve
> panelde gösterilir, ancak herhangi bir geçerli `sk_…` anahtarı
> satıcınız için herhangi bir `/b2b/v1/*` uç noktasını çağırabilir.
> Scope'lara güvenlik sınırı olarak güvenmeyin. Erişimi kısıtlamak için
> anahtarları rotate edin veya iptal edin.

## Başarısız doğrulama

İmza, `X-Client-ID` veya timestamp geçersizse istek, API'ye ulaşmadan
**401 `INVALID_SIGNATURE`** ile reddedilir. Yalnızca `/b2b/v1/*` istekleri
bu şekilde imzalanır. Webhook'lar ayrı bir şema kullanır (aşağıya bakın).

## Sırada ne var

- [Hatalar](https://docs.infraio.xyz/tr/api-reference/errors) — 4xx/5xx'te yanıt şekli.
- [Güvenlik → API anahtarları](https://docs.infraio.xyz/tr/security/api-keys) — rotation, iptal,
  bir secret sızarsa ne yapılacağı.
- [Webhook'lar → İmza doğrulama](https://docs.infraio.xyz/tr/webhooks/signature-verification) —
  *farklı* bir HMAC şeması kullanır (`X-Signature: sha256=…` başlığı,
  `X-Timestamp + "." + raw_body` imzalar, artı 24 saatlik rotation kayma
  penceresinde opsiyonel bir `X-Signature-Prev`). Şemaları karıştırmayın
  — hash algoritmasını paylaşırlar ama imzalanan baytlar ve secret ailesi
  (`whsec_…` vs `sk_…`) farklıdır.
