> ## Documentation Index
> Fetch the complete documentation index at: https://docs.azalt.co/llms.txt
> Use this file to discover all available pages before exploring further.

# Kaynak içe aktarma API'si

> Excel dosyası yüklemeden kaynak adaptörlerinize JSON veri gönderin; bulut ve şirket içi kurulumlarda aynı akışı kullanın

ERP veya başka bir sistemdeki satırları Excel dosyası yüklemeden doğrudan Azalt'a gönderin. Mevcut bir kaynak adaptörünü ID ile seçin; beklediği sayfa adlarını, sütun adlarını ve değerleri iletin. Azalt, `/data` sayfasındaki içe aktarmalarla aynı eşleme, doğrulama, yinelenen veri işleme, hesaplama, onay ve kaynak satırı geçmişi akışını kullanır.

Bu kılavuz kaynak adaptörü REST API'sini anlatır; MCP sunucusunu veya doğrudan aktivite oluşturmayı değil.

## Başlamadan önce

Kurulumunuz, JSON kaynak içe aktarma API'sini içeren sürümü ve veritabanı migrasyonunu kullanmalıdır. Kendi kurulumunuzun `/api/v1/openapi.json` dosyasında `/source-adapters` ve `/source-imports` yollarını kontrol edin; eski sürümlerde bu uç noktalar bulunmaz. Bu kılavuzun yayımlanması kurulumu güncellemez. Aşağıdaki [Şirket içi ve Helm split kurulumu](#şirket-içi-ve-helm-split-kurulumu) bölümüne bakın.

Gereksinimler:

* Organizasyon sahibi tarafından JSON API girdi sözleşmesi tanımlanmış, aktif bir kaynak adaptörü.
* İlgili organizasyonda **Ayarlar → API anahtarları** (`/settings/api-keys`) üzerinden alınmış bir API anahtarı. Entegrasyon için ayrı bir kullanıcı kullanın; anahtarı kaynak kodunda veya paylaşılan günlüklerde değil, bir gizli bilgi yönetim sisteminde saklayın.
* İçe aktarma göndermek ve çalıştırmak için **Collector**, **Approver**, **Manager** veya **Owner** rolü ve hedef lokasyonlara erişim. Adaptör keşfi ve izin verilen çalıştırmaları okumak için **Viewer** erişimi yeterlidir.
* Örnekleri uygulamak için `curl` ve `jq`.

İstekler `Authorization: Bearer YOUR_API_KEY` kullanır. Organizasyonu ve kullanıcıyı anahtar belirler; tarayıcıda organizasyonu değiştirmek anahtarın hedefini değiştirmez. Rol, aktif üyelik ve lokasyon erişimi güncel izinlere göre kontrol edilir.

`AZALT_API_KEY` ortam değişkenini güvenli biçimde ayarlayın. Temel URL olarak kendi kurulumunuzu kullanın; sonuna eğik çizgi veya `/api/v1` eklemeyin:

```bash theme={null}
export AZALT_API_URL="https://azalt.example.com"
```

Azalt Cloud için API sürümü oraya dağıtıldıktan sonra `https://app.azalt.co` kullanılır. Şirket içi entegrasyonlarda müşterinin kendi Azalt adresi kullanılır.

## 1. Adaptörü etkinleştirin

Organizasyon sahibi **Özelleştirme → Kaynak adaptörleri** bölümünden adaptörü düzenler ve **JSON API girdi sözleşmesi** alanını doldurur. Adaptörü aktif tutun ve yapılandırmayı kaydedin.

Aşağıdaki örnek kurgusal fatura değerleri içeren bir şablondur; tüm faturalar için ortak bir format değildir. Sözleşme, adaptör betiğinin kullandığı sayfa ve sütun adlarıyla eşleşmelidir. Sözleşme girdiyi tanımlar ve doğrular; betiği veya hedef eşlemelerini değiştirmez.

```json theme={null}
{
  "enabled": true,
  "context": { "yearRequired": true, "siteRequired": false },
  "sheets": [
    {
      "name": "Sheet1",
      "required": true,
      "additionalColumns": false,
      "fields": [
        {
          "name": "FATURA ID",
          "type": "string",
          "required": true,
          "example": "INV-2026-0001"
        },
        {
          "name": "TUTAR",
          "type": "number",
          "required": true,
          "example": -125.5
        },
        {
          "name": "BİRİM",
          "type": "string",
          "required": true,
          "example": "Litre"
        }
      ]
    }
  ]
}
```

Mevcut adaptörlerde JSON içe aktarma otomatik olarak açılmaz. Sözleşmeyi kaldırmak veya `enabled` değerini `false` yapmak, dosya yüklemelerini kapatmadan yeni JSON içe aktarmalarını durdurur. Daha önce kaydedilmiş önizlemeler eşlenmiş taslaklarını korur.

### Kabul edilen veri türleri

| Tür        | JSON örneği                   | Anlamı                                                                            |
| ---------- | ----------------------------- | --------------------------------------------------------------------------------- |
| `string`   | `"00001234"`                  | Metin; kimlik alanlarında baştaki sıfırları ve hassasiyeti korumak için kullanın. |
| `number`   | `-125.5`                      | Sonlu bir JSON sayısı; tırnak içinde sayısal metin değil.                         |
| `integer`  | `42`                          | JavaScript'in güvenli tamsayı aralığında bir tamsayı.                             |
| `boolean`  | `true`                        | JSON mantıksal değeri; `"true"` veya `1` değil.                                   |
| `date`     | `"2026-09-08"`                | `YYYY-MM-DD` biçiminde geçerli tarih.                                             |
| `datetime` | `"2026-09-08T10:30:00+03:00"` | Saat dilimi (`Z` veya fark) içeren ISO 8601 tarih-saat değeri.                    |

Alanlarda `description`, `example`, `required` (varsayılan `false`) ve `nullable` (varsayılan `false`) bulunabilir. `required`, anahtarın bulunmasını zorunlu kılar; metnin boş olmamasını değil. Açıkça `null` göndermek için `nullable: true` gerekir; gönderilmeyen isteğe bağlı alanlar doldurulmaz. Tarihler metin olarak kalır ve türler arasında otomatik dönüşüm yapılmaz. `"1.234,50"` gibi yerel biçimli tutarları yalnızca adaptörünüz bu biçimi ayrıştırıyorsa `string` olarak tanımlayın.

Sayfa ve sütun adları tam eşleşir, büyük/küçük harfe duyarlıdır. Bilinmeyen sayfalar reddedilir. Sayfada `additionalColumns: true` yoksa bilinmeyen sütunlar da reddedilir. Zorunlu sayfada en az bir satır bulunmalıdır. Adların başında/sonunda boşluk veya ayrılmış nesne anahtarları bulunamaz. Hücreler iç içe nesne veya dizi, NUL karakteri ya da geçersiz Unicode içeremez.

Boşluklar, sıfır, mantıksal değerler, null ve negatif sayılar dahil kaynak değerler korunur. Hedef tutarların pozitif olması gerekiyorsa dönüşümü adaptörde uygulayın; API otomatik olarak mutlak değer almaz. Kaydedilen kaynakta gönderilen negatif değer görünmeye devam eder.

## 2. Adaptörleri ve sözleşmelerini listeleyin

```bash theme={null}
curl --fail-with-body \
  "$AZALT_API_URL/api/v1/source-adapters?limit=50&offset=0" \
  -H "Authorization: Bearer $AZALT_API_KEY"
```

Yanıt, her adaptörün `id`, `name`, `description`, `isActive`, `apiReady` ve `adapterVersion` alanlarını içeren bir dizidir. `apiReady: true` olan bir adaptör seçin. Sonraki sayfa için `offset` değerini artırın; `limit` varsayılan olarak 50'dir ve 100'ü geçemez.

Aşağıdaki ID'yi seçtiğiniz adaptörün ID'siyle değiştirin:

```bash theme={null}
export AZALT_ADAPTER_ID="REPLACE_WITH_ADAPTER_ID"

curl --fail-with-body \
  "$AZALT_API_URL/api/v1/source-adapters/$AZALT_ADAPTER_ID" \
  -H "Authorization: Bearer $AZALT_API_KEY" \
  --output adapter.json

jq '{id, apiReady, adapterVersion, inputContract, limits, exampleRequest}' adapter.json
```

Detay uç noktası kabul edilen sayfaları, sütunları, türleri, sınırları ve örnek isteği döndürür; adaptör betiğini döndürmez. Örneği bir çalışma dosyasına kopyalayın:

```bash theme={null}
jq -e 'if .apiReady == true and .exampleRequest != null then .exampleRequest else error("Adapter is not API-ready") end' \
  adapter.json > submission.json
```

Göndermeden önce `submission.json` dosyasını düzenleyin: örnek satırları gerçek verilerle değiştirin, doğru `context.year` ve gerekiyorsa `context.siteId` değerlerini girin. Örnek değerler iş kurallarına uygun eşleme garantisi vermez. Yıl 1900–2200 arasında bir tamsayı olmalı, lokasyon ID'si entegrasyon kullanıcısının erişebildiği bir lokasyona ait olmalıdır.

İstek yapısı aşağıdaki gibidir. `ADAPTER_ID` ve `COPY_VERSION_FROM_ADAPTER_RESPONSE` yer tutucudur: uç noktadan dönen gerçek ID'yi ve 64 karakterlik `adapterVersion` değerini aynen kullanın. Üretilen `exampleRequest` bunları zaten içerir.

```json theme={null}
{
  "sourceAdapterDefinitionId": "ADAPTER_ID",
  "adapterVersion": "COPY_VERSION_FROM_ADAPTER_RESPONSE",
  "mode": "preview",
  "context": { "year": 2026 },
  "sheets": [
    {
      "name": "Sheet1",
      "rows": [
        { "FATURA ID": "INV-2026-0001", "TUTAR": -125.5, "BİRİM": "Litre" }
      ]
    }
  ]
}
```

## 3. Önizleme gönderin

Her mantıksal veri paketi için sabit bir idempotency anahtarı belirleyin. Yeniden denemeler için hem anahtarı hem istek gövdesini saklayın; zaman aşımından sonra yeni bir anahtar üretmeyin.

```bash theme={null}
export AZALT_BATCH_KEY="erp-invoices-2026-09-08-batch-001"

curl --fail-with-body "$AZALT_API_URL/api/v1/source-imports" \
  -H "Authorization: Bearer $AZALT_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $AZALT_BATCH_KEY" \
  --data-binary @submission.json \
  --output preview.json

jq '{run, counts, execution, replayed}' preview.json
export AZALT_RUN_ID="$(jq -er '.run.id' preview.json)"
```

Varsayılan mod `preview`'dur. Kaynak satırlarını ve eşlenmiş taslakları kaydeder, ancak hedef kayıtları yazmaz. Her sayfanın ilk veri satırı `rowIndex: 2` alır; 1. satır Excel başlık düzeni için ayrılmıştır.

Satır bazındaki sonuçları okuyun ve çalıştırma için ek onay gerekip gerekmediğini kontrol edin:

```bash theme={null}
curl --fail-with-body \
  "$AZALT_API_URL/api/v1/source-imports/$AZALT_RUN_ID/rows?limit=100&offset=0" \
  -H "Authorization: Bearer $AZALT_API_KEY"

curl --fail-with-body \
  "$AZALT_API_URL/api/v1/source-imports/$AZALT_RUN_ID/readiness" \
  -H "Authorization: Bearer $AZALT_API_KEY"
```

Satır yanıtı `rows` ve `total` içerir. Her satırda `sheetName`, `rowIndex`, `rawRow`, `status`, `warnings` ve `error` bulunur. Sayfalama varsayılan olarak 100 satırdır, en fazla 200 olabilir. Yalnızca hataları almak için `status=failed` ekleyin; bu durumda `total` yalnızca eşleşen satırları sayar.

## 4. Kaydedilen önizlemeyi çalıştırın

Eşleme sonuçlarını ve hazırlık durumunu inceledikten sonra aynı çalıştırma ID'sini kullanın:

```bash theme={null}
curl --fail-with-body \
  "$AZALT_API_URL/api/v1/source-imports/$AZALT_RUN_ID/execute" \
  -H "Authorization: Bearer $AZALT_API_KEY" \
  -H "Content-Type: application/json" \
  --data '{}' \
  --output execution.json

jq '{run, counts, execution}' execution.json
```

Hedef form gerekli lokasyon ve yıl için açılmamışsa çalıştırma onay bekler. Yanıt, çalıştırma ID'sini korur ve `execution.blocked: true` ile `execution.readiness.missingFormSites` döndürür. Hazırlık uç noktası da etkilenen formları, lokasyonları, yılları ve kaynak satırlarını listeler.

Eksik form açılışlarını ancak inceleyip onayladıktan sonra, çalıştırma isteğini şu gövdeyle tekrarlayın:

```json theme={null}
{ "allowMissingFormSiteCreation": true }
```

Yerleşik bir otomatik entegrasyonda ilk gönderimde `mode: "execute"` kullanmak tek istekte önizleme oluşturur ve çalıştırır. İşlem eşzamanlıdır; arka plan kuyruğuna bırakılmaz. İlk gövdede açıkça `allowMissingFormSiteCreation: true` belirtilmedikçe eksik form açılışları yine onay gerektirir.

### Sonucu yorumlama

HTTP 200, hatta `run.status: "completed"` bile her satırın içe aktarıldığını garanti etmez. Bazı satırlar hata verirken geçerli taslaklar işlenebilir. Her zaman `execution.blocked`, satır sayıları ve ayrı ayrı uyarı/hataları kontrol edin.

| Yanıt alanı                        | Kontrol edilmesi gereken                                                                         |
| ---------------------------------- | ------------------------------------------------------------------------------------------------ |
| `run.id`                           | Durum sorgulama ve güvenli çalıştırma tekrarları için bu ID'yi veri paketiyle birlikte saklayın. |
| `run.status`                       | `previewed`, `completed` veya `failed` gibi güncel işlem durumu.                                 |
| `counts.total`                     | Gönderilen kaynak satırı sayısı; hedef kayıt sayısı değil.                                       |
| `counts.parsed` / `counts.ready`   | Ayrıştırılmış veya çalıştırılmaya hazır satırlar.                                                |
| `counts.imported`                  | İçe aktarma motorunun aktarılmış olarak işaretlediği satırlar.                                   |
| `counts.reduced`                   | Başka bir satırın form değeri yazımında birleştirilmiş satırlar; kayıp veri değil.               |
| `counts.skipped` / `counts.failed` | Aktarılmayan satırlar; sonuçlarını inceleyin.                                                    |
| `execution.blocked`                | Eksik form onayı gibi müdahale gerektiren bir durum var.                                         |
| `replayed`                         | Yeni içe aktarma yerine mevcut istek/çalıştırma yeniden kullanıldı.                              |

Bir kaynak satırı birden fazla taslak üretebilir. Gerçek yazım sayıları `run.activityWriteCount` ve `run.formValueWriteCount` alanlarındadır. Aktarılan değerler normal onay ve raporlama yapılandırmasına tabidir; içe aktarmanın tamamlanması onayı atlamaz veya her kayıt görünümünde görünmeyi garanti etmez.

JSON içe aktarmaları normal içe aktarma geçmişinde “API submission” içeren bir adla görünür. Kayıtlar tablosunda yapılandırılmış kaynak belge bağlantıları, kaydedilen satırlarda arama yapmayı ve bunları uygulama içinde veya tam ekran açmayı destekler. Yalnızca JSON gönderiminde indirilebilecek orijinal bir Excel dosyası yoktur.

## Yeniden denemeler ve adaptör değişiklikleri

* `POST /source-imports` için `Idempotency-Key` zorunludur: boşluk içermeyen 1–200 yazdırılabilir ASCII karakteri. Kapsamı organizasyon ve API anahtarı sahibidir.
* Aynı anahtar ve gövde tekrar gönderilirse aynı çalıştırma `replayed: true` ile döner. Nesne anahtarlarının sırası önemsizdir; sayfa ve satır dizilerinin sırası önemlidir. Aynı anahtarla farklı veri, mod, sürüm veya onay ayarı göndermek **409** döndürür.
* Önizlemeyi çalıştırmak için `/source-imports/{id}/execute` çağrısını kullanın. İlk isteğin `mode` değerini aynı anahtar altında değiştirmeyin. Çalıştırma uç noktası idempotency başlığı gerektirmez ve aynı çalıştırma için güvenle tekrarlanabilir.
* Zaman aşımı veya geçici hata sonrasında aynı isteği/çalıştırmayı tekrarlayın. Veritabanı kilitleri farklı replikalardan ve arayüzden gelen eşzamanlı denemeleri koordine eder. Bazı yazımlar tamamlanmış olabilir; aynı çalıştırmayı tekrarlamak yeni içe aktarma başlatmak yerine kalan hazır taslakları tamamlar.
* Farklı anahtarlar farklı içe aktarmalar oluşturur. Paketler arasında iş verisinin yinelenmesini önlemek hâlâ adaptörün `idempotencyKey` ve yinelenen veri stratejisine bağlıdır. Strateji bunu karşılamıyorsa başarılı satırları yeni anahtarla tekrar göndermeyin.
* Betik veya girdi sözleşmesi değişikliği `adapterVersion` değerini günceller. Eski sürümle yapılan yeni gönderimler **409** döndürür. Güncel sözleşmeyi alın, değişiklikleri inceleyin ve yeni bir paket hazırlayın. Mevcut önizlemeler, düzenlenmiş adaptör betiğini yeniden çalıştırmadan kaydedilmiş taslaklarını işler.
* Adaptör hata verirse kaydedilen satır hatalarını inceleyin, girdiyi veya adaptörü düzeltin ve düzeltilmiş paketi yeni anahtarla gönderin. Hatalı isteği değiştirmeden tekrarlamak eşlemeyi yeniden çalıştırmaz.
* Silinmiş çalıştırmalara bu uç noktalardan erişilemez. Kalıcı silme idempotency rezervasyonunu korur; aynı anahtarı tekrar kullanmak yeni içe aktarma değil **409** döndürür.

Çalıştırma okuma ve yürütme işlemleri, yöneticiler dahil, **aynı organizasyonda aynı API anahtarı sahibinin** oluşturduğu JSON içe aktarmalarıyla sınırlıdır. Aynı kullanıcı için anahtar yenilemek erişimi korur. Üyelik veya lokasyon erişiminin kaldırılması mevcut bir çalıştırmaya erişimi engelleyebilir. Bu uç noktalar diğer kullanıcıların çalıştırmalarını veya eski dosya yüklemelerini açmaz; yetkili çalışanlar arayüzdeki içe aktarma geçmişini kullanmaya devam edebilir.

## Uç nokta referansı

Aşağıdaki tüm yollar kendi kurulumunuzdaki `/api/v1` önekine göredir. Kurulumun `/api/v1/openapi.json` dosyası dağıtılmış sürümün istek ve yanıt şemalarını sunar.

| Yöntem | Yol                              | Amaç                                                                              |
| ------ | -------------------------------- | --------------------------------------------------------------------------------- |
| GET    | `/source-adapters`               | Adaptörleri ve API hazırlığını listeleme; `limit` ve `offset` ile sayfalama.      |
| GET    | `/source-adapters/{id}`          | Girdi sözleşmesi, sürüm, sınırlar ve örnek isteği alma.                           |
| POST   | `/source-imports`                | Önizleme kaydetme veya önizleyip çalıştırma; `Idempotency-Key` gerektirir.        |
| GET    | `/source-imports/{id}`           | Güncel çalıştırmayı, sürümü ve satır sayılarını okuma.                            |
| GET    | `/source-imports/{id}/rows`      | Kaynak satırlarını ve hataları okuma; isteğe bağlı `status`, `limit` ve `offset`. |
| GET    | `/source-imports/{id}/readiness` | Eksik form/lokasyon/yıl açılışlarını inceleme.                                    |
| POST   | `/source-imports/{id}/execute`   | Kaydedilen önizlemeyi çalıştırma, gerekirse eksik açılışları onaylama.            |

## Sınırlar ve hatalar

Her istek en fazla **10 MiB JSON, toplam 10.000 satır, 50 sayfa, satır başına 200 sütun ve metin hücresi başına 16.000 karakter** destekler. Daha büyük veri kümelerini farklı anahtarlara sahip ayrı paketlere bölün. Ingress veya barındırma sağlayıcınız daha düşük gövde boyutu ya da zaman aşımı sınırı uygulayabilir.

| HTTP durumu | Yapılacak işlem                                                                                                             |
| ----------- | --------------------------------------------------------------------------------------------------------------------------- |
| 400         | JSON yapısını, sözleşmedeki alan türlerini, zorunlu bağlamı ve idempotency anahtarını kontrol edin.                         |
| 401         | Aktif organizasyon üyesine ait geçerli bir Bearer API anahtarı gönderin.                                                    |
| 403         | Kullanıcının rolünü ve tüm hedef lokasyonlara erişimini kontrol edin.                                                       |
| 404         | Adaptör/çalıştırma ID'sini, organizasyonu, çalıştırma sahibini, silinme durumunu ve dağıtılmış API sürümünü kontrol edin.   |
| 409         | Eski adaptör sürümü, aynı anahtarla değişen gövde veya silinmiş çalıştırmaya ayrılmış anahtar olup olmadığını kontrol edin. |
| 412         | Adaptörü aktif yapın ve etkin bir JSON API girdi sözleşmesi tanımlayın.                                                     |
| 413         | İstek boyutunu API ve ingress sınırlarına sığacak şekilde azaltın.                                                          |
| 415         | `Content-Type: application/json` gönderin.                                                                                  |

İş kuralı doğrulama hataları HTTP hatası yerine satır sonucu olarak dönebilir. Bir paketi başarılı saymadan önce her zaman yanıt gövdesini inceleyin.

## Şirket içi ve Helm split kurulumu

API hem birleşik Next.js uygulamasında hem de Helm split kurulumlarının bağımsız backend servisinde çalışır. Normal frontend adresinizi veya kurulum yöneticisinin özellikle dışarı açtığı bir backend adresini kullanın.

Entegrasyonu etkinleştirmeden önce kurulum yöneticisi:

1. Hedef veritabanını yedeklemeli ve normal Helm migrasyon işi/süreciyle sürümün ekleme yapan `20260908000000_add_source_import_api_requests.ts` migrasyonunu uygulamalıdır. Bu migrasyon isteklerin yinelenmesini önleyen tabloyu oluşturur.
2. Split kurulumda birbirine uyumlu güncel frontend ve backend imajlarını dağıtmalıdır. Yalnızca frontend'i güncellemek backend uç noktalarını eklemez.
3. Ingress/proxy üzerinde `/api/v1` yönlendirmesini ve `Authorization`, `Content-Type`, `Idempotency-Key` başlıklarını korumalıdır. Kimlik doğrulamalı yanıtlar önbelleğe alınmamalıdır.
4. İstek gövdesi ve eşzamanlı istek zaman aşımı sınırlarını kontrol etmeli; ardından dağıtılmış OpenAPI belgesini doğrulayıp çalıştırma öncesinde küçük, incelenmiş bir önizleme denemelidir.

JSON içe aktarmaları ve kaydedilmiş kaynak veri önizlemesi için S3, MinIO, orijinal dosya yükleme, yeni depolama ortam değişkenleri veya arka plan kuyruğu gerekmez. Mevcut dosya içe aktarmaları kendi depolama gereksinimlerini korur.

Uygulama imajlarını geri alırken yeniden deneme geçmişini korumak için yeni istek tablosunu tutun. Tabloyu kaldırmak hedef kayıtlar ve kaynak anlık görüntüleri kalsa bile API üzerinden çalıştırma erişimini ve yinelenme önleme geçmişini siler. Bu geçmiş kaldırıldıktan sonra eski paketleri yeniden göndermeyin.
