API Dokümantasyonu
SMS ve WhatsApp Business mesajlaşma için tam REST API referansı. Her endpoint'in yanındaki "AI'ya Kopyala" butonu, endpoint metadata'sını yapay zeka asistanlarına yapıştırılınca eksiksiz çalışacak yapılandırılmış prompt'a çevirir.
https://betesemes.comX-Api-Keyapplication/jsonHızlı Başlangıç
- 1. Hesap oluştur (30 saniye, e-posta + parola).
- 2. Panelde
/app/api-keyssayfasından bir API anahtarı oluştur. Anahtar formatı:gsms_xxxxxxxxxxxxxxxx(sadece 1 kez gösterilir, kaydet). - 3. Test isteğini at:
curl https://betesemes.com/api/v1/me \ -H "X-Api-Key: gsms_xxxxxxxxxxxxxxxx"
Kimlik Doğrulama
Tüm authenticated istekler X-Api-Key header'ı ile yapılır. Anahtarlar sunucuda SHA-256 hash olarak saklanır; plaintext sadece üretim anında bir kez gösterilir. Anahtar sızdığında /app/api-keys sayfasından anında iptal edebilirsin. Per-key audit log (son 30 gün) görüntülenebilir.
Rate Limit
Varsayılan limit her API anahtarı için 30 istek/sn. Premium müşterilerde 100/sn'e yükseltilebilir. Her yanıt aşağıdaki header'ları içerir:
X-RateLimit-Limit: 30 X-RateLimit-Policy: 30;w=1 X-RateLimit-Remaining: 28
Limit aşıldığında 429 RATE_LIMIT döner. Retry-After saniye olarak yanıt header'ında gelir. Client tarafında exponential backoff önerilir.
Yetkilendirme
/api/v1/meAuth GerekirHesap bilgisi
API anahtarınızın geçerliliğini test etmek ve hesap kimliği + rolü doğrulamak için kullanılır. Bu endpoint çağrısı kredi yakmaz.
| HTTP | Code | Açıklama |
|---|---|---|
| 401 | NO_KEY | X-Api-Key header eksik |
| 401 | INVALID_KEY | API anahtarı geçersiz |
curl https://betesemes.com/api/v1/me \ -H "X-Api-Key: gsms_xxxxxxxxxxxxxxxx"
{
"ok": true,
"userId": 42,
"email": "ops@bahis123.com",
"role": "USER",
"balanceCredits": 1250.5,
"balanceWaCredits": 800
}SMS Endpoint'leri
/api/v1/sms/sendAuth GerekirToplu SMS gönderimi
Bir veya birden fazla alıcıya SMS gönderir. Kampanya olarak kayıt edilir, DLR webhook'larıyla durumu takip edilir. Segment hesaplaması otomatik (GSM-7 için 160 char, Unicode için 70 char). Kredi düşümü gönderim öncesi atılır, başarısız mesajlar için iade yapılır. NOT: Mesajdaki linkler teslimat için otomatik normalize edilir, http(s):// ve www. kaldırılır (ör. https://www.site.com → site.com). Linki noktasıyla yazmanız yeterli; operatör filtresi ve ulaşılabilirlik için bu işlem otomatik yapılır.
| Ad | Tip | Açıklama |
|---|---|---|
| to* | string | string[] | E.164 formatında alıcı(lar): '+905551234567'. Tek string veya dizi. Tek istekte en fazla 100.000 alıcı |
| text* | string | Mesaj gövdesi. En az 1 karakter, en fazla 5 segment |
| from | string | Geriye dönük uyumluluk için kabul edilir ancak yok sayılır — tüm mesajlar tek global gönderici adıyla gider. Göndermeseniz de olur |
| scheduled | string (ISO8601) | İleri tarihli gönderim zamanı. Boş = anında |
| dlr_url | string (https) | Bu gönderime özel DLR webhook URL'i (https zorunlu). Boş bırakılırsa hesap ayarlarındaki varsayılan kullanılır |
| HTTP | Code | Açıklama |
|---|---|---|
| 400 | BAD_JSON | Gövde geçerli JSON değil |
| 401 | NO_KEY | X-Api-Key header eksik |
| 401 | INVALID_KEY | API anahtarı geçersiz |
| 402 | INSUFFICIENT_CREDIT | Yetersiz kredi |
| 409 | DUPLICATE_REQUEST | Aynı istek kısa süre içinde tekrarlandı (Idempotency-Key) |
| 413 | TOO_MANY | Alıcı limiti aşıldı (maks 100.000) |
| 422 | VALIDATION | Gövde doğrulanamadı |
| 422 | NO_RECIPIENTS | Geçerli E.164 alıcı yok |
| 422 | ALL_SUPPRESSED | Tüm alıcılar bastırılmış (opt-out/blacklist) |
| 422 | TOO_LONG | Mesaj 5 segmenti aşıyor |
| 429 | RATE_LIMIT | Hız limiti aşıldı (30 istek/sn) |
| 503 | QUEUE_UNAVAILABLE | Kuyruk geçici olarak kullanılamıyor, tekrar deneyin |
curl -X POST https://betesemes.com/api/v1/sms/send \
-H "X-Api-Key: gsms_xxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"to": ["+905551234567", "+905559876543"],
"text": "Bonusunuz hazır: 500 TL"
}'{
"to": [
"+905551234567",
"+905559876543"
],
"text": "Bonusunuz hazır: 500 TL"
}{
"campaignId": 4521,
"totalRecipients": 2,
"suppressedSkipped": 0,
"segments": 1,
"costCredits": 2,
"costCreditsHuman": "2",
"status": "QUEUED",
"spamScore": {
"score": 0,
"level": "low",
"warnings": []
}
}/api/v1/sms/balanceAuth GerekirSMS bakiyesi
SMS kredi bakiyenizi döner. 1 kredi = 1 SMS segmenti. (balance ve usdt alanları geriye dönük uyumluluk için bırakılmıştır, artık kullanılmaz.)
| HTTP | Code | Açıklama |
|---|---|---|
| 401 | NO_KEY | X-Api-Key header eksik |
| 401 | INVALID_KEY | API anahtarı geçersiz |
curl https://betesemes.com/api/v1/sms/balance \ -H "X-Api-Key: gsms_xxxxxxxxxxxxxxxx"
{
"credits": 1248,
"creditsHuman": "1.248",
"currency": "BeteSemes Credit",
"balance": 0,
"usdt": null
}/api/v1/campaignsAuth GerekirKampanya listesi
SMS kampanyalarınızı sayfalı olarak döner. ?page (varsayılan 1) ve ?pageSize (varsayılan 25, maks 100) ile sayfalanır. total alanı toplam kayıt sayısıdır.
| Ad | Tip | Açıklama |
|---|---|---|
| page | number | Sayfa numarası (1'den başlar), varsayılan 1 |
| pageSize | number | Sayfa başına kayıt (1-100), varsayılan 25 |
| HTTP | Code | Açıklama |
|---|---|---|
| 401 | INVALID_KEY | API anahtarı geçersiz |
| 429 | RATE_LIMIT | Hız limiti |
curl "https://betesemes.com/api/v1/campaigns?page=1&pageSize=25" \ -H "X-Api-Key: gsms_xxxxxxxxxxxxxxxx"
{
"data": [
{
"id": 4521,
"name": "Hafta sonu bonus",
"status": "COMPLETED",
"totalRecipients": 2,
"sentCount": 2,
"deliveredCount": 2,
"failedCount": 0,
"createdAt": "2026-05-19T10:30:00.000Z"
}
],
"total": 137,
"page": 1,
"pageSize": 25
}/api/v1/campaigns/:idAuth GerekirKampanya detayı
Kampanyanın anlık durum ve sayaçları. Canlı kampanyalarda 5sn aralıklarla poll'lanabilir.
| Ad | Tip | Açıklama |
|---|---|---|
| id* | number | Kampanya ID |
| HTTP | Code | Açıklama |
|---|---|---|
| 401 | INVALID_KEY | API anahtarı geçersiz |
| 404 | NOT_FOUND | Kampanya bulunamadı (veya başka müşteriye ait) |
curl https://betesemes.com/api/v1/campaigns/4521 \ -H "X-Api-Key: gsms_xxxxxxxxxxxxxxxx"
{
"id": 4521,
"name": "Hafta sonu bonus",
"sender": "BETESEMES",
"text": "Bonusunuz hazır: 500 TL",
"status": "SENDING",
"segments": 1,
"encoding": "GSM7",
"totalRecipients": 1000,
"sentCount": 750,
"deliveredCount": 620,
"failedCount": 30,
"pendingCount": 250,
"creditsReserved": 1000,
"creditsSpent": 750,
"creditsReservedHuman": "1.000",
"creditsSpentHuman": "750",
"scheduledAt": null,
"createdAt": "2026-05-19T10:30:00.000Z",
"updatedAt": "2026-05-19T10:45:00.000Z"
}/api/v1/contactsAuth GerekirKontak listesi
Numara rehberindeki kişileri sayfalı döner. ?page (varsayılan 1) ve ?pageSize (varsayılan 50, maks 100) ile sayfalanır. ?q ile telefona göre arama yapılır.
| Ad | Tip | Açıklama |
|---|---|---|
| page | number | Sayfa numarası (1'den başlar), varsayılan 1 |
| pageSize | number | Sayfa başına kayıt (1-100), varsayılan 50 |
| q | string | Telefon numarasına göre arama (contains) |
curl "https://betesemes.com/api/v1/contacts?page=1&pageSize=50" \ -H "X-Api-Key: gsms_xxxxxxxxxxxxxxxx"
{
"data": [
{
"id": "1234567890",
"phone": "+905551234567",
"firstName": "Ahmet",
"lastName": "Yılmaz",
"email": null,
"country": "TR",
"tags": [
"vip"
],
"customFields": null,
"optedOut": false,
"createdAt": "2026-04-01T08:00:00.000Z"
}
],
"total": 4210,
"page": 1,
"pageSize": 50
}/api/v1/contactsAuth GerekirKontak oluştur
Yeni kontak ekler. Telefon E.164 formatında, duplicate kontroli sunucuda yapılır.
| Ad | Tip | Açıklama |
|---|---|---|
| phone* | string | E.164 (+905551234567) |
| firstName | string | Ad |
| lastName | string | Soyad |
| string | E-posta | |
| tags | string[] | Etiketler (örn ["vip","futbol"]) |
| customFields | object | Custom JSON alanlar |
| HTTP | Code | Açıklama |
|---|---|---|
| 409 | DUPLICATE | Bu telefonla kişi zaten var |
| 422 | VALIDATION | Gövde doğrulanamadı (örn. phone E.164 değil) |
curl -X POST https://betesemes.com/api/v1/contacts \
-H "X-Api-Key: gsms_xxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"phone": "+905551234567",
"firstName": "Ahmet",
"tags": ["vip"]
}'{
"phone": "+905551234567",
"firstName": "Ahmet",
"lastName": "Yılmaz",
"tags": [
"vip",
"yatirim_5000_plus"
],
"customFields": {
"signupSource": "site_form"
}
}{
"id": "1234567890",
"phone": "+905551234567",
"firstName": "Ahmet",
"lastName": "Yılmaz",
"email": null,
"country": "TR",
"tags": [
"vip"
],
"customFields": {
"signupSource": "site_form"
},
"optedOut": false,
"createdAt": "2026-05-19T11:00:00.000Z"
}/api/v1/contacts/:idAuth GerekirKişi detayı
Tek bir kişiyi ID ile döndürür. Yalnızca kendi hesabınıza ait kişilere erişebilirsiniz. Kredi yakmaz.
| Ad | Tip | Açıklama |
|---|---|---|
| id* | string (bigint) | Kişi kimliği (liste/oluşturma yanıtındaki id) |
| HTTP | Code | Açıklama |
|---|---|---|
| 404 | NOT_FOUND | Kişi bulunamadı veya size ait değil |
curl https://betesemes.com/api/v1/contacts/1234567890 \ -H "X-Api-Key: gsms_xxxxxxxxxxxxxxxx"
{
"id": "1234567890",
"phone": "+905551234567",
"firstName": "Ahmet",
"lastName": null,
"email": null,
"country": "TR",
"tags": [
"vip"
],
"customFields": null,
"optedOut": false,
"createdAt": "2026-05-20T10:00:00.000Z"
}/api/v1/contacts/:idAuth GerekirKişi güncelle
Bir kişinin alanlarını kısmi günceller, yalnızca gönderdiğiniz alanlar değişir. PUT da aynı şekilde çalışır. phone gönderirseniz hesabın varsayılan ülkesine göre E.164'e normalize edilir. tags gönderildiğinde mevcut etiketlerin tamamını değiştirir.
| Ad | Tip | Açıklama |
|---|---|---|
| id* | string (bigint) | Kişi kimliği |
| Ad | Tip | Açıklama |
|---|---|---|
| phone | string | Yeni numara, E.164'e normalize edilir |
| firstName | string | null | Ad |
| lastName | string | null | Soyad |
| string | null | Geçerli e-posta adresi | |
| tags | string[] | Etiket listesi (tümünü değiştirir) |
| customFields | object | Serbest anahtar/değer alanları |
| optedOut | boolean | Çıkış (opt-out) durumu |
| HTTP | Code | Açıklama |
|---|---|---|
| 404 | NOT_FOUND | Kişi bulunamadı |
| 422 | VALIDATION | Geçersiz gövde |
| 422 | INVALID_PHONE | Telefon normalize edilemedi |
curl -X PATCH https://betesemes.com/api/v1/contacts/1234567890 \
-H "X-Api-Key: gsms_xxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{"firstName":"Mehmet","tags":["vip","2026"]}'{
"firstName": "Mehmet",
"tags": [
"vip",
"2026"
]
}{
"id": "1234567890",
"phone": "+905551234567",
"firstName": "Mehmet",
"lastName": null,
"email": null,
"country": "TR",
"tags": [
"vip",
"2026"
],
"customFields": null,
"optedOut": false,
"createdAt": "2026-05-20T10:00:00.000Z"
}/api/v1/contacts/:idAuth GerekirKişi sil
Bir kişiyi kalıcı olarak siler. Başarılı silmede gövde dönmez (HTTP 204 No Content). Geri alınamaz.
| Ad | Tip | Açıklama |
|---|---|---|
| id* | string (bigint) | Silinecek kişi kimliği |
| HTTP | Code | Açıklama |
|---|---|---|
| 404 | NOT_FOUND | Kişi bulunamadı veya size ait değil |
curl -X DELETE https://betesemes.com/api/v1/contacts/1234567890 \ -H "X-Api-Key: gsms_xxxxxxxxxxxxxxxx"
204 No Content, yanıt gövdesi yoktur.
/api/v1/sms/:messageIdAuth GerekirMesaj durumu sorgula
Tek bir mesajın güncel teslim durumunu döndürür. messageId, mesajın benzersiz kimliğidir — DLR webhook payload'ındaki messageId alanından gelir (gönderim yanıtı kampanya bazlıdır, tekil messageId döndürmez). errorCode yalnızca kalıcı hatalarda doludur ve jeneriktir (ham operatör kodu içermez). Kredi yakmaz.
| Ad | Tip | Açıklama |
|---|---|---|
| messageId* | string | Gönderim yanıtındaki provider mesaj kimliği |
| HTTP | Code | Açıklama |
|---|---|---|
| 400 | BAD_ID | messageId eksik |
| 404 | NOT_FOUND | Mesaj bulunamadı |
curl https://betesemes.com/api/v1/sms/2003b23d-4765-44f7-bdf7-bb14bbb0e36c \ -H "X-Api-Key: gsms_xxxxxxxxxxxxxxxx"
{
"messageId": "2003b23d-4765-44f7-bdf7-bb14bbb0e36c",
"campaignId": 4521,
"phone": "+905551234567",
"status": "DELIVERED",
"errorCode": null,
"segments": 1,
"sentAt": "2026-05-20T10:00:00.000Z",
"deliveredAt": "2026-05-20T10:00:05.000Z"
}/api/v1/dlrAuth GerekirDLR test (echo)
Entegrasyon test ucu: gönderdiğiniz JSON gövdesini (POST) ya da query parametrelerini (GET) aynen 'received' içinde geri döndürür. Gerçek teslim raporları bu uçtan GELMEZ, onlar sizin webhook URL'inize POST edilir (bkz. Webhooks › DLR webhook). Bu uç yalnızca kendi tarafınızı denemek/log akışını görmek içindir; GET ve POST kabul eder, kredi yakmaz.
| Ad | Tip | Açıklama |
|---|---|---|
| (serbest) | object | Herhangi bir JSON, değişmeden 'received' alanında döner |
| HTTP | Code | Açıklama |
|---|---|---|
| 401 | INVALID_KEY | API anahtarı geçersiz |
| 405 | METHOD | GET/POST dışında bir method kullanıldı |
curl -X POST https://betesemes.com/api/v1/dlr \
-H "X-Api-Key: gsms_xxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{"messageId":"abc-123","status":"DELIVERED"}'{
"messageId": "abc-123",
"status": "DELIVERED"
}{
"ok": true,
"received": {
"messageId": "abc-123",
"status": "DELIVERED"
}
}OTP Endpoint'leri
/api/v1/otp/sendAuth GerekirOTP gönder
Bir telefon numarasına tek kullanımlık doğrulama kodu (OTP) gönderir. Kod sunucuda üretilir ve güvenli saklanır; siz yalnızca bir requestId alırsınız (kod yanıtta DÖNMEZ). Şablon {code} placeholder'ı içermelidir; mesaj 5 segmenti aşamaz. Kredi gönderim anında düşülür.
| Ad | Tip | Açıklama |
|---|---|---|
| phone* | string | Alıcı numara (E.164 veya hesabın varsayılan ülkesine göre normalize edilir) |
| sender* | string | Şema gereği zorunlu ancak yok sayılır — OTP daima tek global gönderici adıyla gider (maks 15 karakter) |
| template | string | Mesaj şablonu; {code} yerine kod konur. Varsayılan: 'BeteSemes dogrulama kodunuz: {code}' |
| length | number | Kod uzunluğu, 4-10 |
| ttl | number | Geçerlilik süresi (saniye), 60-1800 |
| maxAttempts | number | İzin verilen doğrulama denemesi, 1-10 |
| HTTP | Code | Açıklama |
|---|---|---|
| 400 | INVALID_PHONE | Geçersiz telefon numarası |
| 400 | INVALID_TEMPLATE | Şablon {code} placeholder içermiyor |
| 402 | INSUFFICIENT_CREDITS | Yetersiz kredi |
| 422 | TOO_LONG | OTP mesajı 5 segmenti aşıyor |
| 429 | RATE_LIMITED | Aynı numaraya çok sık OTP isteği |
| 502 | SEND_FAILED | SMS gönderimi başarısız |
curl -X POST https://betesemes.com/api/v1/otp/send \
-H "X-Api-Key: gsms_xxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{"phone":"+905551234567","sender":"BETESEMES","template":"Kodunuz: {code}"}'{
"phone": "+905551234567",
"sender": "BETESEMES",
"template": "Kodunuz: {code}",
"length": 6,
"ttl": 300
}{
"requestId": "otp_a1b2c3d4",
"phone": "+905551234567",
"expiresAt": "2026-05-20T10:05:00.000Z",
"status": "PENDING",
"costCredits": 1
}/api/v1/otp/verifyAuth GerekirOTP doğrula
Kullanıcının girdiği kodu, otp/send'den dönen requestId ile doğrular. verified=true ise kod doğru. Yanlış kodda triesRemaining kalan deneme sayısını verir; denemeler bitince veya süre dolunca status REJECTED/EXPIRED olur.
| Ad | Tip | Açıklama |
|---|---|---|
| requestId* | string | otp/send yanıtındaki requestId |
| code* | string | Kullanıcının girdiği kod |
| HTTP | Code | Açıklama |
|---|---|---|
| 404 | NOT_FOUND | OTP isteği bulunamadı |
| 422 | VALIDATION | requestId/code eksik veya geçersiz |
curl -X POST https://betesemes.com/api/v1/otp/verify \
-H "X-Api-Key: gsms_xxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{"requestId":"otp_a1b2c3d4","code":"123456"}'{
"requestId": "otp_a1b2c3d4",
"code": "123456"
}{
"verified": true,
"status": "APPROVED",
"triesRemaining": 0
}/api/v1/otp/statusAuth GerekirOTP durumu
Bir OTP isteğinin güncel durumunu döndürür. Süresi geçmiş PENDING istekler bu çağrıda EXPIRED'a çevrilir. Kredi yakmaz.
| Ad | Tip | Açıklama |
|---|---|---|
| requestId* | string | otp/send yanıtındaki requestId |
| HTTP | Code | Açıklama |
|---|---|---|
| 404 | NOT_FOUND | OTP isteği bulunamadı |
| 422 | VALIDATION | requestId gereklidir |
curl "https://betesemes.com/api/v1/otp/status?requestId=otp_a1b2c3d4" \ -H "X-Api-Key: gsms_xxxxxxxxxxxxxxxx"
{
"requestId": "otp_a1b2c3d4",
"status": "PENDING",
"phone": "+905551234567",
"expiresAt": "2026-05-20T10:05:00.000Z",
"verifyAttempts": 0,
"maxAttempts": 3,
"createdAt": "2026-05-20T10:00:00.000Z"
}Webhook Formatı
[Senin webhook URL'in]DLR webhook (SMS + WhatsApp)
Mesaj teslim durumu kesinleştikçe (DELIVERED/FAILED/EXPIRED/REJECTED) sistem senin kayıtlı webhook URL'ine POST yapar. İmza: x-betesms-signature header'ında HMAC-SHA256(raw body, webhook secret); ayrıca x-betesms-event: dlr header'ı gelir. 2xx beklenir; 5xx/ağ hatasında 5 deneme exponential backoff (yaklaşık 5s, 25s, 2dk, 10dk, 50dk), 4xx kalıcı hata sayılır. status alanı jeneriktir; ham operatör kodları gönderilmez.
# Webhook URL'ini hesap ayarlarından kaydet:
# /app/settings → Webhook URL → Kaydet
# İmza doğrulama (Node.js):
import crypto from "node:crypto";
const sig = req.headers["x-betesms-signature"];
const expected = crypto
.createHmac("sha256", USER_WEBHOOK_SECRET)
.update(req.rawBody)
.digest("hex");
if (!crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected))) {
return res.status(401).send("Invalid signature");
}
// process req.body...
res.status(200).send("ok");{
"event": "dlr",
"campaignId": 4521,
"phone": "+905551234567",
"messageId": "a1b2c3d4-...",
"status": "DELIVERED",
"timestamp": "2026-05-19T12:05:00.000Z"
}// Beklenen yanıt: 2xx (HTTP 200-299). Body göz ardı edilir. // 4xx/5xx alırsa exponential backoff retry yapılır.
[Senin webhook URL'in]WhatsApp inbound message webhook
Müşterilerinizden gelen tüm WhatsApp mesajları (text, image, button reply, vb.) webhook URL'ine POST edilir. İmza aynı DLR mantığı. Ek alanlar: messageDirection, contentType, mediaUrl, templateName (eğer önceki template'e yanıtsa).
# Aynı imza doğrulama akışı, yukarıda DLR örneğine bak.
{
"event": "message.inbound",
"channel": "whatsapp",
"numberId": 7,
"phone": "+905551234567",
"providerMessageId": "wamid.HBgM...",
"contentType": "TEXT",
"text": "Bonusumu nasıl alırım?",
"timestamp": "2026-05-19T12:01:00Z",
"windowOpened": true
}// Beklenen yanıt: 2xx. Aynı imza doğrulama mantığı. // İçerik: text mesajda "text"; medyalı mesajda "mediaUrl" alanı dolu gelir.
Tüm Hata Kodları
Hata yanıtları daima { "error": "...", "code": "..." } formatındadır (error insan-okur mesaj, code makine-okur kod). HTTP status koduyla birlikte code alanını kontrol et.
| HTTP | Code | Açıklama |
|---|---|---|
| 400 | BAD_JSON | İstek gövdesi geçerli JSON değil |
| 401 | NO_KEY | X-Api-Key header eksik |
| 401 | INVALID_KEY | API anahtarı geçersiz veya iptal edilmiş |
| 405 | METHOD | Endpoint için izin verilmeyen HTTP method |
| 404 | NOT_FOUND | Kaynak bulunamadı veya başka müşteriye ait |
| 422 | VALIDATION | Body veya query doğrulanamadı |
| 429 | RATE_LIMIT | Hız limiti aşıldı (30 req/sn varsayılan); Retry-After header'ına bak |
| 429 | AUTH_RATE_LIMIT | Kimlik doğrulama denemesi çok sık (IP bazlı) |
| 500 | INTERNAL | Beklenmeyen sunucu hatası |
| 402 | INSUFFICIENT_CREDIT | Yetersiz kredi |
| 409 | DUPLICATE_REQUEST | Aynı istek kısa süre içinde tekrarlandı (Idempotency-Key) |
| 413 | TOO_MANY | Alıcı limiti aşıldı (maks 100.000) |
| 422 | NO_RECIPIENTS | Geçerli E.164 alıcı yok |
| 422 | ALL_SUPPRESSED | Tüm alıcılar bastırılmış (opt-out/blacklist) |
| 422 | TOO_LONG | Mesaj 5 segmenti aşıyor |
| 503 | QUEUE_UNAVAILABLE | Kuyruk geçici olarak kullanılamıyor, tekrar deneyin |
| 409 | DUPLICATE | Bu telefonla kişi zaten kayıtlı |
| 422 | INVALID_PHONE | Telefon E.164'e normalize edilemedi |
| 400 | INVALID_TEMPLATE | OTP şablonu {code} placeholder içermiyor |
| 402 | INSUFFICIENT_CREDITS | OTP için yetersiz kredi |
| 429 | RATE_LIMITED | Aynı numaraya çok sık OTP isteği |
| 502 | SEND_FAILED | OTP SMS gönderimi başarısız |
| 422 | TEMPLATE_NOT_APPROVED | WhatsApp şablonu APPROVED değil |
| 422 | CHANNEL_NOT_ACTIVE | WhatsApp numarası aktif değil |
| 422 | CSW_WINDOW_CLOSED | 24h CSW kapalı, template gerek |
| 422 | BRAND_TERMS_NOT_ACCEPTED | MARKETING için BrandKit terms gerekli |
| 422 | FREQ_CAP | 24h içinde aynı alıcıya tekrar gönderim engellendi |
| 422 | QUALITY_LOW | Numara LOW quality, MARKETING bloklandı |
| 422 | OPTED_OUT | Alıcı STOP/DUR ile opt-out etmiş |