İçeriğe geç

Geliştiriciler

WhatsApp, Instagram, Messenger ve web sohbeti için tek API.

REST API v1, herkese açık OpenAPI belgesi, gönderimde zorunlu Idempotency-Key ve Standard Webhooks ile imzalı olaylar. Örnekler curl, PHP, Node.js ve Python ile.

  • OpenAPI 3.1 belgesi
  • İmzalı, sıralı webhook'lar
  • Dört dilde örnek
POST/v1/messages

İstek

curl -sS -X POST "https://messaging.uppu.net/v1/messages" \
  -H "Authorization: Bearer $UPPU_API_KEY" \
  -H "Idempotency-Key: siparis-1001-kargo" \
  -H "Content-Type: application/json" \
  -d '{"channel_id": "01j9z0ch5k2m4n6p8q0r2s4t6v",
       "to": {"contact_id": "01j8x7ct5k2m4n6p8q0r2s4t6v"},
       "content": {"type": "text",
                   "text": {"body": "Siparişiniz yola çıktı."}},
       "client_reference": "siparis-1001"}'
202 Acceptedardından webhook'unuza message.status

Buradan başlayın

Ortamlar

UPPU'nun iki ayrı ortamı vardır; her birinin paneli, anahtarları ve verisi ayrıdır. Sahne ortamı entegrasyonları denemek içindir; oradaki hiçbir şey canlı firmanıza ulaşmaz.

Ortamlar
OrtamPanelAPI taban adresiAnahtar öneki
Canlıhttps://app.uppu.nethttps://messaging.uppu.net/v1uppu_live_
Sahnehttps://staging.uppu.nethttps://messaging-staging.uppu.net/v1uppu_test_

Öteki ortamın anahtarı 401 wrong_environment alır. API yalnızca bu iki adreste yanıt verir; panel bu adreslerde sunulmaz.

Erişim ve API anahtarları

  1. API erişimi isteyin

    API, UPPU ekibi açana kadar her firmada kapalıdır. Ne kurmak istediğinizi bize yazın; API'yi firmanız için açalım.

  2. Panelde anahtar oluşturun

    Firma sahibi anahtarı ekip ayarlarındaki «Geliştiriciler» sayfasında oluşturur. Oluştururken sahibin parolası sorulur; anahtar yalnızca bir kez gösterilir.

  3. Sunucunuzdan çağırın

    Anahtarı her istekte Authorization: Bearer … başlığıyla gönderin. Origin başlığı taşıyan istek 403 browser_request_refused alır ve CORS başlığı gönderilmez; anahtarı tarayıcıya ve mobil uygulamaya koymayın.

Anahtarlar

  • Biçim: uppu_live_, 12 karakter, _, 43 karakter (sahnede uppu_test_). Önek sayesinde sır tarayıcıları sızan anahtarı tanır.
  • UPPU anahtarın yalnızca SHA-256 özetini saklar. Bir firmada en çok 25 etkin anahtar olabilir; 90 gün kullanılmayan anahtar için firma sahibine e-posta gider. Anahtar hiçbir zaman kendiliğinden iptal edilmez.
  • Her anahtarın ayarları: kapsamlar, tek kanal ya da bütün kanallar, IP izin listesi (CIDR aralıkları) ve 30, 90, 180 ya da 365 günlük süre. İptal hemen geçerli olur.
  • Anahtarı yenilemek («Yenile») aynı kapsam, kanal ve IP aralıklarıyla ikiz bir anahtar üretir. Eski anahtar bir geçiş süresi daha çalışır: varsayılan 24 saat, en çok 7 gün.
  • Firma sahibi etkin bir anahtarın kapsamlarını ve kanalını sırrını değiştirmeden güncelleyebilir; değişiklik sonraki istekte geçerlidir.
Kapsamlar
Kapsamİzin verdiği
her anahtarGET /v1/channels ve GET /v1/channels/{id}, yalnızca anahtarın kanalları
messages:sendPOST /v1/messages ve POST /v1/messages/{id}/read
messages:readGET /v1/messages ve GET /v1/messages/{id}
templates:readGET /v1/templates ve GET /v1/templates/{id}
contacts:readPOST /v1/contacts/lookup
media:writePOST /v1/media
media:readGET /v1/media/{id} ve GET /v1/media/{id}/content
events:readGET /v1/events
consents:writeŞablon gönderiminde satır içi consent (izin kaydı)
conversations:writeVerilebilir; bugün bunu kullanan bir uç nokta yok
Paneldeki hazır kapsam seçimleri
SeçimKapsamlar
botmessages:send, messages:read, conversations:write, media:read, media:write, templates:read, contacts:read
«Bildirim gönderici» (notifier)messages:send, messages:read, media:write, templates:read, contacts:read, consents:write, events:read
«Salt okuma» (read_only)messages:read, media:read, templates:read, contacts:read, events:read

Hazır seçim, anahtar oluşturulurken anahtara kopyalanır. bot anahtarıyla olay yedeğini de okuyacaksanız events:read ekleyin.

Hızlı başlangıç

Anahtardan teslim edilen mesaja kadar. Örnekler sahne ortamının taban adresini ve uppu_test_ anahtarını kullanır; canlı için iki değişkeni değiştirin. Kimlikler uydurmadır: kendinizinkileri 1. adımdan alın.

Hazırlık: taban adres, anahtar ve küçük bir yardımcı işlev

cURL

# Sahne; canlı için https://messaging.uppu.net/v1 ve uppu_live_ anahtarı.
# Anahtarı depoya ya da günlüğe yazmayın.
export UPPU_API_BASE="https://messaging-staging.uppu.net/v1"
export UPPU_API_KEY="uppu_test_XXXXXXXXXXXX_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"

Anahtarı sır kasanızda ya da ortam değişkeninde tutun. Koda, günlüğe, destek kaydına ya da tarayıcıya koymayın.

1. Kanallarınızı listeleyin

GET/v1/channels

cURL

curl -sS "$UPPU_API_BASE/channels" \
  -H "Authorization: Bearer $UPPU_API_KEY" \
  -H "Accept: application/json"
Yanıt (kısaltılmış)
{"object": "list",
 "data": [{"object": "channel",
           "id": "01j9z0ch5k2m4n6p8q0r2s4t6v",
           "type": "whatsapp",
           "handling": "inbox",
           "sending": "active",
           "capabilities": {"content_types": ["text", "interactive", "image", "video", "audio",
                                              "document", "template", "reaction", "location"],
                            "limits": {"text_body": 4000, "buttons": 3},
                            "window_hours": 24,
                            "phone_addressing": true}}],
 "next_cursor": null}

capabilities her kanalın neyi gönderebildiğini söyler: içerik türleri, alan sınırları ve yanıt penceresi. Tek kanala bağlı anahtar yalnızca o kanalı görür.

2. Gönderilebilir bir şablon bulun

GET/v1/templates

cURL

curl -sS "$UPPU_API_BASE/templates?channel_id=01j9z0ch5k2m4n6p8q0r2s4t6v&status=APPROVED" \
  -H "Authorization: Bearer $UPPU_API_KEY"

Şablonlar kanalın arkasındaki WhatsApp Business hesabınındır; Meta ile 6 saatte bir ve paneldeki isteğinizle eşitlenir. Her şablonda sendable, unsendable_reason, parametre şeması ve send_example vardır: şablonun kendi örnek değerleriyle kurulmuş, olduğu gibi gönderilebilen bir content nesnesi.

3. Onaylı bir şablon gönderin

WhatsApp'ta onaylı şablon her zaman gönderilebilir. Diğer bütün türler 24 saatlik yanıt penceresini ister; pencere, kişinin son mesajından Meta'nın saatiyle sayılır.

POST/v1/messages

cURL

curl -sS -X POST "$UPPU_API_BASE/messages" \
  -H "Authorization: Bearer $UPPU_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: siparis-1001-kargo" \
  -d '{"channel_id": "01j9z0ch5k2m4n6p8q0r2s4t6v",
       "to": {"contact_id": "01j8x7ct5k2m4n6p8q0r2s4t6v"},
       "content": {"type": "template",
                   "template": {"name": "order_update", "language": "tr",
                                "body": {"parameters": ["Ayşe", "1001"]}}},
       "client_reference": "siparis-1001"}'
  • Hizmet (utility) şablonu kayıtlı bir hizmet izni ister; ya da kişinin bu numaradan, son geri çekmesinden sonra yazmış olması yeter.
  • Pazarlama (marketing) şablonu kayıtlı pazarlama izni ister. Kişi DUR, STOP ya da İPTAL yazarsa izin geri çekilir.
  • Kimlik doğrulama (authentication) şablonu gönderilmez: 422 template_category_not_allowed.
  • Sıralı (positional) şablon liste alır (["Ayşe", "1001"]; ilk değer {{1}}), adlı (named) şablon ad ve değer nesnesi alır. Değerler yalnızca metindir.

Size hiç yazmamış bir WhatsApp numarasına "to": {"phone": "+905550000001"} ile gönderin ve satır içi consent ekleyin (kapsam consents:write):

JSON
"consent": {"purpose": "utility",
            "state": "granted",
            "source_text": "Kişinin onayladığı metnin aynısı (en çok 2000 karakter)",
            "source_ref": "web-form:7781",
            "collected_at": "2026-10-15T12:00:00Z"}

4. 24 saatlik pencere içinde serbest metinle yanıt verin

POST/v1/messages

cURL

curl -sS -X POST "$UPPU_API_BASE/messages" \
  -H "Authorization: Bearer $UPPU_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: yanit-01jab3t6ms2m4n6p8q0r2s4t6v" \
  -d '{"channel_id": "01j9z0ch5k2m4n6p8q0r2s4t6v",
       "to": {"contact_id": "01j8x7ct5k2m4n6p8q0r2s4t6v"},
       "content": {"type": "text", "text": {"body": "Siparişiniz yola çıktı."}},
       "client_reference": "siparis-1001"}'
Yanıt 202 (kısaltılmış)
{"object": "message",
 "id": "01jab3a1k9f2m4n6p8q0r2s4t6",
 "channel_id": "01j9z0ch5k2m4n6p8q0r2s4t6v",
 "conversation_id": "01jab39zcv2m4n6p8q0r2s4t6v",
 "direction": "out",
 "author": {"type": "api", "label": "Sipariş botu", "api_key_prefix": "k7Hq2mP0aZ1x"},
 "content": {"type": "text", "text": {"body": "Siparişiniz yola çıktı.", "preview_url": false}},
 "status": "queued",
 "error": null,
 "client_reference": "siparis-1001",
 "provider_message_id": null,
 "created_at": "2026-10-20T09:20:00.120Z"}

Mesajın id'sini saklayın. Durumlar message.status webhook'larıyla gelir (accepted, sent, delivered, read ya da failed) ve sizin client_reference değerinizi taşır. Açık konuşması olmayan kişiye gönderim, baştan çözülmüş yeni bir konuşmaya kaydedilir; kişinin yanıtı her zamanki gibi konuşma açar.

5. Güvenle tekrar deneyin

Idempotency-Key sonuçları
DurumUPPU ne yaparSiz ne yaparsınız
Aynı anahtar, aynı gövdeİlk mesajın güncel hâliyle 200 ve Idempotent-Replayed: trueHiçbir şey: çift mesaj gitmedi
Aynı anahtar, farklı gövde409 idempotency_key_reusedKodu düzeltin: bir mantıksal gönderime bir anahtar ve bir gövde
Ağ hatası, 429 ya da 5xxİlk deneme kaydedilmiş de olabilir, kaydedilmemiş deRetry-After kadar bekleyip aynı anahtar ve gövdeyle tekrar deneyin
Politika reddi (ör. window_closed)Hiçbir şey gönderilmez, anahtar tutulmazNedeni giderin; aynı anahtar yeniden değerlendirilir
Sonradan failed durumu gelirGönderim kesinleşmiştirYeni gönderim yeni anahtar ister
  • Gövdedeki her değeri, client_reference ve consent.collected_at dahil, iş olayından türetin; denemeden ya da şimdiki zamandan değil.
  • window_closed (422) bir alarm değil, beklenen bir sonuçtur: WhatsApp'ta şablon gönderin, Messenger ve Instagram'da kişinin yeniden yazmasını bekleyin.
  • Anahtarlar kanal başına kalıcı olarak tekildir. Her mantıksal gönderim için bir UUID ya da ULID güvenli bir seçimdir.

Uç noktalar

Bugün çalışan bütün uç noktalar bunlardır; yollar taban adrese göredir. Her parametre ve şema API başvuru belgesindedir (İngilizce).

API v1 uç noktaları
Yöntem ve yolKapsamNe işe yarar
GET /v1/channels
GET /v1/channels/{id}
her anahtarKanallar, durumları ve capabilities
POST /v1/messagesmessages:sendMesaj gönderme; Idempotency-Key zorunlu
GET /v1/messages
GET /v1/messages/{id}
messages:readWebhook boşluğundan sonra mutabakat; tek mesajı okuma
POST /v1/messages/{id}/readmessages:sendGelen WhatsApp mesajına okundu bildirimi
POST /v1/contacts/lookupcontacts:readTelefon ya da kimlikle kişi arama; kişisel veri adrese girmez
GET /v1/templates
GET /v1/templates/{id}
templates:readsendable ve send_example ile WhatsApp şablonları
GET /v1/eventsevents:readSon 7 günün webhook olayları
POST /v1/mediamedia:writeGönderilecek dosyayı yükleme (çok parçalı, en çok 25 MB)
GET /v1/media/{id}
GET /v1/media/{id}/content
media:readDosya bilgisi; dosyayı indirme
GET /v1/openapi.jsonanahtarsızBu API'nin OpenAPI belgesi

Kurallar

  • Kimlikler 26 karakterlik küçük harfli ULID'lerdir (^[0-9a-hjkmnp-tv-z]{26}$); her nesnede object alanı bulunur.
  • Zamanlar UTC'de, milisaniyeli RFC 3339'dur (2026-10-20T09:20:00.120Z). Boş alanlar null değeriyle her zaman yer alır.
  • Telefon numaraları artı işaretli E.164'tür (+905550000001). Kişisel veri hiçbir zaman adrese girmez: kişiyi POST /v1/contacts/lookup ile arayın.
  • Bilinmeyen istek alanı 422 validation_failed alır, alan kodu unknown_field.
  • İleri uyumluluk: UPPU v1 içinde yeni alan, uç nokta, olay türü, enum değeri, içerik türü ve hata kodu ekleyebilir. Tanımadığınız alanları ve olay türlerini yok sayın, bilinmeyen enum değerlerini kabul edin, bilinmeyen content.type'ı unsupported sayın.
  • Listeler limit (1-100, varsayılan 25), cursor, order=asc|desc, created_after ve created_before alır; {"object":"list","data":[…],"next_cursor":…} döner. İmleç sıralamayı taşır; zaman süzgeçlerini her sayfada tekrarlayın.
  • Başlıklar: her yanıtta X-Request-Id bulunur (en çok 64 görünür ASCII karakterlik kendi değeriniz aynen döner). Ayrıca RateLimit-Limit, RateLimit-Remaining, RateLimit-Reset, Retry-After ve yeniden oynatmada Idempotent-Replayed: true.
  • Dil: Accept-Language: tr ya da en yalnızca error.message'ı değiştirir. Kararlı sözleşme error.code'dur.

Hız ve boyut sınırları

API anahtarı başına hız sınırları
NeredeSınır
Bütün uç noktalarOrtalama saniyede 50 istek (dakikada 3.000), anlık en çok 100
Gönderim ve okundu bildirimi birlikteSaniyede 20
GET /v1/eventsSaniyede 2
POST /v1/mediaSaniyede 2 ve günde 1 GB
GET /v1/media/{id}/contentSaniyede 10 ve saatte 2 GB
Kanalın gönderim kuyruğu10.000 ya da daha fazla gönderim bekliyorsa ya da en eskisi 15 dakikadan eskiyse 429 channel_backlog ve Retry-After: 30
  • İstek gövdesi en çok 1 MB olabilir (413 payload_too_large). POST /v1/media, en çok 25 MB'lık dosyayla 26 MB'a kadar gövde alır.
  • Bir ağdan gelen geçersiz anahtarlar dakikada 30 sınırını aşarsa o ağ 10 dakika kilitlenir. 401 alan isteği döngüde tekrarlamayın.

Hatalar

Her hata aynı zarfla döner. code kararlı sözleşmedir; message, Accept-Language'a göre insanlar için yazılmış metindir.

Hata zarfı
{"error": {"type": "policy",
           "code": "window_closed",
           "status": 422,
           "retryable": false,
           "message": "İnsan için metin (Accept-Language'e göre; koda bağlamayın)",
           "request_id": "01jace0e1v2m4n6p8q0r2s4t6a",
           "doc_url": "https://messaging.uppu.net/docs/errors#window_closed",
           "details": {"window_closed_at": "2026-10-19T08:58:00.000Z", "hint": "send_template"},
           "provider_error": null}}

retryable yalnızca media_not_ready, rate_limited, channel_backlog, internal_error ve service_unavailable kodlarında doğrudur. Bunları Retry-After kadar bekleyip aynı Idempotency-Key ve gövdeyle tekrar deneyin.

En sık hata kodları
KodHTTPNe yapmalı
missing_api_key401Her istekte Authorization: Bearer … gönderin.
invalid_api_key401Anahtar bilinmiyor, iptal edilmiş ya da süresi dolmuş, ya da firma kapalı. Etkin bir anahtar kullanın; döngüde tekrar etmeyin.
wrong_environment401Canlıda uppu_test_ ya da sahnede uppu_live_ anahtarı. O ortamın anahtarını kullanın.
insufficient_scope403details.required eksik kapsamı söyler. Anahtara ekleyin ya da başka bir anahtar kullanın.
idempotency_key_required400POST /v1/messages 1-64 karakterlik bir Idempotency-Key ister (A-Z a-z 0-9 . _ : -).
idempotency_key_reused409Aynı anahtar, farklı gövde. İlk gönderim zaten var; tekrarı bayt bayt aynı kurun ya da yeni mantıksal gönderime yeni anahtar verin.
validation_failed422details.fields her alanı ve kodunu listeler (ör. unknown_field, too_long). İsteği düzeltin.
window_closed42224 saatlik pencere kapalı. details.hint: send_template (WhatsApp) ya da wait_for_contact (Messenger, Instagram, web sohbeti).
consent_required422Şablonun kategorisi kayıtlı izin ister. Şablonu, kişiden alınmış izinle birlikte satır içi consent ile gönderin.
template_not_approved422Şablon APPROVED değil (details.status). sendable: true olan bir şablon seçin.
rate_limited429Retry-After kadar bekleyin, sonra aynı anahtar ve gövdeyle tekrar deneyin.
channel_backlog429Kanalın gönderim kuyruğu dolu. 30 saniye (Retry-After) bekleyip aynı anahtarla tekrar deneyin.

Hata kodlarının tam listesi, sonradan message.status ile gelen asenkron kodları da içerir.

Mesaj kuyruğa girdikten sonra

Meta'nın yanıtları sonradan, failed durumlu ve error.code taşıyan bir message.status olayıyla gelir; ör. window_closed, marketing_opt_out ya da recipient_unreachable. Yalnızca provider_rate_limited ve provider_unavailable tekrar denenebilir; yeniden gönderim yeni Idempotency-Key ister. UPPU geçici Meta hatalarını vazgeçmeden önce kendisi tekrar dener. unknown durumunda yeniden göndermeyin: 10 dakika sonra mesajda error.code olarak delivery_unverified görünür.

Kim yanıtlar: gelen kutusu kipi ya da API kipi

Her kanalın bir yönetim kipi vardır; firma sahibi panelden seçer. API kipinde kanalı kendi botunuz ya da sisteminiz yönetir, ekibiniz gerektiğinde gelen kutusundan yine devreye girebilir.

Gelen kutusu kipi ve API kipi
ÖzellikGelen kutusu kipiAPI kipi
Gelen mesajlar, kişiler ve konuşmalarKaydedilirKaydedilir
Webhook olaylarıAbone olursanızAbone olursanız
Temsilcilere otomatik atamaYalnızca web sohbetinde, kanalın ayarına göreKapalı
Yanıtsız konuşma e-postasıGelen kutusunda kimse yokkenKapalı
Temsilciler gelen kutusundan yanıt verebilirEvetEvet
Etkinliksiz açık konuşmaAçık kalır24 saat sonra çözülür

Sisteminizin gönderdiği mesajlar konuşmada “API · anahtar etiketi” olarak görünür. Botunuz temsilcilerin yazdıklarını da görsün istiyorsanız message.created olayına abone olun.

Kaynaklar

Neyi bağlamak istediğinizi yazın.

API'yi firmanız için açar, kendi senaryonuzla birlikte üzerinden geçeriz: bildirimler, kendi botunuz ya da CRM'iniz.

  • OpenAPI 3.1
  • Standard Webhooks
  • curl, PHP, Node.js, Python