الأرقام
الرقم («القناة») هو خط واتساب مرتبط بحسابك. ربطه هو تدفّق يفشل بأمان (fail-closed): تعلن عن الرقم، وتعرض رمز QR الذي نُرجعه وتمسحه من ذلك الهاتف، وتقرأ Sendveo الرقم المقترن مجددًا قبل اعتباره متصلًا. رمز QR ملك لك تعرضه: لا توجد صفحة خارجية ولا إعادة توجيه.
كائن الرقم
{
"id": "chn_sales01",
"displayName": "Sales line",
"declaredNumber": "+212661234567",
"pairedNumber": "+212661234567",
"status": "CONNECTED",
"connectedAt": "2026-08-19T09:12:00Z",
"lastReconnectAt": null,
"disconnectReason": null,
"createdAt": "2026-08-16T10:00:00Z",
"updatedAt": "2026-09-09T14:24:00Z"
}دورة حياة الحالة
يُبلّغ كل رقم عن إحدى سبع حالات. اقرأ الحالة، لا وجود رقم مقترن، لتقرّر ما تفعله بعد ذلك.
| الحالة | المعنى |
|---|---|
| في انتظار الاقتران | صدر رمز QR، في انتظار المسح. |
| جارٍ الاتصال | المصافحة جارية: طبيعية، وليست عطلًا. |
| متصل | يعمل وخاضع للفوترة؛ يرسل ويستقبل. |
| يلزم إعادة الربط | انتهت الجلسة: أعِد ربط الرقم. |
| غير مُتحقَّق منه | تم المسح لكن القراءة العكسية فشلت: أعِد المحاولة. |
| رقم خاطئ | اقترن رقم مختلف: ابدأ من جديد. |
| مفصول | غير نشط. |
ربط رقم
أنشئ القناة بالرقم الذي تنوي ربطه. تحصل على كائن qr: qr.data سلسلة نصية تُرمّزها وتعرضها كرمز QR (استخدم أي مكتبة QR)، وqr.expiresAt يخبرك متى تجلب رمزًا جديدًا. يبقى الرقم في حالة PENDING_PAIRING حتى يُمسح.
curl -X POST https://api.sendveo.com/v1/numbers \
-H "X-API-KEY: sv_live_your_key_here" \
-H "Content-Type: application/json" \
-d '{ "declaredNumber": "+212661234567", "displayName": "Sales line" }'{
"channel": { "id": "chn_sales01", "status": "PENDING_PAIRING", "declaredNumber": "+212661234567" },
"qr": {
"data": "2@r1x8...,K3f...,c9...,a2...",
"expiresAt": "2026-09-09T14:24:20Z"
}
}تحديث رمز QR
تتجدّد رموز اقتران واتساب كل بضع ثوانٍ. وبينما لا يزال الرقم في حالة PENDING_PAIRING، اجلب qr جديدًا عند expiresAt (أو قُبيله). وبمجرد أن يتوقّف الرقم عن انتظار المسح، يُرجع هذا الرمز 409.
{
"channel": { "id": "chn_sales01", "status": "PENDING_PAIRING", "declaredNumber": "+212661234567" },
"qr": { "data": "2@n7q2...,P0d...,e4...,b8...", "expiresAt": "2026-09-09T14:24:40Z" }
}التحقّق من الاقتران
المسح وحده ليس اتصالًا مُتحقَّقًا منه. استعلِم عن verify على فترات زمنية بينما الرقم قيد الانتظار: تنتظر Sendveo (مُرجِعةً الرقم دون تغيير) حتى تستقرّ الجلسة، ثم تقرأ الرقم المقترن مجددًا وتُرقّيه بأسلوب يفشل بأمان: يصبح CONNECTED فقط إذا طابق الرقم الممسوح الرقم الذي أعلنته، وإلا فيصبح WRONG_NUMBER_SCANNED أو PAIRING_UNVERIFIED.
curl -X POST https://api.sendveo.com/v1/numbers/chn_sales01/verify \
-H "X-API-KEY: sv_live_your_key_here"إعادة الربط والفصل
إذا انتهت الجلسة لاحقًا، ينتقل الرقم إلى CREDENTIALS. أعِد الربط للحصول على qr جديد لعرضه. أما الفصل فيوقف الخط فورًا.
السلامة
يحمل كل رقم كائن health إلى جانب حالته. وlastSeenAt هو آخر وقت أبلغت فيه خدمة الرسائل أن الهاتف متاح، وlastEventAt هو وقت وقوع آخر حدث سلامة (أي occurredAt الخاص به، لا وقت تخزيننا له).
{
"id": "chn_sales01",
"declaredNumber": "+212661234567",
"status": "CONNECTED",
"health": {
"phoneOnline": null,
"lastSeenAt": null,
"lastEventAt": "2026-09-16T10:05:00Z"
}
}لـ phoneOnline ثلاث قيم، وnull ليست false. فـ null تعني أنه لم يصلنا أي خبر عن الهاتف، وهي حال معظم الأرقام: لا توجد إشارة مخصصة تُقرأ لمعرفة مدى إمكانية الوصول إلى الهاتف، ولن يستنتجها Sendveo من حالة الجلسة. اعرض true كمتصل، وfalse كغير متصل، وnull كلا شيء إطلاقًا. ولوحة تحكم ترسم null كغير متصل تضع تحذيرًا على كل رقم سليم لديها.
فقدان الجلسة وفقدان الهاتف حادثان مختلفان لهما جوابان مختلفان. الجلسة الميتة تحتاج إنسانًا ومسحًا جديدًا؛ والهاتف الموضوع للشحن في الغرفة المجاورة لا يحتاج شيئًا. ولهذا هما حدثان منفصلان وصفّان منفصلان وحقلان منفصلان.
التغييرات الأخيرة
سجلّ ما جرى لرقم واحد، من الأحدث إلى الأقدم. وtype يحمل الاسم نفسه الذي يستعمله الـ webhook وتدفّق لوحة التحكم، فالمعالِج المكتوب للـ webhook يقرأ هذه القائمة دون تغيير. وlimit من 1 إلى 200 وقيمته الافتراضية 50.
{
"numberId": "chn_sales01",
"events": [
{ "id": "cev_m8k3x7q2", "numberId": "chn_sales01", "type": "number.reconnected",
"reason": null, "occurredAt": "2026-09-16T10:12:00Z" },
{ "id": "cev_m8k3wp41", "numberId": "chn_sales01", "type": "number.disconnected",
"reason": "SESSION_EXPIRED", "occurredAt": "2026-09-16T10:05:00Z" }
],
"cursor": null
}reason لا يرافق سوى number.disconnected، وهو من مفردات Sendveo نفسها لا من كلمات حالة خدمة الرسائل: SESSION_EXPIRED (مات الرابط ويلزم مسح جديد) أو REMOVED_UPSTREAM (حُذف الحساب من واتساب).
الترقيم بالمفتاح لا بالإزاحة: السجل ينمو من أعلاه، فالصفحة الثانية المحسوبة بالإزاحة ستعيد عرض صفوف بمجرد وصول حدث جديد بين الطلبين. أعِد معرّف آخر حدث في الصفحة السابقة بوصفه cursor. الصفحة الممتلئة تقدّم مؤشرًا؛ والصفحة القصيرة هي النهاية وتقدّم null. أما المؤشر الذي لا يخص هذا الرقم فيعطي 400 VALIDATION_FAILED بدل صفحة أولى صامتة.
لا يُسجَّل شيء لرقم لم يكتمل ربطه قط: الفشل هناك اقتران لم ينجح، لا خط سقط. ولا يتكرّر أي حدث، فلا يبدو الرقم وكأنه سقط ثلاث مرات لمجرد وصول webhook واحد ثلاث مرات. وفي أول مرة يُقال لنا فيها إن الهاتف متاح، لا يُعلَن شيء، لأن التعافي من عطل لم يره أحد يُقرأ ضجيجًا.
ملف الخط
ما ينشره خطك عن نفسه: الاسم الذي يراه عملاؤك، وعبارة الحالة تحته، وما إذا كان حساب أعمال، وصورته. والسبب في السؤال ملموس: ربطت رقمًا قيل لك إنه خط المبيعات، وتريد أن ترى من داخل Sendveo أنه فعلًا الحساب الذي تظنه قبل أن توجّه إليه تكاملًا.
{
"profile": {
"numberId": "chn_sales01",
"phone": "+212661234567",
"displayName": "Atlas Traiteur",
"about": "Deliveries 7 days a week",
"business": true,
"pictureUrl": "https://api.sendveo.com/v1/numbers/chn_sales01/picture",
"editable": false
}
}إنه للقراءة فقط، وeditable: false يقول ذلك على المورد نفسه. لا يوجد هنا PATCH ولا PUT ولا POST، وهذه المسارات تعطي 404: لا تنشر خدمة الرسائل أي فعل لكتابة الملف الشخصي لجهاز مربوط، وطرفٌ يفشل في كل مرة، أو ينجح دون أن يغيّر شيئًا، أسوأ من قول ذلك صراحة. غيّر الملف الشخصي داخل واتساب على الهاتف.
phone هو الرقم المقترن المتحقَّق منه، منقولًا عمّا أكّدته القراءة العكسية. وpictureUrl عنوان Sendveo مُعنوَن بمعرّف القناة لا برقم الهاتف، فلا ينتهي خطك أبدًا في سجل متصفّح أو في Referer أو في سجل وسيط. وتكون قيمته null حين لا ينشر الخط صورة، ويجيب مسار الصورة بـ 404 لخط بلا صورة، ولخط يخفيها، ولعثرة عابرة في خدمة الرسائل على السواء.
الرقم غير المتصل، أو الذي لم يُتحقَّق منه بعد، يجيب 409 CONFLICT.