استقبل رسائل Instagram DMs على خادمك — إعداد webhook الرسمي لـ Messaging API، معرّف IGID، مخططات الحمولة لرسائل DMs وإشارات الستوري والتفاعلات، كود Node.js
في هذا الدليل: لماذا API الرسمي فقط · متطلبات الحساب · الأذونات المطلوبة · شرح IGID · خطوات إعداد webhook · مخططات كل أنواع الأحداث · إشارات الستوري والردود · التفاعلات · الرد عبر Send API · صيغة SocialHook الموحّدة

لماذا API الرسمي — ولا شيء غيره

معظم دروس "أتمتة Instagram DM" تستخدم طرقاً غير رسمية: أتمتة المتصفح، استخراج رموز الجلسات، أدوات أتمتة من أطراف ثالثة تتجاوز API الخاص بـ Instagram. كلها تنتهك شروط خدمة Instagram. ويرصد Instagram هذه الأساليب بنشاط ويحظر الحسابات التي تستخدمها — أحياناً بشكل دائم وغالباً دون إنذار أو حق استئناف.

إن Instagram Messaging API الرسمي هو الطريقة الوحيدة التي تكون:

  • معتمدة من Meta ومتوافقة مع شروط خدمة Instagram
  • صالحة للاستخدام التجاري على نطاق واسع (حتى 1,000 طلب API في الساعة لكل مستخدم)
  • مشمولة باتفاقية مستوى الخدمة (SLA) من Meta وموثوقية بنيتها التحتية
  • آمنة لحساب Instagram الخاص بعملك على المدى الطويل

يغطي هذا الدليل حصرياً Meta Graph API v21.0 الخاص بـ Instagram Messaging API الرسمي.

متطلبات الحساب: ما تحتاجه قبل كتابة أي كود

إن Instagram Messaging API له متطلبات حساب أكثر صرامة من Messenger API. يجب أن تتحقق الشروط الثلاثة التالية جميعها:

  1. حساب Instagram Professional: يجب تحويل حساب Instagram الخاص بك إلى حساب Business أو Creator (وليس حساباً شخصياً). افعل ذلك في تطبيق Instagram ← Settings ← Account ← Switch to Professional Account. تختلف ميزات حسابات Creator قليلاً عن حسابات Business — لأتمتة الرسائل، كلاهما يعمل.
  2. صفحة Facebook مرتبطة: يجب أن يكون حساب Instagram Professional الخاص بك مرتبطاً بصفحة Facebook تمتلكها وتديرها. هذا شرط أساسي — إن Instagram Messaging API يصادق عبر البنية التحتية لـ Facebook. اربطها في Instagram Settings ← Account ← Linked Accounts ← Facebook.
  3. تطبيق Facebook Developer: تطبيق Facebook مع إضافة منتج Instagram إليه. يجب ربط حساب Instagram Business الخاص بك في إعدادات Instagram داخل التطبيق. هنا تُولّد رموز الوصول (access tokens) وتسجّل webhook الخاص بك.
لا يمكن لحسابات Instagram الشخصية استخدام Messaging API. إذا كنت تعمل بحساب شخصي، فيجب أولاً التحويل إلى Professional. هذا مجاني وقابل للعكس — التحويل إلى Professional لا يغيّر محتواك ولا متابعيك ولا سير عملك في النشر. يضيف فقط ميزات الأعمال بما فيها الوصول إلى API.

الأذونات المطلوبة

الإذنمطلوب؟ما يسمح به
instagram_manage_messages مطلوب استقبال أحداث webhook الخاصة بـ DM، وإرسال الرسائل بالنيابة عن حساب Instagram. هذا هو الإذن الأساسي لكل ما في هذا الدليل.
pages_messaging مطلوب الاشتراك في أحداث webhook واستقبالها عبر صفحة Facebook المرتبطة. بدون هذا الإذن، لن تُطلق أحداث webhook الخاصة بـ Instagram DM.
pages_read_engagement مطلوب قراءة معلومات حساب Instagram Business اللازمة لاشتراك webhook والتحقق من الرمز.
instagram_manage_insights اختياري الوصول إلى إحصاءات وتحليلات حساب Instagram. ليس مطلوباً لمجرد استقبال/إرسال DM.
instagram_basic اختياري قراءة معلومات الملف الشخصي الأساسية لحساب Instagram المتصل. مفيد للتحقق من إعداد الملف الشخصي.
App Review مطلوب للإنتاج. أثناء التطوير، تعمل الأذونات للحسابات المضافة كمستخدمين تجريبيين (Test Users) في إعدادات تطبيقك. أما للإنتاج (استقبال DMs من عملاء حقيقيين لم يُضافوا كمستخدمين تجريبيين) فيجب تقديم طلب App Review. تطلب المراجعة وصفاً لحالة الاستخدام وتستغرق عادة 5–10 أيام عمل. جهّز وصفاً واضحاً لحالة الاستخدام وتسجيلاً للشاشة يُظهر بوتك أثناء العمل.

المعرّف المُقيّد بـ Instagram (IGSID): كيف يُعرّف Instagram المستخدمين

عندما يرسل مستخدم على Instagram رسالة DM إلى حساب عملك، يُعرّفه Instagram إلى webhook الخاص بك عبر IGSID (Instagram-Scoped ID) — وهو سلسلة رقمية فريدة وغامضة (opaque) خاصة بحساب Instagram Business الخاص بك.

حقائق أساسية عن IGSIDs:

  • مُقيّد بالنطاق. المستخدم نفسه يحصل على IGSID مختلف لكل حساب Instagram Business يراسله. فـ IGSID المستخدم A على حسابك يختلف عن IGSID نفس المستخدم على حساب منافس — خصوصية بحكم التصميم.
  • ليس مطابقاً لـ PSID. حتى لو كنت تدير أيضاً صفحة Facebook متصلة بنفس حساب Instagram، فإن PSID المستخدم على Facebook Messenger و IGSID نفسه على Instagram معرّفان مختلفان. لا تخلط بينهما في قاعدة بياناتك دون وضع لاحقة (label) للنوع.
  • خزّنه كنص لا كعدد صحيح. إن IGSIDs سلاسل رقمية قد تتجاوز Number.MAX_SAFE_INTEGER في JavaScript. خزّنها دائماً كـ VARCHAR/TEXT وليس INT أو BIGINT أبداً. التحويل إلى رقم JavaScript يفقد الدقة في آخر الأرقام.
  • يظهر في: entry[0].messaging[0].sender.id في حمولة webhook الخام — نفس موضع PSID في Messenger.
أنشئ تطبيق Facebook واربط Instagram
  1. اذهب إلى developers.facebook.com ← My Apps ← Create App ← اختر نوع "Business"
  2. أضف منتج Instagram إلى تطبيقك من قائمة Products
  3. تحت Instagram ← Settings، أضف حساب Instagram Business الخاص بك
  4. ولّد Page Access Token: Graph API Explorer ← اختر تطبيقك ← اختر صفحة Facebook ← Generate Token ← امنح instagram_manage_messages + pages_messaging + pages_read_engagement
  5. انسخ Instagram Business Account ID (المعرّف الرقمي، وليس اسم المستخدم) — اعثر عليه في Graph API Explorer بالاستعلام GET /me?fields=id,instagram_business_account
  6. انسخ App Secret من Settings ← Basic
Shell — project setup
mkdir instagram-dm-bot && cd instagram-dm-bot npm init -y npm install express dotenv cat > .env << EOF IG_PAGE_TOKEN=your_page_access_token_here IG_VERIFY_TOKEN=your_custom_verify_secret IG_APP_SECRET=your_app_secret IG_BUSINESS_ID=your_instagram_business_account_id PORT=3000 EOF # Start ngrok for local webhook testing ngrok http 3000
نقطة نهاية التحقق من webhook

تحدّي التحقق مماثل تماماً لـ Facebook Messenger — يستخدم Instagram نفس نمط hub.challenge:

Node.js + Express
index.js
require('dotenv').config(); const express = require('express'); const crypto = require('crypto'); const app = express(); // MUST use express.raw() for HMAC verification on webhook route app.use('/webhook', express.raw({ type: 'application/json' })); app.use(express.json()); // GET /webhook — Instagram verification challenge (same as Messenger) app.get('/webhook', (req, res) => { const mode = req.query['hub.mode']; const token = req.query['hub.verify_token']; const challenge = req.query['hub.challenge']; if (mode === 'subscribe' && token === process.env.IG_VERIFY_TOKEN) { console.log('✓ Instagram webhook verified'); return res.status(200).send(challenge); } res.sendStatus(403); }); app.listen(process.env.PORT || 3000);
Python (Flask)
app.py
import os, hmac, hashlib, json from flask import Flask, request, jsonify app = Flask(__name__) @app.route("/webhook", methods=["GET"]) def verify_webhook(): mode = request.args.get("hub.mode") token = request.args.get("hub.verify_token") challenge = request.args.get("hub.challenge") if mode == "subscribe" and token == os.environ["IG_VERIFY_TOKEN"]: return challenge, 200 return "Forbidden", 403

بعد تشغيل خادمك، سجّل webhook في Facebook Developer Dashboard: App ← Instagram ← Webhooks ← Add Callback URL. أدخل عنوان ngrok الخاص بك متبوعاً بـ /webhook ورمز التحقق الخاص بك. اشترك في الحقل messages — هذا هو الاشتراك الأساسي لرسائل Instagram DMs.

التحقق من توقيع HMAC-SHA256

يستخدم Instagram نفس ترويسة X-Hub-Signature-256 ونمط HMAC المستخدم في Facebook Messenger. نفس middleware التحقق يعمل لكليهما:

Node.js — HMAC middleware (same as Messenger)
verifySignature.js
const crypto = require('crypto'); function verifyInstagramSignature(req, res, next) { const signature = req.headers['x-hub-signature-256']; if (!signature) return res.sendStatus(401); const hash = crypto .createHmac('sha256', process.env.IG_APP_SECRET) .update(req.body) .digest('hex'); const expected = Buffer.from(signature.split('=')[1], 'hex'); const computed = Buffer.from(hash, 'hex'); if (expected.length !== computed.length || !crypto.timingSafeEqual(expected, computed)) { return res.sendStatus(401); } req.body = JSON.parse(req.body.toString('utf8')); next(); } module.exports = { verifyInstagramSignature };
معالج كامل لأحداث webhook عبر POST
Node.js — full Instagram webhook POST handler
webhook.js
const { verifyInstagramSignature } = require('./verifySignature'); app.post('/webhook', verifyInstagramSignature, async (req, res) => { res.sendStatus(200); // acknowledge immediately const body = req.body; // Instagram DMs arrive with object: "instagram" // (contrast: Messenger uses object: "page") if (body.object !== 'instagram') return; for (const entry of body.entry) { const igBusinessId = entry.id; // your Instagram Business Account ID for (const event of (entry.messaging || [])) { const igsid = event.sender.id; // user's IGSID — store as string if (event.message) { const { text, attachments, mid, reply_to } = event.message; if (reply_to?.story) { // User replied to your story await handleStoryReply(igsid, reply_to.story, text); } else if (attachments) { // Image, video, audio, sticker, or share for (const att of attachments) { await handleAttachment(igsid, att); } } else if (text) { // Standard text DM await handleTextDM(igsid, text, mid); } } else if (event.reaction) { // User reacted to one of your messages const { reaction, action, mid } = event.reaction; await handleReaction(igsid, action, reaction, mid); // action: 'react' | 'unreact' } else if (event.read) { // User read your messages await handleRead(igsid, event.read.mid); } else if (event.referral) { // User arrived via story mention or ad CTA await handleReferral(igsid, event.referral); } } } });
Python (Flask)
app.py
@app.route("/webhook", methods=["POST"]) def receive_webhook(): # Verify HMAC signature sig = request.headers.get("X-Hub-Signature-256", "") expected = hmac.new( os.environ["IG_APP_SECRET"].encode(), request.data, hashlib.sha256 ).hexdigest() if not hmac.compare_digest(sig, f"sha256={expected}"): return "Forbidden", 401 body = request.get_json() if body.get("object") != "instagram": return "OK", 200 for entry in body.get("entry", []): for event in entry.get("messaging", []): igsid = event["sender"]["id"] # IGSID — store as string msg = event.get("message") react = event.get("reaction") if msg: reply_to = msg.get("reply_to", {}) if reply_to.get("story"): handle_story_reply(igsid, reply_to["story"], msg.get("text")) elif msg.get("text"): handle_text_dm(igsid, msg["text"]) elif msg.get("attachments"): handle_attachment(igsid, msg["attachments"]) elif react: handle_reaction(igsid, react["action"], react.get("reaction")) return "OK", 200

جميع مخططات أحداث Instagram DM

رسالة نصية DM
messages
event.message.text
رسالة نصية قياسية من مستخدم. النوع الأكثر شيوعاً للأحداث. يحوي نص الرسالة ومعرّفها (mid) الذي يمكنك استخدامه لإيصالات القراءة والتفاعلات.
صورة / فيديو / صوت
attachments
event.message.attachments
وسائط مرسلة في DM. لكل مرفق type (image، video، audio، file) و payload.url للتنزيل. الروابط مؤقتة — نزّلها فوراً.
رد على ستوري
reply_to.story
event.message.reply_to.story
قام مستخدم بالرد على إحدى قصصك (Stories) على Instagram. يحوي معرّف القصة ورابط CDN لوسائطها. يتضمن أيضاً نص رد المستخدم في event.message.text.
ملصق
attachments
event.message.attachments[0].type === 'story_mention'
أرسل المستخدم ملصقاً أو تفاعل قلب/إعجاب (كملصق). نوع المرفق هو sticker. يحدّد sticker_id الملصق المستخدم بالضبط.
تفاعل برمز إيموجي
reaction
event.reaction.action
تفاعل المستخدم (أو ألغى تفاعله) مع إحدى رسائلك. action تكون "react" أو "unreact". reaction هي رمز الإيموجي. mid هو معرّف الرسالة التي تفاعل معها.
إشارة في ستوري
referral
event.referral.source === 'STORY_MENTION'
أشار المستخدم إلى حسابك في قصته ثم أرسل إليك DM. يصل كحدث referral بالقيمة source: "STORY_MENTION". يوجد رابط قصة المستخدم في event.referral.story.url.

صيغة JSON الدقيقة لأكثر ثلاثة أنواع أحداث شيوعاً:

Raw webhook payloads — all key event types
// ── Text DM ───────────────────────────────────────────────────────────── { "object": "instagram", // CRITICAL: "instagram" not "page" like Messenger "entry": [{ "id": "987654321098765", // your Instagram Business Account ID "messaging": [{ "sender": { "id": "12345678901234" }, // user's IGSID — store as string "recipient": { "id": "987654321098765" }, // your IG Business Account ID "timestamp": 1747231892, "message": { "mid": "aWdtc2c...", "text": "Hey, do you ship internationally?" } }] }] } // ── Story Reply ───────────────────────────────────────────────────────── { "message": { "mid": "aWdtc2c...", "text": "Wow, this looks amazing!", // the user's reply text "reply_to": { "story": { "id": "17893310459840806", // story ID they replied to "url": "https://lookaside.fbsbx.com/..." // story media URL (CDN) } } } } // ── Emoji Reaction ────────────────────────────────────────────────────── { "reaction": { "action": "react", // 'react' | 'unreact' "reaction": "❤️", // the emoji character "mid": "aWdtc2c..." // which of your messages they reacted to } }

إشارات الستوري: عندما يُبرز المستخدمون حسابك

عندما يشير مستخدم إلى حساب Instagram Business الخاص بك في قصته (عبر تاغ)، يطلق Instagram حدث referral إلى webhook الخاص بك. هذه إشارة عالية القيمة — فالمستخدم يروّج لعلامتك التجارية أمام متابعيه وغالباً ما يتوقع تفاعلاً منك (إرسال DM، إعادة نشر قصته، إلخ).

Story mention event schema
{ "sender": { "id": "USER_IGSID" }, "recipient": { "id": "YOUR_IG_BUSINESS_ID" }, "timestamp": 1747231892, "referral": { // present for story mentions "ref": "STORY_MENTION", // your tracking string (if set) "source": "STORY_MENTION", "type": "OPEN_THREAD", "story": { "id": "17893310459840806", // story ID from the user's account "url": "https://lookaside...", // story media URL (CDN, may expire) "mention": { "page_id": "YOUR_IG_BUSINESS_ID" // confirms it's your account mentioned } } }, "message": { // often empty for pure story mentions "mid": "aWdtc2c..." } } // Subscribe to messaging_referrals webhook field to receive story mentions // WITHOUT this subscription, story mentions never arrive at your webhook

إرسال الردود عبر Instagram Send API

يستخدم Instagram Send API نفس عنوان URL الأساسي مثل Messenger ولكن بنقطة نهاية مختلفة — معرّف Instagram Business Account الخاص بك بدلاً من /me:

Node.js — Instagram Send API
sendDM.js
const GRAPH = 'https://graph.facebook.com/v21.0'; const IG_BIZ_ID = process.env.IG_BUSINESS_ID; // numeric IG Business Account ID const TOKEN = process.env.IG_PAGE_TOKEN; async function sendInstagramDM(igsid, messageText) { // NOTE: endpoint uses IG_BUSINESS_ID, NOT /me (contrast: Messenger uses /me) const res = await fetch( `${GRAPH}/${IG_BIZ_ID}/messages?access_token=${TOKEN}`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ recipient: { id: igsid }, // user's IGSID message: { text: messageText }, }), } ); if (!res.ok) { const err = await res.json(); throw new Error(`Instagram DM send failed: ${err.error?.message}`); } return await res.json(); // { recipient_id: igsid, message_id: "..." } } // Usage await sendInstagramDM('12345678901234', 'Thanks for reaching out! 🙏');
Python — Instagram Send API
send_dm.py
import os, requests GRAPH = "https://graph.facebook.com/v21.0" IG_BIZ_ID = os.environ["IG_BUSINESS_ID"] # numeric IG Business Account ID TOKEN = os.environ["IG_PAGE_TOKEN"] def send_instagram_dm(igsid: str, text: str) -> dict: # NOTE: endpoint uses IG_BIZ_ID not /me res = requests.post( f"{GRAPH}/{IG_BIZ_ID}/messages", params={ "access_token": TOKEN }, json={ "recipient": { "id": igsid }, "message": { "text": text }, } ) res.raise_for_status() return res.json()

SocialHook: رسائل Instagram DMs مُحلّلة مسبقاً بصيغة موحّدة

عند ربط حساب Instagram الخاص بك بـ SocialHook، تُعالَج كامل المسارات الواردة — التحقق من HMAC، وتحليل object: "instagram"، واستخراج IGSID، وكشف نوع الحدث — قبل وصول الحدث إلى خادمك. ستستقبل:

أسئلة شائعة

ما الأذونات التي أحتاجها لاستخدام Instagram Messaging API؟
ثلاثة أذونات مطلوبة: instagram_manage_messages (استقبال/إرسال رسائل DM)، و pages_messaging (الاشتراك في webhooks عبر الصفحة المرتبطة)، و pages_read_engagement (قراءة معلومات الحساب). أثناء التطوير تعمل هذه الأذونات للحسابات المضافة كمستخدمين تجريبيين في إعدادات تطبيقك. أما للإنتاج (رسائل عملاء حقيقيين) فيجب تقديم الأذونات الثلاثة جميعها إلى Meta App Review.
ما هو IGSID وكيف يختلف عن PSID على Facebook؟
إن IGSID (Instagram-Scoped ID) هو المعرّف الفريد لمستخدم Instagram في سياق حساب Instagram Business الخاص بك تحديداً — بما يشبه PSID في Messenger. يُعرّف PSID مستخدماً على صفحة Facebook، بينما يُعرّف IGSID نفس المستخدم على حساب Instagram الخاص بك. وهما معرّفان مختلفان حتى لو كان حساب Instagram وصفحة Facebook لديك مرتبطين. خزّن IGSIDs دائماً كنصوص (VARCHAR) — فقد تتجاوز قيمة Number.MAX_SAFE_INTEGER في JavaScript.
كيف تختلف نقطة نهاية Instagram Send API عن Facebook Messenger؟
Messenger: POST /me/messages (حيث يُحلّ "me" إلى صفحتك). Instagram: POST /{IG_BUSINESS_ID}/messages (حيث IG_BUSINESS_ID هو المعرّف الرقمي لحساب Instagram Business الخاص بك، وليس اسم المستخدم). كلاهما يستخدم نفس عنوان URL الأساسي ونفس Page Access Token. بنية جسم الرسالة متطابقة — recipient.id يستقبل IGSID و message.text يحوي ردك.
كيف أستقبل إشارات الستوري في webhook الخاص بـ Instagram؟
يجب الاشتراك في حقل webhook المسمى messaging_referrals بالإضافة إلى messages. عندما يشير مستخدم إلى حسابك في قصته، يطلق Instagram حدث referral مع source: "STORY_MENTION" ورابط القصة في الحمولة. يتيح لك الحدث إرسال DM للمستخدم (ضمن نافذة الـ 24 ساعة) لشكره أو طلب إذن إعادة النشر أو تقديم خصم له.
هل يمكنني استقبال رسائل Instagram DM من أي مستخدم أم من متابعيّ فقط؟
يمكنك استقبال رسائل DM من أي مستخدم على Instagram قادر على مراسلة حسابك — لا من متابعيك فقط. افتراضياً، تذهب رسائل DM من غير المتابعين إلى مجلد "Message Requests" ولا تطلق webhooks حتى يتم قبول الطلب. في Instagram Settings ← Privacy ← Messages، اضبط "Others on Instagram" على "Don't require approval" حتى تتدفق رسائل DM فوراً إلى webhook الخاص بك. يمكن لحسابات Business التي تفعّل Message Requests API أن تعالج أحداث الطلبات برمجياً أيضاً.
كيف يختلف نوع كائن webhook الخاص بـ Instagram عن Facebook Messenger؟
تصل webhooks الخاصة بـ Instagram بـ "object": "instagram" في غلاف الحمولة. أما webhooks الخاصة بـ Messenger فتصل بـ "object": "page". هذا أول حقل ينبغي فحصه في معالجك — إذا كنت تعالج كلتا القناتين، فاتخذ المسار بناءً على هذا الحقل. بنية الحمولة المتداخلة (entry[0].messaging[0].sender.id) واحدة لكليهما، لكن نوع معرّف المستخدم يختلف: IGSID لـ Instagram و PSID لـ Messenger.

رسائل DM مُحلّلة مسبقاً
تُسلَّم إلى معالجك.

اربط حساب Instagram Business الخاص بك بـ SocialHook. كل رسالة DM ورد ستوري وإشارة ستوري تصل كـ JSON موحّد — IGSID مستخرَج، نوع الحدث مُعلّم، HMAC تم التحقق منه مسبقاً. نفس صيغة أحداثك على Messenger و WhatsApp.

لا حاجة لبطاقة ائتمان · 50$ شهرياً بعد الفترة التجريبية · Instagram + Messenger + WhatsApp