API referansı
Şablonlar
Meta onaylı mesaj şablonlarını oluşturun, doğrulayın, listeleyin, düzenleyin, kopyalayın ve silin; başlık medyasını yükleyin. Şablonlar işletme hesabı (WABA) düzeyindedir.
#Template nesnesi
idintegerVeri Merkezi şablon kimliği.meta_template_idstring · boş olabilirMeta şablon kimliği.namestringŞablon adı.languagestringDil kodu.categorystringKategori. Meta kategoriyi değiştirdiyse güncel kategori.Değerler:UTILITY,MARKETING,AUTHENTICATIONprevious_categorystringMeta kategoriyi değiştirdiyse önceki kategori; yoksanull.parameter_formatstringDeğişken biçimi:POSITIONAL({{1}}) ya daNAMED({{ad_soyad}}). Oluşturulduktan sonra değişmez.Değerler:POSITIONAL,NAMEDstatusstringDurum.Değerler:DRAFT,PENDING,APPROVED,REJECTED,PAUSED,DISABLEDrejected_reasonstring · boş olabilirMeta'nın ham ret nedeni (INVALID_FORMAT,ABUSIVE_CONTENT,INCORRECT_CATEGORY,SCAM,TAG_CONTENT_MISMATCH…). YalnızREJECTEDiken anlamlıdır.rejected_reason_textstringRet nedeninin Türkçe açıklaması. YalnızREJECTEDiken dolu.quality_scorestring · boş olabilirŞablon kalite puanı (GREEN,YELLOW,RED,UNKNOWN). 2.25.0'dan beri listede de döner.componentsarrayBileşenler.header_mediaobjectMedya başlığı (IMAGE/VIDEO/DOCUMENT) olan şablonlarda başlık medyası; liste ve ayrıntıda döner, medya başlığı yoksanull. Veri Merkezi'nde dosya kopyası varsa{ url, mime_type, file_size, sha256, filename, format, temporary: false }(urlkalıcı, herkese açık bağlantıdır). Kopya yoksa Meta onay örneği{ url, format, temporary: true }(süreli bağlantı, gönderimde güvenmeyin).header_media_refintegerYalnız ayrıntıda: medya başlığının Veri Merkezi'ndeki dosya kopyası (POST /templates/mediayanıtındaki değer); yoksanull.edit_limitobjectYalnız ayrıntıda: düzenleme durumu{ editable, edits_last_30d, max_edits_30d, next_edit_at }.editable: falseise durum düzenlemeye uygun değildir ya da onaylı şablonun sınırı dolmuştur (next_edit_at). Yalnız Veri Merkezi üzerinden yapılan düzenlemeleri sayar.waba_idstringŞablonun ait olduğu WABA.phone_number_idsarrayBu şablonu kullanabilen, aynı WABA'daki aktif numaralar (listede).phone_number_idstring · boş olabilirEski alan: WABA'nın ilk aktif numarası. Yerinephone_number_idskullanın.display_phone_numberstring · boş olabilirEski alan.created_atstringOluşturulma zamanı.submitted_atstring · boş olabilirMeta'ya gönderilme zamanı (ayrıntıda).status_updated_atstring · boş olabilirSon durum değişikliği (ayrıntıda).
Template nesnesi
{
"id": 512,
"meta_template_id": "1249033812345678",
"name": "siparis_onayi",
"language": "tr",
"category": "UTILITY",
"previous_category": null,
"parameter_format": "POSITIONAL",
"status": "APPROVED",
"rejected_reason": null,
"rejected_reason_text": null,
"components": [
{
"type": "BODY",
"text": "Merhaba {{1}}, {{2}} numaralı siparişiniz onaylandı."
}
],
"header_media": null,
"created_at": "2026-09-20 10:12:00",
"waba_id": "1029384756",
"phone_number_ids": [
"1234567890"
],
"phone_number_id": "1234567890",
"display_phone_number": "+90 555 000 00 00",
"client_id": 4,
"quality_score": "GREEN"
}#Şablonları listele
GET
/templatesHesabınızın WABA'larındaki şablonları yeniden eskiye döndürür. Süzgeçler ve imleçle sayfalama desteklenir. Kapsam:
templates:readrefresh kullanıldığında yanıta refreshed, refreshed_at (ve sınırdaysa refresh_retry_after) eklenir; X-Templates-Refreshed başlığı döner.2.25.0'dan beri liste satırında
quality_score, parameter_format, previous_category ve rejected_reason_text da döner. Önizleme için components istemcide çizilir; Veri Merkezi ayrı bir önizleme görüntüsü üretmez.2.25.0: Her şablonda
header_media döner (medya başlığı yoksa null). Kalıcı bağlantı (temporary: false) ile CRM kendi önizlemesini çizer ve her gönderimde dosya seçtirmesine gerek kalmaz; temporary: true yalnız Meta'nın süreli onay örneğidir.Sorgu parametreleri
statusstringisteğe bağlıDurum süzgeci.Değerler:DRAFT,PENDING,APPROVED,REJECTED,PAUSED,DISABLEDcategorystringisteğe bağlıKategori süzgeci.Değerler:UTILITY,MARKETING,AUTHENTICATIONlanguagestringisteğe bağlıDil kodu (ör.tr).qstringisteğe bağlıAd içinde arama.phone_number_idstringisteğe bağlıYalnız bu numaranın WABA'sındaki şablonlar.cursorintegeristeğe bağlıÖnceki yanıttakinext_cursor(bu kimlikten küçük kayıtlar).limitintegeristeğe bağlıSayfa boyutu (1–100).Varsayılan:50refreshbooleanisteğe bağlı1okumadan önce Meta'dan senkron dener (WABA başına dakikada 1). Sınırdaysa hata vermez;refreshed: falsedöner.
Hatalar
| Durum | Kod | Ne zaman |
|---|---|---|
| 403 | insufficient_scope | Anahtarda templates:read kapsamı yok. |
curl -X GET "https://api.verimerkezi.app/wa/templates?status=APPROVED" \
-H "Authorization: Bearer $VM_API_KEY"const res = await fetch("https://api.verimerkezi.app/wa/templates?status=APPROVED", {
method: "GET",
headers: {
Authorization: `Bearer ${process.env.VM_API_KEY}`,
},
});
const data = await res.json();import os, requests
res = requests.get(
"https://api.verimerkezi.app/wa/templates?status=APPROVED",
headers={"Authorization": f"Bearer {os.environ['VM_API_KEY']}"},
)
data = res.json()<?php
$ch = curl_init("https://api.verimerkezi.app/wa/templates?status=APPROVED");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
"Authorization: Bearer " . getenv("VM_API_KEY"),
],
]);
$data = json_decode(curl_exec($ch), true);Yanıt 200
{
"ok": true,
"templates": [
{
"id": 512,
"meta_template_id": "1249033812345678",
"name": "siparis_onayi",
"language": "tr",
"category": "UTILITY",
"previous_category": null,
"parameter_format": "POSITIONAL",
"status": "APPROVED",
"rejected_reason": null,
"rejected_reason_text": null,
"quality_score": "GREEN",
"components": [
{
"type": "BODY",
"text": "Merhaba {{1}}, {{2}} numaralı siparişiniz onaylandı."
}
],
"header_media": null,
"created_at": "2026-09-20 10:12:00",
"waba_id": "1029384756",
"phone_number_ids": [
"1234567890"
],
"phone_number_id": "1234567890",
"display_phone_number": "+90 555 000 00 00",
"client_id": 4
}
],
"has_more": false,
"next_cursor": null
}#Şablon oluştur
POST
/templatesŞablonu oluşturup Meta onayına gönderir ve
PENDING döndürür (Meta anında APPROVED ya da REJECTED de verebilir). Kurallar Meta'ya gitmeden önce denetlenir; ihlaller error.field alan yoluyla birlikte 422 template_invalid ya da 422 invalid_request olarak döner. Aynı WABA'da aynı ad ve dilde şablon varsa 409 template_exists. Meta reddederse yerelde taslak artığı kalmaz. Sonuç template.approved ya da template.rejected olayıyla bildirilir. Kapsam: templates:writeForm butonu için
BUTTONS içine { "type": "FLOW", "text": "Formu doldur", "flow_id": "...", "navigate_screen": "WELCOME", "flow_action": "navigate" } ekleyebilirsiniz.OTP şablonu (
AUTHENTICATION) için gövde metni Meta tarafından sabit üretilir; yalnız güvenlik önerisi, kod süresi ve buton tipini belirlersiniz.allow_category_change alanı dokümanda yer alır ancak sunucu şu an bu alanı Meta'ya iletmez.Medya başlığı: önce
POST /templates/media çağırıp header_handle değerini HEADER bileşeninde example.header_handle[0]'a, header_media_ref değerini gövdenin üst düzeyine koyun.Başlık metni en çok 60 karakter ve en çok 1 değişken içerir; değişken varsa örnek zorunludur.
LOCATION başlığında parametre yoktur (yalnız UTILITY / MARKETING; konum gönderimde verilir). COPY_CODE düğmesi en çok 1 tane olur, example (en çok 20 karakter) verilir, metni Meta koyar. Düğmeler tür sırasına dizilir (en çok 10).NAMED örnek:
"parameter_format": "NAMED"; { "type": "HEADER", "format": "TEXT", "text": "Poliçe {{police_no}}", "example": { "header_text_named_params": [{ "param_name": "police_no", "example": "TR-2026-001" }] } }; { "type": "BODY", "text": "Sayın {{ad_soyad}}, teklifiniz hazır.", "example": { "body_text_named_params": [{ "param_name": "ad_soyad", "example": "Ayşe Yılmaz" }] } }; { "type": "BUTTONS", "buttons": [{ "type": "URL", "text": "Teklifi gör", "url": "https://ornek.com/teklif/{{1}}", "example": ["https://ornek.com/teklif/abc123"] }, { "type": "COPY_CODE", "example": "YENI2026" }] }.NAMED değişkenli, değişkenli metin başlıklı ya da LOCATION başlıklı şablonlar yalnız API ile (POST /messages, components ile) gönderilebilir; panel kampanya ve otomasyonları bunları "yalnız API" uyarısıyla engeller.Oluşturma hızı: WABA başına saatte 100 şablon; WABA başına en çok 250 (doğrulanmamış) / 6000 şablon (Meta sınırı).
Hata Meta'dan geldiyse
meta_code, meta_subcode, meta_message, meta_user_title, meta_user_message ve fbtrace_id alanları da döner.Test anahtarıyla doğrulama yapılır, Meta'ya gidilmez, kayıt oluşmaz:
202 id: 0, status: "PENDING", mode: "test", simulated: true ve X-Test-Mode: 1 başlığı.İstek gövdesi
namestringzorunluŞablon adı (1–512). Yalnız küçük harf, rakam ve alt çizgi; büyük harf ve diğer karakterler_olur. Yanıttakinameesastır. Silinen onaylı şablonun adı 30 gün yeniden kullanılamaz.languagestringzorunluDil kodu.Varsayılan:trcategorystringzorunluKategori.Değerler:UTILITY,MARKETING,AUTHENTICATIONVarsayılan:UTILITYcomponentsarrayzorunluMeta bileşenleri:HEADER(TEXTen çok 1 değişkenli,IMAGE,VIDEO,DOCUMENT,LOCATION),BODY,FOOTER,BUTTONS(QUICK_REPLY,URL,PHONE_NUMBER,COPY_CODE,FLOW,OTP). Değişken için örnek zorunludur:POSITIONALbiçimdeexample.body_text/example.header_text,NAMEDbiçimdeexample.body_text_named_params/example.header_text_named_params([{ param_name, example }]). Ayrıntı: Şablonlar rehberi.parameter_formatstringisteğe bağlıPOSITIONAL(varsayılan,{{1}},{{2}}…) ya daNAMED({{ad_soyad}}: küçük harf, rakam,_; harfle başlar; benzersiz). Oluşturduktan sonra değişmez.Değerler:POSITIONAL,NAMEDVarsayılan:POSITIONALallow_category_changebooleanisteğe bağlıMeta'ya aynen iletilir:trueise Meta kategoriyi kendisi değiştirebilir.message_send_ttl_secondsintegeristeğe bağlıMeta'ya aynen iletilir: mesajın geçerlilik süresi (saniye; en çok 2592000,-1varsayılan süre).cta_url_link_tracking_opted_outbooleanisteğe bağlıMeta'ya aynen iletilir: URL düğmelerinde bağlantı izlemesinden çıkış.header_media_refintegeristeğe bağlıPOST /templates/mediayanıtındaki dosya kopyası. Medya başlığındaexample.header_handle,header_media_refya daheader_media_urldeğerlerinden en az biri gerekir; hiçbiri yoksa422 invalid_request(field: header_media_ref).example.header_handleolarakhttps://adres kabul edilmez.waba_idstringisteğe bağlıHedef WABA. Hesabınızda tek WABA varsa gerekmez; birden çok varsa zorunludur.phone_number_idstringisteğe bağlıwaba_idyerine; WABA numaradan çözülür.header_media_urlstringisteğe bağlıEski yol (2.22): medya başlığı için herkese açıkhttps://adres; dosya indirilip Meta'ya örnek olarak yüklenir. YerinePOST /templates/media+header_media_refönerilir.optout_footerbooleanisteğe bağlıYalnızMARKETING: standart abonelikten çıkış alt bilgisini ekler (varsayılantrue). Kendi alt bilginizi kullanmak içinfalseverin.add_security_recommendationbooleanisteğe bağlıAUTHENTICATION: "Bu kodu kimseyle paylaşmayın" satırı.code_expiration_minutesintegeristeğe bağlıAUTHENTICATION: kod geçerlilik süresi (dakika).otp_typestringisteğe bağlıAUTHENTICATION: buton türü.Değerler:COPY_CODE,ONE_TAPotp_button_textstringisteğe bağlıAUTHENTICATION: buton metni.autofill_textstringisteğe bağlıONE_TAP: otomatik doldurma metni.package_namestringisteğe bağlıONE_TAP: Android uygulama paket adı.signature_hashstringisteğe bağlıONE_TAP: uygulama imza özeti (11 karakter).
Hatalar
| Durum | Kod | Ne zaman |
|---|---|---|
| 403 | insufficient_scope | Anahtarda templates:write kapsamı yok. |
| 404 | number_not_found | Numara/WABA size ait değil ya da aktif WABA yok. |
| 409 | number_detached | Numara hesabınızdan ayrılmış; panelden yeniden bağlayın. |
| 409 | template_exists | Aynı WABA'da aynı ad ve dilde şablon zaten var (field: name, template_id). Meta'ya gidilmez. |
| 413 | media_too_large | Başlık medyası sınırı aşıyor (max_bytes döner). |
| 422 | invalid_request | name, components eksik ya da biçim yanlış; medya başlığında header_media_ref yok (error.field yolu söyler). |
| 422 | waba_required | Birden çok WABA'nız var; waba_id verin. |
| 422 | header_media_fetch_failed | header_media_url indirilemedi. |
| 422 | template_invalid | Meta kurallarına aykırı (Meta'ya gönderilmedi); error.field yolu söyler (ör. components[0].text). |
| 422 | template_rejected | Meta şablonu reddetti. Hata Meta'dan geldiyse meta_code, meta_subcode, meta_message, meta_user_title, meta_user_message ve fbtrace_id alanları da döner. |
| 502 | meta_unavailable | Meta'ya ulaşılamadı ya da Meta 5xx döndü; biraz sonra tekrar deneyin. |
curl -X POST "https://api.verimerkezi.app/wa/templates" \
-H "Authorization: Bearer $VM_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"waba_id": "1029384756",
"name": "police_yenileme_hatirlatma",
"language": "tr",
"category": "UTILITY",
"header_media_url": "https://cdn.example.com/logo.jpg",
"components": [
{
"type": "HEADER",
"format": "IMAGE"
},
{
"type": "BODY",
"text": "Sayın {{1}}, {{2}} plakalı aracınızın poliçesi {{3}} tarihinde sona eriyor.",
"example": {
"body_text": [
[
"Ahmet Yılmaz",
"34 ABC 123",
"12.10.2026"
]
]
}
},
{
"type": "FOOTER",
"text": "Firma Sigorta"
},
{
"type": "BUTTONS",
"buttons": [
{
"type": "QUICK_REPLY",
"text": "Teklif istiyorum"
}
]
}
]
}'const res = await fetch("https://api.verimerkezi.app/wa/templates", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.VM_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
"waba_id": "1029384756",
"name": "police_yenileme_hatirlatma",
"language": "tr",
"category": "UTILITY",
"header_media_url": "https://cdn.example.com/logo.jpg",
"components": [
{
"type": "HEADER",
"format": "IMAGE"
},
{
"type": "BODY",
"text": "Sayın {{1}}, {{2}} plakalı aracınızın poliçesi {{3}} tarihinde sona eriyor.",
"example": {
"body_text": [
[
"Ahmet Yılmaz",
"34 ABC 123",
"12.10.2026"
]
]
}
},
{
"type": "FOOTER",
"text": "Firma Sigorta"
},
{
"type": "BUTTONS",
"buttons": [
{
"type": "QUICK_REPLY",
"text": "Teklif istiyorum"
}
]
}
]
}),
});
const data = await res.json();import os, requests
res = requests.post(
"https://api.verimerkezi.app/wa/templates",
headers={"Authorization": f"Bearer {os.environ['VM_API_KEY']}"},
json={
"waba_id": "1029384756",
"name": "police_yenileme_hatirlatma",
"language": "tr",
"category": "UTILITY",
"header_media_url": "https://cdn.example.com/logo.jpg",
"components": [
{
"type": "HEADER",
"format": "IMAGE"
},
{
"type": "BODY",
"text": "Sayın {{1}}, {{2}} plakalı aracınızın poliçesi {{3}} tarihinde sona eriyor.",
"example": {
"body_text": [
[
"Ahmet Yılmaz",
"34 ABC 123",
"12.10.2026"
]
]
}
},
{
"type": "FOOTER",
"text": "Firma Sigorta"
},
{
"type": "BUTTONS",
"buttons": [
{
"type": "QUICK_REPLY",
"text": "Teklif istiyorum"
}
]
}
]
},
)
data = res.json()<?php
$ch = curl_init("https://api.verimerkezi.app/wa/templates");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
"Authorization: Bearer " . getenv("VM_API_KEY"),
"Content-Type: application/json",
],
CURLOPT_POSTFIELDS => json_encode([
"waba_id" => "1029384756",
"name" => "police_yenileme_hatirlatma",
"language" => "tr",
"category" => "UTILITY",
"header_media_url" => "https://cdn.example.com/logo.jpg",
"components" => [
[
"type" => "HEADER",
"format" => "IMAGE"
],
[
"type" => "BODY",
"text" => "Sayın {{1}}, {{2}} plakalı aracınızın poliçesi {{3}} tarihinde sona eriyor.",
"example" => [
"body_text" => [
[
"Ahmet Yılmaz",
"34 ABC 123",
"12.10.2026"
]
]
]
],
[
"type" => "FOOTER",
"text" => "Firma Sigorta"
],
[
"type" => "BUTTONS",
"buttons" => [
[
"type" => "QUICK_REPLY",
"text" => "Teklif istiyorum"
]
]
]
]
]),
]);
$data = json_decode(curl_exec($ch), true);Yanıt 202
{
"ok": true,
"id": 513,
"meta_template_id": "1249033812345679",
"name": "police_yenileme_hatirlatma",
"language": "tr",
"category": "UTILITY",
"previous_category": null,
"parameter_format": "POSITIONAL",
"status": "PENDING",
"rejected_reason": null,
"rejected_reason_text": null,
"quality_score": null,
"waba_id": "1029384756",
"phone_number_id": "1234567890",
"created_at": "2026-10-10T09:00:00+03:00",
"submitted_at": "2026-10-10T09:00:02+03:00",
"status_updated_at": null
}#Şablonu doğrula
POST
/templates/validateŞablon gövdesini Meta'ya göndermeden
POST /templates ile aynı kurallarla denetler. Kullanıcı "gönder"e basmadan hatayı görmesini sağlar; 2.25.0'dan beri ihlal 422 template_invalid yanıtında error.field (ör. components[0].text) ile hangi alanın hatalı olduğunu söyler. Kapsam: templates:readYazma yapmaz; test anahtarıyla da aynı çalışır.
İstek gövdesi
componentsarrayzorunluDenetlenecek bileşenler.waba_idstringisteğe bağlıHedef WABA.phone_number_idstringisteğe bağlıWABA'yı çözmek için numara.namestringisteğe bağlıŞablon adı.languagestringisteğe bağlıDil kodu.categorystringisteğe bağlıKategori.Değerler:UTILITY,MARKETING,AUTHENTICATIONparameter_formatstringisteğe bağlıPOSITIONALya daNAMED.Değerler:POSITIONAL,NAMEDVarsayılan:POSITIONALheader_media_refintegeristeğe bağlıMedya başlığı içinPOST /templates/mediayanıtındaki değer. Verilmezse doğrulamada yer tutucu sayılır.
Hatalar
| Durum | Kod | Ne zaman |
|---|---|---|
| 403 | insufficient_scope | Anahtarda templates:read kapsamı yok. |
| 404 | number_not_found | Numara/WABA size ait değil. |
| 422 | waba_required | Birden çok WABA'nız var; waba_id verin. |
| 422 | invalid_request | components eksik. |
| 422 | template_invalid | Kural ihlali; message sebebi, error.field alan yolunu söyler. |
curl -X POST "https://api.verimerkezi.app/wa/templates/validate" \
-H "Authorization: Bearer $VM_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"phone_number_id": "1234567890",
"name": "deneme",
"language": "tr",
"category": "UTILITY",
"components": [
{
"type": "BODY",
"text": "Merhaba {{1}}",
"example": {
"body_text": [
[
"Ahmet"
]
]
}
}
]
}'const res = await fetch("https://api.verimerkezi.app/wa/templates/validate", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.VM_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
"phone_number_id": "1234567890",
"name": "deneme",
"language": "tr",
"category": "UTILITY",
"components": [
{
"type": "BODY",
"text": "Merhaba {{1}}",
"example": {
"body_text": [
[
"Ahmet"
]
]
}
}
]
}),
});
const data = await res.json();import os, requests
res = requests.post(
"https://api.verimerkezi.app/wa/templates/validate",
headers={"Authorization": f"Bearer {os.environ['VM_API_KEY']}"},
json={
"phone_number_id": "1234567890",
"name": "deneme",
"language": "tr",
"category": "UTILITY",
"components": [
{
"type": "BODY",
"text": "Merhaba {{1}}",
"example": {
"body_text": [
[
"Ahmet"
]
]
}
}
]
},
)
data = res.json()<?php
$ch = curl_init("https://api.verimerkezi.app/wa/templates/validate");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
"Authorization: Bearer " . getenv("VM_API_KEY"),
"Content-Type: application/json",
],
CURLOPT_POSTFIELDS => json_encode([
"phone_number_id" => "1234567890",
"name" => "deneme",
"language" => "tr",
"category" => "UTILITY",
"components" => [
[
"type" => "BODY",
"text" => "Merhaba {{1}}",
"example" => [
"body_text" => [
[
"Ahmet"
]
]
]
]
]
]),
]);
$data = json_decode(curl_exec($ch), true);Yanıt 200
{
"ok": true,
"valid": true,
"message": "Şablon Meta kurallarına uygun görünüyor."
}#Şablonları Meta'dan senkronla
POST
/templates/syncŞablon listesini Meta'dan hemen çekip durum, kategori, kalite puanı, ret sebebi ve bileşenleri günceller. Meta'da hiçbir şeyi değiştirmez. Gövde boşsa tüm aktif WABA'larınız senkronlanır. Kapsam:
templates:read ya da templates:writetemplates:read ya da templates:write kapsamlarından biri yeterlidir.Yalnız bazı WABA'lar sınırdaysa
200 yanıtında rate_limited (WABA → saniye) alanı döner; hatalı WABA'lar errors alanında listelenir.Arka planda her 15 dakikada bir otomatik senkron çalışır; durum değişiklikleri webhook ile zaten anında işlenir.
İstek gövdesi
phone_number_idstringisteğe bağlıYalnız bu numaranın WABA'sını senkronlar.
Hatalar
| Durum | Kod | Ne zaman |
|---|---|---|
| 403 | insufficient_scope | Anahtarda templates:read ya da templates:write yok. |
| 404 | number_not_found | Numara size ait değil ya da aktif değil. |
| 422 | invalid_request | phone_number_id rakam değil. |
| 429 | sync_rate_limited | WABA başına dakikada 1 senkron. Retry-After ve error.retry_after döner. |
| 502 | sync_failed | Meta şablon listesi alınamadı. |
curl -X POST "https://api.verimerkezi.app/wa/templates/sync" \
-H "Authorization: Bearer $VM_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"phone_number_id": "1234567890"
}'const res = await fetch("https://api.verimerkezi.app/wa/templates/sync", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.VM_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
"phone_number_id": "1234567890"
}),
});
const data = await res.json();import os, requests
res = requests.post(
"https://api.verimerkezi.app/wa/templates/sync",
headers={"Authorization": f"Bearer {os.environ['VM_API_KEY']}"},
json={
"phone_number_id": "1234567890"
},
)
data = res.json()<?php
$ch = curl_init("https://api.verimerkezi.app/wa/templates/sync");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
"Authorization: Bearer " . getenv("VM_API_KEY"),
"Content-Type: application/json",
],
CURLOPT_POSTFIELDS => json_encode([
"phone_number_id" => "1234567890"
]),
]);
$data = json_decode(curl_exec($ch), true);Yanıt 200
{
"ok": true,
"synced": {
"1029384756": 42
},
"templates_changed": 3,
"at": "2026-10-10T12:00:00+03:00"
}#Şablon başlık medyası yükle
POST
/templates/mediaMedya başlıklı (
IMAGE, VIDEO, DOCUMENT) şablon için örnek dosyayı Meta'nın Resumable Upload'ına yükler ve header_handle döndürür. Dönen header_handle değerini HEADER bileşeninde example.header_handle[0]'a, header_media_ref değerini POST /templates gövdesinin üst düzeyine koyun. Üç giriş biçimi vardır (biri): multipart/form-data ile file, JSON url ya da JSON media_id. Kapsam: templates:writeKabul edilen türler:
IMAGE image/jpeg, image/png (en çok 5 MB) · VIDEO video/mp4 (en çok 16 MB) · DOCUMENT application/pdf (en çok 100 MB). Meta medya türleri · Resumable Upload.header_handle kısa ömürlüdür: hemen POST /templates ya da düzenlemede kullanın. Gönderim media_id'si şablon örneği olarak geçmez; bu uç onu yeniden yükleyerek tanıtıcıya çevirir.header_media_ref dosyanın Veri Merkezi'ndeki kopyasıdır. Şablona bağlanınca panel ve kampanya gönderimlerinde başlık medyası otomatik bulunur.cURL:
curl -X POST https://api.verimerkezi.app/wa/templates/media -H "Authorization: Bearer $VM_API_KEY" -F [email protected] -F format=IMAGE.Test anahtarıyla Meta'ya gidilmez ve kayıt yapılmaz:
201 header_handle: "4::test…", header_media_ref: null, simulated: true. multipart girişinde tür ve boyut denetimi canlıdaki gibidir; url / media_id girişinde indirme yapılmaz (mime_type ve file_size null olabilir).İstek gövdesi
filefileisteğe bağlımultipart/form-dataalanı: yüklenecek tek dosya.formatverilmezse dosya türünden çıkarılır.urlstringisteğe bağlıJSON girişi: herkese açıkhttps://adres; sunucu indirir.media_idstringisteğe bağlıJSON girişi:POST /mediaile Meta'ya yüklenmiş (30 gün geçerli) medya kimliği; sunucu Meta'dan indirip yeniden yükler.phone_number_idile birlikte verin.formatstringisteğe bağlıBeklenen biçim; dosya türüyle uyuşmazsa415.Değerler:IMAGE,VIDEO,DOCUMENTwaba_idstringisteğe bağlıHedef WABA. Hesabınızda tek WABA varsa gerekmez; birden çok varsa zorunludur.phone_number_idstringisteğe bağlıwaba_idyerine; WABA numaradan çözülür.
Hatalar
| Durum | Kod | Ne zaman |
|---|---|---|
| 403 | insufficient_scope | Anahtarda templates:write kapsamı yok. |
| 404 | number_not_found | Numara/WABA size ait değil. |
| 413 | media_too_large | Sınır aşıldı (max_bytes döner): IMAGE 5 MB, VIDEO 16 MB, DOCUMENT 100 MB. |
| 415 | media_invalid_format | Tür başlık için desteklenmiyor ya da istenen format ile uyuşmuyor. Kabul: JPEG/PNG, MP4, PDF. |
| 422 | invalid_request | file, url ya da media_id yok; format geçersiz; media_id rakam değil (error.field). |
| 422 | waba_required | Birden çok WABA'nız var; waba_id verin. |
| 422 | header_media_fetch_failed | url indirilemedi ya da media_id Meta'dan alınamadı. |
| 422 | meta_upload_failed | Meta'ya yükleme başarısız. Hata Meta'dan geldiyse meta_code, meta_subcode, meta_message, meta_user_title, meta_user_message ve fbtrace_id alanları da döner. |
| 502 | meta_unavailable | Meta'ya ulaşılamadı ya da Meta 5xx döndü; biraz sonra tekrar deneyin. |
curl -X POST "https://api.verimerkezi.app/wa/templates/media" \
-H "Authorization: Bearer $VM_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://cdn.example.com/kampanya.jpg",
"format": "IMAGE",
"waba_id": "1029384756"
}'const res = await fetch("https://api.verimerkezi.app/wa/templates/media", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.VM_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
"url": "https://cdn.example.com/kampanya.jpg",
"format": "IMAGE",
"waba_id": "1029384756"
}),
});
const data = await res.json();import os, requests
res = requests.post(
"https://api.verimerkezi.app/wa/templates/media",
headers={"Authorization": f"Bearer {os.environ['VM_API_KEY']}"},
json={
"url": "https://cdn.example.com/kampanya.jpg",
"format": "IMAGE",
"waba_id": "1029384756"
},
)
data = res.json()<?php
$ch = curl_init("https://api.verimerkezi.app/wa/templates/media");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
"Authorization: Bearer " . getenv("VM_API_KEY"),
"Content-Type: application/json",
],
CURLOPT_POSTFIELDS => json_encode([
"url" => "https://cdn.example.com/kampanya.jpg",
"format" => "IMAGE",
"waba_id" => "1029384756"
]),
]);
$data = json_decode(curl_exec($ch), true);Yanıt 201
{
"ok": true,
"header_handle": "4::aW1hZ2UvanBlZw==:ARb...",
"header_media_ref": 8812,
"format": "IMAGE",
"mime_type": "image/jpeg",
"file_size": 183244,
"waba_id": "1029384756"
}#Şablon ayrıntısını getir
GET
/templates/{id}Tek bir şablonu tam bileşenleri, kalite puanı, ret nedeni (ham ve Türkçe), değişken biçimi, başlık medyası ve düzenleme durumuyla (
edit_limit) döndürür. Kapsam: templates:readedit_limit.editable false ise düzenleme düğmesini kapatıp next_edit_at zamanını gösterin. Yalnız Veri Merkezi üzerinden yapılan düzenlemeler sayılır; WhatsApp Manager'dan yapılanı Meta 429 template_edit_limit ile bildirir.2.25.0: Her şablonda
header_media döner (medya başlığı yoksa null). Kalıcı bağlantı (temporary: false) ile CRM kendi önizlemesini çizer ve her gönderimde dosya seçtirmesine gerek kalmaz; temporary: true yalnız Meta'nın süreli onay örneğidir.Yol parametreleri
idintegerzorunluVeri Merkezi şablon kimliği.
Hatalar
| Durum | Kod | Ne zaman |
|---|---|---|
| 400 | invalid_template_id | Geçersiz şablon kimliği. |
| 403 | insufficient_scope | Anahtarda templates:read kapsamı yok. |
| 404 | template_not_found | Şablon bulunamadı. |
curl -X GET "https://api.verimerkezi.app/wa/templates/512" \
-H "Authorization: Bearer $VM_API_KEY"const res = await fetch("https://api.verimerkezi.app/wa/templates/512", {
method: "GET",
headers: {
Authorization: `Bearer ${process.env.VM_API_KEY}`,
},
});
const data = await res.json();import os, requests
res = requests.get(
"https://api.verimerkezi.app/wa/templates/512",
headers={"Authorization": f"Bearer {os.environ['VM_API_KEY']}"},
)
data = res.json()<?php
$ch = curl_init("https://api.verimerkezi.app/wa/templates/512");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
"Authorization: Bearer " . getenv("VM_API_KEY"),
],
]);
$data = json_decode(curl_exec($ch), true);Yanıt 200
{
"id": 512,
"meta_template_id": "1249033812345678",
"name": "police_yenileme_hatirlatma",
"language": "tr",
"category": "UTILITY",
"previous_category": null,
"parameter_format": "POSITIONAL",
"status": "REJECTED",
"rejected_reason": "INVALID_FORMAT",
"rejected_reason_text": "Şablon biçimi geçersiz (değişken/örnek eksik olabilir).",
"quality_score": null,
"waba_id": "1029384756",
"phone_number_id": "1234567890",
"created_at": "2026-09-22T09:00:00+03:00",
"submitted_at": "2026-09-22T09:00:03+03:00",
"status_updated_at": "2026-09-22T09:05:41+03:00",
"components": [
{
"type": "BODY",
"text": "Sayın {{1}}, poliçeniz {{2}} tarihinde sona eriyor.",
"example": {
"body_text": [
[
"Ahmet",
"12.10.2026"
]
]
}
}
],
"header_media": {
"url": "https://api.verimerkezi.app/storage/template-media/8812.jpg",
"mime_type": "image/jpeg",
"file_size": 183244,
"sha256": "9f2c...e41a",
"filename": "kampanya.jpg",
"format": "IMAGE",
"temporary": false
},
"display_phone_number": "+90 555 000 00 00",
"ok": true,
"header_media_ref": null,
"edit_limit": {
"editable": true,
"edits_last_30d": 0,
"max_edits_30d": 10,
"next_edit_at": null
}
}#Şablonu düzenle
PATCH
/templates/{id}APPROVED, REJECTED ya da PAUSED şablonun bileşenlerini değiştirir ve yeniden Meta incelemesine gönderir; durum PENDING olur. Düzenleme TÜM bileşenleri değiştirir: gönderdiğiniz liste tam olmalıdır. Onaylı şablon 24 saatte 1, 30 günde en çok 10 kez düzenlenebilir ve kategorisi değişmez; reddedilen ve duraklatılan şablonlarda sınır yoktur ve kategori değişebilir. POST /templates/{id} ile eşdeğerdir. Kapsam: templates:writename, language ve parameter_format düzenlenemez; gövdede gönderilirse 422 invalid_request (field) döner. Yeni ad ya da dil için POST /templates/{id}/copy kullanın.Yanıt
200: güncel şablon nesnesi (status: "PENDING", ayrıntı alanlarıyla).Test anahtarıyla kurallar denetlenir, Meta'ya gidilmez ve kayıt değişmez:
200 status: "PENDING", simulated: true. 404 / 409 / 422 kuralları canlıdaki gibidir.Yol parametreleri
idintegerzorunluVeri Merkezi şablon kimliği.
İstek gövdesi
componentsarrayzorunluTAM bileşen listesi (yalnız kategori değişikliğinde verilmeyebilir). BiçimPOST /templatesile aynıdır.categorystringisteğe bağlıYeni kategori; yalnızREJECTED/PAUSEDşablonda. Onaylıda farklı kategori422 category_not_editableverir.Değerler:UTILITY,MARKETING,AUTHENTICATIONmessage_send_ttl_secondsintegeristeğe bağlıMesaj geçerlilik süresi (saniye).header_media_refintegeristeğe bağlıMedya başlığını değiştirirkenPOST /templates/mediadeğeri. Verilmezse mevcut Veri Merkezi kopyasından yeni tanıtıcı üretilir.header_media_urlstringisteğe bağlıEski yol: herkese açıkhttps://adres.allow_category_changebooleanisteğe bağlıMeta'ya aynen iletilir.cta_url_link_tracking_opted_outbooleanisteğe bağlıMeta'ya aynen iletilir.optout_footerbooleanisteğe bağlıYalnızMARKETING; oluşturmadaki gibi.
Hatalar
| Durum | Kod | Ne zaman |
|---|---|---|
| 400 | invalid_template_id | Geçersiz şablon kimliği. |
| 403 | insufficient_scope | Anahtarda templates:write kapsamı yok. |
| 404 | template_not_found | Şablon bulunamadı. |
| 409 | template_not_editable | Durum APPROVED / REJECTED / PAUSED dışında (ör. PENDING, DISABLED) ya da şablon Meta'ya hiç gönderilmemiş (status döner). |
| 422 | invalid_request | name, language ya da parameter_format gönderildi (düzenlenemez; yeni ad / dil için kopyalayın) ya da components biçimi yanlış (error.field). |
| 422 | category_not_editable | Onaylı şablonda kategori değişikliği istendi (field: category). |
| 422 | template_invalid | Bileşenler Meta kurallarına aykırı; error.field yolu söyler. |
| 422 | template_edit_failed | Meta düzenlemeyi kabul etmedi. Hata Meta'dan geldiyse meta_code, meta_subcode, meta_message, meta_user_title, meta_user_message ve fbtrace_id alanları da döner. |
| 429 | template_edit_limit | Düzenleme sınırı: next_edit_at (en erken zaman) ve retry_after (saniye, Retry-After başlığı) döner. Meta kaynaklıysa meta_* alanları da gelir. |
| 502 | meta_unavailable | Meta'ya ulaşılamadı ya da Meta 5xx döndü; biraz sonra tekrar deneyin. |
curl -X PATCH "https://api.verimerkezi.app/wa/templates/512" \
-H "Authorization: Bearer $VM_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"components": [
{
"type": "BODY",
"text": "Sayın {{1}}, poliçeniz {{2}} tarihinde bitiyor.",
"example": {
"body_text": [
[
"Ahmet",
"12.10.2026"
]
]
}
}
]
}'const res = await fetch("https://api.verimerkezi.app/wa/templates/512", {
method: "PATCH",
headers: {
Authorization: `Bearer ${process.env.VM_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
"components": [
{
"type": "BODY",
"text": "Sayın {{1}}, poliçeniz {{2}} tarihinde bitiyor.",
"example": {
"body_text": [
[
"Ahmet",
"12.10.2026"
]
]
}
}
]
}),
});
const data = await res.json();import os, requests
res = requests.patch(
"https://api.verimerkezi.app/wa/templates/512",
headers={"Authorization": f"Bearer {os.environ['VM_API_KEY']}"},
json={
"components": [
{
"type": "BODY",
"text": "Sayın {{1}}, poliçeniz {{2}} tarihinde bitiyor.",
"example": {
"body_text": [
[
"Ahmet",
"12.10.2026"
]
]
}
}
]
},
)
data = res.json()<?php
$ch = curl_init("https://api.verimerkezi.app/wa/templates/512");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => "PATCH",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
"Authorization: Bearer " . getenv("VM_API_KEY"),
"Content-Type: application/json",
],
CURLOPT_POSTFIELDS => json_encode([
"components" => [
[
"type" => "BODY",
"text" => "Sayın {{1}}, poliçeniz {{2}} tarihinde bitiyor.",
"example" => [
"body_text" => [
[
"Ahmet",
"12.10.2026"
]
]
]
]
]
]),
]);
$data = json_decode(curl_exec($ch), true);Yanıt 200
{
"id": 512,
"meta_template_id": "1249033812345678",
"name": "police_yenileme_hatirlatma",
"language": "tr",
"category": "UTILITY",
"previous_category": null,
"parameter_format": "POSITIONAL",
"status": "PENDING",
"rejected_reason": null,
"rejected_reason_text": null,
"quality_score": null,
"waba_id": "1029384756",
"phone_number_id": "1234567890",
"created_at": "2026-09-22T09:00:00+03:00",
"submitted_at": "2026-09-22T09:00:03+03:00",
"status_updated_at": "2026-09-22T09:05:41+03:00",
"components": [
{
"type": "BODY",
"text": "Sayın {{1}}, poliçeniz {{2}} tarihinde sona eriyor.",
"example": {
"body_text": [
[
"Ahmet",
"12.10.2026"
]
]
}
}
],
"display_phone_number": "+90 555 000 00 00",
"ok": true,
"header_media_ref": null,
"edit_limit": {
"editable": false,
"edits_last_30d": 1,
"max_edits_30d": 10,
"next_edit_at": "2026-10-15T09:05:41+03:00"
}
}#Şablonu düzenle (POST)
POST
/templates/{id}PATCH /templates/{id} ile birebir aynı davranır; PATCH gönderemeyen istemciler için POST eşdeğeridir (2.25.0). Kurallar, gövde, hatalar ve yanıt aynıdır. Kapsam: templates:writeAyrıntılı kurallar için bkz.
PATCH /templates/{id}.Test anahtarında da
PATCH ile aynı simülasyon geçerlidir.Yol parametreleri
idintegerzorunluVeri Merkezi şablon kimliği.
İstek gövdesi
componentsarrayzorunluTAM bileşen listesi (yalnız kategori değişikliğinde verilmeyebilir). BiçimPOST /templatesile aynıdır.categorystringisteğe bağlıYeni kategori; yalnızREJECTED/PAUSEDşablonda. Onaylıda farklı kategori422 category_not_editableverir.Değerler:UTILITY,MARKETING,AUTHENTICATIONmessage_send_ttl_secondsintegeristeğe bağlıMesaj geçerlilik süresi (saniye).header_media_refintegeristeğe bağlıMedya başlığını değiştirirkenPOST /templates/mediadeğeri. Verilmezse mevcut Veri Merkezi kopyasından yeni tanıtıcı üretilir.header_media_urlstringisteğe bağlıEski yol: herkese açıkhttps://adres.allow_category_changebooleanisteğe bağlıMeta'ya aynen iletilir.cta_url_link_tracking_opted_outbooleanisteğe bağlıMeta'ya aynen iletilir.optout_footerbooleanisteğe bağlıYalnızMARKETING; oluşturmadaki gibi.
Hatalar
| Durum | Kod | Ne zaman |
|---|---|---|
| 400 | invalid_template_id | Geçersiz şablon kimliği. |
| 403 | insufficient_scope | Anahtarda templates:write kapsamı yok. |
| 404 | template_not_found | Şablon bulunamadı. |
| 409 | template_not_editable | Durum APPROVED / REJECTED / PAUSED dışında (ör. PENDING, DISABLED) ya da şablon Meta'ya hiç gönderilmemiş (status döner). |
| 422 | invalid_request | name, language ya da parameter_format gönderildi (düzenlenemez; yeni ad / dil için kopyalayın) ya da components biçimi yanlış (error.field). |
| 422 | category_not_editable | Onaylı şablonda kategori değişikliği istendi (field: category). |
| 422 | template_invalid | Bileşenler Meta kurallarına aykırı; error.field yolu söyler. |
| 422 | template_edit_failed | Meta düzenlemeyi kabul etmedi. Hata Meta'dan geldiyse meta_code, meta_subcode, meta_message, meta_user_title, meta_user_message ve fbtrace_id alanları da döner. |
| 429 | template_edit_limit | Düzenleme sınırı: next_edit_at (en erken zaman) ve retry_after (saniye, Retry-After başlığı) döner. Meta kaynaklıysa meta_* alanları da gelir. |
| 502 | meta_unavailable | Meta'ya ulaşılamadı ya da Meta 5xx döndü; biraz sonra tekrar deneyin. |
curl -X POST "https://api.verimerkezi.app/wa/templates/512" \
-H "Authorization: Bearer $VM_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"components": [
{
"type": "BODY",
"text": "Sayın {{1}}, poliçeniz {{2}} tarihinde bitiyor.",
"example": {
"body_text": [
[
"Ahmet",
"12.10.2026"
]
]
}
}
]
}'const res = await fetch("https://api.verimerkezi.app/wa/templates/512", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.VM_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
"components": [
{
"type": "BODY",
"text": "Sayın {{1}}, poliçeniz {{2}} tarihinde bitiyor.",
"example": {
"body_text": [
[
"Ahmet",
"12.10.2026"
]
]
}
}
]
}),
});
const data = await res.json();import os, requests
res = requests.post(
"https://api.verimerkezi.app/wa/templates/512",
headers={"Authorization": f"Bearer {os.environ['VM_API_KEY']}"},
json={
"components": [
{
"type": "BODY",
"text": "Sayın {{1}}, poliçeniz {{2}} tarihinde bitiyor.",
"example": {
"body_text": [
[
"Ahmet",
"12.10.2026"
]
]
}
}
]
},
)
data = res.json()<?php
$ch = curl_init("https://api.verimerkezi.app/wa/templates/512");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
"Authorization: Bearer " . getenv("VM_API_KEY"),
"Content-Type: application/json",
],
CURLOPT_POSTFIELDS => json_encode([
"components" => [
[
"type" => "BODY",
"text" => "Sayın {{1}}, poliçeniz {{2}} tarihinde bitiyor.",
"example" => [
"body_text" => [
[
"Ahmet",
"12.10.2026"
]
]
]
]
]
]),
]);
$data = json_decode(curl_exec($ch), true);Yanıt 200
{
"id": 512,
"meta_template_id": "1249033812345678",
"name": "police_yenileme_hatirlatma",
"language": "tr",
"category": "UTILITY",
"previous_category": null,
"parameter_format": "POSITIONAL",
"status": "PENDING",
"rejected_reason": null,
"rejected_reason_text": null,
"quality_score": null,
"waba_id": "1029384756",
"phone_number_id": "1234567890",
"created_at": "2026-09-22T09:00:00+03:00",
"submitted_at": "2026-09-22T09:00:03+03:00",
"status_updated_at": "2026-09-22T09:05:41+03:00",
"components": [
{
"type": "BODY",
"text": "Sayın {{1}}, poliçeniz {{2}} tarihinde sona eriyor.",
"example": {
"body_text": [
[
"Ahmet",
"12.10.2026"
]
]
}
}
],
"display_phone_number": "+90 555 000 00 00",
"ok": true,
"header_media_ref": null,
"edit_limit": {
"editable": false,
"edits_last_30d": 1,
"max_edits_30d": 10,
"next_edit_at": "2026-10-15T09:05:41+03:00"
}
}#Şablonu kopyala
POST
/templates/{id}/copyMevcut şablonu yeni ad ve/veya dille kopyalayıp Meta onayına gönderir. Kaynağın bileşenleri,
parameter_format değeri ve (Veri Merkezi'nde kopyası varsa) başlık medyası kullanılır; components verilirse onlar esas alınır (çeviri için). Yanıt ve hatalar POST /templates ile aynıdır. Kapsam: templates:writeEşdeğer yol:
GET /templates/{id} ile components alıp POST /templates göndermek.Test anahtarıyla kayıt oluşmaz ve Meta'ya gidilmez:
202 id: 0, status: "PENDING", simulated: true.Yol parametreleri
idintegerzorunluVeri Merkezi şablon kimliği.
İstek gövdesi
namestringzorunluYeni şablon adı.languagestringisteğe bağlıYeni dil; verilmezse kaynağın dili.categorystringisteğe bağlıYeni kategori; verilmezse kaynağın kategorisi.Değerler:UTILITY,MARKETING,AUTHENTICATIONcomponentsarrayisteğe bağlıKaynağın yerine kullanılacak bileşenler (ör. çeviri).waba_idstringisteğe bağlıHedef WABA; verilmezse kaynağın WABA'sı.optout_footerbooleanisteğe bağlıKopyada varsayılanfalse: kaynağın alt bilgisi aynen alınır.header_media_refintegeristeğe bağlıBaşlık medyası içinPOST /templates/mediadeğeri.allow_category_changebooleanisteğe bağlıMeta'ya aynen iletilir.message_send_ttl_secondsintegeristeğe bağlıMesaj geçerlilik süresi (saniye).cta_url_link_tracking_opted_outbooleanisteğe bağlıMeta'ya aynen iletilir.
Hatalar
| Durum | Kod | Ne zaman |
|---|---|---|
| 400 | invalid_template_id | Geçersiz şablon kimliği. |
| 403 | insufficient_scope | Anahtarda templates:write kapsamı yok. |
| 404 | template_not_found | Kaynak şablon bulunamadı. |
| 409 | template_exists | Aynı WABA'da aynı ad ve dil zaten var (field: name, template_id). |
| 422 | invalid_request | name eksik; medya başlıklı kaynağın Veri Merkezi kopyası yoksa field: header_media_ref (önce POST /templates/media, sonra header_media_ref ile tekrar deneyin). |
| 422 | template_invalid | Bileşenler Meta kurallarına aykırı; error.field yolu söyler. |
| 422 | template_rejected | Meta şablonu reddetti. Hata Meta'dan geldiyse meta_code, meta_subcode, meta_message, meta_user_title, meta_user_message ve fbtrace_id alanları da döner. |
| 502 | meta_unavailable | Meta'ya ulaşılamadı ya da Meta 5xx döndü; biraz sonra tekrar deneyin. |
curl -X POST "https://api.verimerkezi.app/wa/templates/512/copy" \
-H "Authorization: Bearer $VM_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "police_yenileme_hatirlatma_en",
"language": "en_US",
"components": [
{
"type": "BODY",
"text": "Dear {{1}}, your policy for {{2}} expires on {{3}}.",
"example": {
"body_text": [
[
"Ahmet Yilmaz",
"34 ABC 123",
"12.10.2026"
]
]
}
}
]
}'const res = await fetch("https://api.verimerkezi.app/wa/templates/512/copy", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.VM_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
"name": "police_yenileme_hatirlatma_en",
"language": "en_US",
"components": [
{
"type": "BODY",
"text": "Dear {{1}}, your policy for {{2}} expires on {{3}}.",
"example": {
"body_text": [
[
"Ahmet Yilmaz",
"34 ABC 123",
"12.10.2026"
]
]
}
}
]
}),
});
const data = await res.json();import os, requests
res = requests.post(
"https://api.verimerkezi.app/wa/templates/512/copy",
headers={"Authorization": f"Bearer {os.environ['VM_API_KEY']}"},
json={
"name": "police_yenileme_hatirlatma_en",
"language": "en_US",
"components": [
{
"type": "BODY",
"text": "Dear {{1}}, your policy for {{2}} expires on {{3}}.",
"example": {
"body_text": [
[
"Ahmet Yilmaz",
"34 ABC 123",
"12.10.2026"
]
]
}
}
]
},
)
data = res.json()<?php
$ch = curl_init("https://api.verimerkezi.app/wa/templates/512/copy");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
"Authorization: Bearer " . getenv("VM_API_KEY"),
"Content-Type: application/json",
],
CURLOPT_POSTFIELDS => json_encode([
"name" => "police_yenileme_hatirlatma_en",
"language" => "en_US",
"components" => [
[
"type" => "BODY",
"text" => "Dear {{1}}, your policy for {{2}} expires on {{3}}.",
"example" => [
"body_text" => [
[
"Ahmet Yilmaz",
"34 ABC 123",
"12.10.2026"
]
]
]
]
]
]),
]);
$data = json_decode(curl_exec($ch), true);Yanıt 202
{
"ok": true,
"id": 514,
"meta_template_id": "1249033812345680",
"name": "police_yenileme_hatirlatma_en",
"language": "en_US",
"category": "UTILITY",
"previous_category": null,
"parameter_format": "POSITIONAL",
"status": "PENDING",
"rejected_reason": null,
"rejected_reason_text": null,
"quality_score": null,
"waba_id": "1029384756",
"phone_number_id": "1234567890",
"created_at": "2026-10-14T09:00:00+03:00",
"submitted_at": "2026-10-14T09:00:02+03:00",
"status_updated_at": null
}#Şablonu sil
DELETE
/templates/{id}Yalnız bu dili (bu kimlikteki satırı) siler: Meta'ya ad ve
hsm_id ile gider. Adın diğer dilleri etkilenmez; tüm dilleri silmek için DELETE /templates?name=… kullanın. Geçmiş mesajlar etkilenmez; Meta silinen onaylı şablonun adını 30 gün yeniden kullandırmaz. Meta'ya hiç gönderilmemiş taslak yalnız yerelden silinir. Kapsam: templates:write2.25.0 düzeltmesi: önceden Meta'da adın tüm dilleri siliniyordu, yerelde ise tek satır; artık yalnız ilgili dil silinir (yanıtta
language).Şablon Meta'da zaten yoksa yerel kayıt yine silinir ve yanıtta
meta_missing: true döner.Test anahtarıyla silinmez; yalnız sahiplik denetlenir:
200 deleted: true, simulated: true.Yol parametreleri
idintegerzorunluVeri Merkezi şablon kimliği.
Hatalar
| Durum | Kod | Ne zaman |
|---|---|---|
| 400 | invalid_template_id | Geçersiz şablon kimliği. |
| 403 | insufficient_scope | Anahtarda templates:write kapsamı yok. |
| 404 | template_not_found | Şablon bulunamadı. |
| 422 | template_delete_failed | Meta silmeyi kabul etmedi (ör. DISABLED şablon silinemez). Hata Meta'dan geldiyse meta_code, meta_subcode, meta_message, meta_user_title, meta_user_message ve fbtrace_id alanları da döner. |
| 502 | meta_unavailable | Meta'ya ulaşılamadı ya da Meta 5xx döndü; biraz sonra tekrar deneyin. |
curl -X DELETE "https://api.verimerkezi.app/wa/templates/512" \
-H "Authorization: Bearer $VM_API_KEY"const res = await fetch("https://api.verimerkezi.app/wa/templates/512", {
method: "DELETE",
headers: {
Authorization: `Bearer ${process.env.VM_API_KEY}`,
},
});
const data = await res.json();import os, requests
res = requests.delete(
"https://api.verimerkezi.app/wa/templates/512",
headers={"Authorization": f"Bearer {os.environ['VM_API_KEY']}"},
)
data = res.json()<?php
$ch = curl_init("https://api.verimerkezi.app/wa/templates/512");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => "DELETE",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
"Authorization: Bearer " . getenv("VM_API_KEY"),
],
]);
$data = json_decode(curl_exec($ch), true);Yanıt 200
{
"ok": true,
"deleted": true,
"id": 512,
"name": "police_yenileme_hatirlatma",
"language": "tr"
}#Şablonu ada göre sil (tüm diller)
DELETE
/templates/{id}Adın TÜM dillerini aynı anda siler (Meta'ya yalnız
name ile gider). Tek dil için DELETE /templates/{id} kullanın. Silinen onaylı şablonun adı 30 gün yeniden kullanılamaz; DISABLED şablon silinemez. Kapsam: templates:writeYanıtta silinen satırların
ids ve languages listesi döner. Meta'da zaten yoksa yerel kayıtlar yine silinir ve meta_missing: true eklenir.Test anahtarıyla silinmez:
200 deleted: true, simulated: true; o adla yerel kayıt yoksa 404 template_not_found.Sorgu parametreleri
namestringzorunluSilinecek şablon adı (küçük harf, rakam, alt çizgi).waba_idstringisteğe bağlıHedef WABA. Hesabınızda tek WABA varsa gerekmez; birden çok varsa zorunludur.phone_number_idstringisteğe bağlıwaba_idyerine; WABA numaradan çözülür.
Hatalar
| Durum | Kod | Ne zaman |
|---|---|---|
| 403 | insufficient_scope | Anahtarda templates:write kapsamı yok. |
| 404 | template_not_found | Bu adla şablon bulunamadı. |
| 404 | number_not_found | Numara/WABA size ait değil. |
| 422 | invalid_request | name eksik ya da geçersiz (field: name). |
| 422 | waba_required | Birden çok WABA'nız var; waba_id verin. |
| 422 | template_delete_failed | Meta silmeyi kabul etmedi. Hata Meta'dan geldiyse meta_code, meta_subcode, meta_message, meta_user_title, meta_user_message ve fbtrace_id alanları da döner. |
| 502 | meta_unavailable | Meta'ya ulaşılamadı ya da Meta 5xx döndü; biraz sonra tekrar deneyin. |
curl -X DELETE "https://api.verimerkezi.app/wa/templates/{id}" \
-H "Authorization: Bearer $VM_API_KEY"const res = await fetch("https://api.verimerkezi.app/wa/templates/{id}", {
method: "DELETE",
headers: {
Authorization: `Bearer ${process.env.VM_API_KEY}`,
},
});
const data = await res.json();import os, requests
res = requests.delete(
"https://api.verimerkezi.app/wa/templates/{id}",
headers={"Authorization": f"Bearer {os.environ['VM_API_KEY']}"},
)
data = res.json()<?php
$ch = curl_init("https://api.verimerkezi.app/wa/templates/{id}");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => "DELETE",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
"Authorization: Bearer " . getenv("VM_API_KEY"),
],
]);
$data = json_decode(curl_exec($ch), true);Yanıt 200
{
"ok": true,
"deleted": true,
"name": "police_yenileme_hatirlatma",
"waba_id": "1029384756",
"ids": [
512,
513
],
"languages": [
"tr",
"en_US"
]
}