انتقل إلى المحتوى

أرسل رسالتك الأولى في خمس دقائق.

تعمل واجهة REST API على الأرقام التي ربطتها في صندوق الرسائل. اعرضها، وابحث عن محادثة، وأرسل، وتابع كل حالة عبر خطافات ويب موقّعة.

POST /v1/messages
Idempotency-Key: 3f1c9a52-7d43-4bb8-9a3e-1e2f5c6d7a80
{ "chat_id": "chat_…", "type": "text",
"text": "Friday works, your order is updated." }
HTTP/1.1 202 Accepted
{ "id": "msg_…", "status": "pending", "chat_id": "chat_…" }
ثم على خطاف الويب لديك
message.sentsent09:12:41
message.statusdelivered09:12:44
message.statusread09:14:10
عنوان URL الأساسي
https://api.wrelay.site/v1
المصادقة
Bearer rl_live_…
الأخطاء
application/problem+json
المواصفة
OpenAPI 3.1

البدء السريع

خمس خطوات من مفتاح API إلى رسالة مُسلَّمة. اختر لغة البرمجة مرة واحدة فتتبعها كل الأمثلة.

  1. أنشئ مفتاح API

    في لوحة التحكم، افتح الإعدادات › المطوّرون › مفاتيح API وأنشئ مفتاحًا. يعمل المفتاح باسم المؤسسة كلها ولا يُعرض إلا مرة واحدة: لا نحتفظ إلا ببصمته.

    الصلاحيات لا تتراكم. يحتاج هذا البدء السريع إلى read وsend، ويحتاج تسجيل نقطة نهاية لخطاف ويب عبر API إلى admin.

    Authorization: Bearer rl_live_…
    # Settings › Developers › API keys › Create key
    export RELAY_API_KEY="rl_live_…"
    بمفتاح مفقود أو ملغى أو منتهي الصلاحية401
    {
    "type": "urn:relay:problem:unauthorized",
    "title": "Authentication required",
    "status": 401,
    "code": "unauthorized",
    "detail": "Send a valid API key as `Authorization: Bearer rl_live_…`."
    }
  2. اعرض أرقامك

    يُرجع GET /v1/numbers أرقام المؤسسة من الأقدم إلى الأحدث. احتفظ بالمعرّف id لرقم حالته status هي working: تدلّ can_send على أنه جاهز.

    القوائم مقسّمة إلى صفحات عبر limit وcursor: أعد إرسال next_cursor حتى تصبح قيمته null.

    GET/v1/numbers
    curl "https://api.wrelay.site/v1/numbers?status=working" \
    -H "Authorization: Bearer $RELAY_API_KEY"
    الاستجابة200
    {
    "data": [
    {
    "id": "num_01a1a1c6c2007a3f9c41e2b7d5a60813",
    "label": "Sales",
    "phone": "+212600000001",
    "display_name": "Atelier Exemple",
    "avatar_url": null,
    "status": "working",
    "status_reason": null,
    "status_changed_at": "2026-11-10T08:02:11.000Z",
    "first_connected_at": "2026-11-03T14:20:05.000Z",
    "connected_at": "2026-11-10T08:02:11.000Z",
    "last_event_at": "2026-11-12T09:11:57.000Z",
    "can_send": true,
    "daily_send_cap": 400,
    "history_import": {
    "status": "completed",
    "started_at": "2026-11-03T14:20:09.000Z",
    "finished_at": "2026-11-03T14:31:52.000Z",
    "chats_total": 214,
    "chats_done": 214,
    "messages": 18342,
    "error_code": null
    },
    "created_at": "2026-11-03T14:18:40.000Z"
    }
    ],
    "has_more": false,
    "next_cursor": null
    }
  3. ابحث عن محادثة أو ابدأ واحدة

    ابحث في محادثات رقم واحد بالاسم أو بأرقام الهاتف، واحتفظ بمعرّف المحادثة id.

    لا توجد محادثة بعد؟ تخطَّ هذه الخطوة وأرسل باستخدام number_id وto بدلًا من chat_id: تُفتح المحادثة مع أول رسالة.

    GET/v1/chats
    curl "https://api.wrelay.site/v1/chats?number_id=num_01a1a1c6c2007a3f9c41e2b7d5a60813&search=Maison" \
    -H "Authorization: Bearer $RELAY_API_KEY"
    الاستجابة200
    {
    "data": [
    {
    "id": "chat_01a1a1d0f4a87c128e5d4b9a2f61c37e",
    "number_id": "num_01a1a1c6c2007a3f9c41e2b7d5a60813",
    "type": "dm",
    "jid": "212612345678@s.whatsapp.net",
    "phone": "+212612345678",
    "name": "Maison Exemple",
    "description": null,
    "avatar_url": null,
    "unread_count": 1,
    "last_message_at": "2026-11-12T09:10:03.000Z",
    "archived": false,
    "pinned": false,
    "pinned_at": null,
    "muted": false,
    "muted_until": null,
    "left_at": null,
    "only_admins_send": false,
    "only_admins_edit": false,
    "group_created_at": null,
    "created_at": "2026-11-03T14:24:17.000Z"
    }
    ],
    "has_more": false,
    "next_cursor": null
    }
  4. أرسل رسالة

    يسجّل POST /v1/messages الرسالة بالحالة pending ويضعها في قائمة الانتظار. تغادر إلى واتساب خلال ثوانٍ، بفاصل بضع ثوانٍ لكل رقم.

    أعد محاولة أي طلب فشل أو انتهت مهلته بالمفتاح Idempotency-Key نفسه والمحتوى نفسه: تحصل على الرسالة نفسها بحالتها الحالية، ولا تُرسَل مرتين أبدًا.

    POST/v1/messages
    curl https://api.wrelay.site/v1/messages \
    -H "Authorization: Bearer $RELAY_API_KEY" \
    -H "Idempotency-Key: $(uuidgen)" \
    -H "Content-Type: application/json" \
    -d '{"chat_id": "chat_01a1a1d0f4a87c128e5d4b9a2f61c37e", "type": "text",
    "text": "Friday works, your order is updated."}'
    الاستجابة202
    {
    "id": "msg_01a1cf07d7407d84b2a619f3c8e05d47",
    "status": "pending",
    "chat_id": "chat_01a1a1d0f4a87c128e5d4b9a2f61c37e"
    }
  5. استقبل خطافات الويب

    أضف نقطة نهاية للحدثين message.received وmessage.status، من لوحة التحكم أو بمفتاح يملك صلاحية admin. تتضمّن الاستجابة سرّ التوقيع مرة واحدة فقط.

    بعد ذلك يصل كل حدث كطلب POST موقّع. أجب بأي رمز 2xx خلال 10 ثوانٍ، وتحقّق من التوقيع قبل الوثوق بالمحتوى.

    POST/v1/webhooks/endpoints
    curl https://api.wrelay.site/v1/webhooks/endpoints \
    -H "Authorization: Bearer $RELAY_ADMIN_KEY" \
    -H "Idempotency-Key: $(uuidgen)" \
    -H "Content-Type: application/json" \
    -d '{"url": "https://example.com/hooks/relay",
    "events": ["message.received", "message.status"]}'
    الاستجابة201
    {
    "id": "whk_01a1c5e0a9407e8db0c27f4a19d3e65b",
    "url": "https://example.com/hooks/relay",
    "description": null,
    "events": [
    "message.received",
    "message.status"
    ],
    "number_ids": [],
    "enabled": true,
    "disabled_at": null,
    "disabled_reason": null,
    "consecutive_failures": 0,
    "last_delivery_at": null,
    "last_success_at": null,
    "created_at": "2026-11-12T09:05:31.000Z",
    "secret": "whsec_…"
    }
    على نقطة النهاية لديك
    POST /hooks/relay
    Content-Type: application/json
    User-Agent: relay-webhooks/1
    X-Relay-Event: message.status
    X-Relay-Delivery: dlv_01a1cf07f1a27b6e9d20c3a85e17f4b9
    X-Relay-Timestamp: 1794474764
    X-Relay-Signature: v1=…
    {
    "id": "evt_01a1cf07f1a27b6e9d20c3a85e17f4b9",
    "event": "message.status",
    "created_at": "2026-11-12T09:12:44.120Z",
    "data": {
    "id": "msg_01a1cf07d7407d84b2a619f3c8e05d47",
    "number_id": "num_01a1a1c6c2007a3f9c41e2b7d5a60813",
    "chat_id": "chat_01a1a1d0f4a87c128e5d4b9a2f61c37e",
    "wa_message_id": "3EB0A7C2F51D9E84B6C3",
    "from_me": true,
    "client_key": "3f1c9a52-7d43-4bb8-9a3e-1e2f5c6d7a80",
    "status": "delivered",
    "error_code": null,
    "sent_at": "2026-11-12T09:12:41.000Z"
    }
    }
طلب واحد، رسالة واحدة.لا توجد نقطة نهاية للإرسال الجماعي أو البثّ: كل طلب يرسل رسالة واحدة إلى محادثة واحدة، ويرسل كل رقم رسائله بفاصل بضع ثوانٍ. راسل من ينتظرون رسائلك.اقرأ سياسة الاستخدام المقبول

كيف تعمل واجهة API

القواعد المشتركة بين كل نقاط النهاية. يوثّق المرجع كل نقطة نهاية بالتفصيل.

المعرّفات العامة

يتكوّن كل معرّف من بادئة تدلّ على المورد و32 حرفًا ست عشريًا. المعرّف التابع لمؤسسة أخرى أو المشوّه أو ذو البادئة الخاطئة يُرجع 404 <resource>_not_found، وليس خطأً مختلفًا.

بنية معرّف رسالة
msg_بادئة المورد01a1cf07d7407d84b2a619f3c8e05d4732 حرفًا ست عشريًا
  • num_رقم
  • chat_محادثة أو مجموعة
  • msg_رسالة
  • ct_جهة اتصال
  • upl_ملف مرفوع
  • media_مرفق مُستلَم
  • whk_نقطة نهاية خطاف ويب
  • dlv_تسليم خطاف ويب
  • evt_حدث خطاف ويب
  • op_عملية

الصلاحيات

يحمل كل مفتاح صلاحية واحدة أو أكثر. أي طلب خارجها يُرجع 403 insufficient_scope، ويقبل GET /v1/operations/{id} أي مفتاح.

readكل طلبات GET: الأرقام والمحادثات والرسائل والمجموعات وجهات الاتصال وتنزيل الوسائط.
sendالإرسال والتفاعلات والتعديل والحذف، وحالة المحادثات (الأرشفة والتثبيت والكتم والقراءة)، والمجموعات، ورفع الملفات، والتحقق من الأرقام.
adminربط الأرقام واقترانها وتسجيل خروجها وحذفها، ونقاط نهاية خطافات الويب وسجل التسليم.

الصلاحيات لا تتراكم: امنح المفتاح كل صلاحية يحتاجها.

منع التكرار

يحتاج كل طلب POST وPATCH وDELETE إلى الترويسة Idempotency-Key: من 1 إلى 150 حرف ASCII مرئي، ويُفضَّل UUID.

  • المفتاح نفسه والمحتوى نفسه خلال 24 ساعة: تعود الاستجابة الأصلية مع Idempotent-Replayed: true، ولا يحدث شيء مرتين.
  • المفتاح نفسه لطلب مختلف: 422 idempotency_key_reused. الطلب الأول ما زال قيد التنفيذ: 409 idempotency_key_in_use.
  • لا تُحفظ إلا الاستجابات الناجحة: بعد أي خطأ، يُعيد المفتاح نفسه تنفيذ الطلب.
  • في الإرسال، المفتاح هو أيضًا client_key للرسالة: إعادة محاولة POST /v1/messages، حتى بعد 24 ساعة، تُرجع الرسالة نفسها بحالتها الحالية.
  • استثناء واحد: لا يأخذ POST /v1/numbers/{id}/pairing-code أي مفتاح، لأن رمزه لا يُخزَّن أبدًا.

حدود المعدّل

لكل مفتاح سقف للدفعات وحصة في الدقيقة، ولكل رقم ولكل مؤسسة حدودهما الخاصة فوق ذلك.

HTTP/1.1 429 Too Many Requests
Content-Type: application/problem+json
RateLimit-Limit: 60
RateLimit-Remaining: 0
RateLimit-Reset: 23
RateLimit-Policy: 20;w=1, 60;w=60
Retry-After: 23
{
"type": "urn:relay:problem:rate_limited",
"title": "Too many requests",
"status": 429,
"code": "rate_limited",
"detail": "This API key is over its rate limit: retry after the number of seconds in Retry-After."
}
الحدالقيمةالاستجابة
دفعة، لكل مفتاح20 طلبًا في الثانيةrate_limited
معدّل مستمر، لكل مفتاححدّ الدقيقة في باقتك، أو حدّ المفتاح نفسهrate_limited
لكل رقم30 طلب إرسال في الدقيقةrate_limited
طلبات API، لكل مؤسسةالحصة الشهرية للباقة، تُعاد في اليوم الأول من الشهر (UTC)quota_exceeded
الرسائل المرسلة، لكل مؤسسةحصة الإرسال الشهرية للباقةquota_exceeded
الإرسال اليومي، لكل رقميرتفع تدريجيًا خلال أول أسبوعين من عمر الرقم الجديدsend_cap_reached
المحادثات الجديدة، لكل رقم في اليوممحدودة، للأشخاص الذين لم يراسلوا الرقم قطrecipient_never_wrote
الباقةطلبات / دقيقة / مفتاحطلبات API / شهررسائل مرسلة / شهر
Starter6010,00010,000
Growth300100,00060,000
Business1,2001,000,000300,000

تحمل كل استجابة موثّقة الترويسات RateLimit-Limit وRateLimit-Remaining وRateLimit-Reset (بالثواني) لأضيق نافذة، وRateLimit-Policy لكل النوافذ. وتضيف الاستجابة 429 الترويسة Retry-After.

الأخطاء

كل استجابة خارج 2xx هي مشكلة وفق RFC 9457 بصيغة application/problem+json. اعتمد على code: لا تُعاد تسمية الرموز ولا تُحذف أبدًا، وقد تُضاف رموز جديدة. يسرد errors الحقول المطلوب تصحيحها.

HTTP/1.1 422 Unprocessable Entity
Content-Type: application/problem+json
{
"type": "urn:relay:problem:validation_failed",
"title": "Unprocessable request",
"status": 422,
"code": "validation_failed",
"detail": "One or more fields are invalid.",
"errors": {
"text": "A text message needs text"
}
}
الحالةالرمزما العمل
400idempotency_key_requiredأضف الترويسة Idempotency-Key إلى طلب الكتابة.
401unauthorizedتحقّق من المفتاح: المفتاح المجهول والملغى والمنتهي يُرجع هذا الرمز نفسه.
403insufficient_scopeاستخدم مفتاحًا يملك صلاحية نقطة النهاية.
404chat_not_foundالمعرّف لا ينتمي إلى هذه المؤسسة، أو بادئته خاطئة.
409number_not_workingالرقم غير متصل: انتظر حتى تصبح قيمة number.status هي working.
422validation_failedصحّح الحقول المذكورة في errors.
429rate_limitedانتظر عدد الثواني في Retry-After ثم أعد المحاولة.
502gateway_<reason>لم يُجب واتساب عن طلب فوري: أعد المحاولة بعد قليل.
503enqueue_failedحُفظ الطلب ولم يدخل قائمة الانتظار: أعد المحاولة بالمفتاح Idempotency-Key نفسه.
اطّلع على كل الرموز في المرجع

العمليات الطويلة

الطلبات التي تنتظر واتساب (ربط رقم أو حذفه، وأوامر المجموعات، والتحقق من الأرقام) تُجيب بالرمز 202 مع operation_id وترويسة Location.

  • استعلم عن GET /v1/operations/{id} كل ثانية إلى ثانيتين حتى تصبح status بالقيمة succeeded (اقرأ result) أو failed (اقرأ error.code)، ثم أعد قراءة المورد.
  • العملية التي لا تنتهي خلال ساعة تصبح failed بالرمز expired.
قُبل الطلب
POST /v1/contacts/check
Idempotency-Key: 3f1c9a52-7d43-4bb8-9a3e-1e2f5c6d7a80
{ "phone": "+212612345678" }
HTTP/1.1 202 Accepted
Location: /v1/operations/op_01a1cf07e6e07f028b3d6a1c94e2f507
{
"operation_id": "op_01a1cf07e6e07f028b3d6a1c94e2f507",
"operation": {
"id": "op_01a1cf07e6e07f028b3d6a1c94e2f507",
"kind": "number_check",
"status": "queued",
"progress": null,
"result": null,
"error": null,
"created_at": "2026-11-12T09:12:44.000Z",
"started_at": null,
"finished_at": null
}
}
بعد بضع ثوانٍ
GET /v1/operations/op_01a1cf07e6e07f028b3d6a1c94e2f507
HTTP/1.1 200 OK
{
"id": "op_01a1cf07e6e07f028b3d6a1c94e2f507",
"kind": "number_check",
"status": "succeeded",
"progress": null,
"result": {
"phone": "+212612345678",
"on_whatsapp": true
},
"error": null,
"created_at": "2026-11-12T09:12:44.000Z",
"started_at": "2026-11-12T09:12:45.000Z",
"finished_at": "2026-11-12T09:12:46.000Z"
}

إرسال الملفات

لا تمرّ الملفات عبر واجهة API أبدًا: تُرفع مباشرة إلى التخزين، ثم تشير الرسالة إليها.

الصور والصوت حتى 16 ميغابايت، والفيديو حتى 64 ميغابايت، والمستندات حتى 100 ميغابايت. يُنزَّل المرفق المُستلَم عبر GET /v1/media/{id} الذي يُرجع رابطًا موقّعًا صالحًا لمدة 5 دقائق.

  1. POST /v1/media/uploads مع mime_type وsize_bytes: تحصل على معرّف upl_ ورابط upload.url موقّع مسبقًا.
  2. أرسل البايتات الخام بطلب PUT إلى upload.url مع upload.headers كما هي تمامًا ودون ترويسة Authorization، خلال 15 دقيقة.
  3. POST /v1/media/uploads/{id}/finalize: تصبح حالة الملف ready.
  4. POST /v1/messages مع type وupload_id وتعليق اختياري في text، خلال 24 ساعة.
POST /v1/media/uploads
Idempotency-Key: 3f1c9a52-7d43-4bb8-9a3e-1e2f5c6d7a80
{ "mime_type": "image/jpeg", "size_bytes": 284512, "file_name": "receipt.jpg" }
HTTP/1.1 201 Created
{
"id": "upl_01a1cf0901bc7a558f612d0c7e9b3a48",
"state": "pending",
"file_name": "receipt.jpg",
"mime_type": "image/jpeg",
"declared_bytes": 284512,
"size_bytes": null,
"expires_at": "2026-11-13T09:20:05.000Z",
"created_at": "2026-11-12T09:20:05.000Z",
"upload": {
"method": "PUT",
"url": "https://…",
"headers": {
"Content-Type": "image/jpeg"
},
"max_bytes": 284512,
"expires_at": "2026-11-12T09:35:05.000Z"
}
}

كل نقاط النهاية في المرجع.

يُولَّد المرجع المستضاف وملف OpenAPI 3.1 من المخططات نفسها التي تتحقق من طلباتك، فلا يمكن أن يختلفا عمّا تقبله الواجهة.