WhatsMod Public API
Kendi sisteminizden WhatsApp üzerinden OTP, mesaj ve medya gönderin. Bearer token, JSON body, REST. WordPress/WooCommerce/OpenCart plugin'lerimiz bu API'nin üzerine kurulu.
Hızlı Başlangıç
- 1Hesap aç + token üret. app.whatsmod.io → Ayarlar → API Tokens → Yeni Token. Scope seçin:
otp(OTP),messages.send(mesaj gönder),messages.read(durum/geçmiş oku) veya*(tam erişim). En az yetki ilkesi: yalnız ihtiyacın olan scope'u ver. - 2WhatsApp hesabı bağlayın. Numaranızı QR kodla bağlayın (Ayarlar → Numaralar). Aktif ve
connectedolmalı. - 3İsteği atın. Aşağıdaki curl örneğini kopyalayın,
wsk_...yerine token'ınızı yapıştırın, telefon numarasını güncelleyin. - 4Cevabı alın. HTTP 202 + JSON:
{sent: true, messageId: "...", creditsRemaining: 498}
Kimlik Doğrulama
Tüm isteklerde Authorization: Bearer wsk_... header'ı zorunlu. Token wsk_ önekiyle başlar ve 52 karakterdir. Sadece üretildiği anda bir kez gösterilir — güvenli bir yerde saklayın.
otp, mesaj gönderme → messages.send, durum/geçmiş okuma → messages.read (veya hepsi için *). Kısıtlı token (örn. OTP-only), WordPress/WooCommerce/OpenCart plugin'leri için önerilir — güvenlik için tam yetki vermeyin. Token ayrıca tek bir numaraya (allowedAccountId) kilitlenebilir; o token başka numaradan gönderemez.Endpoint'ler
Base URL: https://gw.whatsmod.io
/api/public/v1/accountsscope: geçerli tokenTenant'ınızın bağlı WhatsApp numaralarını listeler. Mesaj gönderirken kullanılacak accountId buradan alınır.
İstek (curl)
curl https://gw.whatsmod.io/api/public/v1/accounts \
-H "Authorization: Bearer wsk_YOUR_TOKEN"Cevap
{
"data": [
{
"id": "ck...",
"phoneNumber": "905XXXXXXXXX",
"displayName": "Satış",
"status": "connected",
"lastSeenAt": "2026-05-25T10:00:00.000Z"
}
]
}/api/public/v1/messagesscope: messages.send veya *Metin mesajı gönderir (maks 4096 karakter). 202 Accepted → mesaj kuyruğa alındı. Çift gönderimi önlemek için Idempotency-Key header'ı ekleyin (aşağıda Idempotency bölümü).
İstek (curl)
curl -X POST https://gw.whatsmod.io/api/public/v1/messages \
-H "Authorization: Bearer wsk_YOUR_TOKEN" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 9f1c2e4a-8b3d-4c5e-a1b2-c3d4e5f6a7b8" \
-d '{
"accountId": "ck...",
"to": "+905XXXXXXXXX",
"text": "Merhaba! Siparişiniz hazır."
}'Cevap
{
"message": {
"id": "ck...",
"status": "pending",
"creditsUsed": 1
}
}JavaScript / TypeScript örneği
const res = await fetch('https://gw.whatsmod.io/api/public/v1/messages', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.WHATSMOD_TOKEN}`,
'Content-Type': 'application/json',
'Idempotency-Key': crypto.randomUUID(),
},
body: JSON.stringify({
accountId: 'ck...',
to: '+905XXXXXXXXX',
text: 'Merhaba! Siparişiniz hazır.',
}),
});
const data = await res.json();/api/public/v1/messages/mediascope: messages.send veya *Medya (image/video/audio/document/sticker) + opsiyonel caption gönderir. multipart/form-data, maks 100 MB. Idempotency-Key desteklenir.
İstek (curl)
curl -X POST https://gw.whatsmod.io/api/public/v1/messages/media \
-H "Authorization: Bearer wsk_YOUR_TOKEN" \
-H "Idempotency-Key: 9f1c2e4a-8b3d-4c5e-a1b2-c3d4e5f6a7b8" \
-F "accountId=ck..." \
-F "to=+905XXXXXXXXX" \
-F "type=image" \
-F "caption=Ürün görseli" \
-F "file=@/path/to/product.jpg"Cevap
{
"message": {
"id": "ck...",
"status": "pending",
"creditsUsed": 1
}
}/api/public/v1/messages/{messageId}scope: messages.read veya *Tek bir mesajın durumunu döner: pending/queued/sent/delivered/read/failed, kullanılan kredi ve teslim/okundu zaman damgaları.
İstek (curl)
curl https://gw.whatsmod.io/api/public/v1/messages/ck... \
-H "Authorization: Bearer wsk_YOUR_TOKEN"Cevap
{
"id": "ck...",
"direction": "outbound",
"type": "text",
"status": "delivered",
"creditsUsed": 1,
"deliveredAt": "2026-05-25T10:01:00.000Z",
"readAt": null,
"createdAt": "2026-05-25T10:00:00.000Z"
}/api/public/v1/conversations/{conversationId}/messagesscope: messages.read veya *Bir sohbetin mesaj geçmişini yeniden → eskiye döner. Cursor sayfalama: ?limit=50&cursor=... ; yanıttaki nextCursor sonraki sayfa için kullanılır.
İstek (curl)
curl "https://gw.whatsmod.io/api/public/v1/conversations/ck.../messages?limit=50" \
-H "Authorization: Bearer wsk_YOUR_TOKEN"Cevap
{
"items": [
{
"id": "ck...",
"direction": "inbound",
"type": "text",
"content": "Merhaba",
"status": "read",
"createdAt": "2026-05-25T09:59:00.000Z"
}
],
"nextCursor": "ck...",
"hasMore": true
}/api/public/v1/otp/sendscope: otp veya *WhatsApp üzerinden OTP kodu gönderir. Rate limit: token başına saatlik 500, telefon başına dakikada 1. WordPress/WooCommerce/OpenCart/PrestaShop/Magento eklentileri bunu kullanır.
İstek (curl)
curl -X POST https://gw.whatsmod.io/api/public/v1/otp/send \
-H "Authorization: Bearer wsk_YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"phone": "+905XXXXXXXXX",
"code": "123456",
"site": "Siteniz"
}'Cevap
{
"sent": true,
"messageId": "ck...",
"wamid": "3EB0...",
"creditsRemaining": 498,
"expiresAt": "2026-05-25T14:40:12.000Z"
}PHP örneği
<?php
$ch = curl_init('https://gw.whatsmod.io/api/public/v1/otp/send');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Authorization: Bearer ' . $token,
'Content-Type: application/json',
]);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([
'phone' => '+905XXXXXXXXX',
'code' => '123456',
'site' => 'Siteniz',
]));
$resp = json_decode(curl_exec($ch), true);
curl_close($ch);JavaScript / TypeScript örneği
const res = await fetch('https://gw.whatsmod.io/api/public/v1/otp/send', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.WHATSMOD_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
phone: '+905XXXXXXXXX',
code: '123456',
site: 'Siteniz',
}),
});
const data = await res.json();/api/public/v1/balancescope: otp veya *Mevcut kredi bakiyenizi, plan ve hesap limitinizi döndürür.
İstek (curl)
curl https://gw.whatsmod.io/api/public/v1/balance \
-H "Authorization: Bearer wsk_YOUR_TOKEN"Cevap
{
"creditBalance": 12450,
"plan": "pro",
"accountLimit": 5
}Webhook'lar
Tenant panelinizden (Ayarlar → Webhooks) URL kaydedin, aşağıdaki event tiplerinden seçim yapın. POST isteği JSON body ile ulaşır. Wait-and-retry 3 kez.
otp.sentOTP başarıyla WhatsApp'a iletildi.otp.failedOTP gönderimi başarısız oldu (kredi/telefon/teknik).otp.rate_limitedRate limit aşıldı — abuse tespiti.message.newYeni gelen mesaj (müşteriden WhatsApp üzerinden).message.updateMesaj durumu değişti (sent/delivered/read/failed).conversation.updateSohbet güncellendi (departman, durum, atama).account.statusWhatsApp hesap durumu değişti (connected/disconnected/banned).POST https://your-server.com/webhooks/whatsmod HTTP/1.1
Content-Type: application/json
{
"event": "otp.sent",
"phone": "+9054*****76",
"status": "sent",
"messageId": "ck...",
"wamid": "3EB0...",
"tokenId": "ck...",
"accountId": "ck...",
"sourceHost": "siteniz.com",
"userAgent": "whatsmod-wp/1.0.0",
"occurredAt": "2026-04-24T14:35:12Z"
}Güvenlik: Webhook payload'ında ham OTP kodu asla yer almaz. Telefon numaraları maskelenir (ilk 5 + son 2 karakter). Hassas bilgi sızması riski yoktur.
Rate Limit'ler
| Kural | Limit | Hata |
|---|---|---|
| Aynı telefona OTP | Dakikada 1 | RATE_LIMITED · HTTP 429 |
| Token başına OTP | Saatte 500 | RATE_LIMITED · HTTP 429 |
| API token isteği (global) | Dakikada 600 | RATE_LIMITED · HTTP 429 |
Kurumsal paket kullanıcıları için özel limitler satış ekibimizden talep edilebilir.
Idempotency (Çift Gönderim Önleme)
Ağ kopması veya zaman aşımında isteği güvenle tekrarlayabilmek için POST /messages ve POST /messages/media isteklerine Idempotency-Key header'ı ekleyin (8-255 karakter, UUID önerilir).
- ✓Aynı anahtarla tekrar denenen istek mesajı yeniden GÖNDERMEZ; ilk sonucu aynen döner ve yanıta
Idempotent-Replay: trueheader'ı eklenir. - ✓Yalnız başarılı gönderim 24 saat saklanır. Hata olursa (kredi/ağ) anahtar serbest bırakılır — gerçek bir retry sorunsuz çalışır.
- ✓Aynı anahtarla eşzamanlı ikinci istek
IDEMPOTENCY_IN_PROGRESS(HTTP 409) döner — kısa bir bekleyip tekrar deneyin.
Her mantıksal gönderim için yeni bir anahtar üretin (örn. crypto.randomUUID()). Aynı anahtarı farklı içerikle tekrar kullanırsanız, ikinci içerik gönderilmez — ilk gönderimin sonucu döner.
Hata Kodları
| Kod | HTTP | Açıklama |
|---|---|---|
MISSING_TOKEN | 401 | Authorization header'ı yok veya Bearer formatında değil. |
INVALID_TOKEN | 401 | Token bulunamadı — revoke edilmiş veya yanlış. |
TOKEN_EXPIRED | 401 | Token süresi dolmuş. |
INSUFFICIENT_SCOPE | 403 | Token bu endpoint için yetkisiz. OTP → scope=otp, mesaj gönderme → messages.send, okuma → messages.read (veya *) gerekir. |
ACCOUNT_NOT_ALLOWED | 403 | Token tek bir numaraya kısıtlı (allowedAccountId); farklı bir accountId ile gönderim yapılamaz. |
TENANT_SUSPENDED | 403 | İşletme hesabınız askıda. |
INSUFFICIENT_CREDITS | 402 | Kredi bakiyesi yetersiz. Paket yenileyin. |
ACCOUNT_NOT_CONNECTED | 409 | Hedef WhatsApp numarası bağlı değil (disconnected/banned). Numarayı QR ile yeniden bağlayın. |
IDEMPOTENCY_IN_PROGRESS | 409 | Aynı Idempotency-Key ile bir istek hâlâ işleniyor. Birazdan tekrar deneyin. |
INVALID_IDEMPOTENCY_KEY | 400 | Idempotency-Key 8-255 karakter olmalı (UUID önerilir). |
RATE_LIMITED | 429 | Rate limit aşıldı. Dakikada 1 / saatte 500 (OTP), global dakikada 600. |
INVALID_PHONE | 400 | Telefon formatı hatalı. +905XXXXXXXXX bekleniyor. |
INVALID_CODE | 400 | OTP kodu 4-8 rakam olmalı. |
NO_ACCOUNT | 503 | OTP için: token'a atanmış/aktif WhatsApp hesabı yok. |
SEND_FAILED | 502 | WhatsApp gönderimi başarısız (ağ/Baileys hatası). |
Hata formatı: {code: "...", message: "...", details?: {...}}
Güvenlik
- ✓Tüm istekler HTTPS (TLS 1.3) üzerinden. HTTP kabul edilmez.
- ✓Token'lar DB'de SHA-256 hash olarak saklanır — plain hiçbir yerde yok.
- ✓OTP kodları da sadece SHA-256 hash olarak audit log'unda tutulur (ham kod yok).
- ✓Scope'lu token'lar yalnız izinli endpoint'lere erişir (otp / messages.send / messages.read) — zorlama sunucu tarafında yapılır.
- ✓Token tek bir WhatsApp hesabına
allowedAccountIdile kilitlenir ve gönderimde zorlanır — ele geçirilen token'ın blast radius'unu küçültür. - ✓
Idempotency-Keyile güvenli retry — ağ kopmasında çift mesaj gönderimi engellenir. - ✓Webhook payload'ları telefon numaralarını maskeler, OTP kodu ASLA webhook'ta yer almaz.
Postman ile Hızlı Test
Tüm endpoint'ler Postman collection olarak hazır. İndir, token\'ını yapıştır, test isteği at.
Tüm endpoint'ler hazır. Import → test isteği gönder.
whatsmod-api.postman_collection.jsonbaseUrl + apiToken değişkenleri. apiToken\'ı kendi wsk_... değerinle değiştir.
whatsmod.postman_environment.jsonapiToken değerine wsk_... yapıştır. 4) "OTP — Gönder" isteğinin body\'sinde telefonu güncelle, Send.SDK'lar
Her dilde HTTP isteği yazmak yerine hazır client kullanın. Tam TypeScript desteği, typed errors, retry-safe.
@whatsmod/clientnpm install @whatsmod/clientimport { WhatsMod } from '@whatsmod/client';
const client = new WhatsMod({ apiToken: 'wsk_...' });
await client.otp.send({ phone: '+905...', code: '123456' });whatsmod/clientcomposer require whatsmod/client$client = new \WhatsMod\Client(['api_token' => 'wsk_...']);
$client->otp->send(['phone' => '+905...', 'code' => '123456']);Yardıma mı ihtiyacınız var?
Özel entegrasyon, rate limit artırımı veya kurumsal SLA için iletişime geçin.