Nerzen WP

REST API ve Webhook

Tek bir JSON isteğiyle WhatsApp mesajı, medya, butonlu ve liste mesajı gönderin; gelen mesajları webhook ile sisteminize alın. Örnekler cURL, PHP ve Node.js ile.

API anahtarınızHesap açıp bir cihaz bağladığınızda anahtarınız otomatik oluşur. Aşağıdaki örneklerde API_ANAHTARINIZ yazan yeri kendi anahtarınızla değiştirin.
Ücretsiz anahtar al

Genel bilgiler

Tüm mesaj uçları POST isteği ve Content-Type: application/json gövdesiyle çalışır. Her istekte üç alan bulunur: cihazınıza özel api_key, alıcı receiver ve uca göre değişen data nesnesi.

AlanTürAçıklama
api_keystringzorunluCihaza özel 32 karakterlik anahtar. Cihazlar sayfasında görünür, cihaz ayarlarından yenilenir. Gövde yerine X-API-Key ya da Authorization: Bearer … başlığıyla da gönderilebilir.
receiverstringzorunluAlıcı numarası (905xxxxxxxxx) ya da grup kimliği (120363…@g.us). Ayrıntı: Numara biçimi.
dataobjectzorunluUca göre mesaj içeriği.
Temel adreshttps://wp.nerzen.com
Mesaj, anahtarın ait olduğu cihazdan (numaradan) gider. Birden çok numaranız varsa her cihazın kendi anahtarı vardır. Anahtarı yenilediğinizde eski anahtar hemen geçersiz olur.
API anahtarınızı tarayıcıda çalışan (herkesin görebildiği) JavaScript koduna koymayın; istekleri kendi sunucunuzdan gönderin.

Numara biçimi

receiver alanı ülke koduyla, başında + olmadan yazılır: 905321234567. Kolaylık için boşluk, tire, parantez ve + karakterleri otomatik temizlenir.

  • 05321234567 ve 5321234567 biçimleri Türkiye numarası kabul edilip 905321234567 yapılır.
  • 00 ile başlayan uluslararası biçim desteklenir (0049… → 49…).
  • Numara 10–15 hane olmalıdır; aksi hâlde receiver must be a valid phone number (905xxxxxxxxx) hatası döner.
  • Gruba göndermek için /api/groups ile aldığınız kimliği ([email protected]) yazın.

POSTMetin mesajı gönder

Bir numaraya ya da gruba düz metin mesajı gönderir. En sık kullanılan uçtur: sipariş, randevu, doğrulama kodu bildirimleri.

POSThttps://wp.nerzen.com/api/send-message

data alanları

AlanTürAçıklama
data.messagestringzorunluMesaj metni. En fazla 4096 karakter; WhatsApp biçimlendirmesi (*kalın*, _italik_) ve emoji desteklenir.

Örnek istek

curl -X POST "https://wp.nerzen.com/api/send-message" \
  -H "Content-Type: application/json" \
  -d '{
  "api_key": "API_ANAHTARINIZ",
  "receiver": "905321234567",
  "data": {
    "message": "Merhaba! 48213 numaralı siparişiniz kargoya verildi 🚚"
  }
}'
<?php
$payload = [
    'api_key'  => 'API_ANAHTARINIZ',
    'receiver' => '905321234567',
    'data'     => [
        'message' => 'Merhaba! 48213 numaralı siparişiniz kargoya verildi 🚚',
    ],
];

$ch = curl_init('https://wp.nerzen.com/api/send-message');
curl_setopt_array($ch, [
    CURLOPT_POST           => true,
    CURLOPT_HTTPHEADER     => ['Content-Type: application/json'],
    CURLOPT_POSTFIELDS     => json_encode($payload, JSON_UNESCAPED_UNICODE),
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_TIMEOUT        => 30,
]);
$response = json_decode(curl_exec($ch), true);
curl_close($ch);

if (!empty($response['status'])) {
    echo 'Tamam: ' . $response['message'];
} else {
    echo 'Hata: ' . ($response['message'] ?? 'bilinmiyor');
}
// Node.js 18+ (yerleşik fetch)
const payload = {
  "api_key": "API_ANAHTARINIZ",
  "receiver": "905321234567",
  "data": {
    "message": "Merhaba! 48213 numaralı siparişiniz kargoya verildi 🚚"
  }
};

const res = await fetch('https://wp.nerzen.com/api/send-message', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify(payload),
});
const json = await res.json();
if (json.status) console.log('Tamam:', json.message, json.data);
else console.error('Hata:', json.message, json.errors || '');
{
  "api_key": "API_ANAHTARINIZ",
  "receiver": "905321234567",
  "data": {
    "message": "Merhaba! 48213 numaralı siparişiniz kargoya verildi 🚚"
  }
}
200Başarılı yanıt
{
  "status": true,
  "message": "Mesaj gönderim sırasına alındı.",
  "data": {
    "receiver": "905321234567",
    "queue_id": 1284,
    "position": 1,
    "delay_sec": 10
  }
}
400Doğrulama hatası
{
  "status": false,
  "message": "Geçersiz istek.",
  "errors": [
    {
      "msg": "message is required",
      "param": "data.message",
      "location": "body"
    }
  ]
}

POSTMedya gönder

Herkese açık bir adresteki görsel, video, ses ya da dosyayı açıklamasıyla gönderir. Dosya Yöneticisi'ne yüklediğiniz dosyaların herkese açık linkini doğrudan kullanabilirsiniz.

POSThttps://wp.nerzen.com/api/send-media

data alanları

AlanTürAçıklama
data.urlstringzorunluhttp(s) ile başlayan, herkesin erişebildiği dosya adresi.
data.media_typestringzorunluimage, video, audio veya file.
data.captionstringisteğe bağlıMedya altı açıklama. En fazla 1024 karakter.

Örnek istek

curl -X POST "https://wp.nerzen.com/api/send-media" \
  -H "Content-Type: application/json" \
  -d '{
  "api_key": "API_ANAHTARINIZ",
  "receiver": "905321234567",
  "data": {
    "url": "https://siteniz.com/urunler/yeni-sezon.jpg",
    "media_type": "image",
    "caption": "Yeni sezon ürünlerimiz mağazada 🛍️"
  }
}'
<?php
$payload = [
    'api_key'  => 'API_ANAHTARINIZ',
    'receiver' => '905321234567',
    'data'     => [
        'url'        => 'https://siteniz.com/urunler/yeni-sezon.jpg',
        'media_type' => 'image',
        'caption'    => 'Yeni sezon ürünlerimiz mağazada 🛍️',
    ],
];

$ch = curl_init('https://wp.nerzen.com/api/send-media');
curl_setopt_array($ch, [
    CURLOPT_POST           => true,
    CURLOPT_HTTPHEADER     => ['Content-Type: application/json'],
    CURLOPT_POSTFIELDS     => json_encode($payload, JSON_UNESCAPED_UNICODE),
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_TIMEOUT        => 30,
]);
$response = json_decode(curl_exec($ch), true);
curl_close($ch);

if (!empty($response['status'])) {
    echo 'Tamam: ' . $response['message'];
} else {
    echo 'Hata: ' . ($response['message'] ?? 'bilinmiyor');
}
// Node.js 18+ (yerleşik fetch)
const payload = {
  "api_key": "API_ANAHTARINIZ",
  "receiver": "905321234567",
  "data": {
    "url": "https://siteniz.com/urunler/yeni-sezon.jpg",
    "media_type": "image",
    "caption": "Yeni sezon ürünlerimiz mağazada 🛍️"
  }
};

const res = await fetch('https://wp.nerzen.com/api/send-media', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify(payload),
});
const json = await res.json();
if (json.status) console.log('Tamam:', json.message, json.data);
else console.error('Hata:', json.message, json.errors || '');
{
  "api_key": "API_ANAHTARINIZ",
  "receiver": "905321234567",
  "data": {
    "url": "https://siteniz.com/urunler/yeni-sezon.jpg",
    "media_type": "image",
    "caption": "Yeni sezon ürünlerimiz mağazada 🛍️"
  }
}
200Başarılı yanıt
{
  "status": true,
  "message": "Mesaj gönderim sırasına alındı.",
  "data": {
    "receiver": "905321234567",
    "queue_id": 1284,
    "position": 1,
    "delay_sec": 10
  }
}
400Doğrulama hatası
{
  "status": false,
  "message": "Geçersiz istek.",
  "errors": [
    {
      "msg": "Media Type must be image, video, audio or file.",
      "param": "data.media_type",
      "location": "body"
    }
  ]
}

POSTButonlu mesaj gönder

Seçenekli bir mesaj gönderir. WhatsApp, bu tür etkileşimli mesajları bağlı cihaz oturumlarında artık teslim etmediği için seçenekler numaralı liste olarak iletilir; müşteri numarayı yazarak cevaplar. Cevabı otomatik yanıtlayıcı, akış botu ya da webhook ile yakalayabilirsiniz.

POSThttps://wp.nerzen.com/api/send-button

data alanları

AlanTürAçıklama
data.messagestringzorunluAna metin.
data.footerstringzorunluMesajın altındaki küçük not (işletme adı gibi).
data.buttonsarrayzorunluEn fazla 10 seçenek. Her öğe metin ("Evet") ya da nesne ({"id":"evet","display":"Evet"}) olabilir.

Örnek istek

curl -X POST "https://wp.nerzen.com/api/send-button" \
  -H "Content-Type: application/json" \
  -d '{
  "api_key": "API_ANAHTARINIZ",
  "receiver": "905321234567",
  "data": {
    "message": "Yarın 10:30 randevunuzu onaylıyor musunuz?",
    "footer": "Mavi Klinik",
    "buttons": [
      {
        "id": "evet",
        "display": "Evet, geleceğim"
      },
      {
        "id": "hayir",
        "display": "İptal etmek istiyorum"
      }
    ]
  }
}'
<?php
$payload = [
    'api_key'  => 'API_ANAHTARINIZ',
    'receiver' => '905321234567',
    'data'     => [
        'message' => 'Yarın 10:30 randevunuzu onaylıyor musunuz?',
        'footer'  => 'Mavi Klinik',
        'buttons' => [
            [
                'id'      => 'evet',
                'display' => 'Evet, geleceğim',
            ],
            [
                'id'      => 'hayir',
                'display' => 'İptal etmek istiyorum',
            ],
        ],
    ],
];

$ch = curl_init('https://wp.nerzen.com/api/send-button');
curl_setopt_array($ch, [
    CURLOPT_POST           => true,
    CURLOPT_HTTPHEADER     => ['Content-Type: application/json'],
    CURLOPT_POSTFIELDS     => json_encode($payload, JSON_UNESCAPED_UNICODE),
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_TIMEOUT        => 30,
]);
$response = json_decode(curl_exec($ch), true);
curl_close($ch);

if (!empty($response['status'])) {
    echo 'Tamam: ' . $response['message'];
} else {
    echo 'Hata: ' . ($response['message'] ?? 'bilinmiyor');
}
// Node.js 18+ (yerleşik fetch)
const payload = {
  "api_key": "API_ANAHTARINIZ",
  "receiver": "905321234567",
  "data": {
    "message": "Yarın 10:30 randevunuzu onaylıyor musunuz?",
    "footer": "Mavi Klinik",
    "buttons": [
      {
        "id": "evet",
        "display": "Evet, geleceğim"
      },
      {
        "id": "hayir",
        "display": "İptal etmek istiyorum"
      }
    ]
  }
};

const res = await fetch('https://wp.nerzen.com/api/send-button', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify(payload),
});
const json = await res.json();
if (json.status) console.log('Tamam:', json.message, json.data);
else console.error('Hata:', json.message, json.errors || '');
{
  "api_key": "API_ANAHTARINIZ",
  "receiver": "905321234567",
  "data": {
    "message": "Yarın 10:30 randevunuzu onaylıyor musunuz?",
    "footer": "Mavi Klinik",
    "buttons": [
      {
        "id": "evet",
        "display": "Evet, geleceğim"
      },
      {
        "id": "hayir",
        "display": "İptal etmek istiyorum"
      }
    ]
  }
}

WhatsApp'ta görünümü

Yarın 10:30 randevunuzu onaylıyor musunuz? 1. Evet, geleceğim 2. İptal etmek istiyorum _Seçmek için numarayı yazın._ Mavi Klinik
200Başarılı yanıt
{
  "status": true,
  "message": "Mesaj gönderim sırasına alındı.",
  "data": {
    "receiver": "905321234567",
    "queue_id": 1284,
    "position": 1,
    "delay_sec": 10
  }
}
400Doğrulama hatası
{
  "status": false,
  "message": "Geçersiz istek.",
  "errors": [
    {
      "msg": "footer is required",
      "param": "data.footer",
      "location": "body"
    }
  ]
}

POSTListe mesajı gönder

Başlıklı, bölümlere ayrılmış seçenek listesi gönderir. Butonlu mesajda olduğu gibi seçenekler numaralı metin olarak iletilir; bölüm başlıkları italik ara başlık olur.

POSThttps://wp.nerzen.com/api/send-listmsg

data alanları

AlanTürAçıklama
data.messagestringzorunluAna metin.
data.titlestringzorunluMesajın en üstündeki kalın başlık.
data.footerstringzorunluAlt not.
data.buttonTextstringzorunluListe düğmesinin metni (uyumluluk için zorunludur).
data.sectionsarrayzorunluEn fazla 10 bölüm: [{"title":"…","rows":[{"title":"…","description":"…"}]}].

Örnek istek

curl -X POST "https://wp.nerzen.com/api/send-listmsg" \
  -H "Content-Type: application/json" \
  -d '{
  "api_key": "API_ANAHTARINIZ",
  "receiver": "905321234567",
  "data": {
    "message": "Size nasıl yardımcı olabiliriz?",
    "title": "Destek menüsü",
    "footer": "Mavi Butik",
    "buttonText": "Seçenekler",
    "sections": [
      {
        "title": "Sipariş",
        "rows": [
          {
            "title": "Kargo takibi",
            "description": "Siparişim nerede?"
          },
          {
            "title": "İade talebi"
          }
        ]
      },
      {
        "title": "Diğer",
        "rows": [
          {
            "title": "Temsilciye bağlan"
          }
        ]
      }
    ]
  }
}'
<?php
$payload = [
    'api_key'  => 'API_ANAHTARINIZ',
    'receiver' => '905321234567',
    'data'     => [
        'message'    => 'Size nasıl yardımcı olabiliriz?',
        'title'      => 'Destek menüsü',
        'footer'     => 'Mavi Butik',
        'buttonText' => 'Seçenekler',
        'sections'   => [
            [
                'title' => 'Sipariş',
                'rows'  => [
                    [
                        'title'       => 'Kargo takibi',
                        'description' => 'Siparişim nerede?',
                    ],
                    [
                        'title' => 'İade talebi',
                    ],
                ],
            ],
            [
                'title' => 'Diğer',
                'rows'  => [
                    [
                        'title' => 'Temsilciye bağlan',
                    ],
                ],
            ],
        ],
    ],
];

$ch = curl_init('https://wp.nerzen.com/api/send-listmsg');
curl_setopt_array($ch, [
    CURLOPT_POST           => true,
    CURLOPT_HTTPHEADER     => ['Content-Type: application/json'],
    CURLOPT_POSTFIELDS     => json_encode($payload, JSON_UNESCAPED_UNICODE),
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_TIMEOUT        => 30,
]);
$response = json_decode(curl_exec($ch), true);
curl_close($ch);

if (!empty($response['status'])) {
    echo 'Tamam: ' . $response['message'];
} else {
    echo 'Hata: ' . ($response['message'] ?? 'bilinmiyor');
}
// Node.js 18+ (yerleşik fetch)
const payload = {
  "api_key": "API_ANAHTARINIZ",
  "receiver": "905321234567",
  "data": {
    "message": "Size nasıl yardımcı olabiliriz?",
    "title": "Destek menüsü",
    "footer": "Mavi Butik",
    "buttonText": "Seçenekler",
    "sections": [
      {
        "title": "Sipariş",
        "rows": [
          {
            "title": "Kargo takibi",
            "description": "Siparişim nerede?"
          },
          {
            "title": "İade talebi"
          }
        ]
      },
      {
        "title": "Diğer",
        "rows": [
          {
            "title": "Temsilciye bağlan"
          }
        ]
      }
    ]
  }
};

const res = await fetch('https://wp.nerzen.com/api/send-listmsg', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify(payload),
});
const json = await res.json();
if (json.status) console.log('Tamam:', json.message, json.data);
else console.error('Hata:', json.message, json.errors || '');
{
  "api_key": "API_ANAHTARINIZ",
  "receiver": "905321234567",
  "data": {
    "message": "Size nasıl yardımcı olabiliriz?",
    "title": "Destek menüsü",
    "footer": "Mavi Butik",
    "buttonText": "Seçenekler",
    "sections": [
      {
        "title": "Sipariş",
        "rows": [
          {
            "title": "Kargo takibi",
            "description": "Siparişim nerede?"
          },
          {
            "title": "İade talebi"
          }
        ]
      },
      {
        "title": "Diğer",
        "rows": [
          {
            "title": "Temsilciye bağlan"
          }
        ]
      }
    ]
  }
}

WhatsApp'ta görünümü

*Destek menüsü* Size nasıl yardımcı olabiliriz? _Sipariş_ 1. Kargo takibi — Siparişim nerede? 2. İade talebi _Diğer_ 3. Temsilciye bağlan _Seçmek için numarayı yazın._ Mavi Butik
200Başarılı yanıt
{
  "status": true,
  "message": "Mesaj gönderim sırasına alındı.",
  "data": {
    "receiver": "905321234567",
    "queue_id": 1284,
    "position": 1,
    "delay_sec": 10
  }
}
400Doğrulama hatası
{
  "status": false,
  "message": "Geçersiz istek.",
  "errors": [
    {
      "msg": "sections is required",
      "param": "data.sections",
      "location": "body"
    }
  ]
}

POSTNumara WhatsApp kullanıyor mu?

Toplu gönderimden önce listenizi temizlemek için bir numaranın WhatsApp hesabı olup olmadığını sorgular. Mesaj hakkınızdan düşmez. GET ile ?api_key=…&number=… biçiminde de çağrılabilir.

POSThttps://wp.nerzen.com/api/check-number
curl -X POST "https://wp.nerzen.com/api/check-number" \
  -H "Content-Type: application/json" \
  -d '{
  "api_key": "API_ANAHTARINIZ",
  "receiver": "905321234567"
}'
{
  "api_key": "API_ANAHTARINIZ",
  "receiver": "905321234567"
}
200Yanıt
{
  "status": true,
  "message": "Numara WhatsApp kullanıyor.",
  "data": {
    "receiver": "905321234567",
    "exists": true
  }
}

GETGrupları listele

Cihazın üye olduğu grupları kimlik, ad ve üye sayısıyla döndürür. Buradaki id değerini mesaj uçlarında receiver olarak kullanabilirsiniz. POST ile de çağrılabilir.

GEThttps://wp.nerzen.com/api/groups?api_key=API_ANAHTARINIZ
200Yanıt
{
  "status": true,
  "message": "OK",
  "data": [
    {
      "id": "[email protected]",
      "name": "Bayi Duyuruları",
      "participants": 248
    }
  ]
}

GETCihaz ve paket durumu

Anahtarın bağlı olduğu cihazın bağlantı durumunu, paket adını, bitiş zamanını (epoch saniye) ve kalan mesaj hakkını döndürür. messages_left: -1 sınırsız demektir. Entegrasyonunuzda sağlık kontrolü için idealdir.

GEThttps://wp.nerzen.com/api/device?api_key=API_ANAHTARINIZ
200Yanıt
{
  "status": true,
  "message": "OK",
  "data": {
    "name": "Satış hattı",
    "phone": "905321234567",
    "connected": true,
    "package": "Profesyonel",
    "expires_at": 1790000000,
    "messages_left": 28750,
    "delay_sec": 10
  }
}

Başarılı yanıtlar

Başarılı her istek HTTP 200 ve "status": true döner. İki olası biçim vardır:

200Anında gönderildi — bekleme süreniz 0 ve kuyruk boşsa
{
  "status": true,
  "message": "Mesaj gönderildi.",
  "data": {
    "receiver": "905321234567",
    "sent": true
  }
}
200Kuyruğa alındı — bekleme süreniz 0'dan büyükse ya da kuyrukta mesaj varsa
{
  "status": true,
  "message": "Mesaj gönderim sırasına alındı.",
  "data": {
    "receiver": "905321234567",
    "queue_id": 1284,
    "position": 3,
    "delay_sec": 10
  }
}

position, mesajın bu cihazın kuyruğundaki sırasıdır. Kuyruğa alınan mesajın sonucu (gönderildi / başarısız) panelde Raporlar sayfasında API servisiyle görünür.

Gönderim sıklığı ve kuyruk

Numaranızı korumak için aynı cihaza gelen API istekleri bir kuyruğa girer. İlk mesaj hemen, sonrakiler Ayarlar → API bekleme alanında seçtiğiniz süre aralığıyla gönderilir (0, 5, 10, 15, 30, 60 veya 120 sn; varsayılan 10 sn). API cevabı gönderimi beklemeden hemen döner.

  • Bekleme 0 ise ve kuyrukta mesaj yoksa mesaj anında gönderilir ve yanıtta sent: true döner.
  • Bir anahtarla dakikada en fazla 120 istek kabul edilir; aşılırsa 429 döner.
  • Mesaj hakkı gönderim anında düşer. Kuyruktaki mesaj gönderilirken cihaz bağlı değilse ya da hakkınız bittiyse mesaj başarısız sayılır ve Raporlar'da nedeniyle görünür.

Hata kodları

Hatalı isteklerde "status": false ve Türkçe/İngilizce bir message döner. Alan doğrulaması, anahtar kontrolünden önce yapılır; yani eksik alan varsa anahtarınız yanlış olsa bile önce doğrulama hatasını görürsünüz.

HTTPmessageNe yapmalı?
400Geçersiz istek. (+ errors dizisi)Zorunlu bir alan eksik ya da hatalı, veya gövde geçerli JSON değil. errors[].param hangi alanın sorunlu olduğunu söyler.
400Invalid API Key.Anahtar yok ya da yanlış. Cihazlar sayfasındaki güncel anahtarı kullanın.
400Cihaz bağlı değil. Panelden cihazınızı bağlayın.Cihazın WhatsApp oturumu kapalı; panelden QR ile yeniden bağlayın.
400Gönderim hatası metniAnında gönderimde WhatsApp tarafında oluşan hata (ör. numara WhatsApp kullanmıyor).
402Paket süreniz doldu. Panelden paketinizi yenileyin.Paketinizi yenileyin; API tekrar çalışır.
402Mesaj limitiniz doldu.30 günlük mesaj hakkınız bitti; paketinizi yükseltin ya da döngünün yenilenmesini bekleyin.
403Paketinizde REST API erişimi yok.API erişimi olan bir pakete geçin.
403Hesap askıya alınmış.Destek ile iletişime geçin.
429Çok fazla istek…Dakikada 120 isteği aştınız; kısa bir süre bekleyip tekrar deneyin.
500Sunucu hatasıGeçici bir sorun. İsteği biraz sonra tekrarlayın, devam ederse destek talebi açın.
400Örnek
{
  "status": false,
  "message": "Geçersiz istek.",
  "errors": [
    {
      "msg": "footer is required",
      "param": "data.footer",
      "location": "body"
    }
  ]
}
{
  "status": false,
  "message": "Invalid API Key."
}

Webhook — gelen mesajları alın

Cihaz ayarlarına bir Webhook URL girdiğinizde, bu cihaza gelen her mesaj adresinize POST ile JSON olarak iletilir. İsterseniz bir gizli anahtar belirleyin; her istekte X-Webhook-Secret başlığında gönderilir, böylece isteğin bizden geldiğini doğrularsınız.

Gelen istek

AlanTürAçıklama
fromstringGönderenin numarası (905…). Grup mesajında mesajı yazan üyenin numarası.
messagestringMesaj metni (medyada açıklama; yoksa boş).
isGroupbooleanMesaj bir gruptan mı geldi?
isMebooleanHer zaman false — kendi gönderdiğiniz mesajlar iletilmez.
pushNamestringGönderenin WhatsApp'ta görünen adı.
chatIdstringSohbet kimliği (…@c.us ya da grup için …@g.us).
groupstring | nullGrup mesajında grup numarası, değilse null.
typestringWhatsApp mesaj türü: chat, image, video, audio, ptt, document, sticker, location…
hasMediabooleanMesajda medya var mı?
timestampnumberMesaj zamanı (epoch saniye).
devicestring | nullMesajı alan cihazın numarası.
{
  "from": "905330001122",
  "message": "merhaba",
  "isGroup": false,
  "isMe": false,
  "pushName": "Ahmet",
  "chatId": "[email protected]",
  "group": null,
  "type": "chat",
  "hasMedia": false,
  "timestamp": 1790000000,
  "device": "905321234567"
}

İstek başlıkları: Content-Type: application/json, User-Agent: NerzenWP-Webhook/1.0 ve (tanımladıysanız) X-Webhook-Secret.

Yanıtınızla otomatik cevap verin

Adresiniz 2xx durum koduyla aşağıdaki JSON'u dönerse içerik müşteriye otomatik cevap olarak gönderilir. data alanı JSON metni (string) ya da doğrudan nesne olabilir. Cevap vermek istemiyorsanız "data": false dönün.

Metin cevabı
{
  "status": "success",
  "data": "{\"message_type\":\"text\",\"message\":{\"message\":\"pong 🏓\"}}"
}
Medya cevabı
{
  "status": "success",
  "data": "{\"message_type\":\"media\",\"message\":{\"media_type\":\"image\",\"url\":\"https://siteniz.com/katalog.jpg\",\"caption\":\"Güncel kataloğumuz\"}}"
}
Webhook her mesajda çağrılır; ancak mesaja akış botu, otomatik yanıtlayıcı ya da AI asistan zaten cevap verdiyse sizin cevabınız gönderilmez (çift cevap olmasın diye). Paket süresi dolmuşsa da otomatik cevap gönderilmez.
  • Adresiniz 10 saniye içinde yanıt vermelidir; yönlendirmeler (3xx) izlenmez.
  • Güvenlik gereği yerel ağ ve iç IP adreslerine (localhost, 10.x, 192.168.x …) webhook gönderilmez; herkese açık bir http(s) adresi kullanın.
  • Cevap mesajları mesaj hakkınızdan düşer ve Raporlar'da Webhook servisiyle görünür.

Örnek webhook

<?php
// webhook.php — Nerzen WP gelen mesaj örneği
$secret = 'GIZLI_ANAHTARINIZ'; // Cihaz ayarlarındaki "Webhook gizli anahtarı"
if ($secret !== '' && ($_SERVER['HTTP_X_WEBHOOK_SECRET'] ?? '') !== $secret) {
    http_response_code(401);
    exit;
}

$in      = json_decode(file_get_contents('php://input'), true) ?: [];
$from    = $in['from'] ?? '';
$text    = mb_strtolower(trim($in['message'] ?? ''), 'UTF-8');
$isGroup = !empty($in['isGroup']);

header('Content-Type: application/json; charset=utf-8');

// Gruplara cevap verme
if ($isGroup) {
    echo json_encode(['status' => 'success', 'data' => false]);
    exit;
}

if ($text === 'ping') {
    $reply = ['message_type' => 'text', 'message' => ['message' => 'pong 🏓']];
} elseif ($text === 'katalog') {
    $reply = ['message_type' => 'media', 'message' => [
        'media_type' => 'file',
        'url'        => 'https://siteniz.com/katalog.pdf',
        'caption'    => 'Güncel kataloğumuz',
    ]];
} else {
    // Bilinmeyen mesaj: kendi sisteminize kaydedin, cevap vermeyin
    file_put_contents(__DIR__ . '/gelen.log', date('c') . " $from: $text\n", FILE_APPEND);
    echo json_encode(['status' => 'success', 'data' => false]);
    exit;
}

echo json_encode(
    ['status' => 'success', 'data' => json_encode($reply, JSON_UNESCAPED_UNICODE)],
    JSON_UNESCAPED_UNICODE
);
// webhook.js — Express ile Nerzen WP gelen mesaj örneği
const express = require('express');
const app = express();
app.use(express.json());

const SECRET = process.env.WEBHOOK_SECRET || '';

app.post('/webhook', (req, res) => {
  if (SECRET && req.get('X-Webhook-Secret') !== SECRET) return res.sendStatus(401);
  const { from, message = '', isGroup } = req.body || {};
  const text = message.trim().toLocaleLowerCase('tr-TR');

  if (isGroup) return res.json({ status: 'success', data: false });

  if (text === 'ping') {
    return res.json({
      status: 'success',
      data: JSON.stringify({ message_type: 'text', message: { message: 'pong 🏓' } }),
    });
  }
  console.log('Yeni mesaj', from, message);
  res.json({ status: 'success', data: false });
});

app.listen(3000);

Eski uçlar (uyumluluk)

Önceki entegrasyonlar (ör. WHMCS modülünün eski sürümleri) için korunan uçlardır. Yeni projelerde yukarıdaki uçları kullanın. Anahtar X-API-Key başlığında gönderilir; yanıt biçimi {"success": true|false, …} şeklindedir.

curl -X POST "https://wp.nerzen.com/api/external/send-message" \
  -H "X-API-Key: API_ANAHTARINIZ" \
  -H "Content-Type: application/json" \
  -d '{"to": "905321234567", "message": "Faturanız oluşturuldu."}'
200Yanıt
{
  "success": true,
  "message": "Mesaj gönderim sırasına alındı",
  "sent_to": "905321234567",
  "queue_id": 1285
}

media_url verilirse message medya açıklaması olur; tür media_mimetype alanından (image/…, video/…, audio/…) belirlenir. Hatalarda {"success": false, "error": "…"} döner.