Nordlet

← Belgeler / Kılavuzlar

API kuralları

İstek biçimi, yetkilendirme kapsamları (scope), liste sorguları, para birimleri, hatalar, tekilleştirme (idempotency) ve oran limitleri (rate limit).

İstek biçimi

Her işlem, RPC tarzı bir POST isteğidir:

POST /v1/{module}/{resource}/{action}

Modüller: reference, partners, catalog, sales, purchases, ledger, bank, declarations, files, webhooks, audit. Eylemler ise birer fiştir: create, get, update, delete, list ile birlikte issue, register, match, apply-advance, generate gibi etki alanına özel eylemler.

Kimlik doğrulama ve kapsamlar (scopes)

Authorization: Bearer <api key>. Anahtarlar, her işlemde kontrol edilen kapsamlar barındırır:

  • {module}:read - get/list (getirme/listeleme) eylemleri
  • {module}:write - veri değiştiren (mutation) işlemler
  • {module}:* veya * - tüm yetkileri kapsayan joker karakterler (wildcard)

Eksik kapsam -> 403 forbidden (yasak). Eksik veya geçersiz anahtar -> 401 unauthorized (yetkisiz).

Liste sorguları

Tüm list eylemleri ortak bir sözleşmeyi (contract) paylaşır:

{
  "page": 1,
  "pageSize": 50,
  "sort": [{ "field": "createdAt", "dir": "desc" }],
  "filter": [{ "field": "paymentStatus", "op": "eq", "value": "unpaid" }]
}

Filtre operatörleri: eq (eşit), ne (eşit değil), contains (büyük/küçük harf duyarsız metin eşleşmesi, yalnızca metin alanları için), gte (büyük veya eşit), lte (küçük veya eşit), in (en fazla 500 değer içeren bir listedeki herhangi bir değer). Sıralanabilir ve filtrelenebilir alanlar uç nokta (endpoint) bazında beyaz listede tanımlanmıştır (bkz. OpenAPI belirtimi); bilinmeyen alanlar 400 hatası döndürür. Eşleşen tüm satırlar üzerinden sayısal alanların toplamını almak için isteğe totals: ["field", …] ekleyin; kayıtlar bir para birimi içerdiğinde totalsByCurrency parametresi, aynı toplamları para birimi kodlarına göre ayrı ayrı sunar. Yanıtlar: { rows, total, page, pageSize, totals?, totalsByCurrency? }.

Para birimleri ve tarihler

Parasal değerler, asla kayan noktalı sayı (float) olmamak şartıyla, en fazla 4 ondalık basamağa sahip ondalık dizelerdir ("121.0000"). KDV (VAT), yarı yukarı yuvarlama (half-up rounding) kuralıyla her satır için ayrı hesaplanır. Tarihler YYYY-MM-DD biçimindedir; zaman damgaları ise ISO 8601 UTC standardındadır.

Hatalar

Her yerde tek bir zarf biçimi kullanılır:

{
  "error": {
    "code": "validation",
    "message": "Request validation failed",
    "requestId": "k1x…",
    "key": "request_invalid",
    "fieldErrors": { "lines.0.unitPriceExclVat": ["Invalid value"] }
  }
}

Kodlar: validation (400/422, ayrıca yüklenen bir dosya veya istek gövdesi çok büyük olduğunda 413), unauthorized (401), payment_required (402, deneme süresi veya ön ödemeli bakiye sona ermiştir; hata mesajı nasıl devam edileceğini belirtir), forbidden (403), not_found (404), conflict (409), idempotency_key_reuse (422), idempotency_in_progress (409), rate_limited (429), internal (5xx). Mesaj sabit mesajlardan biri olduğunda, istemcinin kendi çevirisini gösterebilmesi için key alanı bunun adını tutar, params alanı ise mesajın içine gelecek değerleri barındırır (örneğin kilitli bir muhasebe dönemi için { "period": "2026-09" }). Sorun bildirirken requestId değerini mutlaka ekleyin.

Tekilleştirme (Idempotency)

Veri değiştiren herhangi bir çağrıya Idempotency-Key: <en fazla 255 karakterlik herhangi bir dize> başlığını ekleyin:

  • Aynı anahtar ve yükle (payload) ile yeniden deneme -> saklanan yanıt x-idempotent-replay: true başlığıyla bayt bayt yeniden oynatılır.
  • Aynı anahtar, farklı yük -> 422 idempotency_key_reuse.
  • Birinci istek henüz işlenirken gelen eş zamanlı mükerrer istek -> 409 idempotency_in_progress.
  • Anahtarlar, çağrının yapıldığı şirket dahilinde, onları gönderen API anahtarına veya kullanıcıya aittir; böylece bir şirketin iki ayrı entegrasyonu aynı anahtarı kullanabilir. Bir şirket var olmadan önce yapılan çağrılar ve account/* çağrıları, anahtarları kullanıcı bazında tutar; bu sayede tekrarlanan bir account/companies/create çağrısı yalnızca tek bir şirket oluşturur.
  • Saklanan bir yanıt, ancak çağrıyı yapan taraf yetki kontrollerini (kapsam, rol, şirket ve faturalandırma durumu) yeniden başarıyla geçtikten sonra döndürülür; aksi takdirde çağrı güncel hatayı alır.
  • Anahtarlar 24 saat sonra geçerliliğini yitirir. Hata yanıtları (4xx) da yeniden oynatılır; 5xx yanıtları saklanmaz, bu nedenle yeniden denemeler işlemi tekrar çalıştırır.

Oran limitleri (Rate limits)

API anahtarı başına dakikada 300 istek (sunulan kimlik bilgisi başına; kimlik doğrulanmamış istekler IP bazında sınırlandırılır). 429 hatası alındığında retry-after başlığına uyun. x-ratelimit-* başlıkları kullanım kotanızı bildirir.

Webhook'lar

Olaylar (events), değişiklik ile aynı veritabanı işleminde (transaction) işlemsel bir giden kutusuna (outbox) yazılır; geri alınan (rolled-back) bir belge asla olay tetiklemez ve hiçbir olay kaybolmaz. Teslimat mekanizması:

  • Olay JSON verisiyle URL adresinize bir POST isteği gönderilir
  • Teslimatın imzalandığı zamanı belirten x-nordlet-timestamp: <unix saniye> başlığı eklenir
  • Abonelik sırrınız (secret) kullanılarak oluşturulan x-nordlet-signature-v2: t=<timestamp>,v1=<"<timestamp>.<raw body>" ifadesinin onaltılık (hex) HMAC-SHA256 özeti> başlığı eklenir
  • Mevcut alıcılar için değiştirilmeden tutulan x-nordlet-signature: sha256=<ham gövdenin onaltılık HMAC-SHA256 özeti> başlığı eklenir
  • Teslimat kimliğini taşıyan ve bir teslimatın tüm yeniden denemelerinde aynı kalan x-nordlet-delivery başlığı eklenir
  • 2xx dışı bir yanıt veya yönlendirme (redirect) alındığında; teslimat başarısız olarak işaretlenmeden önce sırasıyla 30 saniye, 2 dakika, 10 dakika, 30 dakika, 1 saat, 3 saat, 6 saat ve 12 sonra (toplamda yaklaşık 24 saat içinde) yeniden denenir
  • Her teslimat aynı anda tek bir sunucu tarafından gönderilir, bu nedenle birden fazla API örneğini (instance) çalıştırmak teslimatın iki kez gönderilmesine neden olmaz

Yük güvenilir kabul edilmeden önce x-nordlet-signature-v2 doğrulaması sabit zamanlı karşılaştırma (constant-time comparison) ile yapılmalı ve zaman damgası saatinizle 5 dakikadan fazla fark olan teslimatlar reddedilmelidir. Zaman damgası imzalanan metnin bir parçası olduğu için, yakalanan bir teslimat daha sonra yeni bir zaman damgasıyla yeniden oynatılamaz. Söz konusu zaman penceresi içindeki mükerrer bildirimleri yok saymak için işlediğiniz x-nordlet-delivery kimliklerini saklayın. Başarısız bir teslimat webhooks/deliveries/redeliver kullanılarak yeniden gönderilebilir.

Denetim (Audit)

Her veri değiştirme işlemi (actor, action, entity, diff) kaydedilir ve audit/list aracılığıyla sorgulanabilir.

Muhasebe garantileri

  • Yevmiye kayıtları dengelidir; bu kural yalnızca uygulama koduyla değil, işlem onay (commit) anında ertelenmiş bir veritabanı tetikleyicisi (database trigger) ile zorunlu kılınır.
  • Belge numaraları seri/yıl bazında boşluksuzdur (gapless); numara tahsisi eş zamanlılık güvenlidir (concurrency-safe).
  • Kilitli muhasebe dönemleri, içine tarihlendirilmiş her türlü kaydı reddeder (409).
  • Mantıksal olarak silinen (soft-deleted) belgeler denetim izlerini (audit trail) korur; tescil edilmiş veya resmiyet kazanmış belgeler silinemez.