API referansı
Webhook abonelikleri
Olayların sunucunuza gönderileceği webhook aboneliklerini yönetin; imza anahtarını döndürün ve ölü teslimleri yeniden kuyruğa alın.
#WebhookSubscription nesnesi
idintegerAbonelik kimliği.namestring · boş olabilirAbonelik adı (description).urlstringTeslim adresi (https).eventsarrayAbone olunan olaylar.*kaydedilirken o anki 12 klasik olaya genişletilir.activebooleanAbonelik etkin mi.secret_prefixstring · boş olabilirİmza anahtarının ilk 16 karakteri.last_success_atstring · boş olabilirSon başarılı teslim.last_failure_atstring · boş olabilirSon başarısız teslim.failure_countintegerArdışık başarısız teslim sayısı.created_atstring · boş olabilirOluşturulma zamanı.
WebhookSubscription nesnesi
{
"id": 17,
"name": "Üretim botu",
"url": "https://api.example.com/wa-webhook",
"events": [
"message.received",
"message.status.delivered",
"template.approved"
],
"active": true,
"secret_prefix": "whsec_9f3akq2m7",
"last_success_at": "2026-10-10T11:00:00+03:00",
"last_failure_at": null,
"failure_count": 0,
"created_at": "2026-10-01T12:00:00+03:00"
}#Abonelikleri listele
GET
/webhooksHesabınızın webhook aboneliklerini döndürür. İmza anahtarı dönmez; yalnız
secret_prefix görünür. Kapsam: webhooks:readHatalar
| Durum | Kod | Ne zaman |
|---|---|---|
| 403 | insufficient_scope | Anahtarda webhooks:read kapsamı yok. |
curl -X GET "https://api.verimerkezi.app/wa/webhooks" \
-H "Authorization: Bearer $VM_API_KEY"const res = await fetch("https://api.verimerkezi.app/wa/webhooks", {
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/webhooks",
headers={"Authorization": f"Bearer {os.environ['VM_API_KEY']}"},
)
data = res.json()<?php
$ch = curl_init("https://api.verimerkezi.app/wa/webhooks");
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,
"webhooks": [
{
"id": 17,
"name": "Üretim botu",
"url": "https://api.example.com/wa-webhook",
"events": [
"message.received",
"message.status.delivered",
"template.approved"
],
"active": true,
"secret_prefix": "whsec_9f3akq2m7",
"last_success_at": "2026-10-10T11:00:00+03:00",
"last_failure_at": null,
"failure_count": 0,
"created_at": "2026-10-01T12:00:00+03:00"
}
]
}#Abonelik oluştur
POST
/webhooksYeni bir webhook aboneliği oluşturur. İmza anahtarı (
secret) yalnız bu yanıtta bir kez döner. Kapsam: webhooks:write* artık saklanmaz; kayıt anındaki 12 klasik olaya genişletilir. Sonradan eklenen olaylar bu aboneliğe kendiliğinden gelmez. * gönderildiğinde yanıtta note alanı bunu hatırlatır.İmza anahtarını kaybederseniz
POST /webhooks/{id}/rotate-secret ile yenileyin.İstek gövdesi
urlstringzorunluHerkese açıkhttps://adres. İç ağ, özel, loopback ve link-local adresler reddedilir.eventsarrayisteğe bağlıOlay adları ya da*. Hiç gönderilmezse*; boş dizi ya da bilinmeyen olay422döner.Varsayılan:["*"]descriptionstringisteğe bağlıAbonelik adı (1–80 karakter).Varsayılan:API webhook
Hatalar
| Durum | Kod | Ne zaman |
|---|---|---|
| 403 | insufficient_scope | Anahtarda webhooks:write kapsamı yok. |
| 409 | webhook_url_exists | Bu adrese zaten aktif bir abonelik var (existing_id döner). |
| 422 | invalid_request | url zorunlu. |
| 422 | invalid_webhook | Adres https değil/genel değil ya da olay listesi geçersiz. |
| 500 | webhook_create_failed | Abonelik oluşturulamadı. |
curl -X POST "https://api.verimerkezi.app/wa/webhooks" \
-H "Authorization: Bearer $VM_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://api.example.com/wa-webhook",
"events": [
"message.received",
"message.status.delivered",
"template.approved"
],
"description": "Üretim botu"
}'const res = await fetch("https://api.verimerkezi.app/wa/webhooks", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.VM_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
"url": "https://api.example.com/wa-webhook",
"events": [
"message.received",
"message.status.delivered",
"template.approved"
],
"description": "Üretim botu"
}),
});
const data = await res.json();import os, requests
res = requests.post(
"https://api.verimerkezi.app/wa/webhooks",
headers={"Authorization": f"Bearer {os.environ['VM_API_KEY']}"},
json={
"url": "https://api.example.com/wa-webhook",
"events": [
"message.received",
"message.status.delivered",
"template.approved"
],
"description": "Üretim botu"
},
)
data = res.json()<?php
$ch = curl_init("https://api.verimerkezi.app/wa/webhooks");
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://api.example.com/wa-webhook",
"events" => [
"message.received",
"message.status.delivered",
"template.approved"
],
"description" => "Üretim botu"
]),
]);
$data = json_decode(curl_exec($ch), true);Yanıt 201
{
"ok": true,
"id": 17,
"url": "https://api.example.com/wa-webhook",
"events": [
"message.received",
"message.status.delivered",
"template.approved"
],
"active": true,
"secret": "whsec_9f3akq2m7x1p8s0d4v6b2n5c3z7l9h1j",
"secret_prefix": "whsec_9f3akq2m7"
}#Aboneliği güncelle
PATCH
/webhooks/{id}Adresi, olay listesini, etkinliği ya da adı değiştirir. En az bir alan gönderin. Kapsam:
webhooks:writeYol parametreleri
idintegerzorunluAbonelik kimliği.
İstek gövdesi
urlstringisteğe bağlıYenihttpsadres.eventsarrayisteğe bağlıYeni olay listesi.activebooleanisteğe bağlıfalseaboneliği pasifleştirir.descriptionstringisteğe bağlıYeni ad (1–80 karakter).
Hatalar
| Durum | Kod | Ne zaman |
|---|---|---|
| 400 | invalid_request | Geçersiz abonelik kimliği. |
| 403 | insufficient_scope | Anahtarda webhooks:write kapsamı yok. |
| 404 | webhook_not_found | Abonelik bulunamadı. |
| 422 | invalid_webhook | Alan yok, adres geçersiz ya da olay listesi hatalı. |
curl -X PATCH "https://api.verimerkezi.app/wa/webhooks/17" \
-H "Authorization: Bearer $VM_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"events": [
"message.received",
"message.status.failed",
"flow.completed"
],
"active": true
}'const res = await fetch("https://api.verimerkezi.app/wa/webhooks/17", {
method: "PATCH",
headers: {
Authorization: `Bearer ${process.env.VM_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
"events": [
"message.received",
"message.status.failed",
"flow.completed"
],
"active": true
}),
});
const data = await res.json();import os, requests
res = requests.patch(
"https://api.verimerkezi.app/wa/webhooks/17",
headers={"Authorization": f"Bearer {os.environ['VM_API_KEY']}"},
json={
"events": [
"message.received",
"message.status.failed",
"flow.completed"
],
"active": True
},
)
data = res.json()<?php
$ch = curl_init("https://api.verimerkezi.app/wa/webhooks/17");
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([
"events" => [
"message.received",
"message.status.failed",
"flow.completed"
],
"active" => true
]),
]);
$data = json_decode(curl_exec($ch), true);Yanıt 200
{
"id": 17,
"name": "Üretim botu",
"url": "https://api.example.com/wa-webhook",
"events": [
"message.received",
"message.status.failed",
"flow.completed"
],
"active": true,
"secret_prefix": "whsec_9f3akq2m7",
"last_success_at": "2026-10-10T11:00:00+03:00",
"last_failure_at": null,
"failure_count": 0,
"created_at": "2026-10-01T12:00:00+03:00",
"ok": true
}#Aboneliği sil
DELETE
/webhooks/{id}Aboneliği kalıcı olarak siler. Kapsam:
webhooks:writeYol parametreleri
idintegerzorunluAbonelik kimliği.
Hatalar
| Durum | Kod | Ne zaman |
|---|---|---|
| 400 | invalid_request | Geçersiz abonelik kimliği. |
| 403 | insufficient_scope | Anahtarda webhooks:write kapsamı yok. |
| 404 | webhook_not_found | Abonelik bulunamadı. |
curl -X DELETE "https://api.verimerkezi.app/wa/webhooks/17" \
-H "Authorization: Bearer $VM_API_KEY"const res = await fetch("https://api.verimerkezi.app/wa/webhooks/17", {
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/webhooks/17",
headers={"Authorization": f"Bearer {os.environ['VM_API_KEY']}"},
)
data = res.json()<?php
$ch = curl_init("https://api.verimerkezi.app/wa/webhooks/17");
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": 17
}#Test bildirimi gönder
POST
/webhooks/{id}/testAboneliğe hemen imzalı bir
test.ping olayı gönderir ve teslimin sonucunu döndürür. Kapsam: webhooks:writeTeslim başarısızsa
ok: false ve result: "failed" döner. test.ping kuyruğa girmez, yeniden denenmez.Yol parametreleri
idintegerzorunluAbonelik kimliği.
Hatalar
| Durum | Kod | Ne zaman |
|---|---|---|
| 400 | invalid_request | Geçersiz abonelik kimliği. |
| 403 | insufficient_scope | Anahtarda webhooks:write kapsamı yok. |
| 404 | webhook_not_found | Abonelik bulunamadı. |
curl -X POST "https://api.verimerkezi.app/wa/webhooks/17/test" \
-H "Authorization: Bearer $VM_API_KEY"const res = await fetch("https://api.verimerkezi.app/wa/webhooks/17/test", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.VM_API_KEY}`,
},
});
const data = await res.json();import os, requests
res = requests.post(
"https://api.verimerkezi.app/wa/webhooks/17/test",
headers={"Authorization": f"Bearer {os.environ['VM_API_KEY']}"},
)
data = res.json()<?php
$ch = curl_init("https://api.verimerkezi.app/wa/webhooks/17/test");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
"Authorization: Bearer " . getenv("VM_API_KEY"),
],
]);
$data = json_decode(curl_exec($ch), true);Yanıt 200
{
"ok": true,
"result": "delivered"
}#İmza anahtarını döndür
POST
/webhooks/{id}/rotate-secretAboneliği silmeden imza anahtarını yeniler; kimlik, istatistik ve geçmiş korunur. Yeni anahtar yalnız bu yanıtta döner. Geçiş süresince eski anahtarla ikinci bir imza da gönderilir. Kapsam:
webhooks:writeprevious_valid_until, grace_seconds: 0 ise ya da eski kayıtta şifreli anahtar yoksa null döner.Geçiş süresi içinde ikinci kez döndürürseniz en eski anahtar artık kabul edilmez.
Yol parametreleri
idintegerzorunluAbonelik kimliği.
İstek gövdesi
grace_secondsintegeristeğe bağlıEski anahtarınX-VeriMerkezi-Signature-256-Previousbaşlığıyla gönderileceği süre (0–604800).0anında geçiş.Varsayılan:86400
Hatalar
| Durum | Kod | Ne zaman |
|---|---|---|
| 400 | invalid_request | Geçersiz abonelik kimliği. |
| 403 | insufficient_scope | Anahtarda webhooks:write kapsamı yok. |
| 404 | webhook_not_found | Abonelik bulunamadı. |
| 422 | invalid_request | grace_seconds aralık dışında (field: grace_seconds). |
curl -X POST "https://api.verimerkezi.app/wa/webhooks/17/rotate-secret" \
-H "Authorization: Bearer $VM_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"grace_seconds": 86400
}'const res = await fetch("https://api.verimerkezi.app/wa/webhooks/17/rotate-secret", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.VM_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
"grace_seconds": 86400
}),
});
const data = await res.json();import os, requests
res = requests.post(
"https://api.verimerkezi.app/wa/webhooks/17/rotate-secret",
headers={"Authorization": f"Bearer {os.environ['VM_API_KEY']}"},
json={
"grace_seconds": 86400
},
)
data = res.json()<?php
$ch = curl_init("https://api.verimerkezi.app/wa/webhooks/17/rotate-secret");
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([
"grace_seconds" => 86400
]),
]);
$data = json_decode(curl_exec($ch), true);Yanıt 200
{
"ok": true,
"id": 17,
"secret": "whsec_2m8c4x9v1b7n3k5q0p6z8l2j4h7g1f3d",
"secret_prefix": "whsec_2m8c4x9v1",
"previous_valid_until": "2026-10-11T12:00:00+03:00"
}#Ölü teslimleri yeniden kuyruğa al
POST
/webhooks/redeliverTüm denemeleri tükenip ölü (dead-letter) duruma düşen teslimlerinizi yeniden kuyruğa alır. Olaylar dakikalık teslim turunda yeniden gönderilir. Kapsam:
webhooks:write ya da messages:read ya da inbox:readwebhooks:write, messages:read ya da inbox:read kapsamlarından biri yeterlidir.Tek çağrıda en fazla 5000 teslim kuyruğa alınır.
call.connect olaylarında SDP bilgisi teslimden sonra maskelendiği için yeniden gönderilen olayda SDP bulunmaz.İstek gövdesi
sincestringzorunluISO 8601; en fazla son 7 gün.
Hatalar
| Durum | Kod | Ne zaman |
|---|---|---|
| 403 | insufficient_scope | Anahtarda webhooks:write, messages:read ya da inbox:read yok. |
| 422 | invalid_since | since eksik, ISO 8601 değil ya da 7 günden eski. |
curl -X POST "https://api.verimerkezi.app/wa/webhooks/redeliver" \
-H "Authorization: Bearer $VM_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"since": "2026-10-08T00:00:00Z"
}'const res = await fetch("https://api.verimerkezi.app/wa/webhooks/redeliver", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.VM_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
"since": "2026-10-08T00:00:00Z"
}),
});
const data = await res.json();import os, requests
res = requests.post(
"https://api.verimerkezi.app/wa/webhooks/redeliver",
headers={"Authorization": f"Bearer {os.environ['VM_API_KEY']}"},
json={
"since": "2026-10-08T00:00:00Z"
},
)
data = res.json()<?php
$ch = curl_init("https://api.verimerkezi.app/wa/webhooks/redeliver");
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([
"since" => "2026-10-08T00:00:00Z"
]),
]);
$data = json_decode(curl_exec($ch), true);Yanıt 202
{
"ok": true,
"requeued": 12,
"since": "2026-10-08T03:00:00+03:00",
"note": "Olaylar dakikalık teslimat turunda yeniden gönderilir."
}