API dokümanı

Normal kullanıcı

API dokümanı

WhatsApp mesajlarınızı kendi yazılımınızdan gönderin: onaylı şablonlar ve doğrulama kodları, zamanlanmış kampanyalar ve gelen kutusu yanıtları.

Temel URL

https://podimessage.io/api/v1
API anahtarı oluşturun →

Her istekte gönderilen başlıklar

Authorization: Bearer podi_xxxxxxxxxxxxxxxx
Accept: application/json
Content-Type: application/json

Genel bakış

Hesabınız

API anahtarınız hesabınız olarak çalışır: bakiyeniz, bağlı WhatsApp numaralarınız, şablonlarınız, kampanyalarınız ve gelen kutunuz. Numaranızı panelin WhatsApp bağlantısı sayfasından bağlarsınız. Çağrılar en son bağlanan aktif numarayı kullanır; başka bir numara için phone_number_id gönderin.

Kredi ve fiyatlar

API’deki tutarlar (balance, cost, required) panelde gördüğünüz Podi cinsinden tam sayılardır: hesap para biriminizin 1 birimi 1.000 Podi eder.

Yanıtlar birimi currency alanında PODI olarak belirtir.

  • Gönderilen her şablon mesajı (doğrulama kodları ve kampanya mesajları dahil) için bakiyenizden hesabınızın mesaj fiyatı düşülür. messages/send yanıtı bunu cost, kalan bakiyeyi balance olarak döndürür.
  • WhatsApp’ın gönderim anında reddettiği mesaj ücretlendirilmez: ücret iade edilir. WhatsApp’ın kabul ettiği mesaj, daha sonra failed olarak bildirilse bile ücretli kalır. 24 saatlik yanıt süresi içindeki serbest metin yanıtları (gelen kutusu yanıtları) ücretlendirilmez.
  • Bakiye panelin Bakiye sayfasından yüklenir; API bakiye yüklemez. Güncel bakiyeyi GET /api/v1/me döndürür.

Kimlik doğrulama

API anahtarınızı her istekte Authorization: Bearer … başlığıyla gönderin. Anahtarları panelin API & OTP sayfasında hesap sahibi oluşturur ve iptal eder. Anahtarı yalnızca sunucunuzda tutun, tarayıcıya veya mobil uygulamaya koymayın.

İstek sınırları

  • Mesaj, şablon, kampanya ve gelen kutusu uç noktaları: hesap başına dakikada 60 istek.

Yanıtlarda X-RateLimit-Limit ve X-RateLimit-Remaining başlıkları bulunur. Sınır aşılırsa saniye cinsinden Retry-After başlığıyla 429 alırsınız.

Biçimler

  • Content-Type: application/json ve Accept: application/json ile JSON gönderin.
  • Zamanlar saat farkıyla birlikte ISO 8601 biçimindedir, örneğin 2026-11-02T10:15:00+03:00. Sorgu dizesinde + işaretini %2B olarak kodlayın.
  • Telefon numaraları ülke koduyla birlikte, + ve baştaki 0 olmadan yalnızca rakamdır: 905321234567.
  • Listeler per_page (1–100, varsayılan 50) ve page alır; current_page, last_page ve total içeren meta döndürür. Sohbet mesajları ise id ile sayfalanır.

Hatalar

Hatalar message alanı olan JSON’dur; bazılarında makinenin okuyacağı bir code ve başka alanlar da bulunur. Metne değil, HTTP durum koduna ve code alanına göre işlem yapın: mesajlar insanlar için yazılır ve değişebilir. Mesajlar her zaman platformun varsayılan dilindedir; Accept-Language başlığı dili değiştirmez. Gönderim uç noktalarında kontroller şu sırayla yapılır: girdi (422), aktif WhatsApp numarası (409), kredi (402).

200 Başarılı.
201 Oluşturuldu.
204 Silindi; gövde yok.
401 API anahtarı eksik veya tanınmıyor.
402 Kredi yetersiz. Gövdede balance ve biliniyorsa required bulunur.
403 Hesap askıya alınmış.
404 Bilinmeyen ya da başka bir hesaba ait id.
405 Yol doğru ama HTTP yöntemi yanlış; izin verilen yöntemler Allow başlığındadır.
409 Aktif WhatsApp numarası yok ya da aynı tekrar anahtarıyla gönderilen istek hâlâ işleniyor.
422 Geçersiz girdi ya da WhatsApp isteği reddetti (message ve code alanlarına bakın).
429 Çok fazla istek.
502 WhatsApp medya dosyasını vermedi.

Geçersiz girdi, hatalı alanları errors altında listeleyen 422 döndürür:

# HTTP 422
{
  "message": "amount 10 değerinin katı olmalıdır.",
  "errors": {
    "amount": [
      "amount 10 değerinin katı olmalıdır."
    ]
  }
}

Güvenli tekrar (idempotency)

Ağ hataları olur. Aşağıdaki uç noktalarda her işlemle birlikte benzersiz bir anahtar gönderin: aynı anahtarla 24 saat içinde tekrarlanan istek, işi ikinci kez yapmak yerine ilk sonucu döndürür.

  • messages/send: gövdede idempotency_key, hesap bazında. Yalnızca başarılı gönderimler hatırlanır; başarısız bir gönderimi aynı anahtarla yeniden deneyebilirsiniz. Aynı anahtar başka bir alıcı ya da şablonla gelirse code: idempotency_key_reused ile 422 döner.
  • conversations/{id}/reply: Idempotency-Key başlığı (veya gövdede idempotency_key), sohbet bazında. Tekrarlanan yanıtta Idempotent-Replayed: true başlığı bulunur; ilk istek hâlâ sürüyorsa code: in_progress ile 409 alırsınız.
  • otp/send ve campaigns anahtar almaz: yeniden denemeden önce sonucu kontrol edin.

Hızlı başlangıç

API anahtarınızdan çift yönlü bir sohbete beş adımda ulaşın.

  1. 1

    API anahtarı oluşturun

    Panelde API & OTP sayfasından bir anahtar oluşturun. Anahtar yalnızca bir kez gösterilir; sunucunuzda saklayın. WhatsApp numaranız bağlı ve en az bir şablonunuz onaylı olmalıdır.

  2. 2

    Anahtarınızı doğrulayın

    İsteğin hangi hesap olarak çalıştığını ve bakiyenizi döndürür.

    Örnek istek — GET /api/v1/me

    curl 'https://podimessage.io/api/v1/me' \
      -H 'Authorization: Bearer podi_xxxxxxxxxxxxxxxx' \
      -H 'Accept: application/json'
    <?php
    $ch = curl_init('https://podimessage.io/api/v1/me');
    curl_setopt_array($ch, [
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_HTTPHEADER => [
            'Authorization: Bearer podi_xxxxxxxxxxxxxxxx',
            'Accept: application/json',
        ],
    ]);
    $response = json_decode(curl_exec($ch), true);
    $status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);
    const res = await fetch('https://podimessage.io/api/v1/me', {
      headers: {
        Authorization: 'Bearer podi_xxxxxxxxxxxxxxxx',
        Accept: 'application/json',
      },
    });
    const data = await res.json();
  3. 3

    Onaylı bir şablon gönderin

    Sizin başlattığınız mesajlar Meta’nın onayladığı bir şablonla gönderilmelidir (şablonu panelden ya da POST /api/v1/templates ile oluşturabilirsiniz). Yanıt, ücreti ve yeni bakiyenizi gösterir.

    Örnek istek — POST /api/v1/messages/send

    curl -X POST 'https://podimessage.io/api/v1/messages/send' \
      -H 'Authorization: Bearer podi_xxxxxxxxxxxxxxxx' \
      -H 'Accept: application/json' \
      -H 'Content-Type: application/json' \
      -d '{
        "to": "905321234567",
        "template": "appointment_reminder",
        "language": "tr",
        "params": [
          "Ayşe",
          "12.11.2026 14:30"
        ],
        "idempotency_key": "reminder-8812"
      }'
    <?php
    $ch = curl_init('https://podimessage.io/api/v1/messages/send');
    curl_setopt_array($ch, [
        CURLOPT_POST => true,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_HTTPHEADER => [
            'Authorization: Bearer podi_xxxxxxxxxxxxxxxx',
            'Accept: application/json',
            'Content-Type: application/json',
        ],
        CURLOPT_POSTFIELDS => json_encode([
            'to' => '905321234567',
            'template' => 'appointment_reminder',
            'language' => 'tr',
            'params' => ['Ayşe', '12.11.2026 14:30'],
            'idempotency_key' => 'reminder-8812',
        ]),
    ]);
    $response = json_decode(curl_exec($ch), true);
    $status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);
    const res = await fetch('https://podimessage.io/api/v1/messages/send', {
      method: 'POST',
      headers: {
        Authorization: 'Bearer podi_xxxxxxxxxxxxxxxx',
        Accept: 'application/json',
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        to: '905321234567',
        template: 'appointment_reminder',
        language: 'tr',
        params: ['Ayşe', '12.11.2026 14:30'],
        idempotency_key: 'reminder-8812',
      }),
    });
    const data = await res.json();
  4. 4

    Yanıtları alın

    Kişi yanıt yazdığında sohbet güncellenir. GET /api/v1/conversations adresini updated_since ile yoklayın, sohbetin yeni mesajlarını after_id ile alın.

    Örnek istek — GET /api/v1/conversations

    curl 'https://podimessage.io/api/v1/conversations?status=pool&updated_since=2026-11-02T10%3A00%3A00%2B03%3A00&per_page=20' \
      -H 'Authorization: Bearer podi_xxxxxxxxxxxxxxxx' \
      -H 'Accept: application/json'
    <?php
    $ch = curl_init('https://podimessage.io/api/v1/conversations?status=pool&updated_since=2026-11-02T10%3A00%3A00%2B03%3A00&per_page=20');
    curl_setopt_array($ch, [
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_HTTPHEADER => [
            'Authorization: Bearer podi_xxxxxxxxxxxxxxxx',
            'Accept: application/json',
        ],
    ]);
    $response = json_decode(curl_exec($ch), true);
    $status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);
    const res = await fetch('https://podimessage.io/api/v1/conversations?status=pool&updated_since=2026-11-02T10%3A00%3A00%2B03%3A00&per_page=20', {
      headers: {
        Authorization: 'Bearer podi_xxxxxxxxxxxxxxxx',
        Accept: 'application/json',
      },
    });
    const data = await res.json();
  5. 5

    Yanıtlayın

    Kişinin son mesajından sonraki 24 saat içinde serbest metinle yanıt verebilirsiniz. Bu yanıtlardan bakiye düşülmez; Meta ise her numarada ayda ilk 1.000 hizmet mesajından sonra kendi ücretini alır.

    Örnek istek — POST /api/v1/conversations/{conversation}/reply

    curl -X POST 'https://podimessage.io/api/v1/conversations/12/reply' \
      -H 'Authorization: Bearer podi_xxxxxxxxxxxxxxxx' \
      -H 'Idempotency-Key: reply-77f1c2' \
      -H 'Accept: application/json' \
      -H 'Content-Type: application/json' \
      -d '{
        "text": "Merhaba Ayşe, yarın 14:30 için randevunuzu oluşturduk."
      }'
    <?php
    $ch = curl_init('https://podimessage.io/api/v1/conversations/12/reply');
    curl_setopt_array($ch, [
        CURLOPT_POST => true,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_HTTPHEADER => [
            'Authorization: Bearer podi_xxxxxxxxxxxxxxxx',
            'Idempotency-Key: reply-77f1c2',
            'Accept: application/json',
            'Content-Type: application/json',
        ],
        CURLOPT_POSTFIELDS => json_encode([
            'text' => 'Merhaba Ayşe, yarın 14:30 için randevunuzu oluşturduk.',
        ]),
    ]);
    $response = json_decode(curl_exec($ch), true);
    $status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);
    const res = await fetch('https://podimessage.io/api/v1/conversations/12/reply', {
      method: 'POST',
      headers: {
        Authorization: 'Bearer podi_xxxxxxxxxxxxxxxx',
        'Idempotency-Key': 'reply-77f1c2',
        Accept: 'application/json',
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        text: 'Merhaba Ayşe, yarın 14:30 için randevunuzu oluşturduk.',
      }),
    });
    const data = await res.json();

Mesajlar ve şablonlar

Şablon ve doğrulama kodu gönderme, şablon yönetimi ve kampanyalar. Tutarlar PODI olarak döner.

Kampanya nesnesi
id integer
Kampanya kimliği.
name string
Kampanya adı.
template string
Şablon adı.
language string
Şablon dili.
category string
Ücretlendirme kategorisi: marketing, utility veya authentication.
status string
scheduled, queued, processing, completed, failed veya cancelled.
scheduled_at string|null
Planlanan başlangıç; hemen gönderildiyse null.
total_recipients integer
Alıcı sayısı.
sent integer
WhatsApp’ın kabul ettiği mesajlar.
failed integer
Gönderilemeyen mesajlar.
delivered integer
Telefona teslim edilen mesajlar.
read integer
Okunan mesajlar.
started_at string|null
Gönderimin başladığı zaman.
completed_at string|null
Bütün alıcıların işlendiği zaman.
GET /api/v1/me Anahtarınızı doğrulayın: isteğin hangi hesap olarak çalıştığını ve bakiyesini döndürür.
API anahtarı

Örnek istek

curl 'https://podimessage.io/api/v1/me' \
  -H 'Authorization: Bearer podi_xxxxxxxxxxxxxxxx' \
  -H 'Accept: application/json'
<?php
$ch = curl_init('https://podimessage.io/api/v1/me');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer podi_xxxxxxxxxxxxxxxx',
        'Accept: application/json',
    ],
]);
$response = json_decode(curl_exec($ch), true);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
const res = await fetch('https://podimessage.io/api/v1/me', {
  headers: {
    Authorization: 'Bearer podi_xxxxxxxxxxxxxxxx',
    Accept: 'application/json',
  },
});
const data = await res.json();

Yanıt · HTTP 200

{
  "id": 57,
  "name": "Pati Klinik",
  "email": "info@example.com",
  "balance": 50000,
  "currency": "PODI"
}
POST /api/v1/messages/send Bir numaraya onaylı bir şablon gönderir. Mesaj hemen gönderilir ve ücreti bakiyenizden düşülür.
API anahtarı

Son 24 saatte yazmış bir kişiyi yanıtlamak için bunun yerine gelen kutusundaki reply uç noktasını kullanın: bakiyeden ücret düşülmez.

Parametreler

to
string · gövde zorunlu
Alıcı numarası: ülke koduyla birlikte yalnızca rakam, en fazla 20 karakter.
template
string · gövde zorunlu
Hesabınızdaki onaylı bir şablonun adı.
language
string · gövde
tr veya en_US gibi şablon dil kodu. Varsayılan en_US olduğundan Türkçe şablonlarda mutlaka belirtin.
params
array · gövde
Şablon gövdesindeki {{1}}, {{2}}… alanlarını sırasıyla dolduran en fazla 10 metin (her biri en fazla 1.000 karakter).
phone_number_id
string · gövde
Bağlı numaralarınızdan hangisinin kullanılacağı. Varsayılan: en son bağlanan aktif numara.
idempotency_key
string · gövde
İsteğe bağlı benzersiz anahtar, en fazla 128 karakter. 24 saat içinde tekrarlanırsa ilk başarılı sonuç döner ve hiçbir şey gönderilmez.

Örnek istek

curl -X POST 'https://podimessage.io/api/v1/messages/send' \
  -H 'Authorization: Bearer podi_xxxxxxxxxxxxxxxx' \
  -H 'Accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
    "to": "905321234567",
    "template": "appointment_reminder",
    "language": "tr",
    "params": [
      "Ayşe",
      "12.11.2026 14:30"
    ],
    "idempotency_key": "reminder-8812"
  }'
<?php
$ch = curl_init('https://podimessage.io/api/v1/messages/send');
curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer podi_xxxxxxxxxxxxxxxx',
        'Accept: application/json',
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode([
        'to' => '905321234567',
        'template' => 'appointment_reminder',
        'language' => 'tr',
        'params' => ['Ayşe', '12.11.2026 14:30'],
        'idempotency_key' => 'reminder-8812',
    ]),
]);
$response = json_decode(curl_exec($ch), true);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
const res = await fetch('https://podimessage.io/api/v1/messages/send', {
  method: 'POST',
  headers: {
    Authorization: 'Bearer podi_xxxxxxxxxxxxxxxx',
    Accept: 'application/json',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    to: '905321234567',
    template: 'appointment_reminder',
    language: 'tr',
    params: ['Ayşe', '12.11.2026 14:30'],
    idempotency_key: 'reminder-8812',
  }),
});
const data = await res.json();

Yanıt · HTTP 200

{
  "status": "sent",
  "message_id": 1234,
  "wamid": "wamid.HBgMOTA1MzIxMjM0NTY3FQIAERgSQ0Y2…",
  "to": "905321234567",
  "cost": 20,
  "currency": "PODI",
  "balance": 49980
}

Diğer yanıtlar

402 Bakiyeniz mesajın ücretine yetmiyor; hiçbir şey gönderilmedi.
{
  "message": "Bakiye yetersiz. Bakiye yükleyip isteği tekrarlayın. Yanıttaki balance alanı mevcut bakiyeyi, required alanı (varsa) gereken miktarı gösterir.",
  "required": 20,
  "balance": 0,
  "currency": "PODI"
}
409 Hesabınızda aktif bir WhatsApp numarası yok (ya da belirttiğiniz phone_number_id aktif değil).
{
  "message": "Bağlı ve aktif bir WhatsApp numarası yok. Panelden WhatsApp bağlantısını kurun."
}
422 WhatsApp mesajı reddetti: code Meta’nın hata kodu, message_id başarısız kaydın kimliğidir. Ücret iade edilir.
{
  "message": "(#132001) Template name does not exist in the translation",
  "code": "132001",
  "message_id": 1234
}
POST /api/v1/otp/send Onaylı bir Kimlik Doğrulama (Authentication) şablonuyla doğrulama kodu gönderir. Kodu siz üretir ve siz kontrol edersiniz.
API anahtarı

Parametreler

to
string · gövde zorunlu
Alıcı numarası: ülke koduyla birlikte yalnızca rakam, en fazla 20 karakter.
template
string · gövde zorunlu
Kimlik Doğrulama (Authentication) kategorisindeki onaylı bir şablonun adı.
code
string · gövde zorunlu
Ürettiğiniz kod, en fazla 30 karakter. Şablon gövdesine ve düğmesine yerleştirilir.
language
string · gövde
tr veya en_US gibi şablon dil kodu. Varsayılan en_US olduğundan Türkçe şablonlarda mutlaka belirtin.
include_button
boolean · gövde
Varsayılan true. Şablonda düğme yoksa false gönderin.
button_sub_type
string · gövde
url (varsayılan; tek dokunuşla doldurma ve kod kopyalama düğmelerinde çalışır) veya copy_code.
phone_number_id
string · gövde
Bağlı numaralarınızdan hangisinin kullanılacağı. Varsayılan: en son bağlanan aktif numara.

Örnek istek

curl -X POST 'https://podimessage.io/api/v1/otp/send' \
  -H 'Authorization: Bearer podi_xxxxxxxxxxxxxxxx' \
  -H 'Accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
    "to": "905321234567",
    "template": "login_code",
    "language": "tr",
    "code": "482913"
  }'
<?php
$ch = curl_init('https://podimessage.io/api/v1/otp/send');
curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer podi_xxxxxxxxxxxxxxxx',
        'Accept: application/json',
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode([
        'to' => '905321234567',
        'template' => 'login_code',
        'language' => 'tr',
        'code' => '482913',
    ]),
]);
$response = json_decode(curl_exec($ch), true);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
const res = await fetch('https://podimessage.io/api/v1/otp/send', {
  method: 'POST',
  headers: {
    Authorization: 'Bearer podi_xxxxxxxxxxxxxxxx',
    Accept: 'application/json',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    to: '905321234567',
    template: 'login_code',
    language: 'tr',
    code: '482913',
  }),
});
const data = await res.json();

Yanıt · HTTP 200

{
  "status": "sent",
  "message_id": 1234,
  "wamid": "wamid.HBgMOTA1MzIxMjM0NTY3FQIAERgSQ0Y2…",
  "to": "905321234567",
  "cost": 20,
  "currency": "PODI",
  "balance": 49980
}

Diğer yanıtlar

402 Bakiyeniz mesajın ücretine yetmiyor; hiçbir şey gönderilmedi.
409 Hesabınızda aktif bir WhatsApp numarası yok (ya da belirttiğiniz phone_number_id aktif değil).
{
  "message": "Bağlı ve aktif bir WhatsApp numarası yok. Panelden WhatsApp bağlantısını kurun."
}
422 WhatsApp mesajı reddetti: code Meta’nın hata kodu, message_id başarısız kaydın kimliğidir. Ücret iade edilir.
GET /api/v1/templates Hesabınızın şablonları, Meta’nın döndürdüğü hâliyle (en fazla 5 dakika önbelleklenir).
API anahtarı

Parametreler

status
string · sorgu
ALL (varsayılan), APPROVED, PENDING, REJECTED, PAUSED veya DISABLED.
phone_number_id
string · sorgu
Bağlı numaralarınızdan hangisinin kullanılacağı. Varsayılan: en son bağlanan aktif numara.

Örnek istek

curl 'https://podimessage.io/api/v1/templates?status=APPROVED' \
  -H 'Authorization: Bearer podi_xxxxxxxxxxxxxxxx' \
  -H 'Accept: application/json'
<?php
$ch = curl_init('https://podimessage.io/api/v1/templates?status=APPROVED');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer podi_xxxxxxxxxxxxxxxx',
        'Accept: application/json',
    ],
]);
$response = json_decode(curl_exec($ch), true);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
const res = await fetch('https://podimessage.io/api/v1/templates?status=APPROVED', {
  headers: {
    Authorization: 'Bearer podi_xxxxxxxxxxxxxxxx',
    Accept: 'application/json',
  },
});
const data = await res.json();

Yanıt · HTTP 200

{
  "data": [
    {
      "id": "1489022265523517",
      "name": "appointment_reminder",
      "language": "tr",
      "category": "UTILITY",
      "components": [
        {
          "type": "BODY",
          "text": "Merhaba {{1}}, {{2}} tarihli randevunuzu hatırlatırız.",
          "example": {
            "body_text": [
              [
                "Ayşe",
                "12.11.2026 14:30"
              ]
            ]
          }
        }
      ],
      "status": "APPROVED",
      "rejected_reason": "NONE"
    }
  ]
}

Diğer yanıtlar

409 Hesabınızda aktif bir WhatsApp numarası yok (ya da belirttiğiniz phone_number_id aktif değil).
422 WhatsApp isteği reddetti; code Meta’nın hata kodudur.
POST /api/v1/templates Yeni bir şablonu Meta’nın incelemesine gönderir. Şablon PENDING olarak başlar; sonucunu GET /api/v1/templates ile izleyin.
API anahtarı

Parametreler

name
string · gövde zorunlu
Küçük harf, rakam ve _; en fazla 512 karakter.
language
string · gövde zorunlu
tr gibi dil kodu.
category
string · gövde zorunlu
MARKETING, UTILITY veya AUTHENTICATION.
components
array · gövde zorunlu
Meta’nın şablon biçiminde en fazla 10 bileşen (başlık, gövde, alt bilgi, düğmeler). Gövdedeki değişkenler için example gerekir.
phone_number_id
string · gövde
Bağlı numaralarınızdan hangisinin kullanılacağı. Varsayılan: en son bağlanan aktif numara.

Örnek istek

curl -X POST 'https://podimessage.io/api/v1/templates' \
  -H 'Authorization: Bearer podi_xxxxxxxxxxxxxxxx' \
  -H 'Accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
    "name": "appointment_reminder",
    "language": "tr",
    "category": "UTILITY",
    "components": [
      {
        "type": "BODY",
        "text": "Merhaba {{1}}, {{2}} tarihli randevunuzu hatırlatırız.",
        "example": {
          "body_text": [
            [
              "Ayşe",
              "12.11.2026 14:30"
            ]
          ]
        }
      }
    ]
  }'
<?php
$ch = curl_init('https://podimessage.io/api/v1/templates');
curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer podi_xxxxxxxxxxxxxxxx',
        'Accept: application/json',
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode([
        'name' => 'appointment_reminder',
        'language' => 'tr',
        'category' => 'UTILITY',
        'components' => [
            [
                'type' => 'BODY',
                'text' => 'Merhaba {{1}}, {{2}} tarihli randevunuzu hatırlatırız.',
                'example' => [
                    'body_text' => [
                        ['Ayşe', '12.11.2026 14:30'],
                    ],
                ],
            ],
        ],
    ]),
]);
$response = json_decode(curl_exec($ch), true);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
const res = await fetch('https://podimessage.io/api/v1/templates', {
  method: 'POST',
  headers: {
    Authorization: 'Bearer podi_xxxxxxxxxxxxxxxx',
    Accept: 'application/json',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    name: 'appointment_reminder',
    language: 'tr',
    category: 'UTILITY',
    components: [
      {
        type: 'BODY',
        text: 'Merhaba {{1}}, {{2}} tarihli randevunuzu hatırlatırız.',
        example: {
          body_text: [
            ['Ayşe', '12.11.2026 14:30'],
          ],
        },
      },
    ],
  }),
});
const data = await res.json();

Yanıt · HTTP 201

{
  "id": "1489022265523517",
  "status": "PENDING",
  "category": "UTILITY"
}

Diğer yanıtlar

409 Hesabınızda aktif bir WhatsApp numarası yok (ya da belirttiğiniz phone_number_id aktif değil).
422 WhatsApp isteği reddetti; code Meta’nın hata kodudur.
DELETE /api/v1/templates/{name} Bir şablonu Meta’da siler.
API anahtarı

Parametreler

name
string · yol zorunlu
Şablon adı. Bu ada sahip şablonun bütün dilleri silinir.
phone_number_id
string · sorgu
Bağlı numaralarınızdan hangisinin kullanılacağı. Varsayılan: en son bağlanan aktif numara.

Örnek istek

curl -X DELETE 'https://podimessage.io/api/v1/templates/appointment_reminder' \
  -H 'Authorization: Bearer podi_xxxxxxxxxxxxxxxx' \
  -H 'Accept: application/json'
<?php
$ch = curl_init('https://podimessage.io/api/v1/templates/appointment_reminder');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'DELETE',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer podi_xxxxxxxxxxxxxxxx',
        'Accept: application/json',
    ],
]);
$response = json_decode(curl_exec($ch), true);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
const res = await fetch('https://podimessage.io/api/v1/templates/appointment_reminder', {
  method: 'DELETE',
  headers: {
    Authorization: 'Bearer podi_xxxxxxxxxxxxxxxx',
    Accept: 'application/json',
  },
});
const data = await res.json();

Yanıt · HTTP 200

{
  "status": "deleted",
  "name": "appointment_reminder"
}

Diğer yanıtlar

409 Hesabınızda aktif bir WhatsApp numarası yok (ya da belirttiğiniz phone_number_id aktif değil).
422 WhatsApp isteği reddetti; code Meta’nın hata kodudur.
POST /api/v1/campaigns Onaylı bir şablonu en fazla 5.000 alıcıya hemen ya da scheduled_at zamanında gönderir. Bakiye baştan kontrol edilir; her mesajın ücreti gönderildiğinde düşülür.
API anahtarı

Hemen gönderilen kampanya queued → processing → completed, zamanlanmış kampanya scheduled → processing → completed sırasıyla ilerler; planlanan anda bakiye yetmezse failed olur. Zamanlanmış kampanyayı başlamadan DELETE /api/v1/campaigns/{campaign} ile iptal edebilir, ilerlemeyi GET /api/v1/campaigns/{campaign} ile izleyebilirsiniz.

Parametreler

name
string · gövde zorunlu
Kampanyaya verdiğiniz ad, en fazla 120 karakter.
template
string · gövde zorunlu
Onaylı bir şablonun adı.
language
string · gövde
Şablon dili. Belirtilmezse bu ada sahip ilk şablon kullanılır.
recipients
array · gövde zorunlu
1 ile 5.000 arasında alıcı.
recipients.*.phone
string · gövde zorunlu
Ülke koduyla numara, en fazla 20 karakter; boşluk ve işaretler silinir.
recipients.*.name
string · gövde
İsteğe bağlı, en fazla 120 karakter.
recipients.*.params
array · gövde
Bu alıcı için {{1}}, {{2}}… alanlarını dolduran en fazla 10 metin.
scheduled_at
date · gövde
İsteğe bağlı, ileri bir zaman (ISO 8601). Belirtilmezse gönderim hemen başlar.
phone_number_id
string · gövde
Bağlı numaralarınızdan hangisinin kullanılacağı. Varsayılan: en son bağlanan aktif numara.

Örnek istek

curl -X POST 'https://podimessage.io/api/v1/campaigns' \
  -H 'Authorization: Bearer podi_xxxxxxxxxxxxxxxx' \
  -H 'Accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
    "name": "Kasım aşı hatırlatmaları",
    "template": "appointment_reminder",
    "language": "tr",
    "recipients": [
      {
        "phone": "905321234567",
        "name": "Ayşe",
        "params": [
          "Ayşe",
          "12.11.2026 14:30"
        ]
      },
      {
        "phone": "905339876543",
        "name": "Mehmet",
        "params": [
          "Mehmet",
          "13.11.2026 10:00"
        ]
      }
    ],
    "scheduled_at": "2026-11-10T09:00:00+03:00"
  }'
<?php
$ch = curl_init('https://podimessage.io/api/v1/campaigns');
curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer podi_xxxxxxxxxxxxxxxx',
        'Accept: application/json',
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode([
        'name' => 'Kasım aşı hatırlatmaları',
        'template' => 'appointment_reminder',
        'language' => 'tr',
        'recipients' => [
            [
                'phone' => '905321234567',
                'name' => 'Ayşe',
                'params' => ['Ayşe', '12.11.2026 14:30'],
            ],
            [
                'phone' => '905339876543',
                'name' => 'Mehmet',
                'params' => ['Mehmet', '13.11.2026 10:00'],
            ],
        ],
        'scheduled_at' => '2026-11-10T09:00:00+03:00',
    ]),
]);
$response = json_decode(curl_exec($ch), true);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
const res = await fetch('https://podimessage.io/api/v1/campaigns', {
  method: 'POST',
  headers: {
    Authorization: 'Bearer podi_xxxxxxxxxxxxxxxx',
    Accept: 'application/json',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    name: 'Kasım aşı hatırlatmaları',
    template: 'appointment_reminder',
    language: 'tr',
    recipients: [
      {
        phone: '905321234567',
        name: 'Ayşe',
        params: ['Ayşe', '12.11.2026 14:30'],
      },
      {
        phone: '905339876543',
        name: 'Mehmet',
        params: ['Mehmet', '13.11.2026 10:00'],
      },
    ],
    scheduled_at: '2026-11-10T09:00:00+03:00',
  }),
});
const data = await res.json();

Yanıt · HTTP 201

{
  "id": 7,
  "name": "Kasım aşı hatırlatmaları",
  "template": "appointment_reminder",
  "language": "tr",
  "category": "utility",
  "status": "scheduled",
  "scheduled_at": "2026-11-10T09:00:00+03:00",
  "total_recipients": 2,
  "sent": 0,
  "failed": 0,
  "delivered": 0,
  "read": 0,
  "started_at": null,
  "completed_at": null
}

Diğer yanıtlar

402 Bakiyeniz bütün alıcılara yetmiyor.
{
  "message": "Bakiye yetersiz. Bakiye yükleyip isteği tekrarlayın. Yanıttaki balance alanı mevcut bakiyeyi, required alanı (varsa) gereken miktarı gösterir.",
  "required": 40,
  "balance": 20,
  "currency": "PODI"
}
409 Hesabınızda aktif bir WhatsApp numarası yok (ya da belirttiğiniz phone_number_id aktif değil).
422 Bu ada (ve dile) sahip onaylı bir şablon yok.
{
  "message": "Bu adla (ve gönderildiyse bu dilde) onaylı bir şablon yok. template ve language değerlerini kontrol edin."
}
GET /api/v1/campaigns/{campaign} Bir kampanya ve ilerlemesi.
API anahtarı

Parametreler

campaign
integer · yol zorunlu
Kampanyanın id değeri.

Örnek istek

curl 'https://podimessage.io/api/v1/campaigns/7' \
  -H 'Authorization: Bearer podi_xxxxxxxxxxxxxxxx' \
  -H 'Accept: application/json'
<?php
$ch = curl_init('https://podimessage.io/api/v1/campaigns/7');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer podi_xxxxxxxxxxxxxxxx',
        'Accept: application/json',
    ],
]);
$response = json_decode(curl_exec($ch), true);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
const res = await fetch('https://podimessage.io/api/v1/campaigns/7', {
  headers: {
    Authorization: 'Bearer podi_xxxxxxxxxxxxxxxx',
    Accept: 'application/json',
  },
});
const data = await res.json();

Yanıt · HTTP 200

{
  "id": 7,
  "name": "Kasım aşı hatırlatmaları",
  "template": "appointment_reminder",
  "language": "tr",
  "category": "utility",
  "status": "scheduled",
  "scheduled_at": "2026-11-10T09:00:00+03:00",
  "total_recipients": 2,
  "sent": 0,
  "failed": 0,
  "delivered": 0,
  "read": 0,
  "started_at": null,
  "completed_at": null
}

Diğer yanıtlar

404 Bu hesapta böyle bir kampanya yok.
{
  "message": "Kampanya bulunamadı."
}
GET /api/v1/campaigns Kampanyalarınız (panelden ve API’den açılanlar), en yeni başta.
API anahtarı

Parametreler

status
string · sorgu
Yalnızca bu durumdaki kampanyalar: scheduled, queued, processing, completed, failed veya cancelled.
per_page
integer · sorgu
1–100, varsayılan 50.
page
integer · sorgu
Sayfa numarası, varsayılan 1.

Örnek istek

curl 'https://podimessage.io/api/v1/campaigns?status=scheduled&per_page=20' \
  -H 'Authorization: Bearer podi_xxxxxxxxxxxxxxxx' \
  -H 'Accept: application/json'
<?php
$ch = curl_init('https://podimessage.io/api/v1/campaigns?status=scheduled&per_page=20');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer podi_xxxxxxxxxxxxxxxx',
        'Accept: application/json',
    ],
]);
$response = json_decode(curl_exec($ch), true);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
const res = await fetch('https://podimessage.io/api/v1/campaigns?status=scheduled&per_page=20', {
  headers: {
    Authorization: 'Bearer podi_xxxxxxxxxxxxxxxx',
    Accept: 'application/json',
  },
});
const data = await res.json();

Yanıt · HTTP 200

{
  "data": [
    {
      "id": 7,
      "name": "Kasım aşı hatırlatmaları",
      "template": "appointment_reminder",
      "language": "tr",
      "category": "utility",
      "status": "scheduled",
      "scheduled_at": "2026-11-10T09:00:00+03:00",
      "total_recipients": 2,
      "sent": 0,
      "failed": 0,
      "delivered": 0,
      "read": 0,
      "started_at": null,
      "completed_at": null
    }
  ],
  "meta": {
    "current_page": 1,
    "last_page": 1,
    "total": 1
  }
}
DELETE /api/v1/campaigns/{campaign} Planlanmış bir kampanyayı başlamadan iptal eder: hiçbir mesaj gönderilmez ve bakiyeden bir şey düşülmez.
API anahtarı

Yalnızca scheduled durumundaki kampanya iptal edilebilir. Planlanan zaman gelince kampanya processing olur ve artık durdurulamaz; iptali bundan önce yapın. İptal başarılı olduysa hiçbir mesaj gönderilmez.

Parametreler

campaign
integer · yol zorunlu
Kampanyanın id değeri.

Örnek istek

curl -X DELETE 'https://podimessage.io/api/v1/campaigns/7' \
  -H 'Authorization: Bearer podi_xxxxxxxxxxxxxxxx' \
  -H 'Accept: application/json'
<?php
$ch = curl_init('https://podimessage.io/api/v1/campaigns/7');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'DELETE',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer podi_xxxxxxxxxxxxxxxx',
        'Accept: application/json',
    ],
]);
$response = json_decode(curl_exec($ch), true);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
const res = await fetch('https://podimessage.io/api/v1/campaigns/7', {
  method: 'DELETE',
  headers: {
    Authorization: 'Bearer podi_xxxxxxxxxxxxxxxx',
    Accept: 'application/json',
  },
});
const data = await res.json();

Yanıt · HTTP 200

{
  "id": 7,
  "name": "Kasım aşı hatırlatmaları",
  "template": "appointment_reminder",
  "language": "tr",
  "category": "utility",
  "status": "cancelled",
  "scheduled_at": "2026-11-10T09:00:00+03:00",
  "total_recipients": 2,
  "sent": 0,
  "failed": 0,
  "delivered": 0,
  "read": 0,
  "started_at": null,
  "completed_at": null
}

Diğer yanıtlar

404 Bu hesapta böyle bir kampanya yok.
409 Kampanya artık planlanmış değil (başladı, bitti ya da zaten iptal edildi); status güncel durumunu gösterir. Başlamış bir kampanya durdurulamaz.
{
  "message": "Kampanya artık planlanmış durumda değil: başladı, bitti ya da zaten iptal edildi; iptal edilemez.",
  "code": "not_scheduled",
  "status": "processing"
}

Gelen kutusu

WhatsApp sohbetlerinizi okuyun ve kendi yazılımınızdan yanıtlayın.

24 saatlik yanıt süresi

WhatsApp, işletmelerin serbest metni yalnızca kişinin son mesajından sonraki 24 saat içinde göndermesine izin verir. Yanıt süresinin dolup dolmadığını can_reply ve reply_window_expires_at gösterir. Süre dolduktan sonra reply, code: window_closed ile 422 döner: bunun yerine POST /api/v1/messages/send ile onaylı bir şablon gönderin (her şablon gibi ücretlendirilir). Kişi yeniden yazınca 24 saat yeniden başlar.

Güncel kalmak

Yeni mesajlar için GET /api/v1/conversations adresini updated_since ile yoklayın, bir sohbetin yeni mesajlarını after_id ile alın.

API ile verilen yanıt sohbeti panelden devralmaz: sohbetin durumu ve atanan ekip üyesi aynı kalır, ancak kişi artık yanıt bekliyor sayılmaz. POST …/read okunmamış rozetini panel kullanıcıları için de temizler.

Sohbet nesnesi
id integer
Sohbet kimliği.
wa_id string
Kişinin WhatsApp numarası (rakam).
name string|null
Kişinin WhatsApp profil adı.
phone_number_id string|null
Sohbetin geçtiği, size ait numara. Aynı numaradan yazmak için messages/send çağrısına verin.
status string
Paneldeki gibi pool (Bekleyenler’de, henüz kimse üstlenmedi), assigned veya closed.
unread_count integer
Kişiden gelen, okunmamış mesaj sayısı.
last_message_preview string|null
Son mesajın kısa metni.
last_message_at string|null
Her iki yöndeki son mesajın zamanı.
last_inbound_at string|null
Kişinin son mesajının zamanı.
can_reply boolean
24 saatlik yanıt süresi dolmamışken ve numara aktifken true.
reply_window_expires_at string|null
Yanıt süresinin dolacağı zaman (dolduktan sonra geçmişte kalır); kişi hiç yazmadıysa null.
updated_at string|null
Son değişiklik; updated_since ile birlikte kullanın.
Mesaj nesnesi
id integer
Mesaj kimliği.
direction string
inbound (kişiden) veya outbound.
type string
text, image, video, audio, document, sticker, location, button, interactive…
text string|null
Metin veya medya açıklaması.
media object|null
null ya da type, mime, filename (belgelerde) ve download_path; bu yol API sunucusuna göredir ve aynı başlıklarla istenir.
status string|null
Giden mesajlarda sent, delivered, read veya failed; gelen mesajlarda null.
source string|null
Giden mesajın kaynağı: panel, api, auto_reply, template veya business_app (işletmenin telefonundaki WhatsApp Business uygulamasından gönderilen); gelen mesajlarda null.
created_at string
Mesajın kaydedildiği zaman.
GET /api/v1/conversations Sohbetleriniz, en son yazışılan başta.
API anahtarı

Parametreler

status
string · sorgu
pool (Bekleyenler’de, henüz kimse üstlenmedi), assigned, closed veya all (varsayılan).
updated_since
date · sorgu
Yalnızca bu zamanda veya sonrasında değişen sohbetler (ISO 8601). Yeni mesajlar, yanıtlar ve okundu işaretleri değişiklik sayılır.
wa_id
string · sorgu
Yalnızca bu numaradaki kişiyle olan sohbet; rakam dışındaki karakterler yok sayılır.
per_page
integer · sorgu
1–100, varsayılan 50.
page
integer · sorgu
Sayfa numarası, varsayılan 1.

Örnek istek

curl 'https://podimessage.io/api/v1/conversations?status=pool&updated_since=2026-11-02T10%3A00%3A00%2B03%3A00&per_page=20' \
  -H 'Authorization: Bearer podi_xxxxxxxxxxxxxxxx' \
  -H 'Accept: application/json'
<?php
$ch = curl_init('https://podimessage.io/api/v1/conversations?status=pool&updated_since=2026-11-02T10%3A00%3A00%2B03%3A00&per_page=20');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer podi_xxxxxxxxxxxxxxxx',
        'Accept: application/json',
    ],
]);
$response = json_decode(curl_exec($ch), true);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
const res = await fetch('https://podimessage.io/api/v1/conversations?status=pool&updated_since=2026-11-02T10%3A00%3A00%2B03%3A00&per_page=20', {
  headers: {
    Authorization: 'Bearer podi_xxxxxxxxxxxxxxxx',
    Accept: 'application/json',
  },
});
const data = await res.json();

Yanıt · HTTP 200

{
  "data": [
    {
      "id": 12,
      "wa_id": "905321234567",
      "name": "Ayşe Yılmaz",
      "phone_number_id": "106540352242922",
      "status": "pool",
      "unread_count": 1,
      "last_message_preview": "Yarın 14:30 uygun mu?",
      "last_message_at": "2026-11-02T10:12:00+03:00",
      "last_inbound_at": "2026-11-02T10:12:00+03:00",
      "can_reply": true,
      "reply_window_expires_at": "2026-11-03T10:12:00+03:00",
      "updated_at": "2026-11-02T10:12:00+03:00"
    }
  ],
  "meta": {
    "current_page": 1,
    "last_page": 1,
    "per_page": 20,
    "total": 1
  }
}
GET /api/v1/conversations/{conversation} Tek bir sohbet.
API anahtarı

Parametreler

conversation
integer · yol zorunlu
Sohbetin id değeri.

Örnek istek

curl 'https://podimessage.io/api/v1/conversations/12' \
  -H 'Authorization: Bearer podi_xxxxxxxxxxxxxxxx' \
  -H 'Accept: application/json'
<?php
$ch = curl_init('https://podimessage.io/api/v1/conversations/12');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer podi_xxxxxxxxxxxxxxxx',
        'Accept: application/json',
    ],
]);
$response = json_decode(curl_exec($ch), true);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
const res = await fetch('https://podimessage.io/api/v1/conversations/12', {
  headers: {
    Authorization: 'Bearer podi_xxxxxxxxxxxxxxxx',
    Accept: 'application/json',
  },
});
const data = await res.json();

Yanıt · HTTP 200

{
  "id": 12,
  "wa_id": "905321234567",
  "name": "Ayşe Yılmaz",
  "phone_number_id": "106540352242922",
  "status": "pool",
  "unread_count": 1,
  "last_message_preview": "Yarın 14:30 uygun mu?",
  "last_message_at": "2026-11-02T10:12:00+03:00",
  "last_inbound_at": "2026-11-02T10:12:00+03:00",
  "can_reply": true,
  "reply_window_expires_at": "2026-11-03T10:12:00+03:00",
  "updated_at": "2026-11-02T10:12:00+03:00"
}

Diğer yanıtlar

404 Bu hesapta böyle bir sohbet yok.
{
  "message": "Sohbet bulunamadı."
}
GET /api/v1/conversations/{conversation}/messages Bir sohbetin mesajları, yeniden eskiye sıralı.
API anahtarı

Geriye doğru sayfalamak için has_more true olduğu sürece meta.next_before_id değerini before_id olarak gönderin.

Parametreler

conversation
integer · yol zorunlu
Sohbetin id değeri.
per_page
integer · sorgu
1–100, varsayılan 50.
before_id
integer · sorgu
Yalnızca bu id’den eski mesajlar.
after_id
integer · sorgu
Yalnızca bu id’den yeni mesajlar; yoklama için. Geriye sayfalarken de aynı değeri gönderin.

Örnek istek

curl 'https://podimessage.io/api/v1/conversations/12/messages?per_page=2' \
  -H 'Authorization: Bearer podi_xxxxxxxxxxxxxxxx' \
  -H 'Accept: application/json'
<?php
$ch = curl_init('https://podimessage.io/api/v1/conversations/12/messages?per_page=2');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer podi_xxxxxxxxxxxxxxxx',
        'Accept: application/json',
    ],
]);
$response = json_decode(curl_exec($ch), true);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
const res = await fetch('https://podimessage.io/api/v1/conversations/12/messages?per_page=2', {
  headers: {
    Authorization: 'Bearer podi_xxxxxxxxxxxxxxxx',
    Accept: 'application/json',
  },
});
const data = await res.json();

Yanıt · HTTP 200

{
  "data": [
    {
      "id": 345,
      "direction": "inbound",
      "type": "text",
      "text": "Yarın 14:30 uygun mu?",
      "media": null,
      "status": null,
      "source": null,
      "created_at": "2026-11-02T10:12:00+03:00"
    },
    {
      "id": 344,
      "direction": "inbound",
      "type": "image",
      "text": "Aşı karnesi",
      "media": {
        "type": "image",
        "mime": "image/jpeg",
        "filename": null,
        "download_path": "/api/v1/messages/344/media"
      },
      "status": null,
      "source": null,
      "created_at": "2026-11-02T10:11:00+03:00"
    }
  ],
  "meta": {
    "per_page": 2,
    "has_more": true,
    "next_before_id": 344
  }
}

Diğer yanıtlar

404 Bu hesapta böyle bir sohbet yok.
{
  "message": "Sohbet bulunamadı."
}
POST /api/v1/conversations/{conversation}/reply 24 saatlik yanıt süresi içinde serbest metinle yanıt verir. Ücretlendirilmez.
API anahtarı

Parametreler

conversation
integer · yol zorunlu
Sohbetin id değeri.
text
string · gövde zorunlu
Mesaj metni, 1–4.096 karakter.
Idempotency-Key
string · başlık
İsteğe bağlı benzersiz anahtar, en fazla 128 karakter (veya gövdede idempotency_key). 24 saat içinde tekrarlanırsa ilk yanıt döner ve hiçbir şey gönderilmez.

Örnek istek

curl -X POST 'https://podimessage.io/api/v1/conversations/12/reply' \
  -H 'Authorization: Bearer podi_xxxxxxxxxxxxxxxx' \
  -H 'Idempotency-Key: reply-77f1c2' \
  -H 'Accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
    "text": "Merhaba Ayşe, yarın 14:30 için randevunuzu oluşturduk."
  }'
<?php
$ch = curl_init('https://podimessage.io/api/v1/conversations/12/reply');
curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer podi_xxxxxxxxxxxxxxxx',
        'Idempotency-Key: reply-77f1c2',
        'Accept: application/json',
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode([
        'text' => 'Merhaba Ayşe, yarın 14:30 için randevunuzu oluşturduk.',
    ]),
]);
$response = json_decode(curl_exec($ch), true);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
const res = await fetch('https://podimessage.io/api/v1/conversations/12/reply', {
  method: 'POST',
  headers: {
    Authorization: 'Bearer podi_xxxxxxxxxxxxxxxx',
    'Idempotency-Key': 'reply-77f1c2',
    Accept: 'application/json',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    text: 'Merhaba Ayşe, yarın 14:30 için randevunuzu oluşturduk.',
  }),
});
const data = await res.json();

Yanıt · HTTP 200

{
  "status": "sent",
  "message": {
    "id": 346,
    "direction": "outbound",
    "type": "text",
    "text": "Merhaba Ayşe, yarın 14:30 için randevunuzu oluşturduk.",
    "media": null,
    "status": "sent",
    "source": "api",
    "created_at": "2026-11-02T10:15:00+03:00"
  },
  "conversation": {
    "id": 12,
    "wa_id": "905321234567",
    "name": "Ayşe Yılmaz",
    "phone_number_id": "106540352242922",
    "status": "pool",
    "unread_count": 1,
    "last_message_preview": "Yarın 14:30 uygun mu?",
    "last_message_at": "2026-11-02T10:12:00+03:00",
    "last_inbound_at": "2026-11-02T10:12:00+03:00",
    "can_reply": true,
    "reply_window_expires_at": "2026-11-03T10:12:00+03:00",
    "updated_at": "2026-11-02T10:12:00+03:00"
  }
}

Diğer yanıtlar

422 24 saatlik yanıt süresi dolmuş (WhatsApp bildirdiğinde de); bunun yerine şablon gönderin.
{
  "message": "Müşteri son 24 saatte yazmadığı için 24 saatlik yanıt süresi doldu. Bunun yerine POST /api/v1/messages/send ile onaylı bir şablon gönderin.",
  "code": "window_closed",
  "template_endpoint": "/api/v1/messages/send"
}
409 Sohbetin numarası artık aktif değil.
{
  "message": "Bağlı ve aktif bir WhatsApp numarası yok. Panelden WhatsApp bağlantısını kurun.",
  "code": "no_account"
}
409 Aynı Idempotency-Key ile gönderilen istek hâlâ işleniyor.
{
  "message": "Bu idempotency anahtarıyla gönderilen istek hâlâ işleniyor. Biraz sonra tekrar deneyin.",
  "code": "in_progress"
}
422 WhatsApp yanıtı reddetti; retryable yeniden denemenin işe yarayıp yaramayacağını söyler. Hiçbir şey kaydedilmedi.
{
  "message": "(#131026) Message undeliverable",
  "code": "131026",
  "retryable": false
}
404 Bu hesapta böyle bir sohbet yok.
{
  "message": "Sohbet bulunamadı."
}
POST /api/v1/conversations/{conversation}/read Sohbeti okundu olarak işaretler (okunmamış sayısı 0); açık panel gelen kutularında da.
API anahtarı

Parametreler

conversation
integer · yol zorunlu
Sohbetin id değeri.

Örnek istek

curl -X POST 'https://podimessage.io/api/v1/conversations/12/read' \
  -H 'Authorization: Bearer podi_xxxxxxxxxxxxxxxx' \
  -H 'Accept: application/json'
<?php
$ch = curl_init('https://podimessage.io/api/v1/conversations/12/read');
curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer podi_xxxxxxxxxxxxxxxx',
        'Accept: application/json',
    ],
    CURLOPT_POSTFIELDS => '',
]);
$response = json_decode(curl_exec($ch), true);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
const res = await fetch('https://podimessage.io/api/v1/conversations/12/read', {
  method: 'POST',
  headers: {
    Authorization: 'Bearer podi_xxxxxxxxxxxxxxxx',
    Accept: 'application/json',
  },
});
const data = await res.json();

Yanıt · HTTP 200

{
  "id": 12,
  "wa_id": "905321234567",
  "name": "Ayşe Yılmaz",
  "phone_number_id": "106540352242922",
  "status": "pool",
  "unread_count": 0,
  "last_message_preview": "Yarın 14:30 uygun mu?",
  "last_message_at": "2026-11-02T10:12:00+03:00",
  "last_inbound_at": "2026-11-02T10:12:00+03:00",
  "can_reply": true,
  "reply_window_expires_at": "2026-11-03T10:12:00+03:00",
  "updated_at": "2026-11-02T10:12:00+03:00"
}

Diğer yanıtlar

404 Bu hesapta böyle bir sohbet yok.
{
  "message": "Sohbet bulunamadı."
}
GET /api/v1/messages/{message}/media Bir mesajdaki fotoğrafı, videoyu, sesli mesajı, belgeyi veya çıkartmayı WhatsApp’tan aktararak indirir.
API anahtarı

Fotoğraf, video ve sesli mesajlar gerçek türleriyle satır içi gelir; diğer her şey (belgeler, SVG, …) application/octet-stream eki olarak gelir. WhatsApp medyayı yaklaşık 30 gün saklar.

Parametreler

message
integer · yol zorunlu
Mesajın id değeri (media.download_path içindeki gibi).

Örnek istek

curl 'https://podimessage.io/api/v1/messages/344/media' \
  -H 'Authorization: Bearer podi_xxxxxxxxxxxxxxxx' \
  -H 'Accept: application/json' \
  -o media.jpg
<?php
$ch = curl_init('https://podimessage.io/api/v1/messages/344/media');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer podi_xxxxxxxxxxxxxxxx',
        'Accept: application/json',
    ],
]);
file_put_contents('media.jpg', curl_exec($ch));
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
import { writeFile } from 'node:fs/promises';

const res = await fetch('https://podimessage.io/api/v1/messages/344/media', {
  headers: {
    Authorization: 'Bearer podi_xxxxxxxxxxxxxxxx',
    Accept: 'application/json',
  },
});
await writeFile('media.jpg', Buffer.from(await res.arrayBuffer()));

Yanıt · HTTP 200

Dosyanın kendisi, şu başlıklarla:

Content-Type: image/jpeg
Content-Disposition: inline; filename="media-344"
Content-Security-Policy: sandbox; default-src 'none'; img-src 'self' data:; media-src 'self'
X-Content-Type-Options: nosniff
Cache-Control: max-age=300, private

Diğer yanıtlar

404 Böyle bir mesaj yok ya da mesajda medya yok.
{
  "message": "Mesaj medyası bulunamadı."
}
502 WhatsApp dosyayı artık vermiyor; örneğin süresi dolmuş olabilir.
{
  "message": "Medya WhatsApp'tan alınamadı; süresi dolmuş olabilir.",
  "code": "100"
}