API SMS Buluthat

SMS en masse, SMS personnalisés, SMS OTP (code de vérification), SMS entrants, rapport de remise et liste noire.

  • Adresse : https://api.buluthat.com/api/sms.php?action=<eylem>
  • Identifiant : Authorization: Bearer <anahtar> (ou X-Api-Key: <anahtar>). Clé : Panneau > SMS en masse > API et paramètres.
  • Corps : JSON (Content-Type: application/json) ou formulaire. Les réponses sont en JSON, UTF-8.
  • Erreur : {"ok":false,"error":"<kod>","message":"<açıklama>"} + HTTP 4xx/5xx.
  • Numéros 05321234567, 5321234567, +905321234567, 905321234567 est accepté sous les formes.

Longueur du message

Encodage1 SMS2 SMS3 SMS… 7 SMS
Standard1603064591071
Turc (si contient Ş ş Ğ ğ ç ı İ)1552984471043
Unicode (emoji, etc.)70134201469

^ { } \ [ ] ~ | € compte pour deux caractères. Ö ö Ü ü Ç sont dans l'encodage standard.

Envoi — send (POST)

{
  "header": "FIRMAADI",
  "message": "Merhaba {ad}, {tutar} TL ödemeniz alınmıştır.",
  "recipients": [
    {"phone": "05321234567", "name": "Ayşe Yılmaz", "tutar": "1.250", "ref": "CARI-17"},
    {"phone": "05331234567", "name": "Mehmet Kaya", "tutar": "300"}
  ],
  "send_at": "2026-10-01 10:00",
  "is_commercial": false,
  "valid_for": "24:00",
  "rate_per_minute": 500,
  "custom_ref": "EYLUL-KAMPANYA"
}
ChampDescription
headerEn-tête approuvé. Si vide, l'en-tête par défaut.
messageTexte. Variables : {ad} {soyad} {adsoyad} {telefon} {firma} {ret_link} + les autres champs du destinataire.
recipients[{phone, name?, ref?, <alan>…}]. Un même numéro n'est envoyé qu'une fois.
phonesRaccourci : ["0532…","0533…"] ou texte séparé par des virgules (même message pour tous).
messagesUn texte entièrement différent par personne : [{phone, message, ref?}] (dans ce cas message n'est pas nécessaire).
send_atDate ultérieure (maximum 90 jours). Si vide, immédiat.
is_commercialMessage commercial. true si iys_recipient_type: BIREYSEL / TACIR; n'est pas envoyé au destinataire sans consentement İYS.
valid_forDurée d'essai si le téléphone est éteint, SS:DD (00:01 – 48:00).
rate_per_minuteEnvois par minute (0 = le plus rapide).
custom_refVotre propre référence ; status s'interroge avec.

Réponse :

{"ok":true,"data":{"campaign_id":152,"status":"queued","recipients":2,"credits":2,
 "skipped":{"invalid":0,"blacklist":0,"duplicate":0}, ...}}

Les numéros de la liste noire, erronés et (si la protection anti-doublon est active) ayant déjà reçu le même texte aujourd'hui sont ignorés ; aucun crédit n'est déduit. Le crédit d'un message non remis est automatiquement restitué.

Codes d'erreur : missing_recipients, missing_message, request_failed (crédit insuffisant, en-tête non approuvé, message trop long… — message précise), account_inactive.

Rapport — status (GET)

?action=status&campaign_id=152 ou &custom_ref=EYLUL-KAMPANYA; facultatif status, phone, limit (≤1000), offset.

États des messages : queued (en file), sending, waiting (en attente du rapport de l'opérateur), delivered, failed, expired, rejected, cancelled.

Autres actions

ActionMéthodeDescription
balanceGET{"sms":1200,"otp":500,"lots":[…]} crédit restant et dates d'expiration
headersGETEn-têtes approuvés
campaignsGETListe d'envoi (from, to, limit, offset)
cancelPOSTcampaign_id — messages non envoyés annulés, crédit restitué
inboundGETSMS entrants : since_id, limit → [{id, from, to, keyword, text, optout, received_at}]
blacklistGETListe noire
blacklist_add / blacklist_removePOSTphones: ["0532…"]

SMS OTP

POST ?action=otp_send   {"phone":"05321234567","reference":"UYE-1452"}
→ {"ok":true,"data":{"id":88,"status":"sent","expires_at":"…"},"code":"482913"}

POST ?action=otp_verify {"id":88,"code":"482913"}
→ {"ok":true,"verified":true}
   hata: wrong_code | expired | too_many_attempts | already_verified | not_found

GET  ?action=otp_status&id=88
  • Vous pouvez aussi fournir le code vous-même (code, 4-10 chiffres) ; si nous l'avons généré, il n'est renvoyé qu'une fois dans cette réponse, seul le hash est conservé.
  • template vous pouvez modifier le texte avec ({kod} obligatoire, {firma}, {sure}).
  • L'OTP est débité d'abord du crédit OTP, puis du crédit SMS ; envoi sans attente.
  • Il existe une limite d'envoi vers le même numéro sur 10 minutes.

Webhook

Si vous saisissez une adresse dans Panneau > SMS en masse > API et paramètres, les événements sont envoyés en POST :

X-Buluthat-Event: sms.delivery | sms.inbound | sms.optout
X-Buluthat-Signature: sha256=<HMAC-SHA256(gövde, sır)>

{"event":"delivery","data":{"message_id":9012,"campaign_id":152,"ref":"CARI-17",
 "phone":"905321234567","status":"delivered","detail":"İletildi","done_at":"…"}}
{"event":"inbound","data":{"id":44,"from":"905321234567","to":"…","keyword":"","text":"…","optout":false}}

Si vous ne renvoyez pas de 2xx, nouvelle tentative après 1 min, 5 min, 15 min, 1 h, 3 h, 6 h.

Exemple (PHP)

$ch = curl_init('https://api.buluthat.com/api/sms.php?action=send');
curl_setopt_array($ch, [
  CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true,
  CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $key, 'Content-Type: application/json'],
  CURLOPT_POSTFIELDS => json_encode(['message' => 'Siparişiniz kargoda.', 'phones' => ['05321234567']]),
]);
$res = json_decode(curl_exec($ch), true);