İçeriğe geç
Uygulama API'si · WhatsApp Ücretli uç

WhatsApp şablonuyla mesaj gönderme

Kendi sisteminizden bir telefon numarasına onaylı bir WhatsApp şablonu gönderirsiniz. Şablonun başında resim, belge ya da video varsa dosyanın bağlantısını da verirsiniz. Örnek: sisteminizde tamamlanan her işlem için müşteriye bir belge görseli ve işlemin bilgileri.

POST /v1/whatsapp/conversations
Neden şablon?

WhatsApp, işletmenin kendisine son 24 saatte yazmamış birine serbest metin göndermesine izin vermez. Böyle bir numaraya ilk mesaj, Meta'nın onayladığı bir şablonla gider. Numarayla daha önce yazışmış olmanız gerekmez.

Akış

  1. Şablon listesini bir kez okuyunKullanacağınız şablonun ref değerini ve gönderebileceği hatları (line_keys) alın.
  2. Her işlemde gönderim ucunu çağırınNumara, şablon, değişken değerleri ve varsa dosya bağlantısı. İşlem numaranızı tekrar anahtarı olarak verin.
  3. Gerekirse teslim durumunu sorgulayınMesajın iletildiğini ve okunduğunu mesaj listesinden okursunuz.

Temel adres ve anahtarın isteğe nasıl konacağı: Temel adres ve kimlik doğrulama. Anahtarda WhatsApp uygulaması işaretli olmalı.

1. Şablon listesi

GET /v1/whatsapp/templates

Firmanızın bağlı WhatsApp Business hesaplarındaki onaylı şablonları verir. Liste her istekte Meta'dan okunur; yeni onaylanan şablon kendiliğinden görünür. Bu uç ücretsizdir, müşteriye mesaj çıkmaz.

Sorgu parametresi

AdTürAçıklama
used_bystringBoş, AGENT, SYSTEM ya da ALL. Panelde şablona verilen kullanım işaretine göre süzer. Boşsa personelin kullandığı ve işaretsiz şablonlar gelir; sistem gönderimine ayrılmış şablonlar (SYSTEM) gelmez. Hepsini görmek için ALL kullanın. Süzgeç yalnız listeyi daraltır: refini bildiğiniz şablon listede görünmese de gönderilebilir.

Örnek yanıt · 200

{
  "templates": [
    {
      "ref": "12:islem_bildirimi",
      "name": "islem_bildirimi",
      "language": "tr",
      "category": "UTILITY",
      "status": "APPROVED",
      "used_by": "SYSTEM",
      "body": "Sayın {{1}}, {{2}} numaralı işleminiz tamamlandı. Tarih: {{3}}.",
      "placeholders": 3,
      "header_format": "IMAGE",
      "line_keys": ["<HAT_ANAHTARI>"],
      "fields": [
        { "slot": "1", "value": "" },
        { "slot": "2", "value": "" },
        { "slot": "3", "value": "" }
      ],
      "needs_place": false
    }
  ],
  "place": ""
}

Kullanacağınız alanlar

AlanAçıklama
refGönderimde template alanına yazılacak değer. Şablonun adıyla birlikte bağlı olduğu hesabı da taşır; aynı ad iki hesapta bulunabildiği için yalnız ad yetmez.
bodyMüşterinin okuyacağı metin, yer tutucularıyla.
placeholdersMetindeki yer tutucu sayısı; variables dizisi bu kadar değer taşır.
header_formatBaşlığın türü: IMAGE, DOCUMENT ya da VIDEO. Bu durumda gönderimde media verilir. Başlıksız şablonda alan gelmez.
line_keysBu şablonun gönderilebileceği hatlar. Gönderimde line alanına bunlardan biri yazılır.
categoryMeta'nın verdiği kategori; gönderimin ücret kalemini belirler.
fieldsHer yer tutucunun kutusu. Firmanızın panelde bağladığı değer (şube adı gibi) varsa mapped_slots listesinde yer alır; o sıraları boş bırakabilirsiniz.

2. Gönderim

POST /v1/whatsapp/conversations

Numarayla konuşmayı açar (varsa var olanı kullanır) ve şablonu gönderir. Bu uç ücretlidir; bkz. Ücret. Örnek istek sağ sütunda.

Başlıklar

AdTürAçıklama
AuthorizationzorunlustringBearer <API_ANAHTARINIZ>
Content-Typezorunlustringapplication/json
Idempotency-KeystringTekrar anahtarı; bkz. Tekrar anahtarı.

Gövde alanları

Tabloda olmayan bir alan gönderilirse istek 400 BAD_REQUEST ile reddedilir.

AlanTürAçıklama
tozorunlustringAlıcının numarası, ülke koduyla: 905XXXXXXXXX. Rakam dışındaki karakterler (+, boşluk, tire) yok sayılır.
templatezorunlustringŞablon listesindeki ref değeri.
linekoşullustringMesajın çıkacağı hat; şablonun line_keys değerlerinden biri. Seçilebilecek birden çok hat varsa zorunludur. Her istekte vermenizi öneririz.
languagestringŞablonun dil kodu, örneğin tr. Boşsa şablonun kendi dili kullanılır.
variableskoşullustring[]Yer tutucuların değerleri, sırayla: ilk eleman {{1}}, ikincisi {{2}}. Şablonda yer tutucu varsa her biri dolu olmalı. Boş dize bırakılan sırayı firmanızın panelde bağladığı değer doldurur; bağlı değer yoksa istek reddedilir.
mediakoşulluobjectBaşlığı dosya olan şablonda zorunlu. Alanları aşağıda.
expectedstringMüşteriye gidecek metnin sizin ekranınızda gösterdiğiniz hâli. Verilirse gidecek metin bununla aynı olmalı; değilse mesaj gönderilmez ve 409 TEMPLATE_CHANGED döner.
placestringŞablon şube bilgisi içeriyorsa şubenin kodu (GET /v1/whatsapp/places). Firmanın tek şubesi varsa gerekmez.
agentobjectKonuşmayı sizin sisteminizdeki bir personele bağlar: {"external_id": "...", "name": "..."}. Programla yapılan gönderimlerde verilmez.

media alanları

AlanTürAçıklama
kindzorunlustringIMAGE, DOCUMENT ya da VIDEO. Şablonun başlık türüyle aynı olmalı.
linkzorunlustringDosyanın bağlantısı. Dosya VeriTakibi'ye yüklenmez; bağlantı olduğu gibi Meta'ya iletilir ve dosyayı Meta bu adresten indirir. Bu yüzden bağlantı herkese açık bir HTTPS adresi olmalı, oturum açma istememeli.
filenamestringYalnız DOCUMENT için: müşterinin telefonunda görünecek dosya adı, örneğin belge.pdf.

Değer kuralları

  • Bir değer satır sonu ya da sekme içeremez.
  • Bir değerde dörtten fazla ardışık boşluk olamaz.
  • Değerler yerleştikten sonra metin 1024 karakteri geçemez.

Kurala uymayan istek gönderilmez; 400 TEMPLATE_VALUE_INVALID hangi sıranın neden reddedildiğini söyler.

Başarılı gönderim 200 döner ve açılan konuşmayı verir (sağ sütunda yanıtın bir kısmı). id konuşmanın kimliğidir; kendi kaydınızda işlemle birlikte saklayın, teslim durumunu bununla sorgularsınız.

Teslim ve okunma durumu

GET /v1/whatsapp/conversations/{id}/messages

Mesajın telefona ulaşıp ulaşmadığını ve okunup okunmadığını sorgulayarak öğrenirsiniz. VeriTakibi bu durum değişikliklerini sizin sisteminize bildirmez; bildirim (itme) yok, gerektiğinde bu ucu çağırırsınız. {id} gönderim yanıtındaki konuşma kimliğidir. Bu uç ücretsizdir.

Yanıt konuşmanın mesajlarını verir. Giden mesajlarda ("direction": "OUT") şu alanlar bulunur:

AlanTürAçıklama
delivered_atstringMesajın alıcının telefonuna ulaştığı an; RFC 3339, UTC. Henüz bilinmiyorsa alan gelmez.
read_atstringAlıcının mesajı okuduğu an; RFC 3339, UTC. Henüz bilinmiyorsa alan gelmez.
delivery_statestringSENT: mesaj gönderildi. FAILED: gönderim başarısız oldu.
delivery_error_codestringGönderim başarısız olduysa sağlayıcının hata kodu.

Örnek yanıt · 200 (kısaltılmış)

{
  "messages": [
    {
      "id": 90211,
      "direction": "OUT",
      "sent_at": "2026-10-12T06:30:05Z",
      "delivered_at": "2026-10-12T06:30:07Z",
      "read_at": "2026-10-12T06:41:52Z",
      "delivery_state": "SENT",
      ...
    }
  ],
  "next_id": 0
}

Tekrar anahtarı

Ağ koptuğunda ya da yanıt gelmediğinde isteği yeniden göndermeniz gerekir. Tekrar anahtarı olmadan her yeniden deneme yeni bir mesaj ve yeni bir ücret demektir. İsteğe bağlı Idempotency-Key başlığı bunu önler.

  • Kendi sisteminizdeki işlem numarasını anahtar yapın, örneğin islem-A000123. Aynı işlem için her denemede aynı anahtarı, farklı işlemler için farklı anahtarlar kullanın.
  • Anahtar en çok 255 karakterdir ve satır sonu gibi denetim karakteri içeremez; uymayan başlık 400 BAD_REQUEST alır.
  • Anahtarlar firmanıza özeldir; başka bir firmanın anahtarıyla çakışmaz.
DurumYanıt
Aynı anahtar, aynı gövde, ilk istek başarılı200, ilk isteğin konuşması ve Idempotent-Replayed: true başlığı. İkinci mesaj gönderilmez, ikinci ücret yazılmaz.
Aynı anahtar, farklı gövde409 IDEMPOTENCY_KEY_REUSED. Hiçbir şey gönderilmez.
İlk istek sürüyor ya da sunucu yoğun409 IDEMPOTENCY_IN_PROGRESS ve Retry-After: 1. Retry-After kadar (saniye) bekleyip aynı anahtarla yeniden deneyin.
İlk istek hata almıştıYalnız başarılı gönderim hatırlanır. Sorunu giderip aynı anahtarla yeniden denediğinizde gönderim yapılır.

Gövdeler karşılaştırılırken numaranın yazılışı (+90… ile 90…) ve alanların sırası fark yaratmaz.

Yeniden deneme kuralı

Aldığınız sonuçNe yapmalı
Yanıt yok, zaman aşımı, 500, 502Aynı anahtarla yeniden deneyin. İlk istek gitmişse ikinci deneme yalnız ilk sonucu döner.
409 IDEMPOTENCY_IN_PROGRESSRetry-After kadar bekleyip aynı anahtarla yeniden deneyin.
429 RATE_LIMITEDBir süre bekleyip aynı anahtarla yeniden deneyin.
402 OVER_CREDIT_LIMITBakiye düzeldikten sonra aynı anahtarla yeniden deneyin.
Öteki 4xx yanıtlarYeniden denemeyin; önce isteği ya da ayarı düzeltin.

Hatalar

Hata gövdesi bir kod taşır. Bazı kodlarda detail alanı da gelir:

{ "error": "TEMPLATE_VALUE_INVALID", "detail": { "slot": "2", "reason": "unresolved" } }
KodHTTPAnlamıNe yapmalı
BAD_REQUEST400Gövde okunamadı, bilinmeyen alan var, to ya da template boş, line tanınmıyor ya da Idempotency-Key geçersiz. Şablon listesinde used_by tanınmıyor.İsteği düzeltin.
LINE_REQUIRED400Hangi hattan gönderileceği belli değil: birden çok hat var ve line verilmedi, ya da şablonun hesabında gönderilebilecek hat bulunamadı.line alanına şablonun line_keys değerlerinden birini yazın.
TEMPLATE_VALUE_INVALID400Bir değer kurala uymuyor. detail.slot sırayı, detail.reason sebebi verir: unresolved (boş ya da eksik), line_break (satır sonu ya da sekme), spaces (fazla boşluk), long (değer çok uzun), body_long (metnin tamamı 1024 karakteri geçiyor).Değeri düzeltin. Mesaj gönderilmedi.
UNAUTHORIZED401Anahtar yok, yanlış ya da iptal edilmiş.Anahtarı kontrol edin.
OVER_CREDIT_LIMIT402Bakiye kredi limitini aştı; giden mesajlar kapalı. Gönderim denenmedi.Bakiye düzeldikten sonra yeniden deneyin.
FORBIDDEN403Anahtarda WhatsApp işaretli değil ya da istek izinli adreslerin dışından geldi.Panelde anahtarın ayarını kontrol edin.
PLACE_NOT_FOUND404place kodu tanınmıyor.Şube listesinden geçerli bir kod verin.
IDEMPOTENCY_KEY_REUSED409Aynı tekrar anahtarı farklı bir gövdeyle kullanıldı.Her işleme ayrı anahtar verin.
IDEMPOTENCY_IN_PROGRESS409Aynı anahtarlı ilk istek sürüyor ya da sunucu o an yoğun.Retry-After kadar bekleyip aynı anahtarla yeniden deneyin.
TEMPLATE_CHANGED409expected verildi ve gidecek metin ondan farklı. detail.body gidecek metni verir. Mesaj gönderilmedi.Şablonu yeniden okuyun ve metni güncelleyin.
CONVERSATION_BLOCKED409Numara firmanızca engellenmiş. Mesaj gönderilmedi.Engeli panelden kaldırmadan göndermeyin.
ALREADY_CLAIMED409Yalnız agent verildiğinde: konuşma başka bir personelde. Mesaj gönderilmedi.Programla yapılan gönderimde agent vermeyin.
RATE_LIMITED429Anahtar başına dakikada 300 istek sınırı aşıldı.Bekleyip yeniden deneyin.
INTERNAL500Sunucu isteği tamamlayamadı.Aynı anahtarla yeniden deneyin.
SEND_FAILED502Gönderim yapılamadı ya da sağlayıcı reddetti; örneğin başlığı dosya olmayan şablona media verildi ya da media.kind geçersiz.İsteği kontrol edin; geçici bir arızaysa aynı anahtarla yeniden deneyin.
TEMPLATES_UNAVAILABLE502Şablonlar Meta'dan okunamadı (şablon listesinde ya da expected verilen gönderimde).Bir süre sonra yeniden deneyin.

Ücret

  • Her başarılı gönderim ücretlidir.
  • Ücret kalemi şablonun kategorisine göre belirlenir: pazarlama, bilgilendirme ya da doğrulama. Kategoriyi Meta verir ve gönderimden sonra bildirir.
  • Bakiye kredi limitini aşmışsa gönderim hiç denenmez ve 402 OVER_CREDIT_LIMIT döner.
  • Tekrar anahtarıyla yakalanan yeniden deneme ikinci bir ücret yazmaz.
  • TEMPLATE_VALUE_INVALID ve TEMPLATE_CHANGED istek Meta'ya çıkmadan verilir; ücret yazılmaz.
  • Şablon listesini ve mesaj listesini okumak ücretsizdir.