> ## Documentation Index
> Fetch the complete documentation index at: https://docs.orbit.devotel.io/llms.txt
> Use this file to discover all available pages before exploring further.

# دورة حياة التسليم: من queued إلى delivered والحالات المتوسطة

> كيف تنتقل الرسالة الصادرة من queued عبر sent إلى delivered (أو نتيجة فاشلة)، ومن يدفع كل انتقال، وكيف تُحرّك إيصالات التسليم (DLRs) ذلك، والاستثناءات الخاصة بكل قناة التي تحتاجها قبل أول webhook.

# دورة حياة التسليم

كل رسالة صادرة ترسلها عبر Orbit تحمل حقل `status` يتقدم بينما تنتقل الرسالة من استدعاءك للواجهة البرمجية نحو جهاز المستلم — أو نحو نتيجة فاشلة. تشرح هذه الصفحة هذه الآلة الحالة المفهومية: ما تعنيه الحالات، ما الذي يدفع كل انتقال، وأين توجد الحواف الخاصة بالمشغّل. اقرأها قبل اشتراكك في أول webhook لك أو تفرّع تكاملك على نتيجة الرسائل.

تعيش دلالات الحالة، جدول الانتقالات الكامل، وخريطة حدث webhook في [مرجع دورة حياة حالة الرسائل](/api-reference/messages-status-lifecycle)؛ مخطط الاستجابة لقراءة الحالة الحالية للرسالة موجود في [مرجع واجهة API للمراسلة](/api-reference/endpoints/messaging). هذه الصفحة تربط بينهما بمستوى أعلى.

## المسار السعيد

رسالة تنجح من طرف إلى طرف تمر عبر:

`pending → queued → sending → sent → delivered → read`

كل انتقال يُدفَع بواسطة جهاز مختلف — لا طرف واحد يرى المسار كله:

| الانتقال           | المعنى                                     | ما يدفعه                                                                                                                          |
| ------------------ | ------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------- |
| `pending → queued` | السجل موجود ويوضع في قائمة انتظار الإرسال. | مسار الإرسال، عند قبول `POST /messages/<channel>`. `pending` هي حالة انتقالية قبل قائمة الانتظار نادراً ما ستلاحظها.              |
| `queued → sending` | متسخّر أخذ الرسالة ويوزّعها إلى المقدم.    | قائمة إرسال خط الأنابيب عند الإزالة من قائمة الانتظار.                                                                            |
| `sending → sent`   | المقدم وفّق الإرسال على السلك.             | مسار الإرسال، في اللحظة التي يقبل فيها المقدم (اكتشاف إرسال SMPP، معرف رسالة المقدم، معرف تسليم Meta — أيًا كان قبول سلك القناة). |
| `sent → delivered` | المشغّل وفّق التسليم إلى المستلم.          | إيصال تسليم (DLR) يرجع من المشغّل، يُعالج بواسطة خط أنابيب DLR.                                                                   |
| `delivered → read` | المستلم فتح الرسالة.                       | إيصال قراءة (DLR)، على القنوات التي تصدرها (WhatsApp وRCS والبريد الإلكتروني). يعني أن السجل تم تسلميه أولاً.                     |

جهازان يجلسان بجانب هذا المسار ويمكنهما إخراج سجل منه:

* **جدولة no-DLR.** عندما لا يُرجع مشغّل إيصالاً للتسليم على الإطلاق، تروّخ الجدولة `sent` إلى `submitted_no_receipt` بعد نافذة سماح خاصة بالقناة — راجع [المؤكد من المشغّل مقابل. وسيط أولي على السلك](#التحقق-من-المشغ-مقابل-وسيط-أولي-على-السلك).
* **أنت (المشغّل).** إلغاء رسالة مجدوّلة لم تُرسَل أذّ بها إلى `cancelled`، حالة نهائية لا يلمسها أي استدعاء للمقدم ولا أي DLR. تُحل مرسلات الصندوق إلى `test_sent`، حالة نهائية يُبلّغ إليها قبل أي نشر للمقدم. حذف سجل ينقل أي حالة نهائية إلى `deleted`، بعدئذ لا شيء يمكن أن يلمسه.

رسالة مجدوّلة للمستقبل تتوقف في `scheduled` حتى وقت الإطلاق ثم تنضم إلى قائمة الانتظار. لا يمكن أن تغادر `scheduled` إلا ثلاث طرق: ترقيتها إلى `queued` عند وقت الإطلاق، `cancelled` منك، أو `expired` إذا انتهت نافذة صلاحيتها قبل النشر.

## التحقق من المشغّل مقابل. وسيط أولي على السلك

أهم تمييز للتقارير والتسوية هو ما إذا كانت الحالة نتيجة **مؤكَّدة من المشغّل** أم **حاربها القبّيل على السلك**:

* `delivered` و `read` مؤكَّدان من المشغّل. llegó DLR حقيقي؛ المشغّل نفسه اكتفى بالنتيجة.
* `submitted_no_receipt` حاربه أولي. يعني "قُبِلت الإرسال، ولم يُعاد أي إيصال ضمن نافذة السماح." يُوصَف أنه أولي (`state_class: "intermediate"`, `is_terminal: false`) على كل webhook، لأن DLR `delivered` أو `read` أو فاشل حقيقي يمكن أن يصل لاحقًا ويستبدله.

عامل `submitted_no_receipt` على أنه *نتيجة مجهولة*، لا كتسليم. ما إذا كان "مجهول" يميل إلى إيجابي أو مجرد محوّل يعتمد على القناة — راجع [تنوعات القناة](#تنوعات-القناة).

`expired` هو النظر عن الجانب الآخر: llegó DLR، لكن للغاية متاخرًا بحيث أن نافذة الإيصال كانت قد أُغلقَت. لا يمكن معرفة النتيجة والسجل مغلق؛ `expired` يُوزَّع على المشتركين كحدث `message.failed`.

## تنـوعات القناة

* **قنوات DM من Meta (Instagram, Messenger).** واجهة الإرسال الخاصة بـ Meta لا تصدر إيصالات التسليم أبدًا. يغادر الإرسال Orbit كـ `sent`، يعلمز `no_dlr_channel` في متطافات الرسالة، ويتحول إلى `submitted_no_receipt` بعد 5 دقائق. في مستلم تم مقبول اختيارياً، يضمن Meta التسليم على القبول — لذلك في هذه القنوات يتصرف `submitted_no_receipt` مثل إشارة وظيفية للتسليم، ومتطافات الرسالة تحمل `no_dlr_channel: true` لتستطيع التمييز بين الحالة.
* **قنوات تدعمها SMPP (SMS, MMS, صوت، فاكس، RCS).** نافذة السماح 30 دقيقة. هنا `submitted_no_receipt` هو محوّل حقيقي: قد يكون الجهاز قد تلقّى الرسالة بدون إيصال تم الإبلاغ عنه، قد لا يُرسل المشغّل إيصالات أبدًا على ذلك الطريق، أو قد يكون الإيصال قد أُسقِطَ في العبور. تتبَّع هذه النسبة على إشارة منفصلة عن نسبة التسلميات — نسبة `submitted_no_receipt` المترسّخة على وجهة واحدة تُشير إلى طريق غير متوَلِيّ أو إلى طريق إيصال مكسور، وهي تستحق التحقيق في أيّ من الحالتين.
* **البريد الإلكتروني.** يضيف نتيجة فاشلة لا يملكها غار Channels: `bounced`، عندما يرفُض خادم البريد الاستقبال الرسالة. عدد الارتداد ضد معدل الفشل النهائي الخاص بك مثل `failed`، لكنه حالة مفروقَة لتمكينك من فصل الرفضات من جانب المستلم عن تلك الجانب المقدم.
* **إلغاء المشغّل.** `cancelled` يُبلّغ إليها فقط من أنت — عبر `POST /messages/:id/cancel` على رسالة لم تُرسَل. لا مشغّل يكتبها أبدًا، ونتيجةً لا تطلق **أي حدث webhook**؛ لا شيء يُخبِر المشترك عن الإلغاء. استشِر `GET /messages/:id` إذا كنت تُعرِّض الإلغاء في واجهتك وتحتاج إلى مراقبته.
* **الصندوق / وضع الاختبار.** مرسلات الاختبار تحل إلى `test_sent` قبل أي نشر للمقدم. تطلق `message.sent` مع `status: "test_sent"` و `metadata.test_mode: true`، لذا المشترك يجب أن يُفرّع على `metadata.test_mode` ليبقي حركة الصندوق خارج معالجة الإنتاج.

## ما يُفرّع عنه

يجب أن تتبدأ التكاملات على الحقول القابلة للقراءة آلياً فقط، أبدًا على الأوصاف العرضية:

* **`status`** — الحالة الحالية للرسالة. هذه نقطة التفرّع الأولية. تعامل مع المجموعة كاملة: غير حالات المسار السعيد والنتيجة المتفقّلة، لا تنس `cancelled`، `test_sent`، `submitted_no_receipt`، و `bounced`.
* **`metadata.classified_error_code`** — موجود على النتائج النهائية الفاشلة؛ الفئة الفاشلة المُعرَّفة آلياً والمُمَكِّنَة آلة. ادمِجها مع `error_code` / `error_message` خام على webhook `message.failed` عندما تريد كلمات المشغّل.
* **`metadata.no_dlr_channel`** — موجود على سجلات DM من Meta؛ يخبرك أن `submitted_no_receipt` هو حالة التسليم المضمونة من Meta، لا الحالة المحوّلة من SMPP.
* **`state_class` / `is_terminal`** — على webhook الحياة. `is_terminal: true` (بالم زوجة `state_class: "terminal"`) يعني أن النتيجة نهائية؛ `submitted_no_receipt` تبلغ `is_terminal: false` بالضبط لكي لا تغلِق الكتاب عليها.

## أخطاء شائعة

1. **تعامل `message.created` على القبول.** `message.created` يطلق في اللحظة التي توضع السجل في قائمة الانتظار، قبل أي استدعاء للمقدم. رفض متزامن (4xx على الإرسال، أو `rejected`/`failed` فوري) يترك ذلك الحدث مسلَّم. اجمِعه مع `message.sent` قبل أن تستنتج أن الرسالة خرجت.
2. **تفترض أن `delivered` غير قابلة للتغيّر.** المشغّلون على الطرق بعض يصدِرون إيصالًا للتسليم، ثم تصحيحًا بعد دقائق — بعض المشغّلين الهنديين والبرازيليين يفعلون ذلك. Orbit يحترم ذلك: يمكن للسجل أن ينتقل من `delivered → undelivered` أو من `delivered → failed`. إذا ربَّيت الحالات في مخزن بياناتك الخاص، طبِّق التحديثات بشكل عدم تثويري حسب معرف الرسالة بدلاً من تجاهل الانتقالات لرسالة وعلها من قبل.
3. **تنتظر webhook على `cancelled`.** لن يأتي أبدًا — الإلغاء يرتَبط باستدعاءك للواجهة البرمجية، لا باستدعاء المشغّل، لذا المنصة لا تصدر حدثًا له. السجل يجلس ببساطة في `cancelled` حتى تحذِفه.
4. **ترمي `submitted_no_receipt` في مجرى الفشل.** يصل على نوع حدث `message.failed` لأسباب التعَبب (لا يوجد حدود مخصص)، لكن حذرن يكتو حول `data.status`، لا نوع الحدث، واحصِر بها خارج مقاعع الفشل الثابت.
5. **تتوقع حدثًا نهائيًا واحدًا لكل رسالة.** قد تصدر رسالة `message.failed` مع `status: "submitted_no_receipt"` ثم `message.delivered`، عندما يصل إيصال المشغّل البطيء أخيرًا ضمن نافذة الوصول المتراخَى. إحدِّثه وجهّزه بواسطة `message_id`، ودَع الحدث المتأخر يغلب.

بمجرد أن تكون الآلة الحالة واضحة، فإن مجموعات الإيزاء لكل حالة في [مرجع أحداث webhook](/reference/webhook-events)، والدلالات الوحيدة للحالة في [مرجع دورة حياة حالة الرسائل](/api-reference/messages-status-lifecycle).
