# SMS gönderme

> Bir ya da daha fazla alıcıya SMS gönderen bir görev oluşturur.

- **İstek:** `POST https://ext-api.netgsm.com.tr/sms/v3/send`
- **Canlı ortam:** `https://ext-api.netgsm.com.tr/sms/v3`
- **Kimlik doğrulama:** `Authorization: Bearer <token>`
- **HTML sayfası:** https://api-docs.netgsm.com.tr/send-sms/
- **OpenAPI tanımı:** https://api-docs.netgsm.com.tr/openapi/sms-v3.yaml (operationId: `sendSms`)

## Açıklama

Bir ya da daha fazla alıcıya SMS gönderen bir görev oluşturur. Görev iletim için kabul
edildiğinde 202 döner; iletim sonradan yapılır. Her alıcı `messages` dizisinde ayrı bir kayıttır
ve her kaydın kendi metni olabilir.

**Kayıt başına doğrulama.** Hatalı kayıtlar toplu gönderimi başarısız kılmaz: geçerli kayıtlar
gönderilir, hatalılar yanıttaki `rejectedItems` içinde konumları (`index`) ve nedenleriyle
bildirilir. Kayıtların hepsi hatalıysa görev oluşturulmaz ve 422 `NO_DELIVERABLE_MESSAGES`
döner; bu yanıt da reddedilen kayıtları aynı biçimde `rejectedItems` ve
`rejectedItemsTruncated` alanlarında taşır.

**İstek biçimi.** `Content-Type: application/json`; gövde sıkıştırılmamış olmalı ve 500 MB'ı
aşmamalıdır. Bilinmeyen alanlar yok sayılır; `null` verilen bir alan hiç verilmemiş sayılır.

**İstek sınırı.** Hesap başına dakikada 50.000 istek (mesaj değil, istek). Süre penceresi ilk
istekle başlar ve sabittir; reddedilen istekler sayılmaz. Aşıldığında 429 `Retry-After` başlığıyla döner.
Toplu gönderimler için çok sayıda alıcıyı tek istekte göndermenizi öneririz.

**Yeniden deneme.** İsteklerin tekilleştirilmesi yoktur: aynı istek iki kez gönderilirse iki
görev oluşur. 503 `SERVICE_UNAVAILABLE` çoğunlukla hiçbir şeyin kuyruğa alınmadığını gösterir. Toplu
gönderimi körlemesine yeniden göndermeden önce `GET /report` ile kontrol edebilirsiniz. 400, 403, 413 ve 422
yanıtları aynı istekle tekrarlandığında yine aynı sonucu verir.

**Sonrası.** Yanıttaki `jobId` ile iletim raporlarını `GET /report`, gönderim istatistiklerini
`GET /stats` ile sorgulayabilirsiniz. `status` `SCHEDULED` olan bir görev, başlangıç zamanına kadar
`POST /cancel` ile iptal edebilirsiniz.

## İstek

### Gövde (`application/json`, zorunlu)

- `sender` (string, zorunlu, en az uzunluk 1, en fazla uzunluk 35): Gönderici başlığı. Hesaba kayıtlı bir başlıkla yazıldığı gibi birebir eşleşmelidir: büyük/küçük harf dahil, kırpma yapılmaz. Alfanümerik bir başlık (örneğin `NETGSM`) ya da hesabın abone numarası olabilir; abone numarası başında `0` ya da `90` olmadan yazılır (`5061234567`). Kullanabileceğiniz başlıkları ve her birinin kullanılabilir olup olmadığını `GET /senders` ile görebilirsiniz. Eşleşmezse istek 422 `REJECTED_HEADER` ile reddedilir; boş ya da yalnızca boşluktan oluşan bir değer ise 400 ile reddedilir. Örnek: `NETGSM`.
- `messages` (array<object>, zorunlu, en az kayıt 1, en fazla kayıt 1000000): Gönderilecek mesajlar; her alıcı için bir kayıt. En az 1, en fazla 1.000.000 kayıt; fazlası 400 ile reddedilir.
- `messages[].text` (string, zorunlu): Mesaj metni. Boş olamaz (`INVALID_MESSAGE`). En fazla uzunluk `encoding` değerine ve göndericinin türüne bağlıdır (`MESSAGE_TOO_LONG`); bkz. `encoding` ve `/length`. Örnek: `Siparişiniz kargoya verildi.`.
- `messages[].recipient` (string, zorunlu, desen `^(90\d{10}|-\d{9,17})$`): Alıcı numarası, iki biçimden biriyle yazılır; yalnızca rakamlar ve yurt dışı için baştaki tek `-` kullanılabilir, boşluk, parantez ya da tire ayracı olmaz: Örnek: `905061234567`.

  | Tür | Biçim | Örnek |
  |---|---|---|
  | Türkiye | `90` ve ardından 10 rakam; `+` ya da baştaki `0` olmadan | `+90 506 123 45 67` için `905061234567` |
  | Yurt dışı | `-` ve ardından ülke koduyla birlikte 9–17 rakam; `+` ya da `00` olmadan | `+49 151 12345678` için `-4915112345678` |

  Yanlış yazımlar: `+905061234567`, `05061234567`, `5061234567`, `0049151…`, `-+49151…`.
  Bu biçimlere uymayan kayıt `INVALID_RECIPIENT` ile reddedilir. Numaranın gerçekte var olup
  olmadığı ya da hangi operatöre ait olduğu burada denetlenmez; iletim sonucunu `GET /report` ile
  görebilirsiniz. Hesabın yurt dışı gönderim izni yoksa yurt dışı kayıtlar `NO_INTERNATIONAL_PERMISSION`
  ile reddedilir.

- `encoding` (string, isteğe bağlı): Metnin karakter kodlaması. Tüm kayıtlara uygulanır. Büyük/küçük harfe duyarlıdır; listede olmayan bir değer (`turkish`, `GSM` dahil) istek 400 `1 field(s) rejected` ile reddedilir; `violations` alanı (`encoding`) ve geçerli değerleri belirtir. Değerler: `DEFAULT`, `TURKISH`, `UNICODE`. Varsayılan: `DEFAULT`.

  | Değer | Ne zaman | En fazla uzunluk |
  |---|---|---|
  | `DEFAULT` | Standart GSM alfabesi. Türkçe karakterler Latin karşılıklarına çevrilir (ç→c, ş→s gibi). | 917 |
  | `TURKISH` | Türkçe karakterlerin (çğıöşüÇĞİÖŞÜ) korunması gerektiğinde. `çğışĞİŞ` iki karakter sayılır. | 888 |
  | `UNICODE` | Emoji ya da Arapça, Kiril gibi GSM alfabesinde olmayan karakterler için. | 396 |

  Alfanümerik bir gönderici başlığında her sınır 5 karakter azdır. Sınırı aşan kayıt
  `MESSAGE_TOO_LONG` ile reddedilir. Bir metnin kaç SMS'e bölüneceğini `POST /length` ile
  hesaplayabilirsiniz.

- `iysFilter` (string, isteğe bağlı): İYS (İleti Yönetim Sistemi) izin filtresi; ticari iletilerde alıcının izni olmayanlar gönderimden çıkarılır. Büyük/küçük harf fark etmez: Değerler: `NONE`, `BRAND`, `RETAILER`, `BRAND_AND_RETAILER`. Varsayılan: `NONE`.

  | Değer | Anlamı |
  |---|---|
  | `NONE` | Filtre yok. Yalnızca bilgilendirme (ticari olmayan) iletiler için. |
  | `BRAND` | Marka adına alınmış izinlere göre filtrelenir. |
  | `RETAILER` | Bayi adına alınmış izinlere göre filtrelenir. |
  | `BRAND_AND_RETAILER` | Her ikisine göre filtrelenir. |

  Bunların dışındaki her değer `NONE` sayılır. Hesap ticari gönderim (marka ya da bayi) tipinde
  tanımlıysa istekteki değer yok sayılır ve hesabın tipi uygulanır.

  `BRAND` ya da `RETAILER` uygulanacaksa göndericinin İYS marka kodu olmalıdır; hesap İYS
  modunda değilse bu iki değer istek 422 `REJECTED_IYS` ile reddedilir. `BRAND_AND_RETAILER`
  için bu iki kontrol yapılmaz.

- `startAt` (string, date-time, isteğe bağlı): En erken gönderim zamanı, saat dilimi farkıyla (`2026-09-10T09:00:00+03:00`). Verilmezse ya da geçmişteyse gönderim hemen başlar. 18 aydan daha ilerisi 400 `INVALID_SEND_WINDOW` ile reddedilir. Bir dakikadan daha ileri bir başlangıç görevi `SCHEDULED` yapar. Saat dilimi farkı olmayan ya da okunamayan bir tarih istek 400 ile reddedilir.
- `stopAt` (string, date-time, isteğe bağlı): En geç gönderim zamanı, saat dilimi farkıyla. Verilmezse ya da geçmişteyse `startAt` + 21 saat kabul edilir. Aralık, 1000 ve üzeri mesajda 10 dakikadan, daha azında 5 dakikadan kısaysa bu süreye uzatılır; 21 saatten uzunsa 21 saate kısaltılır. Bu düzeltmeler hata döndürmez ve belirlenen aralık yanıtta yer almaz.
- `partnerCode` (string, isteğe bağlı, en fazla uzunluk 32): İş ortağı (bayi) kodu. Yalnızca kayıt amaçlıdır; gönderimi etkilemez.
- `referenceId` (string, isteğe bağlı, en fazla uzunluk 50): Yanıtta aynen geri döndürülür.
- `appName` (string, isteğe bağlı, en fazla uzunluk 50): Gönderimi yapan uygulamanın adı. Yalnızca kayıt amaçlıdır; gönderimi etkilemez.

Örnek gövde:

```json
{
  "sender": "NETGSM",
  "messages": [
    {
      "text": "Merhaba",
      "recipient": "905xxxxxxxxx"
    }
  ],
  "referenceId": "order-4711"
}
```

## Örnek istek

```bash
curl -X POST 'https://ext-api.netgsm.com.tr/sms/v3/send' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "sender": "NETGSM",
  "messages": [
    {
      "text": "Merhaba",
      "recipient": "905xxxxxxxxx"
    }
  ],
  "referenceId": "order-4711"
}'
```

## Yanıtlar

### 202 — Görev oluşturuldu. İletim sonradan yapılır.

Gövde (`application/json`):

- `jobId` (string, zorunlu): Oluşturulan görevin numarası. Rapor, istatistik ve iptal için kullanılır; destek taleplerinde belirtmelisiniz.
- `status` (string, zorunlu): Değerler: `QUEUED`, `SCHEDULED`.

  | Değer | Anlamı |
  |---|---|
  | `QUEUED` | Gönderim hemen başladı; görev iptal edilemez. |
  | `SCHEDULED` | Görev `startAt` zamanına kadar bekletiliyor (dakikaya göre bir dakikadan daha ileri bir başlangıç); o zamana kadar `POST /cancel` ile iptal edebilirsiniz. |

- `accepted` (integer, zorunlu): Gönderime alınan kayıt sayısı. `accepted + rejected`, istekteki kayıt sayısına eşittir.
- `rejected` (integer, zorunlu): Reddedilen kayıt sayısı. `rejectedItems` kısaltılsa da bu sayı tamdır.
- `rejectedItems` (array<object>, zorunlu, en fazla kayıt 100): Reddedilen kayıtlar, `index` sırasıyla ilk 100 tanesi. Hiçbiri reddedilmediyse boş dizi.
- `rejectedItems[].index` (integer, zorunlu): Kaydın istekteki `messages` dizisindeki sırası, sıfırdan başlar.
- `rejectedItems[].recipient` (string, null olabilir, zorunlu): Kayıttaki alıcı. Kayıt `null` ise ya da alıcısı yoksa `null`.
- `rejectedItems[].reason` (string, zorunlu): Değerler: `INVALID_RECIPIENT`, `INVALID_MESSAGE`, `MESSAGE_TOO_LONG`, `MALFORMED_ENTRY`, `DUPLICATE_RECIPIENT`, `NO_INTERNATIONAL_PERMISSION`.

  | Değer | Ne zaman |
  |---|---|
  | `INVALID_RECIPIENT` | Numara eksik ya da biçimi yanlış; bkz. `recipient`. |
  | `INVALID_MESSAGE` | Metin eksik ya da boş. |
  | `MESSAGE_TOO_LONG` | Metin, `encoding` ve gönderici türüne göre sınırı aşıyor; bkz. `encoding`. |
  | `MALFORMED_ENTRY` | Kayıt `null`. |
  | `DUPLICATE_RECIPIENT` | Aynı alıcı istekte daha sonra yeniden geçiyor. Yalnızca son geçen kayıt gönderilir, öncekiler bu nedenle reddedilir; son kayıt başka bir nedenle reddedilse bile. Numaralar yazıldığı gibi karşılaştırılır. Mükerrer gönderime izin verilen hesaplarda uygulanmaz. |
  | `NO_INTERNATIONAL_PERMISSION` | Numara yurt dışı (`-` ile başlıyor) ve hesabın yurt dışı gönderim izni yok. İzin için destek ekibiyle iletişime geçmelisiniz. Yalnızca başka bir hatası olmayan kayıtlarda bildirilir. |

  Bir kayıt birden fazla nedenle hatalıysa tek neden bildirilir; öncelik: `DUPLICATE_RECIPIENT`,
  `MALFORMED_ENTRY`, `MESSAGE_TOO_LONG`, `INVALID_RECIPIENT`, `INVALID_MESSAGE`,
  `NO_INTERNATIONAL_PERMISSION`.

- `rejectedItemsTruncated` (boolean, zorunlu): 100'den fazla kayıt reddedildiği için `rejectedItems` kısaltıldıysa `true`. `accepted` ve `rejected` yine tamdır.
- `referenceId` (string, null olabilir, zorunlu): İstekte verilen `referenceId`; verilmediyse `null`.

Örnek:

```json
{
  "jobId": "179309912974612345062827",
  "status": "QUEUED",
  "accepted": 1,
  "rejected": 1,
  "rejectedItems": [
    {
      "index": 1,
      "recipient": "+905xxxxxxxxx",
      "reason": "INVALID_RECIPIENT"
    }
  ],
  "rejectedItemsTruncated": false,
  "referenceId": "order-4711"
}
```

### 400 — İstek gövdesi geçersiz. `code` ve `message`:

| `code` | `message` | Ne zaman |
|---|---|---|
| `INVALID_REQUEST` | `N field(s) rejected` | Alanlar doğrulamadan geçmedi: `sender` eksik, boş ya da 35 karakterden uzun, `messages` eksik ya da boş, ya da bir alan uzunluk sınırını aşıyor; ya da bir alanın değeri türüne uymuyor: `encoding` listede olmayan bir değer (büyük/küçük harf dahil), `startAt` / `stopAt` saat dilimi farkı olan bir tarih değil, `messages` dizi değil gibi. Hangi alanın neden reddedildiği `violations` içindedir; `encoding` için geçerli değerler de listelenir. |
| `INVALID_REQUEST` | `request body could not be read as json` | Gövde geçerli bir JSON değil (sözdizimi hatası). `violations` `null`'dır. |
| `INVALID_REQUEST` | `N messages exceeds the limit of 1000000` | 1.000.000'dan fazla mesaj. |
| `INVALID_SEND_WINDOW` | — | `startAt` 18 aydan daha ileride. |

Gövde (`application/json`):

- `code` (string, zorunlu): Değerler: `INVALID_REQUEST`, `INVALID_SEND_WINDOW`.
- `message` (string, zorunlu): Okunabilir ayrıntı. `UNAUTHENTICATED` için `no bearer token` ya da `invalid or expired token`. `REJECTED_HEADER` için ret adıdır; yalnızca rakamlardan oluşan bir göndericide ` (subscriber number headers were not offered)` ekini taşıyabilir. `RATE_LIMITED` için sınırı belirtir; `FORBIDDEN` ve `REJECTED_IYS` için sabit bir cümledir. `SERVICE_UNAVAILABLE` ve `INTERNAL_ERROR` genel bir cümle taşır; bildirirken `requestId` değerini paylaşmanız gerekir.
- `requestId` (string, zorunlu): İsteğe özgü kimlik, 32 onaltılık karakter. Bir sorun bildirirken bu değeri paylaşmanız, isteğin kayıtlarda bulunmasını sağlar.
- `timestamp` (string, date-time, zorunlu)
- `violations` (array<object>, null olabilir, zorunlu): Yalnızca gövde doğrulamasından gelen INVALID_REQUEST için dolu, aksi halde `null`.
- `violations[].field` (string, isteğe bağlı)
- `violations[].message` (string, isteğe bağlı)
- `rejectedItems` (array<object>, isteğe bağlı, en fazla kayıt 100): Yalnızca `NO_DELIVERABLE_MESSAGES` yanıtında bulunur; diğer hatalarda alan hiç yer almaz. Reddedilen kayıtlar, `index` sırasıyla ilk 100 tanesi; 202 yanıtındaki `rejectedItems` ile aynıdır.
- `rejectedItems[].index` (integer, zorunlu): Kaydın istekteki `messages` dizisindeki sırası, sıfırdan başlar.
- `rejectedItems[].recipient` (string, null olabilir, zorunlu): Kayıttaki alıcı. Kayıt `null` ise ya da alıcısı yoksa `null`.
- `rejectedItems[].reason` (string, zorunlu): Değerler: `INVALID_RECIPIENT`, `INVALID_MESSAGE`, `MESSAGE_TOO_LONG`, `MALFORMED_ENTRY`, `DUPLICATE_RECIPIENT`, `NO_INTERNATIONAL_PERMISSION`.

  | Değer | Ne zaman |
  |---|---|
  | `INVALID_RECIPIENT` | Numara eksik ya da biçimi yanlış; bkz. `recipient`. |
  | `INVALID_MESSAGE` | Metin eksik ya da boş. |
  | `MESSAGE_TOO_LONG` | Metin, `encoding` ve gönderici türüne göre sınırı aşıyor; bkz. `encoding`. |
  | `MALFORMED_ENTRY` | Kayıt `null`. |
  | `DUPLICATE_RECIPIENT` | Aynı alıcı istekte daha sonra yeniden geçiyor. Yalnızca son geçen kayıt gönderilir, öncekiler bu nedenle reddedilir; son kayıt başka bir nedenle reddedilse bile. Numaralar yazıldığı gibi karşılaştırılır. Mükerrer gönderime izin verilen hesaplarda uygulanmaz. |
  | `NO_INTERNATIONAL_PERMISSION` | Numara yurt dışı (`-` ile başlıyor) ve hesabın yurt dışı gönderim izni yok. İzin için destek ekibiyle iletişime geçmelisiniz. Yalnızca başka bir hatası olmayan kayıtlarda bildirilir. |

  Bir kayıt birden fazla nedenle hatalıysa tek neden bildirilir; öncelik: `DUPLICATE_RECIPIENT`,
  `MALFORMED_ENTRY`, `MESSAGE_TOO_LONG`, `INVALID_RECIPIENT`, `INVALID_MESSAGE`,
  `NO_INTERNATIONAL_PERMISSION`.

- `rejectedItemsTruncated` (boolean, isteğe bağlı): Yalnızca `rejectedItems` ile birlikte bulunur. 100'den fazla kayıt reddedildiğinde true.

Örnek:

```json
{
  "code": "INVALID_REQUEST",
  "message": "1 field(s) rejected",
  "requestId": "3b9e2f1a6c4d48e7a05f9d2c1b8e7a64",
  "timestamp": "2026-09-07T16:42:31.123+03:00",
  "violations": [
    {
      "field": "sender",
      "message": "must not be blank"
    }
  ]
}
```

### 401 — UNAUTHENTICATED. Bearer token yok ya da token geçersiz veya süresi dolmuş; `message` `no bearer token` ya da `invalid or expired token`.

Gövde (`application/json`): alanlar 400 yanıtıyla aynı; farklı olanlar:

- `code` (string, zorunlu): Değerler: `UNAUTHENTICATED`.

Örnek (şemadan üretildi):

```json
{
  "code": "UNAUTHENTICATED",
  "message": "string",
  "requestId": "string",
  "timestamp": "2026-01-01T10:00:00+03:00",
  "violations": [
    {
      "field": "string",
      "message": "string"
    }
  ],
  "rejectedItems": [
    {
      "index": 0,
      "recipient": "string",
      "reason": "INVALID_RECIPIENT"
    }
  ],
  "rejectedItemsTruncated": true
}
```

### 403 — FORBIDDEN. Hesap bu gönderimi yapamaz; `message` şunlardan biridir:

| `message` | Anlamı |
|---|---|
| `account is not activated for this operation` | Hesapta SMS gönderimi etkin değil. |
| `sub user may not use the sms api` | Alt kullanıcının SMS API'sini kullanma izni yok. |
| `account operator is not served for this operation` | Hesabın operatörüne bu uç noktadan hizmet verilmiyor. |

Gövde (`application/json`): alanlar 400 yanıtıyla aynı; farklı olanlar:

- `code` (string, zorunlu): Değerler: `FORBIDDEN`.

Örnek (şemadan üretildi):

```json
{
  "code": "FORBIDDEN",
  "message": "string",
  "requestId": "string",
  "timestamp": "2026-01-01T10:00:00+03:00",
  "violations": [
    {
      "field": "string",
      "message": "string"
    }
  ],
  "rejectedItems": [
    {
      "index": 0,
      "recipient": "string",
      "reason": "INVALID_RECIPIENT"
    }
  ],
  "rejectedItemsTruncated": true
}
```

### 413 — INVALID_REQUEST. Gövde 500 MB'tan büyük ya da toplu gönderim kuyruğa alınamayacak kadar büyük (`message` hangisi olduğunu belirtir). Toplu gönderimi birden fazla isteğe bölmelisiniz.

Gövde (`application/json`): alanlar 400 yanıtıyla aynı; farklı olanlar:

- `code` (string, zorunlu): Değerler: `INVALID_REQUEST`.

Örnek (şemadan üretildi):

```json
{
  "code": "INVALID_REQUEST",
  "message": "string",
  "requestId": "string",
  "timestamp": "2026-01-01T10:00:00+03:00",
  "violations": [
    {
      "field": "string",
      "message": "string"
    }
  ],
  "rejectedItems": [
    {
      "index": 0,
      "recipient": "string",
      "reason": "INVALID_RECIPIENT"
    }
  ],
  "rejectedItemsTruncated": true
}
```

### 422 — İstek geçerli ama gönderim yapılamaz. `code` ve `message`:

| `code` | `message` | Anlamı ve çözüm |
|---|---|---|
| `REJECTED_HEADER` | `NO_HEADERS_REGISTERED` | Hesapta kayıtlı başlık yok. |
| `REJECTED_HEADER` | `NOT_REGISTERED` | `sender` hesaba kayıtlı değil. Kayıtlı başlıkları `GET /senders` ile görebilirsiniz. |
| `REJECTED_HEADER` | `CASE_MISMATCH` | Başlık kayıtlı ama büyük/küçük harfi farklı yazılmış; kayıtlı hâliyle göndermelisiniz. |
| `REJECTED_HEADER` | `ROUTING_CODE_MISSING` | Alfanümerik başlık için hesapta yönlendirme kodu tanımlı değil. |
| `REJECTED_HEADER` | `SUBSCRIBER_NUMBER_RESTRICTED` | Hesapta abone numarasından gönderim kısıtlı. |
| `REJECTED_IYS` | `sender header has no iys brand code` | `BRAND` ya da `RETAILER` filtresi uygulanacak ama başlığın İYS marka kodu yok. |
| `REJECTED_IYS` | `account is not in iys mode, filtering cannot be applied` | Hesap İYS modunda değil; `iysFilter` `BRAND` ya da `RETAILER` olamaz. |
| `NO_DELIVERABLE_MESSAGES` | `all N messages rejected` | Kayıtların hepsi reddedildi; görev oluşturulmadı. Hangi kaydın neden reddedildiği `rejectedItems` içindedir (202 yanıtındakiyle aynı biçim ve aynı 100 kayıt sınırı). |

Abone numarasından gönderime onaylı olmayan bir hesapta, tamamı rakamlardan oluşan bir `sender`
için `NOT_REGISTERED` ve `NO_HEADERS_REGISTERED` mesajlarının sonuna
` (subscriber number headers were not offered)` eklenir.

Gövde (`application/json`): alanlar 400 yanıtıyla aynı; farklı olanlar:

- `code` (string, zorunlu): Değerler: `REJECTED_HEADER`, `REJECTED_IYS`, `NO_DELIVERABLE_MESSAGES`.

Örnek: Gönderici kayıtlı değil

```json
{
  "code": "REJECTED_HEADER",
  "message": "NOT_REGISTERED",
  "requestId": "ca6fa668966d42169e615c6d236191e2",
  "timestamp": "2026-09-07T16:42:31.123+03:00",
  "violations": null
}
```

Örnek: Tüm kayıtlar reddedildi

```json
{
  "code": "NO_DELIVERABLE_MESSAGES",
  "message": "all 1 messages rejected",
  "requestId": "5d1f0c2a7b3e4f6a9c8d7e6f5a4b3c2d",
  "timestamp": "2026-09-07T16:42:31.123+03:00",
  "violations": null,
  "rejectedItems": [
    {
      "index": 0,
      "recipient": "-4915112345678",
      "reason": "NO_INTERNATIONAL_PERMISSION"
    }
  ],
  "rejectedItemsTruncated": false
}
```

### 429 — RATE_LIMITED. `message` şunlardan biridir:

- `send rate limit exceeded`: hesap başına dakikada 50.000 istek aşıldı. `Retry-After` kadar
  bekleyip yeniden denemelisiniz.
- `sending is suspended for this account`: hesabın gönderimi askıya alınmış. `Retry-After`
  yoktur; beklemek işe yaramaz, destek ekibiyle iletişime geçmelisiniz.

Başlıklar:

- `Retry-After` (integer): Yeniden denemeden önce beklenecek süre (saniye). Askıya alınmış hesapta bulunmaz.

Gövde (`application/json`): alanlar 400 yanıtıyla aynı; farklı olanlar:

- `code` (string, zorunlu): Değerler: `RATE_LIMITED`.

Örnek (şemadan üretildi):

```json
{
  "code": "RATE_LIMITED",
  "message": "string",
  "requestId": "string",
  "timestamp": "2026-01-01T10:00:00+03:00",
  "violations": [
    {
      "field": "string",
      "message": "string"
    }
  ],
  "rejectedItems": [
    {
      "index": 0,
      "recipient": "string",
      "reason": "INVALID_RECIPIENT"
    }
  ],
  "rejectedItemsTruncated": true
}
```

### 500 — INTERNAL_ERROR, `message` `internal error`. Beklenmeyen hata; bildirirken `requestId` değerini paylaşmanız gerekir.

Gövde (`application/json`): alanlar 400 yanıtıyla aynı; farklı olanlar:

- `code` (string, zorunlu): Değerler: `INTERNAL_ERROR`.

Örnek (şemadan üretildi):

```json
{
  "code": "INTERNAL_ERROR",
  "message": "string",
  "requestId": "string",
  "timestamp": "2026-01-01T10:00:00+03:00",
  "violations": [
    {
      "field": "string",
      "message": "string"
    }
  ],
  "rejectedItems": [
    {
      "index": 0,
      "recipient": "string",
      "reason": "INVALID_RECIPIENT"
    }
  ],
  "rejectedItemsTruncated": true
}
```

### 503 — SERVICE_UNAVAILABLE. Servis geçici olarak kullanılamıyor. Görev çoğunlukla kuyruğa alınmamıştır. Toplu gönderimi körlemesine yeniden göndermeden önce `GET /report` ile kontrol edebilirsiniz.

Gövde (`application/json`): alanlar 400 yanıtıyla aynı; farklı olanlar:

- `code` (string, zorunlu): Değerler: `SERVICE_UNAVAILABLE`.

Örnek (şemadan üretildi):

```json
{
  "code": "SERVICE_UNAVAILABLE",
  "message": "string",
  "requestId": "string",
  "timestamp": "2026-01-01T10:00:00+03:00",
  "violations": [
    {
      "field": "string",
      "message": "string"
    }
  ],
  "rejectedItems": [
    {
      "index": 0,
      "recipient": "string",
      "reason": "INVALID_RECIPIENT"
    }
  ],
  "rejectedItemsTruncated": true
}
```
