# Belge Şeması

https://dev.wisecp.com/tr/belge-semasi

Hangi belgenin kimden isteneceğini tanımlayan on uç: alan havuzu ve onu kullanan filtreler.

## Genel Bakış

Belge şeması iki katmandır. **Alanlar** paylaşılan bir havuzdur — "kimlik fotokopisi", "vergi levhası" gibi tek tek girdiler. **Filtreler** bu havuzdan bir küme seçer ve o kümenin *kimden* isteneceğini söyleyen kuralları taşır.

Aynı alan birden çok filtrede kullanılabilir; havuz bunun içindir. Bir alanı güncellemek onu kullanan bütün filtreleri aynı anda etkiler.

## Referans

### Filtreleri Listeleme

get/api/v1/admin/clients/document-filters

`Clients/GetDocumentFilters` admin

Tanımlı belge filtrelerini döndürür. Her filtre bir alan kümesi ve o kümenin kimden isteneceğini söyleyen kurallar taşır.

Sorgu parametreleri 3

statusstring`active` ya da `inactive`.

pageintVarsayılan 1.

limitintVarsayılan 25, en çok 100.

Dönen alanlar data[] — 5

idintFiltre kimliği.

namestringFiltre adı.

statusstring`active` ya da `inactive`.

fieldsint[]Alan havuzundaki kimliklerin **sıralı** listesi. Sıra müşterinin gördüğü sıradır.

rulesobject[] 3 alanFiltrenin kime uygulanacağını belirleyen kurallar.

typestringKuralın neye baktığı: `email_provider`, `vpn_proxy`, `account_age`, `service_count`, `total_spending`, `country_mismatch`, `country`.

valuestringTipe göre değişir: alan adı listesi, `yes`, sayısal eşik ya da ülke kimliği. `extra` değeri `between` olan `age` kuralı `18-30` gibi uçları dahil bir aralık alır; başka bir değer `rule_value_invalid` ile reddedilir.

extrastringTipe göre ek değer. Çoğu kuralda boş kalır.

Hatalar 1

insufficient_scope403Anahtarda ilgili scope yok.

İstek cURL JavaScript PHP (HTTP) PHP (Dahili)

```bash
curl -G 'https://panel.ornek.com/api/v1/admin/clients/document-filters' \
  -H "Authorization: Bearer $API_KEY" \
  -d status=active
```

```javascript
const url = new URL('https://panel.ornek.com/api/v1/admin/clients/document-filters');
url.searchParams.set('status', 'active');

const res  = await fetch(url, { headers: { Authorization: `Bearer ${apiKey}` } });
const body = await res.json();
```

```php
$url = 'https://panel.ornek.com/api/v1/admin/clients/document-filters?' . http_build_query(['status' => 'active']);

$ch = curl_init($url);
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER     => ['Authorization: Bearer ' . $apiKey],
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
```

```php
$response = Api::Clients()->GetDocumentFilters([], ['status' => 'active']);
```

### Filtre Ekleme

post/api/v1/admin/clients/document-filters

`Clients/CreateDocumentFilter` admin

Yeni bir filtre tanımlar. Alan kimlikleri havuzda var olmalıdır.

Gövde 4

namestringzorunluFiltre adı.

fieldsint[]zorunluSıralı alan kimlikleri, örneğin `[3, 1]`.

activeboolVarsayılan `false`; filtre `inactive` doğar.

rulesobject[] 3 alanUygulama kuralları.

typestringKuralın neye baktığı: `email_provider`, `vpn_proxy`, `account_age`, `service_count`, `total_spending`, `country_mismatch`, `country`.

valuestringTipe göre değişir: alan adı listesi, `yes`, sayısal eşik ya da ülke kimliği. `extra` değeri `between` olan `age` kuralı `18-30` gibi uçları dahil bir aralık alır; başka bir değer `rule_value_invalid` ile reddedilir.

extrastringTipe göre ek değer. Çoğu kuralda boş kalır.

Dönen alanlar data — 5

idintYeni filtrenin kimliği.

namestringFiltre adı.

statusstring`active` ya da `inactive`. `active` göndermediyseniz yeni filtre pasif doğar.

fieldsint[]Kaydedilen sıralı alan kimlikleri.

rulesobject[]Kaydedilen kurallar — listelemedeki `type` / `value` / `extra` şeklinin aynısı.

Hatalar 5

name_required422`name` boş.

fields_required422`fields` boş ya da geçersiz.

fields_invalid422Verilen kimliklerin hiçbiri alan havuzunda yok.

filter_add_failed500Kayıt oluşturulamadı.

insufficient_scope403Anahtar gerekli kapsamı taşımıyor.

İstek cURL JavaScript PHP (HTTP) PHP (Dahili)

```bash
curl -X POST 'https://panel.ornek.com/api/v1/admin/clients/document-filters' \
  -H "Authorization: Bearer $API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"name":"Yuksek harcama","fields":[3,1],"active":true,"rules":[{"type":"total_spending","value":"5000","extra":""}]}'
```

```javascript
const res = await fetch('https://panel.ornek.com/api/v1/admin/clients/document-filters', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${apiKey}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({"name":"Yuksek harcama","fields":[3,1],"active":true,"rules":[{"type":"total_spending","value":"5000","extra":""}]}),
});

const body = await res.json();
```

```php
$ch = curl_init('https://panel.ornek.com/api/v1/admin/clients/document-filters');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST           => true,
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer ' . $apiKey,
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode([
        'name'   => 'Yuksek harcama',
        'fields' => [3, 1],
        'active' => true,
    ]),
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
```

```php
$response = Api::Clients()->CreateDocumentFilter([
    'name'   => 'Yuksek harcama',
    'fields' => [3, 1],
    'active' => true,
    'rules'  => [
        ['type' => 'total_spending', 'value' => '5000', 'extra' => ''],
    ],
]);
```

### Filtre Detayı

get/api/v1/admin/clients/document-filters/{fid}

`Clients/GetDocumentFilter` admin

Tek bir filtreyi döndürür; şema listedekiyle aynıdır.

Dönen alanlar data — 5

idintFiltre kimliği.

namestringFiltre adı.

statusstring`active` ya da `inactive`.

fieldsint[]Sıralı alan kimlikleri; listelemenin döndürdüğünün aynısı.

rulesobject[]Kurallar — listelemedeki `type` / `value` / `extra` şeklinin aynısı.

Hatalar 2

not_found404Kayıt bulunamadı.

insufficient_scope403Anahtar gerekli kapsamı taşımıyor.

İstek cURL JavaScript PHP (HTTP) PHP (Dahili)

```bash
curl 'https://panel.ornek.com/api/v1/admin/clients/document-filters/7' \
  -H "Authorization: Bearer $API_KEY"
```

```javascript
const res  = await fetch('https://panel.ornek.com/api/v1/admin/clients/document-filters/7', {
  headers: { Authorization: `Bearer ${apiKey}` },
});
const body = await res.json();
```

```php
$ch = curl_init('https://panel.ornek.com/api/v1/admin/clients/document-filters/7');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER     => ['Authorization: Bearer ' . $apiKey],
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
```

```php
$response = Api::Clients()->GetDocumentFilter(['fid' => 7]);
```

### Filtre Güncelleme

patch/api/v1/admin/clients/document-filters/{fid}

`Clients/UpdateDocumentFilter` admin

Filtrenin adını, alan sırasını, durumunu ya da kurallarını değiştirir.

Gövde en az biri

namestringFiltre adı.

fieldsint[]Yeni sıralı alan listesi. Gönderilen liste eskisinin yerine geçer.

activeboolFiltreyi açar ya da kapatır.

rulesobject[]Yeni kural listesi. Bu da yerine geçer, eklenmez.

Dönen alanlar data — 5

idintFiltre kimliği.

namestringGüncelleme sonrası filtre adı.

statusstring`active` ya da `inactive`.

fieldsint[]Kaydedilen alan sırası — yerine geçmenin geriye ne bıraktığını buradan okuyun.

rulesobject[]Kaydedilen kurallar; boş dizi filtrenin artık herkese uygulandığı anlamına gelir.

Hatalar 5

not_found404Filtre bulunamadı.

name_required422`name` boş gönderildi.

fields_required422`fields` boş ya da geçersiz gönderildi.

fields_invalid422Kimliklerden biri alan havuzunda yok.

insufficient_scope403Anahtarda ilgili scope yok.

İstek cURL JavaScript PHP (HTTP) PHP (Dahili)

```bash
curl -X PATCH 'https://panel.ornek.com/api/v1/admin/clients/document-filters/7' \
  -H "Authorization: Bearer $API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"active":false}'
```

```javascript
const res = await fetch('https://panel.ornek.com/api/v1/admin/clients/document-filters/7', {
  method: 'PATCH',
  headers: {
    Authorization: `Bearer ${apiKey}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ active: false }),
});

const body = await res.json();
```

```php
$ch = curl_init('https://panel.ornek.com/api/v1/admin/clients/document-filters/7');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST  => 'PATCH',
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer ' . $apiKey,
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode(['active' => false]),
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
```

```php
$response = Api::Clients()->UpdateDocumentFilter([
    'fid'    => 7,
    'active' => false,
]);
```

### Filtre Silme

delete/api/v1/admin/clients/document-filters/{fid}

`Clients/DeleteDocumentFilter` admin

Filtreyi siler. Alan havuzuna dokunmaz; alanlar başka filtrelerde durmaya devam eder.

Dönen alanlar data — 2

deletedboolSilme başarılı mı.

idintSilinen filtrenin kimliği.

Hatalar 1

not_found404Filtre bulunamadı.

İstek cURL JavaScript PHP (HTTP) PHP (Dahili)

```bash
curl -X DELETE 'https://panel.ornek.com/api/v1/admin/clients/document-filters/7' \
  -H "Authorization: Bearer $API_KEY"
```

```javascript
const res = await fetch('https://panel.ornek.com/api/v1/admin/clients/document-filters/7', {
  method: 'DELETE',
  headers: { Authorization: `Bearer ${apiKey}` },
});

const body = await res.json();
```

```php
$ch = curl_init('https://panel.ornek.com/api/v1/admin/clients/document-filters/7');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST  => 'DELETE',
    CURLOPT_HTTPHEADER     => ['Authorization: Bearer ' . $apiKey],
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
```

```php
$response = Api::Clients()->DeleteDocumentFilter(['fid' => 7]);
```

### Alanları Listeleme

get/api/v1/admin/clients/document-fields

`Clients/GetDocumentFields` admin

Paylaşılan alan havuzunu döndürür. Filtreler alanlarını buradan seçer.

Sorgu parametreleri 4

statusstring`active` ya da `inactive`.

pageintVarsayılan 1.

limitintVarsayılan 25, en çok 100.

typestringGiriş tipine göre süzer.

Dönen alanlar data[] — 8

idintAlan kimliği. Filtrelerin `fields` listesi buraya işaret eder.

statusstring`active` ya da `inactive`. Pasif alan müşteriye gösterilmez.

typestring`input`, `textarea`, `selectbox`, `radio`, `checkbox`, `file`.

labelsobjectDile göre etiket, örneğin `{"tr": "Kimlik fotokopisi"}`.

optionsobjectDile göre seçenekler. Yalnız seçim tiplerinde anlamlı.

allowed_extstringİzin verilen dosya uzantıları. Yalnız `file` tipinde.

max_sizeintMB cinsinden en büyük dosya boyutu. Yalnız `file` tipinde.

used_inobject[]Bu alanı kullanan filtreler: `[{ id, name }]`.

Hatalar 1

insufficient_scope403Anahtarda ilgili scope yok.

İstek cURL JavaScript PHP (HTTP) PHP (Dahili)

```bash
curl -G 'https://panel.ornek.com/api/v1/admin/clients/document-fields' \
  -H "Authorization: Bearer $API_KEY" \
  -d type=file
```

```javascript
const url = new URL('https://panel.ornek.com/api/v1/admin/clients/document-fields');
url.searchParams.set('type', 'file');

const res  = await fetch(url, { headers: { Authorization: `Bearer ${apiKey}` } });
const body = await res.json();
```

```php
$url = 'https://panel.ornek.com/api/v1/admin/clients/document-fields?' . http_build_query(['type' => 'file']);

$ch = curl_init($url);
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER     => ['Authorization: Bearer ' . $apiKey],
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
```

```php
$response = Api::Clients()->GetDocumentFields([], ['type' => 'file']);
```

### Alan Ekleme

post/api/v1/admin/clients/document-fields

`Clients/CreateDocumentField` admin

Havuza yeni bir alan ekler. Etiket en az bir dilde verilmelidir.

Gövde 6

typestringzorunluGiriş tipi.

labelsobjectzorunluDile göre etiket; en az bir dil.

activeboolVarsayılan `true`.

optionsobjectDile göre seçenekler. Seçim tiplerinde pratikte gerekir.

allowed_extstringİzinli uzantılar. Yalnız `file` tipinde.

max_sizeintMB cinsinden sınır. `file` tipine özgü.

Dönen alanlar data — 7

idintYeni alanın kimliği.

statusstring`active` ya da `inactive`.

typestringKaydedilen giriş tipi.

labelsobjectKaydedilen etiketler, dil başına.

optionsobjectKaydedilen seçenekler, dil başına.

allowed_extstringİzinli dosya uzantıları.

max_sizeintMB cinsinden en büyük dosya boyutu.

used_in—Bu yanıtta yer almaz: yeni oluşturulan alan henüz hiçbir filtreye ait değildir.

Hatalar 4

type_invalid422`type` izinli giriş tiplerinden değil.

labels_required422Hiçbir dilde dolu etiket gönderilmedi.

field_add_failed500Kayıt oluşturulamadı.

insufficient_scope403Anahtar gerekli kapsamı taşımıyor.

İstek cURL JavaScript PHP (HTTP) PHP (Dahili)

```bash
curl -X POST 'https://panel.ornek.com/api/v1/admin/clients/document-fields' \
  -H "Authorization: Bearer $API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"type":"file","labels":{"tr":"Kimlik fotokopisi","en":"ID copy"},"allowed_ext":"jpg,png,pdf","max_size":5}'
```

```javascript
const res = await fetch('https://panel.ornek.com/api/v1/admin/clients/document-fields', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${apiKey}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    type: 'file',
    labels: {"tr":"Kimlik fotokopisi","en":"ID copy"},
    allowed_ext: 'jpg,png,pdf',
    max_size: 5,
  }),
});

const body = await res.json();
```

```php
$ch = curl_init('https://panel.ornek.com/api/v1/admin/clients/document-fields');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST           => true,
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer ' . $apiKey,
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode([
        'type'        => 'file',
        'labels'      => ['tr' => 'Kimlik fotokopisi', 'en' => 'ID copy'],
        'allowed_ext' => 'jpg,png,pdf',
        'max_size'    => 5,
    ]),
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
```

```php
$response = Api::Clients()->CreateDocumentField([
    'type'        => 'file',
    'labels'      => ['tr' => 'Kimlik fotokopisi', 'en' => 'ID copy'],
    'allowed_ext' => 'jpg,png,pdf',
    'max_size'    => 5,
]);
```

### Alan Detayı

get/api/v1/admin/clients/document-fields/{fid}

`Clients/GetDocumentField` admin

Tek bir alanı döndürür. `used_in` ile hangi filtrelerde kullanıldığı da gelir.

Dönen alanlar data — 8

idintAlan kimliği — bir filtrenin `fields` listesi buraya işaret eder.

statusstring`active` ya da `inactive`. Pasif alan, bir filtre onu hâlâ listelese bile müşteriye gösterilmez.

typestringGiriş tipi: `input`, `textarea`, `selectbox`, `radio`, `checkbox`, `file`.

labelsobjectDil başına etiket, örneğin `{ "en": "Passport copy" }`.

optionsobjectListe tipleri için dil başına seçenekler. Diğer tiplerde boştur.

allowed_extstringİzinli dosya uzantıları — `file` tipine özgü.

max_sizeintMB cinsinden en büyük dosya boyutu — `file` tipine özgü.

used_inobject[]Bu alanı kullanan filtreler, `{ id, name }` biçiminde. Silmeden önce okuyun — hepsi bu alanı kaybeder.

Hatalar 2

not_found404Alan bulunamadı.

insufficient_scope403Anahtarda ilgili scope yok.

İstek cURL JavaScript PHP (HTTP) PHP (Dahili)

```bash
curl 'https://panel.ornek.com/api/v1/admin/clients/document-fields/3' \
  -H "Authorization: Bearer $API_KEY"
```

```javascript
const res  = await fetch('https://panel.ornek.com/api/v1/admin/clients/document-fields/3', {
  headers: { Authorization: `Bearer ${apiKey}` },
});
const body = await res.json();
```

```php
$ch = curl_init('https://panel.ornek.com/api/v1/admin/clients/document-fields/3');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER     => ['Authorization: Bearer ' . $apiKey],
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
```

```php
$response = Api::Clients()->GetDocumentField(['fid' => 3]);

// Silmeden önce: bu alan hangi filtrelerde duruyor?
$usedIn = $response['data']['used_in'] ?? [];
```

### Alan Güncelleme

patch/api/v1/admin/clients/document-fields/{fid}

`Clients/UpdateDocumentField` admin

Alanı günceller. Değişiklik onu kullanan bütün filtrelere aynı anda yansır.

Gövde 6

typestringzorunluGiriş tipi. Güncellemede de zorunludur — bu uç tek tek anahtar yamamaz, alanı yeniden yazar.

labelsobjectzorunluDil başına etiket; en az biri dolu olmalı.

activeboolAlanı açar ya da kapatır. Varsayılan `true`.

optionsobjectDil başına seçenekler. Liste tiplerinde pratikte zorunludur.

allowed_extstringİzinli uzantılar. Yalnız `file` tipinde.

max_sizeintMB cinsinden sınır. `file` tipine özgü.

Dönen alanlar data — 7

idintAlan kimliği.

statusstring`active` ya da `inactive`.

typestringKaydedilen giriş tipi.

labelsobjectKaydedilen etiketler, dil başına.

optionsobjectKaydedilen seçenekler, dil başına.

allowed_extstringİzinli dosya uzantıları.

max_sizeintMB cinsinden en büyük dosya boyutu.

Hatalar 4

not_found404Alan bulunamadı.

type_invalid422`type` izinli giriş tiplerinden değil.

labels_required422Hiçbir dilde dolu etiket gönderilmedi.

insufficient_scope403Anahtarda ilgili scope yok.

İstek cURL JavaScript PHP (HTTP) PHP (Dahili)

```bash
curl -X PATCH 'https://panel.ornek.com/api/v1/admin/clients/document-fields/3' \
  -H "Authorization: Bearer $API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"max_size":10}'
```

```javascript
const res = await fetch('https://panel.ornek.com/api/v1/admin/clients/document-fields/3', {
  method: 'PATCH',
  headers: {
    Authorization: `Bearer ${apiKey}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ max_size: 10 }),
});

const body = await res.json();
```

```php
$ch = curl_init('https://panel.ornek.com/api/v1/admin/clients/document-fields/3');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST  => 'PATCH',
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer ' . $apiKey,
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode(['max_size' => 10]),
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
```

```php
$response = Api::Clients()->UpdateDocumentField([
    'fid'      => 3,
    'max_size' => 10,
]);
```

### Alan Silme

delete/api/v1/admin/clients/document-fields/{fid}

`Clients/DeleteDocumentField` admin filtreleri etkiler

Alanı havuzdan siler.

Dönen alanlar data — 2

deletedboolSilme başarılı mı.

idintSilinen alanın kimliği.

Hatalar 1

not_found404Alan bulunamadı.

İstek cURL JavaScript PHP (HTTP) PHP (Dahili)

```bash
curl -X DELETE 'https://panel.ornek.com/api/v1/admin/clients/document-fields/3' \
  -H "Authorization: Bearer $API_KEY"
```

```javascript
const res = await fetch('https://panel.ornek.com/api/v1/admin/clients/document-fields/3', {
  method: 'DELETE',
  headers: { Authorization: `Bearer ${apiKey}` },
});

const body = await res.json();
```

```php
$ch = curl_init('https://panel.ornek.com/api/v1/admin/clients/document-fields/3');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST  => 'DELETE',
    CURLOPT_HTTPHEADER     => ['Authorization: Bearer ' . $apiKey],
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
```

```php
$response = Api::Clients()->DeleteDocumentField(['fid' => 3]);
```

## Tuzaklar

> **Alan listesi sıralıdır**
> 
> `fields` bir küme değil, **sıralı** bir listedir; müşteri alanları o sırada görür. Güncellerken gönderdiğiniz liste eskisinin yerine geçer, üstüne eklenmez.

> **Alan paylaşılır, kopyalanmaz**
> 
> Bir alanı güncellemek ya da silmek onu kullanan **her** filtreyi etkiler. Silmeden önce alan detayındaki `used_in` listesine bakın.

> **Yeni filtre kapalı doğar**
> 
> `active` göndermezseniz filtre `inactive` oluşur ve kimseden belge istemez. Kurup unutmak, çalışmayan bir doğrulama bırakır.

## İlgili Makaleler

- [Müşteri Uçları](https://dev.wisecp.com/tr/musteri-uclari)
- [İstek ve Yanıt Biçimi](https://dev.wisecp.com/tr/istek-ve-yanit-bicimi)
