Threadwire by TriTech

→ مرجع الـ API

إرسال الرسائل

كل شيء يُرسل بطلب واحد: POST /v1/messages. ويحتاج دائمًا إلى instance_id وإلى الجهة المرسل إليها: to، وهو رقم هاتف بالصيغة الدولية (مثل 201012345678)، أو chat_id لمجموعة أو قناة. ثم أضف نوعًا واحدًا من المحتوى أدناه.

الرد فوري: 202 مع status: "queued" (أو "scheduled"). ثم تُرسل الرسالة بإيقاع بشري، وتصلك تغيّرات حالتها كأحداث message.status على الويب هوك. وقد تنتظر الرسالة، أو تفشل مع ذكر السبب. وتجد في الانتظار والأخطاء وإعادة المحاولة متى يحدث ذلك، وكم يطول، وما الذي تعيد محاولته.

النص

{"instance_id": "…", "to": "201012345678", "text": "Hi Sara, your order 1042 is on its way."}

حتى 4,096 حرفًا. يعرض واتساب معاينة لأول رابط في النص، كما في التطبيق. أضف "link_preview": false لإخفائها. ولا تُعرض معاينة الروابط إلا إذا كانت تشير إلى عناوين عامة.

الصور والمستندات والفيديو والرسائل الصوتية

ضع الملف في media، بعنوانه أو بصيغة base64. ويصبح text تعليقًا عليه.

{"instance_id": "…", "to": "201012345678", "text": "Your ticket",
 "media": {"url": "https://example.com/ticket.pdf", "mimetype": "application/pdf", "filename": "ticket.pdf"}}
{"instance_id": "…", "to": "201012345678",
 "media": {"data": "JVBERi0xLjQK…", "mimetype": "application/pdf", "filename": "ticket.pdf"}}
  • mimetype يحدد طريقة ظهور الملف: image/… يظهر صورة، وvideo/… فيديو، وaudio/… رسالة صوتية (تُحوَّل إلى الصيغة التي يشغّلها واتساب)، وأي شيء آخر مستندًا.
  • بالعنوان: يجب أن يكون url عنوانًا عامًا يبدأ بـ http:// أو https:// على المنفذ المعتاد. نجلب الملف عند إرسال الرسالة، ونتبع حتى 3 تحويلات إلى عناوين عامة، خلال 30 ثانية. قدّمه دون ضغط. وإن لم يرد خادمك، أو رد بخطأ، نحاول مرتين أخريين خلال دقائق قليلة، ثم تفشل الرسالة مع ذكر السبب. والعنوان داخل شبكة خاصة يُرفض بـ 422.
  • بصيغة base64: ضع محتوى الملف في data بدلًا من url، للملفات غير العامة.
  • الحجم: حتى 16 ميجابايت.
  • ملفات اليوم بصيغة base64: يمكن للحساب إرسال 2 جيجابايت من الملفات بصيغة base64 في data يوميًا، عبر رسائله ورسائله الجماعية وحالاته. والحد 200 ميجابايت في التجربة المجانية وفي أصغر باقة. وبعد تجاوزه، يرد الطلب الذي يحمل data بـ 429 مع الرمز file_budget_used، ويوضح Retry-After وmessage متى يبدأ اليوم من جديد. أما الملفات المرسلة بـ url فلا تُحتسب، فأرسل الملفات الكبيرة أو الكثيرة بهذه الطريقة.
  • القواعد نفسها تنطبق على url الملصق وملف الحالة وصورة الملف الشخصي (الملصق حتى 1 ميجابايت؛ وصورة الملف الشخصي حتى 2 ميجابايت، وتُجلب فورًا، خلال 15 ثانية).

الملصقات والمواقع وبطاقات جهات الاتصال والاستطلاعات

يُرسل كلٌّ منها بدلًا من text:

{"sticker": {"url": "https://example.com/sticker.webp"}}
{"location": {"latitude": 30.0444, "longitude": 31.2357, "title": "Our office"}}
{"contact": {"name": "Sara Ali", "phone": "201012345678", "organization": "Acme"}}
{"poll": {"name": "Which day suits you?", "options": ["Sunday", "Monday"], "multiple_answers": false}}
  • الملصق: صورة WebP حتى 1 ميجابايت، بـ url أو data بصيغة base64. والملصقات التي يرسلها الناس إليك تصل بـ type قيمته sticker، والصورة في media.
  • الاستطلاع: من 2 إلى 12 من options. وmultiple_answers يسمح للناس باختيار أكثر من إجابة. ويعرض poll في الرسالة results (الأصوات لكل إجابة) وvotes (آخر اختيار لكل شخص). وكل تصويت، أو تغيير تصويت، أو سحب تصويت يصل كحدث message.poll_vote على الويب هوك.
  • title في الموقع وorganization في بطاقة جهة الاتصال اختياريان.
  • لا يمكن لأيٍّ من هذه الأربعة بدء محادثة مع من لم يراسل الرقم من قبل: أرسل نصًا قصيرًا أولًا.

الاقتباس والجدولة والمجموعات

  • اقتباس رسالة: أضف "reply_to": "<message id>"، وهي رسالة في المحادثة نفسها. تظهر كرد في واتساب، ويُسجَّل reply_to في الرسالة التي أرسلتها. وإن لم تكن الرسالة المقتبسة قد أُرسلت، أو لم يجدها واتساب، تُرسل رسالتك دون الاقتباس.
  • الإرسال لاحقًا: أضف "send_at": "2026-10-01T09:00:00+03:00" (بصيغة ISO 8601 مع فرق التوقيت؛ وبتوقيت UTC إن لم يُذكر؛ وحتى 14 يومًا مقدمًا). تنتظر الرسالة بحالة scheduled، ثم تُرسل كأنها أُرسلت في تلك اللحظة، وتُطبَّق عليها كل القواعد حينها.
  • مجموعة أو قناة: استخدم "chat_id": "…@g.us" (مجموعة) أو "…@newsletter" (قناة يديرها الرقم) بدلًا من to. راجع المحادثات وجهات الاتصال والمجموعات.
  • شخص راسلك دون رقم هاتف: يخفي واتساب أحيانًا رقم الشخص، فيحمل message.received الخاص به "phone": null وchat_id ينتهي بـ @lid. ردّ عليه بهذا الـ chat_id بدلًا من to. ويعمل ذلك كرد فقط، ومن الرقم الذي راسله. فالـ chat_id الذي لم يراسلك منه أحد يُرفض (422)، لأن الرسالة الأولى تحتاج إلى رقم هاتف. نعرف أولًا صاحب المحادثة، فتعرض الرسالة phone الخاص به وتنطبق كل القواعد على الشخص. فإن كان قد كتب «STOP» من رقمه، لا تُرسل. وعندما لا يستطيع واتساب إخبارنا بالرقم في تلك اللحظة، يرد الطلب بـ 503 مع الرمز person_unknown وRetry-After، ولا يُرسل شيء: حاول مرة أخرى.

إعادة المحاولة آمنة

أرسل ترويسة Idempotency-Key (أي نص فريد من عندك، حتى 255 حرفًا، مثل معرّف طلبك). إعادة المحاولة بالمفتاح نفسه على الرقم نفسه تعيد الرسالة الأولى بدلًا من إرسال ثانية، حتى إن وصل الطلبان معًا. وترد إعادة المحاولة بـ 200 مع الترويسة Idempotent-Replayed: true. والطلب الأول هو المعتمد أيًّا كان محتوى إعادة المحاولة: فمحتواها لا يُقرأ، لذا استخدم مفتاحًا جديدًا لرسالة مختلفة. وتُقارن المفاتيح حرفيًا (Order-7 وorder-7 مفتاحان)، ولكل رقم مفاتيحه.

ونحن أيضًا لا نرسل نسخة ثانية أبدًا. إن لم يرد واتساب على الإرسال في الوقت المناسب، نتحقق هل أُرسلت الرسالة قبل أن نحاول من جديد. وإن تعذّر التحقق، تفشل الرسالة مع ذكر أنها ربما وصلت. راجع المحادثة قبل إرسالها مرة أخرى. والحالة التي لم يؤكدها واتساب في الوقت المناسب تفشل بالطريقة نفسها، ولا تُنشر من جديد تلقائيًا: راجع الهاتف أولًا. ورسالة كهذه تحتفظ بـ sent_at (وقت تسليمنا إياها إلى واتساب)، وتُحتسب من حدود الرقم كأنها أُرسلت. لذلك لا تتبعها «رسالة أولى» ثانية. لكنها لا تُعد مُرسلة أو واصلة في إحصاءاتك.

المفتاح نفسه يظل يعيد الرسالة الأولى، حتى بعد فشلها. لإرسال رسالة فشلت من جديد، استخدم مفتاحًا جديدًا. وتجد الردود التي تُعاد محاولتها في الانتظار والأخطاء وإعادة المحاولة.

بعد الإرسال

  • تابعها: GET /v1/messages/{id}، أو أحداث message.status على الويب هوك: queued → sent → delivered → read، أو failed مع السبب في error وerror_code الخاص به.
  • اعرض الرسائل: GET /v1/messages، الأحدث أولًا، مع التصفية بـ instance_id وphone وdirection. اتبع links.next للأقدم. تُحفظ الرسائل 30 يومًا.
  • التعديل: PATCH /v1/messages/{id} مع text يغيّر نصًا أرسله الرقم، خلال 15 دقيقة من إرساله (409 بعد ذلك). ويراه الشخص وعليه علامة «معدّلة». والرسالة التي أُرسلت إلى من لم يراسل الرقم من قبل (رسالة أولى، أو متابعة لها) لا يمكن تعديلها (422).
  • الحذف لدى الجميع: DELETE /v1/messages/{id} على رسالة مُرسلة يحذفها من المحادثة، خلال يومين من إرسالها (409 بعد ذلك). ويُحذف نصها وملفها من Threadwire أيضًا. والرسالة التي أُرسلت إلى من لم يراسل الرقم من قبل لا يمكن حذفها لدى الجميع كذلك (422): فهي التي بدأت المحادثة.
  • الإلغاء قبل الإرسال: DELETE /v1/messages/{id} على رسالة scheduled يحذفها (204). وعلى رسالة queued يلغيها (200): تبقى بحالة failed مع error نصّه «Cancelled before it was sent.»، ويتبعها حدث message.status على الويب هوك. والرسالة التي سُلّمت إلى واتساب، أو أُرسلت أو فشلت في الأثناء، لا يمكن إلغاؤها بعد ذلك (409). وأثناء إرسال الرقم رسالة أخرى يكون الرد 409 مع Retry-After: حاول مرة أخرى بعد ثوانٍ قليلة. ويمكن لفريقك فعل الشيء نفسه بزر «إلغاء» في المحادثة، أو من «سجل الرسائل» في لوحة التحكم. والرسالة الملغاة لا تُحتسب بعد ذلك من رسائل باقتك لذلك اليوم.
  • التفاعل: POST /v1/messages/{id}/reaction مع emoji يتفاعل مع رسالة أرسلها إليك أحد، وemoji فارغ يسحب التفاعل. ويعرض reaction في الرسالة تفاعلك، وreactions تفاعلات الآخرين (phone، emoji). وهذه تصل أيضًا كأحداث message.reaction على الويب هوك. والتفاعل يُشعر الشخص كالرسالة. لذلك لا يُرسل أي تفاعل إلى من طلب التوقف، وبحد أقصى 10 في الساعة للشخص الواحد.
  • التعليم كمقروءة: POST /v1/messages/{id}/read يعلّم محادثة رسالة أرسلها إليك أحد كمقروءة، حين يقرؤها فريقك في نظامك أنت. والرد على من راسلك خلال آخر يوم يفعل ذلك تلقائيًا.

التفاعلات وعلامات القراءة تكون فقط على رسائل أرسلها إليك أحد، والتعديل والحذف فقط على رسائل أرسلها الرقم. والأربعة تحتاج إلى مفتاح مسموح له بالإرسال، وحدّها مجتمعة 20 في الدقيقة لكل رقم.

هل رقم الهاتف على واتساب؟

POST /v1/instances/{id}/check مع phone يرد بـ on_whatsapp: true أو false. استخدمه لمن أعطوك أرقامهم. ففحص القوائم المشتراة أو المخمَّنة يخالف سياسة الاستخدام المقبول، وواتساب يعدّ الفحوص الكثيرة لأرقام مجهولة جمعًا للبيانات. لذلك تتبع الفحوص حماية الرقم: عدد قليل يوميًا ما دام جديدًا، ويزيد مع إحمائه (checks_left_today يوضح كم بقي). وبحد أقصى 10 في الدقيقة، ولا فحص ليلًا أو أثناء توقف محادثاته الجديدة مؤقتًا. والرفض يكون 429 مع ذكر السبب. نتذكر الإجابة «نعم» لمدة أسبوع و«لا» لمدة يوم، فالسؤال من جديد لا يكلّف شيئًا. والرسالة إلى ذلك الشخص لا تحتاج بعدها إلى فحص ثانٍ.