OmniStream Docs
  • Panduan Pengguna
  • Developer
  • API Reference
Developer Hub
Pendahuluan
Autentikasi
Model Data
Webhook
    Webhook WhatsApp inboundWebhook Instagram inboundWebhook MessengerWebhook Email inbound dan HMAC signatureOutgoing webhook — dispatcher, event schema, dan retry
WebSocket
Self-Hosting
Error & Rate Limit
Webhook

Webhook Instagram inbound

Webhook Instagram inbound

Halaman ini menjelaskan bagaimana webhook-ingestor menangani webhook dari Instagram Graph API. Kode sumbernya ada di crates/webhook-ingestor/src/routes.rs::receive_instagram_webhook.

Integrasi Instagram memakai Instagram Login (OAuth per-akun), berbeda dengan WhatsApp yang memakai kredensial bersama dari Business Account. Akibatnya lookup integration_account_id di Instagram menggunakan entry[].id (Instagram user id) sebagai kunci, bukan phone_number_id.

Endpoint

ItemNilai
MetodeGET (verifikasi) dan POST (webhook event)
Path/webhook/instagram
Hostwebhook-ingestor di WEBHOOK_INGESTOR_PORT (default 3001)
AuthHMAC-SHA256 header X-Hub-Signature-256

Catatan topologi: webhook-ingestor adalah satu binary yang mengekspos rute WhatsApp, Instagram, Messenger, dan Email pada port yang sama. Lihat Webhook WhatsApp inbound untuk detail.

1. Handshake verifikasi (GET /webhook/instagram)

Alur handshake identik dengan WhatsApp: Meta mengirim GET /webhook/instagram?hub.mode=subscribe&hub.verify_token=<token>&hub.challenge=<nonce>, ingestor memeriksa hub.mode + hub.verify_token melawan META_VERIFY_TOKEN, lalu mengembalikan hub.challenge sebagai body plain text.

Token yang sama (META_VERIFY_TOKEN) dipakai untuk ketiga saluran Meta (WhatsApp, Instagram, Messenger) karena Meta tidak membedakannya per-channel.

Kode: routes.rs::verify_instagram_webhook.

2. Penerimaan event (POST /webhook/instagram)

2.1 Verifikasi HMAC

Seperti WhatsApp, Instagram mengirim X-Hub-Signature-256: sha256=<hex>. Ingestor memverifikasi dengan META_APP_SECRET. Meta memakai app secret yang sama untuk semua saluran karena app tunggal di App Dashboard mencakup keduanya.

Detail lengkap verifikasi ada di HMAC signature.

2.2 Lookup integration_account_id

Payload Instagram memiliki bentuk:

Code
{ "object": "instagram", "entry": [ { "id": "17841412345678901", "time": 1776113600, "messaging": [ { "sender": { "id": "9876543210" }, "recipient": { "id": "17841412345678901" }, "timestamp": 1776113600000, "message": { "mid": "aWdfbXM6MQoEASl...", "text": "Halo, tanya produk" } } ] } ] }

entry[].id adalah Instagram user id (akun bisnis yang menerima pesan). Ingestor menggunakannya untuk mencari baris integration account:

Code
SELECT id FROM integration_accounts WHERE channel = 'instagram' AND config->>'user_id' = $1 AND is_active = true

Jika tidak ditemukan, integration_account_id diset None. Event tetap diproduksi supaya tidak ada kehilangan data, tetapi chat-engine biasanya menjatuhkannya karena tidak tahu kontak mana yang dimaksud.

2.3 Model token per-akun

Berbeda dengan WhatsApp yang memakai satu META_ACCESS_TOKEN untuk semua nomor, Instagram menyimpan access token terpisah per akun di integration_accounts.config->>'access_token'. Token ini diperoleh ketika admin menyelesaikan alur OAuth Instagram Login dan berlaku selama 60 hari (long-lived token). message-sender-instagram membaca token dari baris yang cocok ketika mengirim balasan.

Detail alur OAuth ada di docs-site/pages/developer/webhook dan implementasi di crates/api-gateway/src/routes/integrations/instagram.rs.

2.4 Produksi ke Kafka dan audit

Sama seperti WhatsApp: event dikemas ke InboundRawEvent dengan channel: "instagram" dan diproduksi ke channel.inbound.raw. Audit ditulis fire-and-forget ke koleksi MongoDB webhook_audit dengan source: "instagram:<ig_user_id>".

Code
InboundRawEvent { event_id: Uuid::new_v4(), timestamp: Utc::now(), channel: "instagram".to_string(), integration_account_id: account_id, payload: payload.clone(), }

3. Konsumsi oleh chat-engine

Binary chat-engine-instagram berlangganan channel.inbound.raw dengan filter channel == "instagram" dan melakukan:

  1. Mengekstrak pesan dari payload.entry[0].messaging[0].
  2. Upsert kontak di contacts berdasarkan sender.id (Instagram Scoped User ID / IGSID).
  3. Upsert conversations untuk (contact_id, integration_account_id).
  4. Simpan pesan ke MongoDB messages.
  5. Publikasi ConversationUpdateEvent ke Redis conversation_updates.

Parser ada di crates/chat-engine/src/parser/instagram.rs (fungsi parse_instagram_message).

4. Dari Redis ke WebSocket

Identik dengan WhatsApp — lihat Webhook WhatsApp inbound.

5. Dispatch ke webhook keluar

Identik dengan WhatsApp. Event untuk pesan inbound Instagram menghasilkan webhook message.received dengan channel: "instagram". Lihat Outgoing webhook.

Perbedaan kunci vs WhatsApp

AspekWhatsAppInstagram
Kunci lookupphone_number_identry[].id (ig user id)
Model tokenShared META_ACCESS_TOKENPer-akun, OAuth Instagram Login
Lifetime tokenPermanen (system user)Long-lived 60 hari, refresh sebelum expire
Format senderfrom: "62812..." (MSISDN)sender.id (IGSID, opaque)
Template pre-approvedWajib untuk outbound di luar 24 jamTidak berlaku — Instagram memakai 24h messaging window saja

Troubleshooting

  • 401 InvalidSignature — META_APP_SECRET tidak cocok. Sama dengan WhatsApp; restart ingestor setelah mengubah .env.
  • Event tiba tetapi integration_account_id selalu None — baris integration_accounts dengan channel = 'instagram' tidak memiliki config->>'user_id' yang cocok dengan entry[].id. Periksa dengan:
    Code
    SELECT id, config FROM integration_accounts WHERE channel = 'instagram';
  • message-sender-instagram gagal 401 saat reply — access token akun kedaluwarsa. Jalankan refresh token via POST /api/integrations/instagram/refresh/:id atau biarkan scheduler menjalankannya otomatis.
  • Pesan masuk tetapi tidak muncul di inbox — chat-engine-instagram mungkin mati. Periksa logs; ia adalah binary terpisah dari chat-engine-whatsapp meskipun kodenya berbagi.

File terkait

  • HTTP handler: crates/webhook-ingestor/src/routes.rs::receive_instagram_webhook
  • Verifikasi signature: crates/webhook-ingestor/src/signature.rs
  • OAuth handler: crates/api-gateway/src/routes/integrations/instagram.rs
  • Parser chat-engine: crates/chat-engine/src/parser/instagram.rs
  • Sender: crates/message-sender/src/instagram.rs
Last modified on June 8, 2026
Webhook WhatsApp inboundWebhook Messenger
On this page
  • Endpoint
  • 1. Handshake verifikasi (GET /webhook/instagram)
  • 2. Penerimaan event (POST /webhook/instagram)
    • 2.1 Verifikasi HMAC
    • 2.2 Lookup integration_account_id
    • 2.3 Model token per-akun
    • 2.4 Produksi ke Kafka dan audit
  • 3. Konsumsi oleh chat-engine
  • 4. Dari Redis ke WebSocket
  • 5. Dispatch ke webhook keluar
  • Perbedaan kunci vs WhatsApp
  • Troubleshooting
  • File terkait
JSON
Rust