İçeriğe geç

Geliştirici

Messaging API v1

WhatsApp, Instagram, X ve website sohbetlerini sunucunuzdan okuyun ve yanıtlayın. WhatsApp’ta 24 saat dışında onaylı şablon zorunludur. Anahtar düz metin saklanmaz; her istek HMAC-SHA256 ile imzalanır.

Temel URL

https://www.aidiance.com/api/v1/{resource}

JSON. CORS yok (tarayıcıya anahtar koymayın). Yalnızca HTTPS. Anahtarları panelden oluşturun: Ayarlar → Entegrasyon.

Kimlik doğrulama

Her istekte dört başlık zorunludur:

BaşlıkAçıklama
AuthorizationBearer aid_live_… — panelde bir kez gösterilir, sunucuda yalnızca HMAC karması tutulur.
X-Aidiance-TimestampUnix saniye (UTC). ±5 dakika pencere.
X-Aidiance-Nonce16–64 hex karakter, anahtar başına tek kullanımlık (replay koruması).
X-Aidiance-SignatureAşağıdaki kanonik metnin HMAC-SHA256 (hex) değeri.
X-Aidiance-Idempotency-Keyİsteğe bağlı (POST gönderim). 24 saat aynı yanıtı döndürür; çift mesajı önler.

Yetkiler (scope): conversations.read, messages.read, messages.send, webhooks.manage (REST hooks), inbox.embed (gömülü konuşmalar). Anahtar isteğe bağlı IP allowlist ve asistan kısıtı ile üretilir.

İmza algoritması

UTF-8, satır sonu \n:

timestamp
nonce
METHOD
resource
canonicalQuery
sha256hex(body)
  • METHOD büyük harf, isteğin gerçek yöntemi: GET / POST (silme de X-HTTP-Method-Override: DELETE başlıklı POST ile yapılır ve POST olarak imzalanır)
  • resource küçük harf, /api/v1/ sonrasındaki yol: messages, conversations, webhooks, webhooks/42, …
  • canonicalQuery: resource hariç sorgu parametreleri, anahtara göre sıralı key=urlencode(value). POST’ta boş satır.
  • body ham baytlar (GET’te boş; SHA-256 boş gövde = e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855)

İmza: HMAC-SHA256(api_key, payload) küçük harf hex. Gönderilen JSON ile hash’lenen gövde birebir aynı olmalıdır.

Konuşma kimliği

Kanalconversation_id
wa:{asistan_token}:{telefon} — telefon ülke kodu ile, yalnızca rakam
instagramig:{asistan_token}:{participant_id}
twitterx:{asistan_token}:{participant_id}
webweb:{grpid}

Liste uçundan gelen id alanını olduğu gibi kullanın. WhatsApp 24 saatlik oturum penceresi Meta kurallarına tabidir.

Uçlar

GET/api/v1/me

Anahtar adı, scope ve kanal özeti. Gövde yok.

GET/api/v1/assistants

Hesaba (ve anahtar kısıtına) ait asistanlar. Scope: conversations.read veya messages.read.

GET/api/v1/conversations

Sorgu: channel (whatsapp | instagram | twitter | web, boş = izinli hepsi), limit (1–50).

{
  "ok": true,
  "items": [
    {
      "id": "wa:TOKEN:905551112233",
      "channel": "whatsapp",
      "assistant_token": "TOKEN",
      "assistant_name": "Satış",
      "contact": "Ayşe",
      "handle": "905551112233",
      "last_message": "Merhaba",
      "last_at": "2026-09-10T16:01:00"
    }
  ]
}

GET/api/v1/messages

Sorgu: conversation_id (zorunlu), since_id (dahil değil, polling), limit (1–50).

{
  "ok": true,
  "items": [
    {
      "id": 1201,
      "provider_id": "wamid....",
      "direction": "inbound",
      "type": "text",
      "text": "Fiyat nedir?",
      "status": "",
      "created_at": "2026-09-10T16:00:12"
    }
  ]
}

Yeni mesaj için son gördüğünüz id ile since_id gönderin (en fazla birkaç saniyede bir; rate limit).

POST/api/v1/messages

{
  "conversation_id": "wa:TOKEN:905551112233",
  "text": "Merhaba, nasıl yardımcı olabilirim?"
}

veya:

{
  "channel": "whatsapp",
  "assistant_token": "TOKEN",
  "to": "905551112233",
  "text": "Merhaba"
}

Başarılı: ok, message_id, conversation_id. Metin en fazla 4096 karakter. WhatsApp’ta 24 saatlik müşteri penceresi kapandıysa serbest metin gitmez; aşağıda şablon gönderimi kullanın.

WhatsApp şablonları (yeni sohbet / 24 saat dışı)

Meta kuralı: müşteri son 24 saatte yazmadıysa yalnızca onaylı mesaj şablonu gönderilebilir. Şablonları panelde oluşturup Meta onayından geçirin; API yalnızca onaylı olanları listeler ve gönderir.

GET/api/v1/templates

Sorgu: assistant_token (zorunlu). Scope: messages.read veya messages.send.

{
  "ok": true,
  "items": [
    {
      "name": "karsilama",
      "language": "tr",
      "category": "UTILITY",
      "status": "APPROVED",
      "body_text": "Merhaba {{1}}, size nasıl yardımcı olabiliriz?",
      "body_variable_count": 1,
      "header_format": "TEXT",
      "header_variable_count": 0,
      "footer_text": ""
    }
  ]
}

POST/api/v1/messages (şablon)

text yerine template gönderin. Scope: messages.send. Aynı HMAC ve isteğe bağlı X-Aidiance-Idempotency-Key.

{
  "channel": "whatsapp",
  "assistant_token": "TOKEN",
  "to": "905551112233",
  "template": {
    "name": "karsilama",
    "language": "tr",
    "body_variables": ["Ayşe"],
    "header_variables": [],
    "header_media_url": "",
    "url_button_suffixes": []
  }
}

Mevcut konuşma için conversation_id da kullanılabilir:

{
  "conversation_id": "wa:TOKEN:905551112233",
  "template": {
    "name": "karsilama",
    "language": "tr",
    "body_variables": ["Ayşe"]
  }
}
  • body_variables: gövdedeki {{1}}, {{2}}, … sırasıyla. Sayı şablondaki body_variable_count ile aynı olmalı.
  • header_variables: üst bilgi metin değişkenleri (varsa).
  • header_media_url: başlık IMAGE/VIDEO/DOCUMENT ise herkese açık HTTPS URL (Meta dosyayı çeker).
  • url_button_suffixes: dinamik URL butonlarındaki {{1}} parçaları (varsa).

Başarılı yanıt: ok, message_id, conversation_id, template, language.

Kişi DUR / İPTAL yazarak pazarlama mesajlarından çıktıysa pazarlama (MARKETING) ya da kategorisi belirlenemeyen şablonlar gönderilmez ve 403 opted_out döner; hizmet (UTILITY) ve doğrulama (AUTHENTICATION) şablonları gönderilebilir.

Webhook'lar (giden olaylar)

Seçtiğiniz olaylar gerçekleştiğinde Aidiance, verdiğiniz HTTPS adresine JSON gövdeyle POST isteği gönderir. Webhook'ları panelde Ayarlar → Webhook & API sayfasından veya REST hooks uçlarıyla yönetin. Her webhook'un kendine ait bir gizli anahtarı (whsec_…) vardır.

POST https://sunucunuz.com/aidiance/webhook
Content-Type: application/json; charset=utf-8
User-Agent: Aidiance-Webhook/1.0
X-Aidiance-Event: message.received
X-Aidiance-Delivery: 18342
X-Aidiance-Timestamp: 1791043200
X-Aidiance-Signature: sha256=5f1c9e…
BaşlıkAçıklama
X-Aidiance-EventOlay adı (ör. message.received; panelden test gönderiminde test).
X-Aidiance-DeliveryTeslim numarası; aynı teslimin yeniden denemelerinde değişmez.
X-Aidiance-Timestampİsteğin imzalandığı an, Unix saniye (UTC); her denemede yenilenir.
X-Aidiance-Signaturesha256= + HMAC-SHA256(gizli anahtar, timestamp + "." + ham gövde), küçük harf hex.

Gövde

{
  "id": "9b2f6c1e-5d4a-4a8e-9f0b-3c7d2e1a6b54",
  "olay": "message.received",
  "zaman": "2026-10-03T14:05:00+03:00",
  "veri": { … }
}
  • id: olay kimliği. Yeniden denemelerde ve aynı olayın farklı webhook'lara teslimlerinde aynıdır; tekrarları bununla ayıklayın.
  • zaman: olayın oluştuğu an (ISO 8601, saat dilimi ofsetli).
  • veri: olaya özel alanlar. Yeni alanlar eklenebilir; tanımadığınız alanları yok sayın.
  • Panelden test gönderiminde gövdeye "test": true ve "ornek_olay" eklenir; veri seçilen olayın örnek verisidir.

Olaylar ve örnek yükler

OlayNe zaman?
message.receivedMüşteriden WhatsApp, Instagram (DM ve yorum), Messenger, X veya web sohbetinden yeni mesaj geldiğinde.
message.sentPanelden, AI'dan, otomatik kuraldan, şablondan, zamanlamadan, mobil uygulamadan veya API'den mesaj gönderildiğinde.
message.statusGiden mesaj iletildi (delivered), okundu (read) veya başarısız oldu (failed).
conversation.assignedKonuşma bir ekip üyesine atandığında.
conversation.status_changedKonuşma açık, beklemede veya kapalı olarak işaretlendiğinde (süre dolunca otomatik kapatma dahil).
conversation.handoffAI asistan konuşmayı insan desteğine devrettiğinde.
lead.createdAI asistan WhatsApp sohbetinden iletişim bilgisi (lead) yakalayıp Formlar'a kaydettiğinde.
order.reminder_sentE-ticaret entegrasyonu terk edilen sepet veya ödenmemiş sipariş için WhatsApp hatırlatması gönderdiğinde.
review.receivedGoogle İşletme profilinize yeni bir değerlendirme geldiğinde.

Mesaj olaylarındaki konusma_id, POST /api/v1/messages isteğindeki conversation_id ile aynı biçimdedir; desteklenen kanallarda gelen mesaja doğrudan yanıt verebilirsiniz. Aşağıdaki yükler örnektir; alanlar olayı üreten modüle göre genişleyebilir.

message.received

{
  "id": "9b2f6c1e-5d4a-4a8e-9f0b-3c7d2e1a6b54",
  "olay": "message.received",
  "zaman": "2026-10-03T14:05:00+03:00",
  "veri": {
    "kanal": "whatsapp",
    "asistan_token": "TOKEN",
    "asistan_adi": "Satış Asistanı",
    "konusma_anahtari": "905551112233",
    "konusma_id": "wa:TOKEN:905551112233",
    "kisi_adi": "Ayşe Yılmaz",
    "mesaj_id": "wamid.HBgM…",
    "tip": "text",
    "metin": "Merhaba, siparişim ne zaman kargoya verilir?",
    "yon": "gelen",
    "kaynak": "musteri",
    "mesaj_zamani": "2026-10-03T14:05:00+03:00"
  }
}

kanal: whatsapp, instagram, instagram_yorum, messenger, x, web. Medya mesajlarında medya_id, medya_url (varsa) ve mime alanları da gelir.

message.sent

"veri": {
  "kanal": "instagram",
  "asistan_token": "TOKEN",
  "asistan_adi": "Satış Asistanı",
  "konusma_anahtari": "17841400000000000",
  "konusma_id": "ig:TOKEN:17841400000000000",
  "kisi_adi": null,
  "mesaj_id": "aWdfZAG1…",
  "tip": "text",
  "metin": "Siparişiniz bugün kargoya verilecek.",
  "yon": "giden",
  "kaynak": "ai",
  "gonderen_kullanici_id": 0,
  "mesaj_zamani": "2026-10-03T14:05:04+03:00"
}

kaynak: panel, ai, otomatik, sablon, zamanlama, api, mobil, harici (kanalın kendi uygulamasından gönderilen). gonderen_kullanici_id panel ve mobil gönderimlerinde ekip üyesinin kimliğidir, diğerlerinde 0.

message.status

"veri": {
  "kanal": "whatsapp",
  "asistan_token": "TOKEN",
  "asistan_adi": "Satış Asistanı",
  "konusma_anahtari": "905551112233",
  "konusma_id": "wa:TOKEN:905551112233",
  "mesaj_id": "wamid.HBgM…",
  "durum": "read",
  "durum_zamani": "2026-10-03T14:06:10+03:00"
}

conversation.assigned

"veri": {
  "kanal": "whatsapp",
  "asistan": "TOKEN",
  "anahtar": "905551112233",
  "atanan_id": 42,
  "atanan_ad": "Mehmet Kaya",
  "atayan_id": 31,
  "otomatik": false,
  "zaman": "2026-10-03T14:05:00+03:00",
  "asistan_adi": "Satış Asistanı",
  "konusma_id": "wa:TOKEN:905551112233"
}

asistan asistan token'ı, anahtar konuşma anahtarıdır (WhatsApp'ta telefon). Otomatik atamada otomatik = true ve atayan_id = 0.

conversation.status_changed

"veri": {
  "kanal": "whatsapp",
  "asistan": "TOKEN",
  "anahtar": "905551112233",
  "durum": "kapali",
  "eski_durum": "acik",
  "degistiren_id": 31,
  "otomatik": false,
  "zaman": "2026-10-03T14:05:00+03:00",
  "asistan_adi": "Satış Asistanı",
  "konusma_id": "wa:TOKEN:905551112233"
}

durum: acik, beklemede, kapali. Süre dolunca otomatik kapatmada otomatik = true ve degistiren_id = 0.

conversation.handoff

"veri": {
  "kanal": "instagram",
  "asistan": "TOKEN",
  "anahtar": "17841400000000000",
  "neden": "Müşteri canlı destek istedi.",
  "atanan_id": 42,
  "zaman": "2026-10-03T14:05:00+03:00",
  "asistan_adi": "Satış Asistanı",
  "konusma_id": "ig:TOKEN:17841400000000000"
}

AI konuşmayı insan desteğine devrettiğinde gelir; otomatik atama yapılamadıysa atanan_id = 0.

lead.created

"veri": {
  "channel": "whatsapp",
  "assistant": "TOKEN",
  "conversation_key": "905551112233",
  "form_id": 1287,
  "fields": {
    "Ad Soyad": "Ayşe Yılmaz",
    "E-posta": "ayse@example.com",
    "Firma": "Yılmaz Tekstil",
    "Kaynak": "WhatsApp",
    "WhatsApp numarası": "905551112233"
  },
  "created_at": "2026-10-03T14:05:00+03:00",
  "assistant_name": "Satış Asistanı",
  "conversation_id": "wa:TOKEN:905551112233"
}

fields yalnızca dolu alanları içerir: Ad Soyad, E-posta, Telefon, Firma, Not; her zaman Kaynak ve WhatsApp numarası. form_id paneldeki Formlar kaydının numarasıdır.

order.reminder_sent

"veri": {
  "magaza_id": 3,
  "magaza": "Örnek Mağaza",
  "platform": "shopify",
  "sepet_id": 981,
  "tur": "sepet",
  "platform_ref": "c1-7f3a9e",
  "musteri": "Ayşe Yılmaz",
  "telefon": "905551112233",
  "eposta": "ayse@example.com",
  "toplam": 1249.9,
  "para_birimi": "TRY",
  "baglanti": "https://ornekmagaza.com/cart/c1-7f3a9e",
  "sablon": "sepet_hatirlatma",
  "mesaj_id": "wamid.HBgM…",
  "zaman": "2026-10-03T14:05:00+03:00"
}

tur: sepet (terk edilen sepet) veya siparis (ödenmemiş sipariş). platform: shopify, woocommerce, ikas, ideasoft, ticimax. Gönderilen WhatsApp şablonu ayrıca message.sent olayı (kaynak otomatik) olarak da gelir.

review.received

"veri": {
  "channel": "google",
  "assistant": "TOKEN",
  "review_id": 512,
  "google_review_name": "accounts/…/locations/…/reviews/…",
  "location": "Örnek Mağaza Kadıköy",
  "rating": 5,
  "comment": "Çok hızlı ve ilgili bir hizmet aldım.",
  "reviewer": "Ali Demir",
  "review_time": "2026-10-03T13:58:00+03:00",
  "has_reply": false,
  "assistant_name": "Satış Asistanı"
}
Olaylar, onları üreten modülün alan adlarını kullanır: mesaj ve konuşma olaylarında Türkçe, lead.created ve review.received olaylarında İngilizce anahtarlar. Aidiance bu olaylara asistan adını (asistan_adi / assistant_name) ve API ile yanıt vermek için kullanılabilecek konuşma kimliğini (konusma_id / conversation_id; WhatsApp, Instagram, X ve web için) ekler. Tüm zamanlar 2026-10-03T14:05:00+03:00 biçimindedir. Yeni alanlar eklenebilir; bilinmeyen alanları yok sayın.

Webhook imzasını doğrulama

  1. İsteğin ham gövdesini okuyun; JSON'u ayrıştırıp yeniden serileştirmeyin.
  2. imzalanan = X-Aidiance-Timestamp + "." + ham gövde (UTF-8).
  3. beklenen = "sha256=" + hex(HMAC-SHA256(gizli anahtar, imzalanan)) (küçük harf).
  4. X-Aidiance-Signature ile sabit zamanlı karşılaştırın; zaman damgası 5 dakikadan eskiyse isteği reddedin.
const crypto = require('crypto');
const express = require('express');
const app = express();

app.post('/aidiance/webhook', express.raw({ type: 'application/json' }), (req, res) => {
  const zaman = req.get('X-Aidiance-Timestamp') || '';
  const imza = req.get('X-Aidiance-Signature') || '';
  const govde = req.body.toString('utf8');
  const beklenen = 'sha256=' + crypto
    .createHmac('sha256', process.env.AIDIANCE_WEBHOOK_SECRET)
    .update(zaman + '.' + govde)
    .digest('hex');
  const gecerli = imza.length === beklenen.length &&
    crypto.timingSafeEqual(Buffer.from(imza), Buffer.from(beklenen));
  if (!gecerli || Math.abs(Date.now() / 1000 - Number(zaman)) > 300) return res.sendStatus(401);
  const olay = JSON.parse(govde); // olay.id ile tekrarları ayıklayın
  console.log(olay.olay, olay.veri);
  res.sendStatus(200);
});

Teslim ve yeniden deneme

  • Alıcı 10 saniye içinde 2xx döndürürse teslim başarılı sayılır; yönlendirmeler (3xx) izlenmez.
  • Başarısız teslimler 1 dk, 5 dk, 30 dk, 2 sa ve 6 sa sonra yeniden denenir (en fazla 6 deneme, toplam ~8,5 saat).
  • 410 Gone yanıtı aboneliği sonlandırır: webhook kapatılır, bekleyen teslimler iptal edilir.
  • Art arda 50 deneme başarısız olur ve 24 saat boyunca hiç başarılı teslim yapılamazsa webhook otomatik kapatılır; hesap sahibine panel bildirimi gönderilir.
  • Teslim en az bir kez garantilidir, sıra garanti edilmez: gövdedeki id ile tekrarları ayıklayın, uzun süren işleri kendi kuyruğunuza alın.
  • Yalnızca herkese açık https:// adresleri kabul edilir. Teslim kayıtları panelde 30 gün görüntülenir ve tek tıkla yeniden gönderilebilir.

REST hooks: webhook'ları API ile yönetme

Zapier veya Make için kendi uygulamanızı geliştiriyorsanız abonelikleri programatik olarak açıp kapatabilirsiniz. Scope: webhooks.manage (anahtarı oluştururken seçin). Webhook'lar hesap genelindeki olayları aldığından asistana kısıtlı anahtarlarla oluşturulamaz; özellik paketinize dahil olmalıdır.

GET/api/v1/webhooks

{
  "ok": true,
  "items": [
    {
      "id": 42,
      "name": "Zapier — CRM",
      "url": "https://hooks.zapier.com/hooks/catch/123456/abcdef/",
      "events": ["message.received", "lead.created"],
      "active": true,
      "source": "api",
      "created_at": "2026-10-03T14:00:00",
      "last_success_at": "2026-10-03T14:05:01",
      "consecutive_failures": 0
    }
  ]
}

POST/api/v1/webhooks

{
  "url": "https://hooks.zapier.com/hooks/catch/123456/abcdef/",
  "events": ["message.received", "lead.created"],
  "name": "Zapier — CRM"
}

events dizi, virgüllü metin veya tüm olaylar için "*" olabilir; url yerine target_url veya hookUrl da kabul edilir. Başarılı yanıt 201:

{
  "ok": true,
  "id": 42,
  "name": "Zapier — CRM",
  "url": "https://hooks.zapier.com/hooks/catch/123456/abcdef/",
  "events": ["message.received", "lead.created"],
  "active": true,
  "secret": "whsec_…"
}

secret yalnızca bu yanıtta döner; imza doğrulaması için saklayın (panelden de görüntülenebilir veya yenilenebilir).

Tekrarlanan istekler (idempotent). Bir hesapta aynı adrese yalnızca bir webhook olabilir; aksi halde her olay iki kez teslim edilirdi. Aynı anahtarla aynı url ve aynı olaylarla tekrar gönderilen istek yeni kayıt açmaz: mevcut webhook 200 ile döner (aynı id ve secret, "existing": true; kapatılmışsa yeniden açılır). Bu nedenle Zapier/Make subscribe adımında zaman aşımından sonra isteği güvenle yineleyebilirsiniz. Adres panelden, başka bir anahtarla ya da farklı olaylarla zaten kayıtlıysa 409 duplicate_webhook döner (mesajda mevcut kaydın id'si yer alır). Aynı hesapta eşzamanlı başka bir webhook işlemi sürüyorsa 409 busy döner; birkaç saniye sonra yineleyin.

GET/api/v1/webhooks/{id}

Tek webhook: { "ok": true, "item": { … } }. Eşdeğeri: GET /api/v1/webhooks?id=42.

POST/api/v1/webhooks/{id} + X-HTTP-Method-Override: DELETE

Webhook'u siler. İsteği POST olarak gönderip X-HTTP-Method-Override: DELETE başlığını ekleyin; gövde boş olabilir. Eşdeğeri: POST /api/v1/webhooks?id=42 + aynı başlık.

POST /api/v1/webhooks/42
X-HTTP-Method-Override: DELETE

{ "ok": true, "deleted": true, "id": 42 }
İmzada METHOD gerçek HTTP yöntemidir (POST); resource, /api/v1/ sonrasındaki yoldur (webhooks/42, ya da ?id= biçiminde webhooks ve canonicalQuery = id=42). Sunucu yapılandırması gerçek DELETE isteklerini engelleyebileceğinden bu yöntemi kullanın. Olmayan kimlik 404 not_found döner.

Zapier REST hook eşlemesi

  • Subscribe: POST /api/v1/webhooks, gövde {"url": "{{bundle.targetUrl}}", "events": ["message.received"]}; dönen id'yi saklayın.
  • Unsubscribe: POST /api/v1/webhooks/{{bundle.subscribeData.id}}, başlık X-HTTP-Method-Override: DELETE.
  • Perform: gelen gövde bundle.cleanedRequest; alanlar veri altındadır.
  • Zap kapatıldığında hook adresi 410 döndürürse webhook burada da otomatik kapanır.

Zapier ve Make ile kodsuz kurulum

Zapier — Webhooks by Zapier

  1. Yeni bir Zap oluşturun; tetikleyici: Webhooks by Zapier → Catch Hook.
  2. Zapier'in verdiği https://hooks.zapier.com/hooks/catch/… adresini kopyalayın.
  3. Panelde Webhook & API → Webhook ekle: adresi yapıştırın ve olayları seçin.
  4. Test gönder ile örnek bir olay yollayın; Zapier'de Test trigger deyin.
  5. Eylem adımlarında veri__metin, veri__kisi_adi, veri__konusma_id gibi alanları kullanın.

Make — Custom webhook

  1. Yeni senaryo oluşturun; ilk modül: Webhooks → Custom webhook → Add.
  2. Verilen https://hook.eu1.make.com/… adresini kopyalayıp panelde webhook olarak ekleyin.
  3. Make modülü veri beklerken panelde Test gönder'e basın; veri yapısı otomatik algılanır.
  4. Sonraki modüllerde veri alanlarını eşleyin ve senaryoyu açın.

Zapier ve Make hook adresleri gizli tutulmalıdır. Kendi sunucunuzda mutlaka imzayı doğrulayın.

Gömülü konuşmalar (iframe)

Panelin Konuşmalar ekranını kendi sitenizde (ör. yönetim sayfanızda) gösterin. Pencerede o kişi için yalnız Konuşmalar ekranını gören kısıtlı bir oturum açılır (ayarlar, API anahtarları, paket ve güvenlik ekranları bu oturuma kapalıdır). İki yol vardır: sunucu kodu gerektirmeyen tek satırlık kod ya da sunucunuzdan otomatik giriş.

Kolay yöntem: tek satır kod + “Aidiance ile bağlan”

  1. Panel › Entegrasyon › Konuşmaları sitenize gömün kartında izinli siteleri (yalnız https) yazıp açın ve kaydedin (yalnız ana hesap). Kartta hesabınızın koduyla hazır iframe ve script kodları çıkar.
  2. Kodlardan birini sitenizde Konuşmaların görüneceği sayfaya yapıştırın:
<iframe src="https://www.aidiance.com/gomulu_giris.aspx?h=HESAP_KODU" style="width:100%;height:720px;border:0" title="Konuşmalar" referrerpolicy="origin" allow="clipboard-write"></iframe>
<script src="https://www.aidiance.com/assets/js/gomulu-konusmalar.js" data-hesap="HESAP_KODU" async></script>
  • Script, pencereyi kodun bulunduğu yere ekler ve yüksekliğini ekrana göre ayarlar. İsteğe bağlı: data-hedef="#kutu" (pencerenin konacağı öğe), data-yukseklik="720px" (sabit yükseklik).
  • Ekipteki her kişi pencerede bir kez Aidiance ile bağlan’a basar. Açılan Aidiance penceresinde (oturum yoksa giriş; iki adımlı doğrulama dahil) hangi hesapla bağlanacağını görüp Bağlan’ı onaylar. Bağlantı o tarayıcıda, yalnız o sitenin penceresinde 30 gün açık kalır; süre dolunca pencere yeniden bağlanmayı ister.
  • Bağlanan kişi bu hesabın ana kullanıcısı ya da Konuşmalar yetkili bir ekip üyesi (alt kullanıcı) olmalıdır; herkes kendi yetkileriyle görür. Başka bir Aidiance hesabıyla bağlanılamaz.
  • Hesap kodu gizli değildir ve tek başına erişim vermez: pencere yalnız izinli sitelerde çerçevelenir, bağlanma Aidiance’ın kendi penceresinde yapılır ve şifre sitenize yazılmaz.
  • Bağlantılar Güvenlik › Aktif oturumlar’da Gömülü konuşmalar (Aidiance ile bağlan) olarak görünür ve oradan kapatılabilir. Özelliği kapatmak ya da siteyi listeden çıkarmak tüm bağlantıları hemen sonlandırır.
  • Tarayıcı gömülü pencerede oturuma izin vermezse (ör. Safari’nin bazı sürümleri) pencerede Konuşmaları yeni sekmede aç düğmesi çıkar ve Konuşmalar normal Aidiance panelinde açılır. Açılır pencere engellenirse tarayıcıda o siteye açılır pencere izni verin.

Gelişmiş: sunucudan otomatik giriş (API)

Sitenize giriş yapmış kişi için Konuşmaları “bağlan” adımı olmadan açmak isterseniz sunucunuz, sayfayı açan kişi için tek kullanımlık bir bağlantı alır ve iframe’e koyar; ekibiniz ayrıca Aidiance şifresi girmez.

  1. Panel › Entegrasyon’da inbox.embed (Gömülü konuşmalar) yetkili, asistana kısıtlanmamış ve tüm kanallara açık bir anahtar oluşturun (bu anahtarı ve gömme ayarını yalnız ana hesap yönetir).
  2. Aynı sayfadaki Konuşmaları sitenize gömün kartında izinli siteleri (yalnız https) yazıp açın. Konuşmalar yalnız bu sitelerde çerçevelenebilir.
  3. Sayfanız her açıldığında sunucunuz aşağıdaki ucu çağırıp dönen url’i iframe’e koyar.

POST/api/v1/embed_sessions

AlanAçıklama
emailİsteğe bağlı. Giriş yapılacak kullanıcının Aidiance e-postası: ana hesap ya da ekip üyesi (alt kullanıcı). Ekip üyesi kendi yetkileriyle görür; Konuşmalar yetkisi olmalıdır. Boşsa ana hesap.
siteİframe’in açılacağı sitenin kökeni (https://yonetim.siteniz.com). Tek izinli site varsa gerekmez.
HTTP 201
{
  "ok": true,
  "url": "https://www.aidiance.com/gomulu_giris.aspx?t=gk_…",
  "expires_in": 300,
  "expires_at": "2026-10-04T12:00:00Z",
  "site": "https://yonetim.siteniz.com",
  "user": "temsilci@firma.com"
}
<iframe src="{url}" style="width:100%;height:720px;border:0" title="Konuşmalar"></iframe>
  • Bağlantı tek kullanımlıktır ve expires_in saniye içinde açılmalıdır; her sayfa açılışında yenisini alın, bağlantıyı önbelleğe almayın ya da paylaşmayın.
  • İmza diğer uçlarla aynıdır: resource = embed_sessions, canonicalQuery boş, gövde gönderdiğiniz JSON’un ham baytları.
  • Oturum çerezi tarayıcının bölümlenmiş çerez desteğiyle (CHIPS) yalnız o sitenin iframe’inde tutulur; tarayıcıdaki Aidiance oturumuna dokunmaz. Tarayıcı izin vermezse (ör. Safari’nin bazı sürümleri) pencerede Yeni sekmede aç düğmesi çıkar; yeni sekmede hangi hesapla açılacağı gösterilir ve kullanıcı onaylayınca açılır.
  • Gömülü oturum en çok 12 saat sürer. Süre dolunca (ya da oturum başka bir nedenle bitince) iframe, sayfanıza { aidiance: "oturum_sona_erdi" } mesajını postMessage ile gönderir; dinleyip sayfayı yenilerseniz yeni bağlantı alınır (mesajın origin’ini denetleyin; döngüye girmemek için yalnız sayfa en az bir dakikadır açıksa yenileyin).
  • Panelde özelliği kapatmak, bir siteyi listeden çıkarmak ya da inbox.embed yetkili anahtarı iptal etmek bu yolla açılmış gömülü oturumları hemen sonlandırır; iptal edilen anahtarla alınmış bağlantılar da açılmaz (anahtar iptali “Aidiance ile bağlan” bağlantılarını etkilemez).
HTTPerror
400site_required / site_not_allowedBirden çok izinli site varken site yok / site listede değil
403insufficient_scope / key_restricted / embed_disabled / feature_unavailableAnahtarda inbox.embed yok / anahtar asistana ya da kanala kısıtlı / özellik kapalı / paket
403user_inactive / forbiddenKullanıcı pasif / ekip üyesinin Konuşmalar yetkisi yok
404 / 409user_not_found / ambiguous_userE-posta hesabınızda bulunamadı / birden çok kullanıcıda kayıtlı

PHP örneği

$key  = getenv('AIDIANCE_API_KEY');                 // inbox.embed yetkili anahtar (yalnız sunucuda)
$body = json_encode(['email' => $kullaniciEposta, 'site' => 'https://yonetim.siteniz.com']);
$ts    = (string) time();
$nonce = bin2hex(random_bytes(16));
$imza  = hash_hmac('sha256', $ts . "\n" . $nonce . "\nPOST\nembed_sessions\n\n" . hash('sha256', $body), $key);
$ch = curl_init('https://www.aidiance.com/api/v1/embed_sessions');
curl_setopt_array($ch, [
    CURLOPT_POST => true, CURLOPT_POSTFIELDS => $body, CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => ['Content-Type: application/json', 'Authorization: Bearer ' . $key,
        'X-Aidiance-Timestamp: ' . $ts, 'X-Aidiance-Nonce: ' . $nonce, 'X-Aidiance-Signature: ' . $imza],
]);
$url = json_decode(curl_exec($ch), true)['url'];  // <iframe src="...">

Hatalar

{
  "ok": false,
  "error": "bad_signature",
  "message": "İmza doğrulanamadı.",
  "request_id": "…"
}
HTTPerror
400bad_request / invalid_json / invalid_url / invalid_eventsGeçersiz istek
401auth_required / invalid_key / bad_signature / replayKimlik veya imza
403https_required / ip_denied / insufficient_scope / forbidden / feature_unavailable / limit_reached / key_restrictedYetki, paket veya limit
403opted_outKişi DUR / İPTAL yazarak pazarlama mesajlarından çıktı; pazarlama (MARKETING) ya da kategorisi bilinmeyen şablon gönderilmez. Hizmet (UTILITY) ve doğrulama (AUTHENTICATION) şablonları gönderilebilir.
404 / 405not_found / method_not_allowedUç veya kayıt bulunamadı
409duplicate_webhook / busy / ambiguous_userAynı adrese ikinci webhook / eşzamanlı işlem / e-posta birden çok kullanıcıda
429rate_limited / auth_lockedHız limiti
502provider_errorWhatsApp / Meta / X

Python örneği

import hashlib, hmac, json, time, uuid, requests

KEY = "aid_live_..."  # panelden
BASE = "https://www.aidiance.com/api/v1"

def call(method, resource, query=None, json_body=None):
    ts = str(int(time.time()))
    nonce = uuid.uuid4().hex
    body = b""
    if json_body is not None:
        body = json.dumps(json_body, ensure_ascii=False, separators=(",", ":")).encode("utf-8")
    q_items = []
    if query:
        for k in sorted(query):
            if k == "resource":
                continue
            q_items.append("%s=%s" % (requests.utils.quote(str(k), safe=""), requests.utils.quote(str(query[k]), safe="")))
    canon_q = "&".join(q_items)
    payload = "\n".join([ts, nonce, method.upper(), resource.lower(), canon_q, hashlib.sha256(body).hexdigest()])
    sig = hmac.new(KEY.encode("utf-8"), payload.encode("utf-8"), hashlib.sha256).hexdigest()
    headers = {
        "Authorization": "Bearer " + KEY,
        "X-Aidiance-Timestamp": ts,
        "X-Aidiance-Nonce": nonce,
        "X-Aidiance-Signature": sig,
        "Content-Type": "application/json",
    }
    url = BASE + "/" + resource
    if query:
        url += "?" + "&".join("%s=%s" % (k, requests.utils.quote(str(query[k]), safe="")) for k in query)
    if method == "GET":
        return requests.get(url, headers=headers, timeout=20)
    headers["X-Aidiance-Idempotency-Key"] = uuid.uuid4().hex
    return requests.post(url, data=body, headers=headers, timeout=20)

print(call("GET", "conversations", {"channel": "whatsapp", "limit": "20"}).json())
print(call("POST", "messages", json_body={
    "conversation_id": "wa:TOKEN:905551112233",
    "text": "Merhaba"
}).json())
print(call("GET", "templates", {"assistant_token": "TOKEN"}).json())
print(call("POST", "messages", json_body={
    "channel": "whatsapp",
    "assistant_token": "TOKEN",
    "to": "905551112233",
    "template": {"name": "karsilama", "language": "tr", "body_variables": ["Ayşe"]}
}).json())

PHP örneği (imza)

function aidiance_sign($key, $ts, $nonce, $method, $resource, $canonQuery, $body) {
    $bodyHash = hash('sha256', $body === null ? '' : $body);
    $payload = $ts."\n".$nonce."\n".strtoupper($method)."\n".strtolower($resource)."\n".$canonQuery."\n".$bodyHash;
    return hash_hmac('sha256', $payload, $key);
}

GET konuşma listesi için canonicalQuery örneği: channel=whatsapp&limit=20 (alfabetik).

Güvenlik kuralları

  • Anahtarı git’e, frontend’e veya log’a yazmayın. Sızıntıda panelden hemen iptal edin.
  • Mümkünse IP allowlist kullanın (sunucu çıkış IP’niz).
  • Gönderim yetkisini yalnızca ihtiyaç varsa verin; salt okuma anahtarı ayrı üretin.
  • Nonce’u her istekte yenileyin; aynı imzayı tekrar kullanmayın.
  • Webhook gizli anahtarını (whsec_…) yalnızca sunucuda saklayın; sızdığını düşünüyorsanız panelden yenileyin.
  • Bu API mobil uygulama oturum API’sinden (/app_api/) ayrıdır.