İçeriğe geç
API sürümü 0.2.0

API başvurusu

Tüm 2X ürünleri aynı API’yi kullanır. Bu sayfa geliştirici için kısa bir başvurudur; tam şema panelde ve OpenAPI belgesinde yer alır.

Durum: e-posta gönderimi ve webhook canlıdır. SMS gönderiminde operatör bağlantısı açılış aşamasındadır. OTP uçları açılış aşamasındadır; alan adları değişebilir.

Genel kurallar

  • Taban adres: https://api.reach2x.com
  • İstek ve yanıtlar JSON (UTF-8). Zamanlar RFC 3339, UTC.
  • Telefon numaraları E.164 (+905321234567) gönderilir, yanıtlarda maskelenir (+90 5** *** ** 67).
  • İleti gövdesi kuruluşunuzun saklama süresi boyunca tutulur ve API’den asla geri döndürülmez. otp kategorisinde gövde hiç saklanmaz.

Kimlik doğrulama

Her isteğe proje API anahtarını Bearer olarak ekleyin:

Authorization: Bearer rx_canli_… (canlı) · rx_test_… (test projesi; gerçek alıcıya hiçbir şey gitmez)

Anahtarlar panelde oluşturulur. Gizli değer yalnız bir kez gösterilir; yalnız karması saklanır. Bir anahtar tek projeye aittir; isteğe bağlı olarak izinli göndericiler, IP izin listesi ve son kullanma tarihi taşır.

Kapsamİzin verdiği
sms.sendSMS gönderme ve zamanlanmış SMS iptali
sms.readSMS ve ileti listesini okuma
email.sendE-posta gönderme
email.readE-posta okuma
otp.sendDoğrulama kodu gönderme (açılış aşamasında)
otp.verifyDoğrulama kodunu kontrol etme (açılış aşamasında)
webhook.manageWebhook uçlarını yönetme
balance.readKota ve kullanım okuma

Idempotency

Bir şey gönderen her çağrı Idempotency-Key başlığı ister: 8–128 karakter, A-Z a-z 0-9 _ - : . (UUID uygundur). Anahtar kuruluş + kimlik başına 24 saat saklanır.

  • Aynı anahtar + aynı gövde → ilk yanıt döner, Idempotent-Replay: true başlığıyla.
  • Aynı anahtar + farklı gövde → 422 idempotency_key_mismatch.
  • İlk istek sürerken → 409 idempotency_in_progress.

E-posta gönder POST /v1/emails

Kapsam email.send. Alıcı başına bir ileti oluşturur ve kalıcı olarak kaydettikten sonra 202 döner. Gönderen alan adının doğrulanmış olması gerekir; ileti o alan için DKIM ile imzalanır. Ek dosya bu sürümde yoktur.

AlanTipAçıklama
fromstring | {email, name}Doğrulanmış gönderen alanınızdan adres. Zorunlu.
tostring | string[]Bir adres ya da en çok 50 adres. Zorunlu.
subjectstring1–998 karakter. Zorunlu.
text / htmlstringEn az biri zorunlu; her biri en çok 500.000 karakter.
categoryinformational | otp | commercialZorunlu. commercial henüz açık değil.
reply_tostringYanıt adresi.
send_atdate-timeEn çok 30 gün ileri; boşsa hemen.
valid_for_minutesinteger1–4320, varsayılan 2880. Süre dolunca expired.
tagsobjectEn çok 10 anahtar/değer; kişisel veri koymayın.
curl E-posta gönder
curl https://api.reach2x.com/v1/emails \
  -H "Authorization: Bearer $REACH2X_API_KEY" \
  -H "Idempotency-Key: rapor-2026-11-0001" \
  -H "Content-Type: application/json" \
  -d '{
    "from": { "email": "[email protected]", "name": "Example" },
    "to": "[email protected]",
    "subject": "Aylık raporunuz hazır",
    "text": "Raporunuz hazır: https://example.com/r/Ab12",
    "category": "informational"
  }'
Yanıt202 Accepted
{
  "batch_id": "7d1c2e60-4a8b-4f0e-9b1a-2f6c1d9e3a10",
  "messages": [{
    "id": "c0a8f1e2-5b3d-4e7f-8a9b-1c2d3e4f5a6b",
    "object": "email",
    "status": "queued",
    "category": "informational",
    "from": "[email protected]",
    "to": "a***@example.org"
  }]
}

Okuma: GET /v1/emails, GET /v1/emails/{id} (olay zaman çizelgesiyle; kapsam email.read).

SMS gönder POST /v1/sms

TXT2X operatör bağlantısı açılış aşamasındadır — yakında canlı. Test anahtarıyla aynı çağrıyı bugün deneyebilirsiniz.

Kapsam sms.send. category hukuki işlemi belirler: informational (işlem bilgisi), otp (gövde saklanmaz), commercial (İYS: alıcı tipi ve marka kodu gerekir; izni olmayan alıcı recipient_no_consent ile düşer).

Kodlama otomatik seçilir: gsm7 160/153, gsm7_tr 155/149, ucs2 70/67 karakter/segment.

AlanTipAçıklama
tostring | string[]E.164 numara ya da en çok 100 farklı numara. Zorunlu.
bodystringKodlamadan sonra en çok 7 segment. Zorunlu.
categoryinformational | otp | commercialZorunlu. Hukuki işlemi belirler.
senderstringOnaylı gönderici adı, 3–11 karakter. Boşsa projenin varsayılanı.
send_atdate-timeEn çok 30 gün ileri.
valid_for_minutesinteger1–2880, varsayılan 1440.
commercial.recipient_typeindividual | merchantcommercial kategoride zorunlu (İYS alıcı tipi).
tagsobjectEn çok 10 anahtar/değer.
curl SMS gönder
curl https://api.reach2x.com/v1/sms \
  -H "Authorization: Bearer $REACH2X_API_KEY" \
  -H "Idempotency-Key: randevu-48213" \
  -H "Content-Type: application/json" \
  -d '{
    "to": "+905321234567",
    "body": "Randevunuz 18 Kasım 14:30. Değişiklik: https://example.com/r/Ab12",
    "category": "informational",
    "sender": "EXAMPLE"
  }'
Yanıt202 Accepted
{
  "batch_id": "3f9a2b7c-1d4e-4a5b-8c6d-7e8f9a0b1c2d",
  "messages": [{
    "id": "8b7a6c5d-4e3f-4a2b-9c1d-0e9f8a7b6c5d",
    "object": "sms",
    "status": "queued",
    "to": "+90 5** *** ** 67",
    "sender": "EXAMPLE",
    "segments": 1,
    "encoding": "gsm7_tr"
  }]
}

Diğer uçlar: GET /v1/sms/{id}, POST /v1/sms/{id}/cancel (yalnız scheduled), GET /v1/balance (kapsam balance.read).

Doğrulama kodu (OTP)

E-posta kanalı canlıdır; SMS kanalı operatör bağlantısıyla birlikte açılır. Her POST bir Idempotency-Key ister; aynı alıcıya 60 sn’de bir kod (saatte en çok 5), 5 yanlış denemede kod kilitlenir, kod tek kullanımlıktır.

  • POST /v1/otp — { channel: "sms" | "email", to, from?, subject?, sender?, length?, ttl_seconds?, template? } → 201 { id, status, attempts_left, expires_at, … }. Kapsam otp.send.
  • POST /v1/otp/{id}/verify — { code } → { verified, attempts_left, status }; hata kodları otp_expired 410, otp_locked 409, otp_already_verified 409, otp_rate_limited 429. Kapsam otp.verify.
curl Kod gönder
curl https://api.reach2x.com/v1/otp \
  -H "Authorization: Bearer $REACH2X_API_KEY" \
  -H "Idempotency-Key: giris-7f3a91c2" \
  -H "Content-Type: application/json" \
  -d '{
    "channel": "email",
    "to": "[email protected]",
    "from": "[email protected]",
    "length": 6,
    "ttl_seconds": 300
  }'
Yanıt
{
  "id": "5e4d3c2b-1a09-4f8e-8d7c-6b5a49382716",
  "object": "otp",
  "channel": "email",
  "status": "pending",
  "to": "a***@ornek.com",
  "attempts_left": 5,
  "expires_at": "2026-11-14T09:35:00Z"
}
curl Kodu doğrula
curl https://api.reach2x.com/v1/otp/5e4d3c2b-1a09-4f8e-8d7c-6b5a49382716/verify \
  -H "Authorization: Bearer $REACH2X_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "code": "482913" }'
Yanıt
{
  "verified": true,
  "attempts_left": 4,
  "status": "verified"
}

İleti durumları

scheduled → queued → sending → sent → delivered | failed | expired; canceled yalnız scheduled’dan.

DurumAnlamı
scheduledsend_at zamanını bekliyor; yalnız bu durumda iptal edilebilir.
queuedKuyrukta; geçici ağ hatasında da buraya döner.
sendingAğa teslim ediliyor (geçici).
sentAğ kabul etti; cihaz raporu bekleniyor.
deliveredSMS: cihaz raporu geldi. E-posta: alıcı sunucusu kabul etti (SMTP 250).
failedTeslim edilemedi; error.code nedeni verir.
expiredGeçerlilik süresi teslimden önce doldu.
canceledZamanlanmış ileti iptal edildi.

Webhook

Uçları GET/POST /v1/webhooks, DELETE /v1/webhooks/{id}, POST /v1/webhooks/{id}/rotate-secret ile yönetin (kapsam webhook.manage). Yalnız herkese açık adrese çözülen https adresleri kabul edilir. İmza sırrı yalnız oluşturma yanıtında bir kez gösterilir.

Olaylar: sms.queued, sms.sent, sms.delivered, sms.failed, sms.expired, email.queued, email.delivered, email.failed, email.expired, otp.verified, otp.failed. Hepsi için "*" kullanın.

curl Webhook ucu kaydet
curl https://api.reach2x.com/v1/webhooks \
  -H "Authorization: Bearer $REACH2X_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com/hooks/2x",
    "events": ["sms.delivered", "sms.failed", "email.delivered", "email.failed"]
  }'
Yanıt201 Created
{
  "webhook": {
    "id": "1b2c3d4e-5f60-4a7b-8c9d-0e1f2a3b4c5d",
    "url": "https://example.com/hooks/2x",
    "status": "active",
    "secret_prefix": "whsec_9fK2"
  },
  "secret": "whsec_… (shown only once)"
}

Her isteği doğrulayın

  1. Başlık x-imza: t=<unix>,v1=<hex>.
  2. HMAC-SHA256(secret, "<t>.<ham gövde>") hesaplayın (küçük harf hex).
  3. v1 ile sabit sürede karşılaştırın; |şimdi − t| > 300 sn ise reddedin.
  4. x-olay-id ile tekrarları ayıklayın (aynı olay birden çok gelebilir).
webhook.js İmzayı doğrula (Node.js)
import crypto from 'node:crypto';

// header "x-imza": t=<unix seconds>,v1=<hex>
export function verify(rawBody, header, secret) {
  const p = Object.fromEntries(header.split(',').map((x) => x.split('=')));
  const expected = crypto
    .createHmac('sha256', secret)
    .update(`${p.t}.${rawBody}`)
    .digest('hex');
  const fresh = Math.abs(Date.now() / 1000 - Number(p.t)) <= 300;
  return (
    fresh &&
    expected.length === p.v1?.length &&
    crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(p.v1))
  );
}

10 saniyede 2xx gelmezse yeniden deneme: 1 dk, 5 dk, 30 dk, 2 sa, 6 sa, 24 sa. 20 ardışık hatada uç devre dışı kalır. Olay sırası garanti edilmez; veri.status ve veri.updated_at’e bakın.

Zarf alanları: id, olay (olay tipi), zaman, kiraci (kuruluş), veri (ileti özeti).

Hata kodları

Hatalar RFC 9457 problem+json’dur. code alanı sabittir; title ve detail insan içindir ve değişebilir.

application/problem+json Hata gövdesi örneği
{
  "type": "https://reach2x.com/docs/errors#sender_not_allowed",
  "title": "Sender not allowed",
  "status": 422,
  "code": "sender_not_allowed",
  "request_id": "req_01JD3Q7Z8K2M"
}
codeHTTPAnlamı
invalid_request400Bozuk JSON, bilinmeyen alan ya da yanlış tip.
idempotency_key_required400Gönderimde Idempotency-Key yok.
unauthorized401Kimlik yok, geçersiz, süresi dolmuş ya da iptal.
forbidden403Kapsam, gönderici ya da IP yetkisi yok.
not_found404Kuruluşunuzda yok (başka kiracının kimliği de 404).
idempotency_in_progress409Aynı anahtarlı istek hâlâ işleniyor.
not_cancelable409İleti artık zamanlanmış değil.
payload_too_large413Gövde 1 MB’tan büyük.
idempotency_key_mismatch422Aynı anahtar farklı gövdeyle kullanıldı.
validation_failed422Anlamca geçersiz girdi; errors[] alanları listeler.
invalid_phone_number422Alıcı geçerli E.164 değil.
body_too_long422Gövde 7 segmentten uzun.
sender_not_allowed422Gönderici onaylı değil ya da anahtara izinli değil.
iys_recipient_type_required422commercial ama recipient_type yok.
iys_brand_code_missing422commercial ama kuruluşun İYS marka kodu yok.
invalid_send_at422send_at geçmişte ya da 30 günden ileri.
sender_domain_not_verified422from alanı doğrulanmış değil (e-posta).
commercial_email_not_supported422commercial e-posta henüz yok.
quota_exceeded429Aylık segment kotası doldu (bilgilendirme/OTP kesilmez).
rate_limited429Çok fazla istek; Retry-After’a uyun.
internal_error500Beklenmeyen hata; request_id ile bildirin.
service_unavailable503Geçici; aynı Idempotency-Key ile güvenle tekrar deneyin.

Teslim hataları (error.code — SMS): undeliverable, unknown_number, rejected_by_carrier, content_rejected, duplicate_message, recipient_no_consent, commercial_not_permitted, recipient_blocked, destination_not_supported, sender_rejected, expired, delivery_failed, delivery_unavailable.

E-posta: recipient_rejected, domain_not_found, message_rejected, delivery_unavailable, expired, delivery_failed.

Okuma ve sayfalama

Listeler en yeniden eskiye döner ve imleç tabanlıdır: limit (1–100, varsayılan 50) + cursor → { data, next_cursor, has_more }. Filtreler: status, category, batch_id, created_after, created_before.

Ücretsiz başla