Geliştirici API'si

Entegrasyonlar İçin Tasarlanmış WhatsApp REST API'si ve Webhook'lar

Şablon ve mesaj gönderin; kişileri, etiketleri ve sohbetleri senkronize edin; her yanıt ve teslim bildirimi için imzalı bir webhook alın. Resmi WhatsApp Business Platformu üzerinde, kapsamlı API anahtarlarıyla /api/v1 adresinde sade REST. Kurulacak SDK yok. API, ayda 100 API mesajı içeren Developer Free’den başlayarak her pakettedir.

✦ 14 günlük ücretsiz deneme · Kendi WhatsApp Business numaranız · Mesajları Meta doğrudan faturalandırır

Tüm WhatsApp CRM'iniz İçin Tek Bir REST API

Bir çalışma alanı API anahtarıyla (Authorization: Bearer sm_live_…) kimlik doğrulayın ve /api/v1 adresini çağırın. Şablon, metin, medya ve etkileşimli mesajlar gönderin; kişileri oluşturun, güncelleyin ve etiketleyin; etiketleri, satış hattı aşamalarını, şablonları ve kampanyaları okuyun; sohbetleri listeleyin, atayın ve çözün; webhook uç noktalarını yönetin; satışları dönüşüm olarak bildirin. Her başarılı yanıt aynı {data, meta} zarfını, her hata ise üzerine karar verebileceğiniz sabit bir kodu kullanır.

  • Anahtarlar Geliştiriciler → API anahtarları bölümünde oluşturulur ve yalnızca bir kez gösterilir
  • Tam erişim, Yalnızca gönderme, Yalnızca okuma ve Özel ön ayarlarıyla 10 kapsam
  • Mesaj ücretlerini Meta doğrudan kendi WhatsApp Business Hesabınıza faturalar; API hiçbir zaman mesaj başına ücret almaz
API referansını açın →
StartMessaging WhatsApp REST API'si

Güvenebileceğiniz İmzalı Webhook'lar

Bir HTTPS uç noktasını 12 olaydan herhangi birine abone edin: alınan, gönderilen, teslim edilen, okunan ve başarısız mesajlar; oluşturulan, abonelikten çıkan ve yeniden abone olan kişiler; atanan ve çözülen sohbetler; şablon durum değişiklikleri; ve tamamlanan kampanyalar. Her teslimat X-SM-Signature başlığında HMAC-SHA256 ile imzalanır, 1dk, 5dk, 30dk, 2sa, 6sa ve 12sa sonra yeniden denenir ve yeniden gönderebileceğiniz bir teslimat günlüğünde listelenir.

  • En az bir kez teslim edilir: olay kimliğine göre yinelenenleri ayıklayın
  • Sürekli başarısız olan uç noktalar (art arda 50 kez veya 24 saat boyunca) kapatılır ve işaretlenir
  • İmzalama sırrını 24 saatlik çakışmayla değiştirin
Webhook rehberini okuyun →
İmzalı WhatsApp webhook olayları
Üretim İçin Tasarlandı

Entegrasyonların Dayandığı Ayrıntılar

  • İdempotent gönderimler

    POST isteğinde bir Idempotency-Key gönderin. Aynı anahtar ve gövde 24 saat içinde orijinal yanıtı Idempotent-Replayed: true ile döndürür; böylece yeniden deneme asla iki kez göndermez.

  • İmleçli sayfalama ve senkronizasyon

    Listeler limit (1–100) ve cursor alır ve nextCursor döndürür. Kişilerde ve sohbetlerde updatedSince, artımlı senkronizasyon için yalnızca değişenleri en eskiden başlayarak döndürür.

  • Kendi referanslarınız

    Bir gönderime sipariş numaranız gibi bir clientReference ekleyin. Yanıtta, GET /messages/{id} üzerinde ve her gönderildi, teslim edildi, okundu ve başarısız webhook'unda geri gelir.

  • En az yetkili anahtarlar

    Her entegrasyona yalnızca ihtiyaç duyduğu kapsamlara sahip kendi anahtarını verin. Bir anahtarla oluşturulan webhook, bir olay ailesini yalnızca o anahtar ilgili okuma kapsamına sahip olduğu sürece alır.

  • İstek ve teslimat günlükleri

    Panelde son 7 gündeki son 500 API isteğini anahtara göre veya yalnızca hatalar olarak filtreleyerek görün; herhangi bir webhook'u uç noktasının teslimat günlüğünden yeniden gönderin.

  • OpenAPI referansı

    /api/v1/openapi.json adresinde bir OpenAPI JSON belgesi ve /api/v1/docs adresinde Swagger UI; her işlemin kapsamı x-scope olarak listelenir. Aynı referans panelde Geliştiriciler bölümünde de bulunur.

Uç Noktalar

API'nin Kapsadıkları

Tüm yollar /api/v1 altındadır. Şablon ve kampanya oluşturma şimdilik yalnızca panelden yapılır: API bunları okur ve onaylı şablonları her seferinde tek mesaj olarak gönderir.

Kaynak Uç noktalar Kapsam Ne yapar
Hesap GET /me, GET /phone-numbers Geçerli herhangi bir anahtar Çalışma alanı, plan, anahtar kapsamları, limitler ve anlık kullanım; kalite puanı ve mesajlaşma limitiyle numaralarınız
Mesajlar POST /messages, GET /messages/{id} messages:send, messages:read Şablon (karuseller ve süreli teklifler dahil), metin, görsel, video, ses, belge ve etkileşimli mesajlar (etkileşimli mesajlar Team veya Business gerektirir); durum, hata nedeni ve Meta’nın fiyat kategorisi
Kişiler GET/POST /contacts, GET/PATCH/DELETE /contacts/{idOrPhone} contacts:read, contacts:write Telefon numarasına göre oluşturma veya güncelleme, etiketler, özel öznitelikler, izin verme ve izni geri çekme; bir kişiyi satış hattı aşamasına koymak Business gerektirir
Etiketler ve satış hattı GET /tags, GET /pipeline-stages contacts:read Kişi sayılarıyla etiketler; lead satış hattı aşamalarınız
Şablonlar GET /templates, GET /templates/{id} templates:read Yalnızca okuma: şablonlar panelde oluşturulur ve Meta tarafından incelenir
Sohbetler GET /conversations, GET /conversations/{id}, GET /conversations/{id}/messages, PATCH /conversations/{id} conversations:read, conversations:write Mesaj geçmişi ve windowOpen; atama, atamayı kaldırma, çözme ve yeniden açma (okuma her pakette çalışır; değişiklikler Team veya Business gerektirir)
Kampanyalar GET /campaigns, GET /campaigns/{id} campaigns:read Yalnızca okunabilir istatistikler; kampanyalar panelde oluşturulur ve başlatılır
Dönüşümler POST /conversions conversions:write Müşteriyi getiren kampanyanın payını alması için bir satışı bildirin (Business)
Webhook'lar GET/POST /webhooks, DELETE /webhooks/{id} webhooks:manage Uç noktaları abone etme ve abonelikten çıkarma (REST hooks)
Hız Limitleri

Plana Göre API Limitleri

Anahtar başına değil, çalışma alanı başına sayılır. Sayılan yanıtlar RateLimit-* başlıklarını, her 429 yanıtı ise Retry-After başlığını taşır. Aylık API mesajlarına yalnızca API ile gönderilen mesajlar sayılır; kota aşıldığında gönderim 402 PLAN_MESSAGE_LIMIT_REACHED alır. Meta’nın numaranız için koyduğu mesajlaşma limiti de geçerlidir.

Plan İstek / dakika API gönderimi / saat API mesajı / ay Webhook uç noktaları
Ücretsiz deneme (14 gün) 300 100 1.000 5
Developer Free 60 2.000 100 2
Developer 1K 120 10.000 1.000 2
Developer 10K 300 10.000 10.000 2
Developer 100K 1.200 10.000 100.000 2
Team 300 10.000 Sınırsız (adil kullanım) 1
Business 1.200 10.000 Sınırsız (adil kullanım) 5
Developer Paketleri

Yalnızca API mi? Bir Developer Boyutu Seçin

Developer paketleri, salt görüntülenen bir panelle birlikte API’dir: 1 koltuk, 2 webhook uç noktası ve burada gösterilen aylık API mesajları. Fiyatlara GST dahildir ve bir yıl on ay fiyatınadır. Ücretli boyutlar kimlik doğrulama şablonlarını asla durdurmaz.

Plan Fiyat / ay API mesajı / ay İstek / dakika
Developer Free ₹0 100 60
Developer 1K ₹100 1.000 120
Developer 10K ₹499 10.000 300
Developer 100K ₹999 100.000 1.200
Hızlı Başlangıç

Anahtarınızı kontrol edin, ardından bir şablon gönderin

GET /me kapsam gerektirmez. Gönderim için messages:send ve onaylı bir şablon gerekir.

# 1. Check your key: workspace, plan, scopes, limits and usage
curl https://waba-api.startmessaging.com/api/v1/me \
  -H "Authorization: Bearer sm_live_your_api_key"

# 2. Send an approved template, safe to retry with the same Idempotency-Key
curl -X POST https://waba-api.startmessaging.com/api/v1/messages \
  -H "Authorization: Bearer sm_live_your_api_key" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: order-10421-ready" \
  -d '{
    "to": "+919812345678",
    "type": "template",
    "template": {
      "name": "order_ready_for_pickup",
      "language": "en_US",
      "parameters": [
        { "text": "Asha" },
        { "text": "10421" }
      ]
    },
    "clientReference": "order-10421"
  }'
const API = 'https://waba-api.startmessaging.com/api/v1';
const auth = { Authorization: 'Bearer sm_live_your_api_key' };

// 1. Check your key
const me = await fetch(`${API}/me`, { headers: auth }).then((r) => r.json());
console.log(me.data.plan.code, me.data.apiKey.scopes, me.data.limits);

// 2. Send an approved template, safe to retry with the same Idempotency-Key
const res = await fetch(`${API}/messages`, {
  method: 'POST',
  headers: {
    ...auth,
    'Content-Type': 'application/json',
    'Idempotency-Key': 'order-10421-ready',
  },
  body: JSON.stringify({
    "to": "+919812345678",
    "type": "template",
    "template": {
      "name": "order_ready_for_pickup",
      "language": "en_US",
      "parameters": [
        { "text": "Asha" },
        { "text": "10421" }
      ]
    },
    "clientReference": "order-10421"
  }),
});

const { data } = await res.json();
console.log(data.id, data.status, res.headers.get('Idempotent-Replayed'));
import requests

API = 'https://waba-api.startmessaging.com/api/v1'
AUTH = {'Authorization': 'Bearer sm_live_your_api_key'}

# 1. Check your key
me = requests.get(f'{API}/me', headers=AUTH).json()['data']
print(me['plan']['code'], me['apiKey']['scopes'], me['limits'])

# 2. Send an approved template, safe to retry with the same Idempotency-Key
res = requests.post(
    f'{API}/messages',
    headers={**AUTH, 'Idempotency-Key': 'order-10421-ready'},
    json={
      "to": "+919812345678",
      "type": "template",
      "template": {
        "name": "order_ready_for_pickup",
        "language": "en_US",
        "parameters": [
          { "text": "Asha" },
          { "text": "10421" }
        ]
      },
      "clientReference": "order-10421"
    },
)

data = res.json()['data']
print(data['id'], data['status'])
<?php
$api = 'https://waba-api.startmessaging.com/api/v1';
$auth = 'Authorization: Bearer sm_live_your_api_key';

// 1. Check your key
$ch = curl_init("$api/me");
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [$auth],
]);
$me = json_decode(curl_exec($ch), true)['data'];
echo $me['plan']['code'] . ' ' . implode(',', $me['apiKey']['scopes']) . "\n";

// 2. Send an approved template, safe to retry with the same Idempotency-Key
$body = <<<'JSON'
{
  "to": "+919812345678",
  "type": "template",
  "template": {
    "name": "order_ready_for_pickup",
    "language": "en_US",
    "parameters": [
      { "text": "Asha" },
      { "text": "10421" }
    ]
  },
  "clientReference": "order-10421"
}
JSON;

$ch = curl_init("$api/messages");
curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        $auth,
        'Content-Type: application/json',
        'Idempotency-Key: order-10421-ready',
    ],
    CURLOPT_POSTFIELDS => $body,
]);
$data = json_decode(curl_exec($ch), true)['data'];
echo $data['id'] . ' ' . $data['status'];
Webhook'lar

Her webhook'u güvenmeden önce doğrulayın

X-SM-Signature değeri v1=HMAC-SHA256(secret, timestamp + "." + ham gövde) şeklindedir. Anahtar olarak whsec_ sırrının tamamını kullanın.

import express from 'express';
import { createHmac, timingSafeEqual } from 'node:crypto';

const app = express();
const SECRET = process.env.SM_WEBHOOK_SECRET; // the whole whsec_… string

function verify(rawBody, headers) {
  const ts = headers['x-sm-timestamp'];
  const sigs = headers['x-sm-signature'];
  if (!/^\d+$/.test(ts ?? '') || typeof sigs !== 'string') return false;
  if (Math.abs(Date.now() / 1000 - Number(ts)) > 300) return false; // 5-minute tolerance
  const expected = createHmac('sha256', SECRET).update(`${ts}.`).update(rawBody).digest();
  return sigs.split(',').some((part) => {
    const m = /^v1=([0-9a-f]{64})$/.exec(part.trim());
    return m !== null && timingSafeEqual(Buffer.from(m[1], 'hex'), expected);
  });
}

app.post('/webhooks/startmessaging', express.raw({ type: 'application/json' }), (req, res) => {
  if (!verify(req.body, req.headers)) return res.sendStatus(401);
  res.sendStatus(200); // answer 2xx within 5 seconds, then do the work

  const event = JSON.parse(req.body);
  // Delivered at least once: skip event.id if you have already handled it.
  if (event.type === 'message.delivered') {
    console.log(event.data.message.clientReference, 'delivered');
  }
});
import hmac, hashlib, json, os, time
from flask import Flask, request

app = Flask(__name__)
SECRET = os.environ['SM_WEBHOOK_SECRET'].encode()  # the whole whsec_… string

def verify(raw_body, ts, sigs):
    if not ts or not ts.isdigit() or not sigs:
        return False
    if abs(time.time() - int(ts)) > 300:  # 5-minute tolerance
        return False
    expected = hmac.new(SECRET, f'{ts}.'.encode() + raw_body, hashlib.sha256).hexdigest()
    return any(
        hmac.compare_digest(part.strip()[3:], expected)
        for part in sigs.split(',') if part.strip().startswith('v1=')
    )

@app.post('/webhooks/startmessaging')
def startmessaging_webhook():
    raw = request.get_data()
    if not verify(raw, request.headers.get('X-SM-Timestamp'), request.headers.get('X-SM-Signature')):
        return '', 401
    event = json.loads(raw)
    # Delivered at least once: skip event['id'] if you have already handled it.
    if event['type'] == 'message.delivered':
        print(event['data']['message']['clientReference'], 'delivered')
    return '', 200
<?php
$secret = getenv('SM_WEBHOOK_SECRET'); // the whole whsec_… string
$raw = file_get_contents('php://input');
$ts = $_SERVER['HTTP_X_SM_TIMESTAMP'] ?? '';
$sigs = $_SERVER['HTTP_X_SM_SIGNATURE'] ?? '';

function sm_verify(string $raw, string $ts, string $sigs, string $secret): bool
{
    if (!ctype_digit($ts) || $sigs === '') return false;
    if (abs(time() - (int) $ts) > 300) return false; // 5-minute tolerance
    $expected = hash_hmac('sha256', $ts . '.' . $raw, $secret);
    foreach (explode(',', $sigs) as $part) {
        $part = trim($part);
        if (strncmp($part, 'v1=', 3) === 0 && hash_equals($expected, substr($part, 3))) {
            return true;
        }
    }
    return false;
}

if (!sm_verify($raw, $ts, $sigs, $secret)) {
    http_response_code(401);
    exit;
}
http_response_code(200); // answer 2xx within 5 seconds

$event = json_decode($raw, true);
// Delivered at least once: skip $event['id'] if you have already handled it.
if ($event['type'] === 'message.delivered') {
    error_log($event['data']['message']['clientReference'] . ' delivered');
}
Dönüşümler

Bir satışı bildirin, kampanyaya yazın

Business paketinde POST /api/v1/conversions, satışı dönüşüm pencereniz içinde (siz değiştirmedikçe 7 gün) o numaraya teslim edilen son kampanyaya yazar ve kampanya raporu tutarı toplar.

# Business plan, scope conversions:write
curl -X POST https://waba-api.startmessaging.com/api/v1/conversions \
  -H "Authorization: Bearer sm_live_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "phone": "+919812345678",
    "orderId": "ORD-10442",
    "value": 2499.5,
    "currency": "INR",
    "occurredAt": "2026-10-12T10:30:00+05:30"
  }'

# 201 = recorded now, 200 = this orderId was reported already
const res = await fetch('https://waba-api.startmessaging.com/api/v1/conversions', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer ' + process.env.SM_API_KEY, // sm_live_your_api_key
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    phone: '+919812345678',
    orderId: 'ORD-10442', // the same orderId again never counts the sale twice
    value: 2499.5,
    currency: 'INR',
  }),
});

const { data } = await res.json();
console.log(data.created, data.conversion.campaign?.name ?? 'no campaign credited');
import os, requests

res = requests.post(
    'https://waba-api.startmessaging.com/api/v1/conversions',
    headers={'Authorization': f"Bearer {os.environ['SM_API_KEY']}"},  # sm_live_your_api_key
    json={
        'phone': '+919812345678',
        'orderId': 'ORD-10442',
        'value': 2499.5,
        'currency': 'INR',
    },
)

data = res.json()['data']
campaign = data['conversion']['campaign']
print(data['created'], campaign['name'] if campaign else 'no campaign credited')
SSS

WhatsApp API — SSS

Bir SDK var mı?

Hayır. API, JSON ile HTTPS üzerinden sade REST'tir; bu yüzden HTTPS isteği yapabilen her dil veya araç çalışır. Belgeler cURL, Node.js, Python ve PHP örnekleri gösterir; OpenAPI belgesi ise her istek ve yanıt alanını açıklar.

Hangi planlar API'yi içerir?

Developer Free dahil her paket. Developer paketleri, aylık API mesajı sayısına göre boyutlanan, salt görüntülenen bir panelle birlikte API’dir: 100 mesajlı Developer Free, ardından 1K, 10K ve 100K. Team ve Business; ortak gelen kutusunu, kişileri ve kampanyaları ekler ve adil kullanım dahilinde aylık API mesaj sınırı yoktur. 14 günlük ücretsiz deneme 1.000 API mesajıyla API’yi içerir. Dakikadaki istek sayısı ve webhook uç noktaları pakete bağlıdır; GET /me paketinizi, limitlerinizi ve bu ayın sayısını gösterir.

API üzerinden şablon veya kampanya oluşturabilir miyim?

Henüz değil. Şablonlar panelde oluşturulur ve Meta tarafından incelenir; kampanyalar paneldeki kampanya sihirbazında hazırlanıp başlatılır. API ikisini de okur, onaylı şablonları POST /messages ile her seferinde tek mesaj olarak gönderir ve bir kampanya bittiğinde campaign.completed webhook'u ile bildirir.

API karusel ve süreli teklif gönderebilir mi?

Evet. Karusel şablonu için her kart için bir giriş içeren template.carouselCards’ı sırayla gönderin; her birinin kendi headerMediaUrl’si (https) ve isteğe bağlı parameters ile buttonParameters’ı olur. Süreli teklif için template.offerExpiresAt’i gelecekteki bir ISO 8601 zamanına ayarlayın; WhatsApp müşteriye bir geri sayım gösterir. Kampanyalar bu şablonları gönderemez; bu yüzden API’den veya gelen kutusundan tek tek gönderilirler.

Aylık API mesaj kotası bitince ne olur?

Developer paketleri ve ücretsiz deneme, ayın 1’inden itibaren sayılan belirli sayıda aylık API mesajı içerir; yalnızca API ile gönderilen mesajlar sayılır. Developer Free ve deneme kotalarında durur. Ücretli bir Developer paketi diğer mesajları boyutunun üç katında durdurur ve kimlik doğrulama şablonlarını asla durdurmaz. Limiti aşan bir gönderim, ayrıntılarında sent, stopAt ve resetsAt bulunan 402 PLAN_MESSAGE_LIMIT_REACHED alır; GET /me bu olmadan önce sayıyı gösterir. Team ve Business’ta aylık API mesaj sınırı yoktur (adil kullanım).

Zapier, Make veya Pabbly Connect'i nasıl bağlarım?

Bu pazar yerlerinde henüz resmi StartMessaging uygulaması yok. Genel modüllerini kullanın: olayları almak için catch-hook veya özel webhook tetikleyicisi, API'yi çağırmak için API anahtarınızla bir HTTP isteği eylemi. Kendi uygulamasını geliştirenler POST /webhooks ve DELETE /webhooks/{id} ile abone olup aboneliği kaldırabilir.

Bir gönderimi yeniden denersem ne olur?

Aynı Idempotency-Key ve aynı gövdeyle 24 saat içinde, orijinal yanıtı Idempotent-Replayed: true ile geri alırsınız ve hiçbir şey iki kez gönderilmez. Bir anahtarı farklı bir gövdeyle yeniden kullanmak IDEMPOTENCY_KEY_REUSED ile reddedilir. 429 veya 5xx sonrasında aynı anahtarla yeniden deneyin.

Hız limitleri nasıl çalışır?

Limitler çalışma alanı başınadır; bu yüzden daha fazla anahtar asla kapasite eklemez. Dakikadaki istek: Developer Free’de 60, Developer 1K’da 120, Developer 10K, Team ve ücretsiz denemede 300, Developer 100K ve Business’ta 1.200. Saatlik API gönderimi: ücretli paketlerde 10.000, Developer Free’de 2.000 ve denemede 100. Bir gönderim iki bütçeden de düşer ve reddedilen bir gönderim saatlik payını geri verir. 429 yanıtı Retry-After ile ne kadar bekleneceğini söyler. Meta’nın numaranız için koyduğu mesajlaşma limiti bunun üzerine uygulanır.

StartMessaging API mesajı başına ücret alıyor mu?

Hayır. StartMessaging bir Meta Tech Provider’dır: kendi WhatsApp Business Hesabınızı bağlarsınız ve Meta mesaj ücretlerini kendi fiyatlarıyla doğrudan bu hesaba fatura eder. Meta, 24 saatlik pencerenin içinde bile yardımcı şablonlar dahil teslim edilen her şablonu ve aylık ücretsiz kotayı aşan hizmet yanıtlarını ücretlendirir. StartMessaging cüzdan ve mesaj başına ek ücret olmadan sabit bir paket ücreti alır; Developer paketleri içerdikleri aylık API mesajı sayısına göre boyutlanır. Her mesajın pricing alanı, Meta’nın onu nasıl sınıflandırdığını gösterir.

WhatsApp API

WhatsApp Entegrasyonunuzu Kurun

İlk çalışma alanınız 14 günlük ücretsiz deneme alır; sonrasında Developer Free, ayda 100 mesajla API’yi açık tutar. Kendi WhatsApp Business numaranızı bağlayın, bir anahtar oluşturun ve ilk çağrınızı yapın.