Hızlı başlangıç
Anahtardan teslim edilen mesaja dört adım; curl, PHP, Node.js ve Python ile.
Geliştiriciler
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.
İ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"}'Yanıt
HTTP/1.1 202 Accepted
Content-Type: application/json
X-Request-Id: 01jab3a1k9f2m4n6p8q0r2s4t6
{"object": "message",
"id": "01jab3a1k9f2m4n6p8q0r2s4t6",
"channel_type": "whatsapp",
"direction": "out",
"status": "queued",
"client_reference": "siparis-1001",
"provider_message_id": null}Webhook
POST /uppu/webhook HTTP/1.1
Host: api.firmaniz.example
webhook-id: 01jace0e1v2m4n6p8q0r2s4t6b
webhook-timestamp: 1792488003
webhook-signature: v1,K5oZfzN95Z9UVu1EsfQmfVNQhnkZ2pj9o9NDN/H/pI4=
Uppu-Event-Type: message.status
{"type": "message.status",
"data": {"status": "delivered", "previous_status": "sent",
"message": {"id": "01jab3a1k9f2m4n6p8q0r2s4t6",
"client_reference": "siparis-1001"}}}message.statusAnahtardan teslim edilen mesaja dört adım; curl, PHP, Node.js ve Python ile.
Mesajlar, durumlar ve kişiler için imzalı olaylar; doğrulayıcınız için deneme vektörü.
Her uç nokta, parametre ve şema; OpenAPI belgesinden üretilir.
Tek hata zarfı, en sık kodlar ve her birinde ne yapmanız gerektiği.
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.
| Ortam | Panel | API taban adresi | Anahtar öneki |
|---|---|---|---|
| Canlı | https://app.uppu.net | https://messaging.uppu.net/v1 | uppu_live_ |
| Sahne | https://staging.uppu.net | https://messaging-staging.uppu.net/v1 | uppu_test_ |
Öteki ortamın anahtarı 401 wrong_environment alır. API yalnızca bu iki adreste yanıt verir; panel bu adreslerde sunulmaz.
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.
Firma sahibi anahtarı ekip ayarlarındaki «Geliştiriciler» sayfasında oluşturur. Oluştururken sahibin parolası sorulur; anahtar yalnızca bir kez gösterilir.
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.
uppu_live_, 12 karakter, _, 43 karakter (sahnede uppu_test_). Önek sayesinde sır tarayıcıları sızan anahtarı tanır.| Kapsam | İzin verdiği |
|---|---|
| her anahtar | GET /v1/channels ve GET /v1/channels/{id}, yalnızca anahtarın kanalları |
messages:send | POST /v1/messages ve POST /v1/messages/{id}/read |
messages:read | GET /v1/messages ve GET /v1/messages/{id} |
templates:read | GET /v1/templates ve GET /v1/templates/{id} |
contacts:read | POST /v1/contacts/lookup |
media:write | POST /v1/media |
media:read | GET /v1/media/{id} ve GET /v1/media/{id}/content |
events:read | GET /v1/events |
consents:write | Şablon gönderiminde satır içi consent (izin kaydı) |
conversations:write | Verilebilir; bugün bunu kullanan bir uç nokta yok |
| Seçim | Kapsamlar |
|---|---|
bot | messages: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.
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.
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"PHP
<?php
// PHP 8+, cURL eklentisi. Döner: ['status' => int, 'body' => array|null].
function uppu_request(string $method, string $path, ?array $body = null, ?string $idempotencyKey = null): array
{
$base = rtrim(getenv('UPPU_API_BASE') ?: 'https://messaging-staging.uppu.net/v1', '/');
$headers = ['Authorization: Bearer ' . getenv('UPPU_API_KEY'), 'Accept: application/json'];
if ($body !== null) {
$headers[] = 'Content-Type: application/json';
}
if ($idempotencyKey !== null) {
$headers[] = 'Idempotency-Key: ' . $idempotencyKey;
}
$ch = curl_init($base . '/' . ltrim($path, '/'));
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => $method,
CURLOPT_HTTPHEADER => $headers,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CONNECTTIMEOUT => 5,
CURLOPT_TIMEOUT => 20,
]);
if ($body !== null) {
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($body, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
}
$raw = curl_exec($ch);
$status = (int) curl_getinfo($ch, CURLINFO_RESPONSE_CODE); // 0: ağ hatası, aynı anahtarla tekrar deneyin
return ['status' => $status, 'body' => is_string($raw) && $raw !== '' ? json_decode($raw, true) : null];
}Node.js
// Node.js 18+, yerleşik fetch. Döner: { status, data, retryAfter }.
const BASE = process.env.UPPU_API_BASE ?? 'https://messaging-staging.uppu.net/v1';
export async function uppuRequest(method, path, body, idempotencyKey) {
const headers = { Authorization: `Bearer ${process.env.UPPU_API_KEY}`, Accept: 'application/json' };
if (body !== undefined) headers['Content-Type'] = 'application/json';
if (idempotencyKey) headers['Idempotency-Key'] = idempotencyKey;
const res = await fetch(`${BASE}/${path}`, {
method,
headers,
body: body === undefined ? undefined : JSON.stringify(body),
signal: AbortSignal.timeout(20000),
});
const data = await res.json().catch(() => null);
return { status: res.status, data, retryAfter: res.headers.get('retry-after') };
}Python
# Python 3.9+, yalnızca standart kitaplık. Döner: (durum, çözülmüş JSON ya da None).
import json
import os
import urllib.error
import urllib.request
BASE = os.environ.get("UPPU_API_BASE", "https://messaging-staging.uppu.net/v1")
def uppu_request(method, path, body=None, idempotency_key=None):
headers = {"Authorization": f"Bearer {os.environ['UPPU_API_KEY']}", "Accept": "application/json"}
data = None
if body is not None:
data = json.dumps(body, ensure_ascii=False).encode("utf-8")
headers["Content-Type"] = "application/json"
if idempotency_key:
headers["Idempotency-Key"] = idempotency_key
request = urllib.request.Request(f"{BASE}/{path}", data=data, headers=headers, method=method)
try:
with urllib.request.urlopen(request, timeout=20) as response:
return response.status, json.loads(response.read() or b"null")
except urllib.error.HTTPError as error: # 4xx ve 5xx hata zarfını taşır
try:
return error.code, json.loads(error.read() or b"null")
except ValueError:
return error.code, NoneAnahtarı 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.
cURL
curl -sS "$UPPU_API_BASE/channels" \
-H "Authorization: Bearer $UPPU_API_KEY" \
-H "Accept: application/json"PHP
$r = uppu_request('GET', 'channels');
foreach ($r['body']['data'] ?? [] as $channel) {
echo $channel['id'], ' ', $channel['type'], ' ', $channel['sending'], PHP_EOL;
}Node.js
const { data: page } = await uppuRequest('GET', 'channels');
for (const channel of page.data) {
console.log(channel.id, channel.type, channel.sending);
}Python
status, page = uppu_request("GET", "channels")
for channel in page["data"]:
print(channel["id"], channel["type"], channel["sending"]){"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.
cURL
curl -sS "$UPPU_API_BASE/templates?channel_id=01j9z0ch5k2m4n6p8q0r2s4t6v&status=APPROVED" \
-H "Authorization: Bearer $UPPU_API_KEY"PHP
$query = http_build_query(['channel_id' => '01j9z0ch5k2m4n6p8q0r2s4t6v', 'status' => 'APPROVED']);
$r = uppu_request('GET', 'templates?' . $query);
foreach ($r['body']['data'] ?? [] as $template) {
// sendable, unsendable_reason, parametreler ve hazır send_example
echo $template['name'], ' ', $template['language'], ' ', $template['sendable'] ? 'ok' : $template['unsendable_reason'], PHP_EOL;
}Node.js
const query = new URLSearchParams({ channel_id: '01j9z0ch5k2m4n6p8q0r2s4t6v', status: 'APPROVED' });
const { data: page } = await uppuRequest('GET', `templates?${query}`);
for (const t of page.data) {
console.log(t.name, t.language, t.sendable ? 'ok' : t.unsendable_reason);
}Python
from urllib.parse import urlencode
query = urlencode({"channel_id": "01j9z0ch5k2m4n6p8q0r2s4t6v", "status": "APPROVED"})
status, page = uppu_request("GET", f"templates?{query}")
for t in page["data"]:
print(t["name"], t["language"], "ok" if t["sendable"] else t["unsendable_reason"])Ş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.
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.
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"}'PHP
// Bir mantıksal gönderim = bir anahtar. Tekrar denemede AYNI anahtar ve AYNI gövde.
$r = uppu_request('POST', 'messages', [
'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',
], 'siparis-1001-kargo');Node.js
// Bir mantıksal gönderim = bir anahtar. Tekrar denemede AYNI anahtar ve AYNI gövde.
const { status, data } = await uppuRequest('POST', 'messages', {
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',
}, 'siparis-1001-kargo');Python
# Bir mantıksal gönderim = bir anahtar. Tekrar denemede AYNI anahtar ve AYNI gövde.
status, message = uppu_request("POST", "messages", {
"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",
}, idempotency_key="siparis-1001-kargo")422 template_category_not_allowed.["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):
"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"}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"}'PHP
$r = uppu_request('POST', 'messages', [
'channel_id' => '01j9z0ch5k2m4n6p8q0r2s4t6v',
'to' => ['contact_id' => '01j8x7ct5k2m4n6p8q0r2s4t6v'],
'content' => ['type' => 'text', 'text' => ['body' => 'Siparişiniz yola çıktı.']],
'client_reference' => 'siparis-1001',
], 'yanit-01jab3t6ms2m4n6p8q0r2s4t6v');
if ($r['status'] === 202 || $r['status'] === 200) {
$messageId = $r['body']['id']; // saklayın; durumlar message.status webhook'larıyla gelir
} else {
$code = $r['body']['error']['code'] ?? 'http_' . $r['status']; // ör. window_closed
}Node.js
const { status, data } = await uppuRequest('POST', 'messages', {
channel_id: '01j9z0ch5k2m4n6p8q0r2s4t6v',
to: { contact_id: '01j8x7ct5k2m4n6p8q0r2s4t6v' },
content: { type: 'text', text: { body: 'Siparişiniz yola çıktı.' } },
client_reference: 'siparis-1001',
}, 'yanit-01jab3t6ms2m4n6p8q0r2s4t6v');
if (status === 202 || status === 200) {
console.log('kaydedildi', data.id); // durumlar message.status webhook'larıyla gelir
} else {
console.log('reddedildi', data?.error?.code); // ör. window_closed
}Python
status, message = uppu_request("POST", "messages", {
"channel_id": "01j9z0ch5k2m4n6p8q0r2s4t6v",
"to": {"contact_id": "01j8x7ct5k2m4n6p8q0r2s4t6v"},
"content": {"type": "text", "text": {"body": "Siparişiniz yola çıktı."}},
"client_reference": "siparis-1001",
}, idempotency_key="yanit-01jab3t6ms2m4n6p8q0r2s4t6v")
if status in (200, 202):
print("kaydedildi", message["id"]) # durumlar message.status webhook'larıyla gelir
else:
print("reddedildi", message["error"]["code"]) # ör. window_closed{"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.
| Durum | UPPU ne yapar | Siz ne yaparsınız |
|---|---|---|
| Aynı anahtar, aynı gövde | İlk mesajın güncel hâliyle 200 ve Idempotent-Replayed: true | Hiçbir şey: çift mesaj gitmedi |
| Aynı anahtar, farklı gövde | 409 idempotency_key_reused | Kodu 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ş de | Retry-After kadar bekleyip aynı anahtar ve gövdeyle tekrar deneyin |
Politika reddi (ör. window_closed) | Hiçbir şey gönderilmez, anahtar tutulmaz | Nedeni giderin; aynı anahtar yeniden değerlendirilir |
Sonradan failed durumu gelir | Gönderim kesinleşmiştir | Yeni gönderim yeni anahtar ister |
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.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).
| Yöntem ve yol | Kapsam | Ne işe yarar |
|---|---|---|
GET /v1/channelsGET /v1/channels/{id} | her anahtar | Kanallar, durumları ve capabilities |
POST /v1/messages | messages:send | Mesaj gönderme; Idempotency-Key zorunlu |
GET /v1/messagesGET /v1/messages/{id} | messages:read | Webhook boşluğundan sonra mutabakat; tek mesajı okuma |
POST /v1/messages/{id}/read | messages:send | Gelen WhatsApp mesajına okundu bildirimi |
POST /v1/contacts/lookup | contacts:read | Telefon ya da kimlikle kişi arama; kişisel veri adrese girmez |
GET /v1/templatesGET /v1/templates/{id} | templates:read | sendable ve send_example ile WhatsApp şablonları |
GET /v1/events | events:read | Son 7 günün webhook olayları |
POST /v1/media | media:write | Gönderilecek dosyayı yükleme (çok parçalı, en çok 25 MB) |
GET /v1/media/{id}GET /v1/media/{id}/content | media:read | Dosya bilgisi; dosyayı indirme |
GET /v1/openapi.json | anahtarsız | Bu API'nin OpenAPI belgesi |
^[0-9a-hjkmnp-tv-z]{26}$); her nesnede object alanı bulunur.2026-10-20T09:20:00.120Z). Boş alanlar null değeriyle her zaman yer alır.+905550000001). Kişisel veri hiçbir zaman adrese girmez: kişiyi POST /v1/contacts/lookup ile arayın.422 validation_failed alır, alan kodu unknown_field.content.type'ı unsupported sayın.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.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.Accept-Language: tr ya da en yalnızca error.message'ı değiştirir. Kararlı sözleşme error.code'dur.| Nerede | Sınır |
|---|---|
| Bütün uç noktalar | Ortalama saniyede 50 istek (dakikada 3.000), anlık en çok 100 |
| Gönderim ve okundu bildirimi birlikte | Saniyede 20 |
GET /v1/events | Saniyede 2 |
POST /v1/media | Saniyede 2 ve günde 1 GB |
GET /v1/media/{id}/content | Saniyede 10 ve saatte 2 GB |
| Kanalın gönderim kuyruğu | 10.000 ya da daha fazla gönderim bekliyorsa ya da en eskisi 15 dakikadan eskiyse 429 channel_backlog ve Retry-After: 30 |
413 payload_too_large). POST /v1/media, en çok 25 MB'lık dosyayla 26 MB'a kadar gövde alır.401 alan isteği döngüde tekrarlamayın.Her hata aynı zarfla döner. code kararlı sözleşmedir; message, Accept-Language'a göre insanlar için yazılmış metindir.
{"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.
| Kod | HTTP | Ne yapmalı |
|---|---|---|
missing_api_key | 401 | Her istekte Authorization: Bearer … gönderin. |
invalid_api_key | 401 | Anahtar bilinmiyor, iptal edilmiş ya da süresi dolmuş, ya da firma kapalı. Etkin bir anahtar kullanın; döngüde tekrar etmeyin. |
wrong_environment | 401 | Canlıda uppu_test_ ya da sahnede uppu_live_ anahtarı. O ortamın anahtarını kullanın. |
insufficient_scope | 403 | details.required eksik kapsamı söyler. Anahtara ekleyin ya da başka bir anahtar kullanın. |
idempotency_key_required | 400 | POST /v1/messages 1-64 karakterlik bir Idempotency-Key ister (A-Z a-z 0-9 . _ : -). |
idempotency_key_reused | 409 | Aynı 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_failed | 422 | details.fields her alanı ve kodunu listeler (ör. unknown_field, too_long). İsteği düzeltin. |
window_closed | 422 | 24 saatlik pencere kapalı. details.hint: send_template (WhatsApp) ya da wait_for_contact (Messenger, Instagram, web sohbeti). |
consent_required | 422 | Şablonun kategorisi kayıtlı izin ister. Şablonu, kişiden alınmış izinle birlikte satır içi consent ile gönderin. |
template_not_approved | 422 | Şablon APPROVED değil (details.status). sendable: true olan bir şablon seçin. |
rate_limited | 429 | Retry-After kadar bekleyin, sonra aynı anahtar ve gövdeyle tekrar deneyin. |
channel_backlog | 429 | Kanalı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.
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.
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.
| Özellik | Gelen kutusu kipi | API kipi |
|---|---|---|
| Gelen mesajlar, kişiler ve konuşmalar | Kaydedilir | Kaydedilir |
| Webhook olayları | Abone olursanız | Abone olursanız |
| Temsilcilere otomatik atama | Yalnızca web sohbetinde, kanalın ayarına göre | Kapalı |
| Yanıtsız konuşma e-postası | Gelen kutusunda kimse yokken | Kapalı |
| Temsilciler gelen kutusundan yanıt verebilir | Evet | Evet |
| Etkinliksiz açık konuşma | Açık kalır | 24 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.
Kurulum, istek biçimi, olay türleri, üç dilde imza doğrulama ve teslim kuralları.
OpenAPI belgesinden üretilir: her uç nokta, parametre, şema ve webhook olayı.
Canlı belge, messaging.uppu.net'te anahtarsız sunulur. API istemcinize ya da kod üreticinize yükleyin.
Eşzamanlı ve asenkron her hata kodu, anlamı ve tekrar denenip denenmeyeceği.
API'yi firmanız için açar, kendi senaryonuzla birlikte üzerinden geçeriz: bildirimler, kendi botunuz ya da CRM'iniz.