واجهة BabylonCare البرمجية والتكاملاتBabylonCare API and integrations

وثائق لمن يربط متجره أو برنامجه ببابيلون كير: تسجيل الطلبات، قراءة البيانات، استقبال الأحداث، وإضافات جاهزة لووكومرس وووردبريس وشوبيفاي.Documentation for anyone connecting a store or software to BabylonCare: register orders, read data, receive events, and ready-made plug-ins for WooCommerce, WordPress and Shopify.

نظرة عامةOverview

لبابيلون كير ثلاث طرق للتكامل مع الأنظمة الخارجية، ولكل منها غرضها:BabylonCare offers three ways to integrate with outside systems, each with its own purpose:

  • واجهة REST بمفتاح bk_: يدفع متجرك أو برنامجك الطلبات إلى كير، ويقرأ المراجع، ويقرأ الطلبات والمتابعة والإحصائيات إن مُنح الصلاحية.REST API with a bk_ key: your store or software pushes orders into Care, reads reference lists, and reads orders, tracking and stats if granted the scope.
  • Webhook صادر: يرسل كير إلى رابطك حدثاً موقّعاً عند كل تغيّر في الطلب.Outbound webhook: Care sends a signed event to your URL whenever an order changes.
  • ربط الموقع (bsl1): عقد موقّع بمفتاح واحد تعتمد عليه BabylonWeby (موقعك من بابيلون) وإضافة ووكومرس؛ تصل به الطلبات إلى صندوق «طلبات الموقع» لتعتمدها بنفسك.Site link (bsl1): a contract signed with a single key, used by BabylonWeby (our own website service) and the WooCommerce plug-in; orders land in the “Website orders” inbox for you to approve.

الإتاحة: مفاتيح API وWebhooks ضمن الباقة الاحترافية (يردّ الخادم 403 FEATURE_DISABLED في الباقة الأساسية). ربط المتجر الإلكتروني متاح لكل المشتركين ويبقى مغلقاً حتى ينشئ المدير مفتاح الربط من الإعدادات.Availability: API keys and webhooks are part of the Professional plan (the Basic plan gets 403 FEATURE_DISABLED). The online-store link is available to every subscriber and stays off until the manager creates the link key in Settings.

لمن هذه الوثائق؟ لمطوّر يربط متجراً أو ERP أو نظام نقاط بيع ببابيلون كير، ولصاحب متجر يريد استخدام إضافة جاهزة دون برمجة (انتقل إلى الإضافات).Who is this for? A developer connecting a store, ERP or point-of-sale system to BabylonCare, and a shop owner who wants a ready-made plug-in without coding (jump to Plug-ins).

العنوان الأساسي والصيغةBase URL and format

عنوان الواجهة هو عنوان نسخة بابيلون كير الخاصة بمتجرك (مثل https://your-shop.example.com)، دائماً عبر HTTPS. الطلبات والردود JSON بترميز UTF-8. الخطأ يعود بهذا الشكل:The API address is your own BabylonCare address (for example https://your-shop.example.com), always over HTTPS. Requests and responses are UTF-8 JSON. An error looks like this:

{ "error": { "code": "INVALID_PHONE", "message": "..." } }

رسائل الخطأ (message) بالعربية للقراءة البشرية؛ اعتمد في برمجتك على code ورمز الحالة HTTP. فحص الحياة GET /api/health متاح لكل مفتاح ويردّ {"ok":true,"time":"…"}.The message text is Arabic for humans; build your logic on code and the HTTP status. The liveness check GET /api/health is open to every key and returns {"ok":true,"time":"…"}.

المصادقة والصلاحياتAuthentication and scopes

أرسل المفتاح في كل طلب:Send the key on every request:

Authorization: Bearer bk_xxxxxxxxxxxxxxxxxxxxxxxx
  • ينشئ المدير المفتاح من الإعدادات ← التكاملات ← مفاتيح API ويختار صلاحياته.The manager creates the key under Settings, Integrations, API keys and chooses its scopes.
  • يظهر المفتاح مرة واحدة فقط لحظة إنشائه، ويُحفظ في كير مجزّأً (hash) فلا يمكن استرجاعه. إن ضاع احذفه وأنشئ غيره.The key is shown only once, when it is created, and Care stores only a hash of it, so it cannot be recovered. If you lose it, delete it and create a new one.
  • يمكن تعطيل المفتاح أو حذفه في أي وقت؛ ويُردّ 401 BAD_API_KEY للمفتاح المعطّل أو المحذوف أو الخاطئ. كل إنشاء أو تعطيل أو حذف يُسجَّل ويُبلَّغ في تنبيهات الأمان لدى المتجر.A key can be disabled or deleted at any time; a disabled, deleted or wrong key gets 401 BAD_API_KEY. Every creation, disable or deletion is logged and sent to the shop's security alerts.
  • اختياري عند الإنشاء: تاريخ انتهاء (بعده يُردّ 401 API_KEY_EXPIRED فأنشئ مفتاحاً جديداً)، وقائمة عناوين IP مسموحة (عناوين IPv4/IPv6 مفردة أو شبكات CIDR، حتى 20؛ من خارجها يُردّ 403 API_KEY_IP_DENIED). يُنصح بهما لكل موصّل يعمل من خادم بعنوان ثابت.Optional at creation: an expiry date (after it you get 401 API_KEY_EXPIRED; create a new key) and an IP allow-list (single IPv4/IPv6 addresses or CIDR networks, up to 20; anything else gets 403 API_KEY_IP_DENIED). Both are recommended for any connector running on a server with a fixed address.
  • المفتاح الصحيح لا يُحجب أبداً بسبب محاولات فاشلة لغيره. المحاولات الخاطئة تُقفل لدقيقة: 20 لكل بادئة مفتاح من العنوان نفسه، أو 120 من العنوان نفسه أياً كانت البادئة، فيُردّ 429 بدل 401.A valid key is never blocked by someone else's failed attempts. Wrong keys are locked out for a minute: 20 per key prefix from the same address, or 120 from the same address whatever the prefix; you then get 429 instead of 401.
  • لا تضع المفتاح في كود يعمل في المتصفح أو تطبيق جوال؛ ضعه في خادمك فقط.Never put the key in browser or mobile-app code; keep it on your server only.

الصلاحيات (Scopes)Scopes

ScopeيفتحGrantsحساسة؟Sensitive?
orders:createPOST /api/registrations
GET /api/registrations/status
لاNo
reference:readGET /api/regions
GET /api/warranty-types
لاNo
orders:readGET /api/admin/orders
GET /api/admin/order
نعم: أسماء وهواتف وعناوين الزبائنYes: customer names, phones, addresses
tracking:readGET /api/admin/trackingنعمYes
stats:readGET /api/admin/analytics
GET /api/admin/analytics/export
نعم: مالياتYes: financial data

أقلّ صلاحية تكفي. مفتاح متجر إلكتروني يحتاج فقط orders:create وreference:read (وهما الافتراضي لأي مفتاح جديد). امنح الصلاحيات الحساسة فقط لنظام موثوق يحتاج قراءة بيانات الزبائن فعلاً، واستعمل مفتاحاً مستقلاً لكل نظام لتعطّله وحده عند الحاجة. استدعاء مسار خارج صلاحيات المفتاح يردّ 403 API_KEY_SCOPE. المفاتيح التي أُنشئت قبل نظام الصلاحيات تبقى بوصولها القديم؛ الأفضل استبدالها بمفاتيح محدّدة الصلاحيات.Grant the least scope that works. An online-store key needs only orders:create and reference:read (the default for a new key). Grant the sensitive scopes only to a trusted system that really must read customer data, and use a separate key per system so you can switch one off on its own. Calling a route outside the key's scopes returns 403 API_KEY_SCOPE. Keys created before scopes existed keep their old access; replace them with scoped keys when you can.

POST /api/registrations

يسجّل طلباً (زبون واحد وعدة منتجات) ويعيد رقم الطلب ومعرّفات الضمان. يتطلب orders:create. الحد الأقصى لحجم الجسم 2 ميغابايت.Registers an order (one customer, several products) and returns the order number and warranty IDs. Requires orders:create. Maximum body size is 2 MB.

حقول الطلبRequest fields

الحقلFieldمطلوبRequiredالوصفDescription
clientRefنعمYesمرجع طلبك عندك (رقم طلب المتجر). 1 إلى 64 حرفاً من A-Z a-z 0-9 . _ : -. البادئة store: محجوزة. يضمن عدم التكرار (انظر أدناه).Your own reference (the store's order number). 1 to 64 characters from A-Z a-z 0-9 . _ : -. The prefix store: is reserved. It prevents duplicates (see below).
phoneنعمYesرقم هاتف عراقي صالح، مثل 07701234567.A valid Iraqi phone number, such as 07701234567.
customerNameلاNoحتى 120 حرفاً.Up to 120 characters.
secondaryPhoneلاNoرقم ثانٍ؛ يُتحقق منه إن وُجد.A second number; validated when present.
governorate, areaنعمYesاسم المحافظة والمنطقة كما تعيدها GET /api/regions حرفياً (شركة التوصيل ترفض اختلاف الإملاء). المنطقة يجب أن تتبع المحافظة.The governorate and area names exactly as GET /api/regions returns them (the delivery company rejects spelling variants). The area must belong to the governorate.
landmarkلاNoأقرب نقطة دالّة، نص حر حتى 200 حرف.Nearest landmark, free text up to 200 characters.
priceWithDeliveryنعم (إلا في الدفع المسبق)Yes (except prepaid)مبلغ التحصيل بالدينار العراقي: عدد صحيح، 1000 على الأقل، ومن مضاعفات 250 (مثل 25000).The amount to collect in Iraqi dinar: an integer, at least 1000 and a multiple of 250 (for example 25000).
purchaseDateلاNoYYYY-MM-DD، الافتراضي اليوم، ولا يكون في المستقبل.YYYY-MM-DD, defaults to today, never in the future.
scheduledForلاNoYYYY-MM-DD يحوّل الطلب إلى حجز لذلك اليوم (من اليوم فصاعداً).YYYY-MM-DD turns the order into a booking for that day (today or later).
notes, hidePriceلاNoملاحظات حتى 500 حرف؛ وإخفاء السعر في ملصق الشحن.Notes up to 500 characters; and hide the price on the shipping label.
prepaid, prepaidPartial, prepaidAmount, prepaidImageلاNoالدفع المسبق: لا يُقبل بلا prepaidImage (صورة التحويل كـ data URL) ومبلغ prepaidAmount. الجزئي يتطلب أيضاً priceWithDelivery (السعر الكلي) والباقي بعد الدفعة يخضع لقاعدة 1000/250.Prepaid orders: not accepted without prepaidImage (the transfer proof as a data URL) and prepaidAmount. A partial payment also needs priceWithDelivery (the full price), and the remainder must follow the 1000/250 rule.
items[]نعمYesمنتج واحد على الأقل وحتى 20.At least one and up to 20 products.

حقول كل منتج في items[]Each entry of items[]

الحقلFieldمطلوبRequiredالوصفDescription
productNameنعمYesمن حرفين إلى 120 حرفاً.2 to 120 characters.
warrantyTypeنعمYesرمز من GET /api/warranty-types؛ الرمز none = بدون ضمان.A code from GET /api/warranty-types; the code none means no warranty.
quantityلا (1)No (1)عدد صحيح من 1 إلى 50. لكل قطعة ضمان مستقل بمعرّف خاص.An integer from 1 to 50. Each unit gets its own warranty with its own ID.
colorلاNoحتى 60 حرفاً.Up to 60 characters.
serialNumberلاNoأرقام تسلسلية مفصولة بفاصلة أو سطر؛ لا يزيد عددها عن quantity، ولا تتكرر داخل الطلب ولا مع طلب سابق.Serial numbers separated by comma or newline; no more than quantity, and never repeated within the order or against an earlier one.
extraلاNoحقول المنتج المخصّصة التي عرّفها المدير في الإعدادات (إن وُجدت).The custom product fields the manager defined in Settings (if any).

مثالExample

curl -X POST https://your-shop.example.com/api/registrations \
  -H "Authorization: Bearer bk_xxxxxxxxxxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "clientRef": "ORDER-1001",
    "customerName": "Ali Hassan",
    "phone": "07701234567",
    "governorate": "بغداد",
    "area": "زيونة",
    "landmark": "near the mosque",
    "priceWithDelivery": 25000,
    "items": [
      { "productName": "Bluetooth speaker X1", "color": "Black", "quantity": 1, "warrantyType": "none" }
    ]
  }'

الردّ 201 لطلب جديد (للمفاتيح ذات الصلاحيات):A new order returns 201 (for scoped keys):

{
  "registration": {
    "orderId": "…", "orderNumber": "BOD-XXXXXX", "createdAt": "2026-10-17T09:30:00.000Z",
    "orderState": "pending", "orderType": "normal", "deliveryMode": "company",
    "scheduledFor": null, "clientRef": "ORDER-1001", "totalQuantity": 1,
    "items": [ { "productName": "Bluetooth speaker X1", "quantity": 1, "warrantyType": "none", "warrantyIds": ["…"] } ]
  }
}

عدم التكرار (Idempotency)Idempotency

  • clientRef إلزامي (وإلا 400 CLIENT_REF_REQUIRED)، وصيغته تُفحص (400 BAD_CLIENT_REF)، والبادئة المحجوزة ترفض بـ 400 RESERVED_REF.clientRef is mandatory (otherwise 400 CLIENT_REF_REQUIRED), its format is checked (400 BAD_CLIENT_REF), and the reserved prefix is refused with 400 RESERVED_REF.
  • إعادة إرسال الطلب نفسه (انقطاع شبكة مثلاً) لا تكرّره: يردّ 200 بالطلب الأصلي مع "duplicate": true.Re-sending the same request (after a network drop, say) never duplicates it: you get 200 with the original order and "duplicate": true.
  • إعادة المرجع نفسه بمحتوى مختلف ترفض بـ 409 IDEMPOTENCY_MISMATCH. المرجع محصور بمفتاحك: لا يتعارض مع مراجع مفاتيح أخرى.Re-using the same reference with a different body is refused with 409 IDEMPOTENCY_MISMATCH. A reference belongs to your key only and never clashes with other keys' references.

أخطاء التسجيل الشائعةCommon registration errors

HTTPcodeالمعنىMeaning
400CLIENT_REF_REQUIRED, BAD_CLIENT_REF, RESERVED_REFمشكلة في clientRefProblem with clientRef
400INVALID_QUANTITYكمية ليست عدداً صحيحاً من 1 إلى 50، أو مجموع القطع في الطلب الواحد يتجاوز 100.A quantity that is not an integer from 1 to 50, or more than 100 units in one request.
400INVALID_PHONE, INVALID_REGION, INVALID_PRICE, INVALID_TYPE, INVALID_PRODUCT, INVALID_DATE, INVALID_SCHEDULE, NO_ITEMS, TOO_MANY_ITEMSبيانات غير صالحة؛ لا تُعد الإرسال قبل تصحيحها.Invalid data; do not retry before fixing it.
409IDEMPOTENCY_MISMATCH, SERIAL_EXISTS, SERIAL_DUPLICATEDتعارض (مرجع بمحتوى مختلف، أو رقم تسلسلي مسجّل).Conflict (reference with different content, or a serial number already registered).
402PLAN_LIMIT_REACHEDبلغ المتجر حدّ باقته الشهري. تُحجز آخر 10% من الحد لتسجيل الموظفين، فيتوقف التسجيل عبر المفتاح قبل بلوغه.The store reached its monthly plan limit. The last 10% of the limit is reserved for staff, so registering through a key stops before it is reached.
429API_DAILY_LIMIT, RATE_LIMITEDانظر الحدود أدناه.See the limits below.

أخطاء 400 و409 دائمة (لا فائدة من إعادتها كما هي)، أما 429 و5xx فأعد المحاولة بعد مهلة بنفس clientRef بأمان.400 and 409 errors are permanent (retrying as-is is pointless); for 429 and 5xx, retry later with the same clientRef, which is safe.

GET /api/registrations/status?clientRef=…

حالة طلب سجّله مفتاحك نفسه بمرجعه، بالحد الأدنى من الحقول (بلا هاتف ولا عنوان ولا مبالغ). يتطلب orders:create. لا طلب بهذا المرجع من هذا المفتاح = 404 NOT_FOUND.The status of an order registered by your own key, by its reference, with minimal fields (no phone, address or amounts). Requires orders:create. No order with that reference from this key returns 404 NOT_FOUND.

{
  "order": {
    "orderId": "…", "orderNumber": "BOD-XXXXXX", "createdAt": "…",
    "orderState": "pending", "orderType": "normal", "deliveryMode": "company",
    "deliveryCompanyKey": null, "deliveryOrderId": null, "deliverySentAt": null,
    "selfStatus": null, "scheduledFor": null, "totalQuantity": 1,
    "deliveryStatus": null, "deliveryStatusAt": null,
    "items": [ { "productName": "…", "quantity": 1, "warrantyType": "none" } ]
  }
}

deliveryStatus هي آخر حالة وصلت من شركة التوصيل (نصها كما تعطيه الشركة) وتبقى null قبل أن يُرسل الطلب إليها.deliveryStatus is the latest status received from the delivery company (its text exactly as the company gives it) and stays null before the order is sent to it.

المراجع: المناطق وأنواع الضمانReference: regions and warranty types

يتطلب الاثنان reference:read.Both require reference:read.

GET /api/regions

قائمة المحافظات ومناطقها لشركة التوصيل المفعّلة، لتعبئة قوائم العنوان. الردّ يُخزَّن في المتصفح يوماً؛ خزّنه أنت أيضاً ولا تطلبه مع كل طلب. المحافظة والمنطقة تُرسلان بالاسم حرفياً.The governorates and their areas for the active delivery company, to fill address dropdowns. The response may be cached for a day; cache it yourself and do not fetch it for every order. Send governorate and area by name, exactly.

{ "governorates": [ { "id": 1, "name": "بغداد", "areas": [ { "id": 101, "name": "زيونة" } ] } ], "company": "…" }

GET /api/warranty-types

الرموز التي يقبلها warrantyType (يضبطها المدير، فلا تكتب رموزاً يدوياً):The codes warrantyType accepts (the manager sets them, so do not hard-code any):

{ "warrantyTypes": [ { "code": "none", "label": "بدون ضمان", "months": 0 } ] }

الطلبات والمتابعة والإحصائياتOrders, tracking and stats

مسارات قراءة للأنظمة الموثوقة فقط، وكلها تتطلب صلاحية حساسة مذكورة أعلاه. تعيد حقولاً مسموحة فقط؛ لا تُعاد روابط التتبع ولا مواقع GPS ولا صور الدفع ولا الحقول الداخلية.Read routes for trusted systems only, each requiring a sensitive scope from the table above. They return allow-listed fields only; tracking links, GPS positions, payment proof images and internal fields are never returned.

المسارRouteScopeالوصفDescription
GET /api/admin/ordersorders:readالطلبات المعلّقة، الأحدث أولاً. الردّ: { orders, total, nextCursor }.Pending orders, newest first. Response: { orders, total, nextCursor }.
GET /api/admin/order?id=…orders:readطلب واحد بمعرّفه (orderId): { order }، أو 404 NOT_FOUND.One order by its orderId: { order }, or 404 NOT_FOUND.
GET /api/admin/trackingtracking:readمتابعة التوصيل. اختياري companies=a,b لتصفية الشركات. الردّ: { orders, total, nextCursor, lastSync }.Delivery tracking. Optional companies=a,b filters companies. Response: { orders, total, nextCursor, lastSync }.
GET /api/admin/analyticsstats:readالإحصائيات (تتطلب لوحة الإحصائيات في الباقة). حدّ 60 طلباً في الدقيقة لكل مفتاح.Statistics (needs the statistics dashboard in the plan). Limit: 60 requests a minute per key.
GET /api/admin/analytics/exportstats:readتصدير Excel. حدّ 6 في الساعة لكل مفتاح، ويشترط from وto (YYYY-MM-DD) لا تزيد المدة بينهما على سنة (وإلا 400 RANGE_TOO_LARGE).Excel export. Limit: 6 an hour per key; from and to (YYYY-MM-DD) are required and may span at most one year (otherwise 400 RANGE_TOO_LARGE).

الترقيم: limit وcursorPagination: limit and cursor

limit عدد صحيح من 1 إلى 100 (افتراضياً 100). إن كان nextCursor غير null فمرّره في الطلب التالي كقيمة cursor حتى يصبح null. قيمة غير صالحة تردّ 400 BAD_LIMIT أو 400 BAD_CURSOR.limit is an integer from 1 to 100 (default 100). While nextCursor is not null, pass it as cursor in the next request until it becomes null. An invalid value returns 400 BAD_LIMIT or 400 BAD_CURSOR.

GET /api/admin/orders?limit=50
GET /api/admin/orders?limit=50&cursor=50

الحدود والأخطاء العامةLimits and general errors

الحدLimitالقيمةValue
قطع الطلب الواحد عبر APIUnits per API request100 (وحتى 20 منتجاً، و50 قطعة للمنتجat most 20 products and 50 units per product)
قطع المفتاح اليوميةUnits per key per day1000 خلال 24 ساعة (وإلا 429 API_DAILY_LIMIT)within 24 hours (otherwise 429 API_DAILY_LIMIT)
معدل الطلباتRequest rate600 في الدقيقة لكل مفتاح من العنوان الواحد، و1200 في الدقيقة للمفتاح من كل العناوين600 a minute per key from one address, and 1200 a minute per key across all addresses
POST /api/registrations60 في الدقيقة لكل عنوان، و120 في الدقيقة لكل مفتاح؛ والطلبات بصورة دفع 20 في الدقيقة60 a minute per address and 120 a minute per key; requests carrying a payment image: 20 a minute
حجم جسم الطلبBody size2 MB (التسجيلregistration)

عند تجاوز المعدل يردّ 429 RATE_LIMITED مع ترويسة Retry-After (ثوانٍ) في الحدود المشتركة للمفتاح؛ انتظر ثم أعد المحاولة. أخطاء المصادقة: 401 BAD_API_KEY، 401 API_KEY_EXPIRED، 403 API_KEY_IP_DENIED، 403 API_KEY_SCOPE، 403 FEATURE_DISABLED.When a rate is exceeded you get 429 RATE_LIMITED, with a Retry-After header (seconds) on the key-wide limits; wait and retry. Authentication errors: 401 BAD_API_KEY, 401 API_KEY_EXPIRED, 403 API_KEY_IP_DENIED, 403 API_KEY_SCOPE, 403 FEATURE_DISABLED.

Webhook الصادرOutbound webhook

يرسل كير POST بجسم JSON إلى رابط تحدده في الإعدادات ← التكاملات عند أحداث الطلب. يمكنك اختيار الأحداث، وتوجد «إرسال تجربة» (حدث test) للتأكد من الاستقبال.Care sends a POST with a JSON body to a URL you set under Settings, Integrations when order events happen. You can choose which events to receive, and a “send test” button (event test) checks your receiver.

الأحداثEvents

eventمتىWhen
order.registeredتسجيل طلبAn order is registered
order.updatedتعديل طلبAn order is edited
order.sentإرسال الطلب لشركة التوصيلThe order is sent to the delivery company
order.deliveredوصل الطلبThe order was delivered
order.returnedرجع الطلبThe order came back
order.issueمشكلة في التوصيلA delivery problem
courier.eventحركة من المندوب (التوصيل الذاتي)A courier action (self delivery)
booking.dueحان موعد حجزA booking is due

الجسم والترويساتBody and headers

POST https://your-receiver.example.com/hooks/care
Content-Type: application/json
User-Agent: BabylonCare-Webhook/1
X-Babylon-Event: order.registered
X-Babylon-Delivery: evt_3f9a…            (unique id, same as body.id; unchanged on retries)
X-Babylon-Attempt: 1                     (1 to 5)
X-Babylon-Timestamp: 2026-10-17T09:30:00.000Z   (same as body.at)
X-Babylon-Signature: sha256=…            (HMAC-SHA256 of the raw body)
X-Babylon-Signature-Ts: sha256=…         (HMAC-SHA256 of  at + "." + raw body)
X-Babylon-Signature-Previous: sha256=…   (only during a secret rotation: same, with the previous secret)
X-Babylon-Signature-Ts-Previous: sha256=…

{ "id": "evt_3f9a…", "event": "order.registered", "at": "2026-10-17T09:30:00.000Z", "data": { … } }

data يحمل الطلب (أو الطلب مع تفاصيل الحدث) وفيه بيانات الزبون؛ عامله كبيانات حساسة.data carries the order (or the order plus the event details), including customer data; treat it as sensitive.

التحقق من التوقيع (إلزامي)Verifying the signature (mandatory)

  1. احسب HMAC-SHA256 بسرّ الـ webhook على البايتات الخام للجسم كما وصلت (لا بعد إعادة ترميز JSON)، وقارنه بـ X-Babylon-Signature بمقارنة زمن ثابت.Compute HMAC-SHA256 with the webhook secret over the raw body bytes exactly as received (not a re-encoded JSON) and compare it with X-Babylon-Signature in constant time.
  2. ارفض الرسالة إن مضى على at أكثر من 5 دقائق (حماية من إعادة الإرسال). التوقيع الأول يغطي at لأنه داخل الجسم.Reject the message if at is more than 5 minutes old (replay protection). The first signature covers at because it sits inside the body.
  3. تجاهل أي id رأيته من قبل (احتفظ بالمعرّفات ساعتين على الأقل: إعادة المحاولة تحمل المعرّف نفسه حتى ساعة).Ignore any id you have already seen (keep ids for at least two hours: retries carry the same id for up to an hour).
  4. تدوير السرّ: عند تدويره من الإعدادات يبقى السرّ القديم صالحاً 24 ساعة، ويُرسل خلالها توقيع إضافي به في X-Babylon-Signature-Previous (و-Ts-Previous)، بينما X-Babylon-Signature بالسرّ الجديد. اقبل الرسالة إن طابق سرّك أياً من الترويستين، ثم حدّث سرّك قبل انقضاء المدة.Secret rotation: when the secret is rotated in Settings, the old secret stays valid for 24 hours. During that window an extra signature made with it is sent in X-Babylon-Signature-Previous (and -Ts-Previous), while X-Babylon-Signature uses the new secret. Accept the message if your secret matches either header, then switch to the new secret before the window ends.
  5. إن كنت تعتمد ترويسة X-Babylon-Timestamp فتحقق من X-Babylon-Signature-Ts بدل الأول: هو HMAC على X-Babylon-Timestamp + "." + الجسم الخام، فالترويسة مشمولة بالتوقيع. لا تثق بترويسة الوقت وحدها مع التوقيع الأول.If you rely on the X-Babylon-Timestamp header, verify X-Babylon-Signature-Ts instead: it is an HMAC over X-Babylon-Timestamp + "." + raw body, so the header is covered. Do not trust the time header alone with the first signature.

Node.js

import { createHmac, timingSafeEqual } from 'node:crypto';

// rawBody: Buffer exactly as received. Returns the parsed message, or null if it must be rejected.
export function verifyCareWebhook(rawBody, headers, secret) {
  const expected = 'sha256=' + createHmac('sha256', secret).update(rawBody).digest('hex');
  const got = String(headers['x-babylon-signature'] || '');
  const a = Buffer.from(expected), b = Buffer.from(got);
  if (a.length !== b.length || !timingSafeEqual(a, b)) return null;
  const msg = JSON.parse(rawBody.toString('utf8'));
  if (Math.abs(Date.now() - Date.parse(msg.at)) > 5 * 60_000) return null;   // replay window
  // then: skip msg.id if you have processed it before
  return msg;
}

PHP

<?php
$raw      = file_get_contents('php://input');
$expected = 'sha256=' . hash_hmac('sha256', $raw, $secret);
$got      = $_SERVER['HTTP_X_BABYLON_SIGNATURE'] ?? '';
if (!hash_equals($expected, $got)) { http_response_code(401); exit; }
$msg = json_decode($raw, true);
if (abs(time() - strtotime($msg['at'])) > 300) { http_response_code(401); exit; }   // replay window
// skip $msg['id'] if already processed, then handle $msg['event'] / $msg['data']
http_response_code(200);

Python

import hashlib, hmac, json, time
from datetime import datetime

def verify_care_webhook(raw: bytes, headers: dict, secret: str):
    expected = "sha256=" + hmac.new(secret.encode(), raw, hashlib.sha256).hexdigest()
    if not hmac.compare_digest(expected, headers.get("X-Babylon-Signature", "")):
        return None
    msg = json.loads(raw)
    sent = datetime.fromisoformat(msg["at"].replace("Z", "+00:00")).timestamp()
    if abs(time.time() - sent) > 300:      # replay window
        return None
    return msg                              # skip msg["id"] if already processed

قواعد التسليمDelivery rules

  • HTTPS فقط وعلى المنفذ 443 أو 8443. الروابط غير الآمنة والعناوين الداخلية مرفوضة.HTTPS only, on port 443 or 8443. Insecure URLs and internal addresses are refused.
  • سرّ التوقيع من 16 إلى 200 حرفاً (حروف وأرقام ورموز بلا مسافات)، ويولّده كير تلقائياً (whsec_…) إن لم تكتبه. لا يُضمَّن في الرسائل.The signing secret is 16 to 200 characters (letters, digits, symbols, no spaces) and Care generates one (whsec_…) if you leave it empty. It is never included in messages.
  • مهلة الاستقبال 10 ثوانٍ، ويُعدّ أي ردّ 2xx نجاحاً. إعادة محاولة تلقائية عند أي ردّ آخر أو خطأ شبكة: حتى 5 محاولات خلال أقل من ساعة (فوراً، ثم بعد 30 ثانية، 2 دقيقة، 10 دقائق، 40 دقيقة) بنفس id ووقت at جديد موقَّع. الطابور محفوظ ويكمل بعد إعادة تشغيل كير، وله سقف (عند امتلائه يُسقط الأقدم). أجب بسرعة وعالج العمل في الخلفية، وصالح ما فات بعد المحاولة الخامسة بقراءة الطلبات عبر الواجهة.The receive timeout is 10 seconds and any 2xx counts as success. Automatic retries on any other response or network error: up to 5 attempts within an hour (immediately, then after 30 seconds, 2 minutes, 10 minutes and 40 minutes), with the same id and a fresh signed at. The queue is persisted, resumes after a Care restart, and is capped (when full, the oldest is dropped). Answer quickly, do the work in the background, and reconcile anything still missing after the fifth attempt by reading orders through the API.

الإضافات والموصّلات الجاهزةReady-made plug-ins and connectors

إن لم تكن مطوّراً فاستخدم إحدى الإضافات التالية. الإضافتان من تطوير Babylon Core LLC، وليستا من منتجات الشركات المذكورة أو معتمدتين منها؛ الأسماء والشعارات لأصحابها.If you are not a developer, use one of these. Both are made by Babylon Core LLC; they are not products of, or endorsed by, the companies named. Names and logos belong to their owners.

WooCommerceWordPress

Babylon Care Connector (ووكومرس / ووردبريسWooCommerce / WordPress)

تصل طلبات متجرك إلى «طلبات الموقع» في كير تلقائياً، ويعود رقم التتبع وتحديثات الحالة إلى الطلب في ووكومرس.Your store's orders reach Care's “Website orders” inbox automatically, and the tracking number and status updates flow back to the order in WooCommerce.

تنزيل الإضافة (ZIP)Download plug-in (ZIP) · 51.4 KB

SHA-256: 9bd5cf2944ec3ed742c75723083d268d25d919ddb99f8b764bba3a940dd7484b

قبل أن تبدأBefore you start

  • ووردبريس + ووكومرس، وعنوان المتجر يبدأ بـ https://.WordPress + WooCommerce, with a store address starting with https://.
  • المتجر على جذر النطاق (مثل shop.example.com) لا في مجلد فرعي.The store is at the root of its domain (such as shop.example.com), not in a sub-folder.
  • الأسعار بالدينار العراقي (IQD) وحساب مدير في المتجر وفي بابيلون كير.Prices in Iraqi dinar (IQD), and an administrator account in the store and in BabylonCare.

التثبيت في 4 خطواتInstall in 4 steps

  1. ارفع الإضافة وفعّلها: من لوحة ووردبريس: إضافات ← أضف جديدة ← رفع إضافة ← اختر babylon-care-connector.zip ← ثبّت الآن ← فعّل.Upload and activate: in WordPress: Plugins, Add New, Upload Plugin, choose babylon-care-connector.zip, Install Now, Activate.
  2. أنشئ مفتاح الربط في بابيلون كير: الإعدادات ← Webhook و API ← ربط الموقع ← إنشاء مفتاح الربط، ثم انسخه (يبدأ بـ bsl1. ويظهر مرة واحدة).Create the link key in BabylonCare: Settings, Webhook and API, site link, Create link key, then copy it (it starts with bsl1. and is shown once).
  3. الصق المفتاح واحفظ: ووكومرس ← بابيلون كير ← الصق المفتاح في الخانة الوحيدة ← حفظ وربط. تظهر نقطة خضراء وكلمة «مرتبط» مع عنوان كير؛ تأكد أنه العنوان الصحيح.Paste the key and save: WooCommerce, Babylon Care, paste the key into the only field, Save and connect. A green dot and “Connected” appear with Care's address; check it is the right one.
  4. جرّب بطلب: اطلب منتجاً بالدفع عند الاستلام؛ يظهر في «طلبات الموقع» خلال دقيقة، وعند موافقتك عليه يظهر رقم التتبع في ووكومرس.Try an order: place a cash-on-delivery order; it appears under “Website orders” within a minute, and once you approve it the tracking number shows up in WooCommerce.

حالة الإضافة بصدق: مغطّاة باختبارات آلية، لكنها لم تُجرَّب بعد على موقع ووردبريس حقيقي. جرّبها على نسخة تجريبية من متجرك قبل الاعتماد عليها. لا تتوفر في دليل إضافات ووردبريس الرسمي؛ تُثبَّت برفع الملف. طلبات الدفع المسبق المعلّقة لا تُرسل حتى تصبح مدفوعة. يتحمّل المتجر نفسه مسؤولية إعدادات الاستضافة (شهادة SSL وضبط الوقت: فرق أكثر من 5 دقائق يرفض الربط).Honest status: covered by automated tests, but not yet run on a real WordPress site. Try it on a staging copy of your store before relying on it. It is not in the official WordPress plug-in directory; you install it by uploading the file. Unpaid prepaid orders are not sent until paid. Hosting settings are your responsibility (an SSL certificate and a correct clock: a difference of more than 5 minutes is refused).

Shopify

محوّل Shopify ذاتي الاستضافةSelf-hosted Shopify adapter

Worker صغير على Cloudflare بلا تبعيات، تنشره أنت على حسابك: يستقبل webhook الطلب من Shopify ويسجّله في كير عبر هذه الواجهة (POST /api/registrations) بمفتاح bk_ محدود الصلاحية.A small, dependency-free Cloudflare Worker that you deploy to your own account: it receives Shopify's order webhook and registers it in Care through this API (POST /api/registrations) with a limited-scope bk_ key.

تنزيل المحوّل (ZIP)Download adapter (ZIP) · 30.3 KB

SHA-256: a8579294cc06f8c226475d8115f475bcbdb0a49831ab601a6c2c57d4032d7ffd

الحالة بصدق: ليس تطبيقاً في متجر تطبيقات Shopify (Shopify App Store)؛ لم يُقدَّم ولم يُراجَع ولم يُعتمد. هو محوّل تنشره بنفسك. مختبَر بوحدات آلية ونماذج طلبات، ولم يُجرَّب بعد على متجر Shopify حقيقي؛ جرّبه على متجر تجريبي أولاً. الاتجاه واحد فقط: من Shopify إلى كير (طلب جديد)؛ لا تعود حالات التوصيل إلى Shopify ولا تُزامَن تعديلات الطلب.Honest status: it is not an app on the Shopify App Store; it was not submitted, reviewed or approved. It is an adapter you deploy yourself. It is covered by automated tests and sample orders, and has not yet been run against a real Shopify store; try it on a development store first. It works in one direction only, from Shopify to Care (new order); delivery statuses do not flow back to Shopify and later order edits are not synced.

ما يتطلبهWhat it needs

  1. مفتاح bk_ في كير بصلاحيتي orders:create وreference:read فقط (باقة احترافية).A bk_ key in Care with only orders:create and reference:read (Professional plan).
  2. حساب Cloudflare ينشر عليه الـ Worker (wrangler deploy)، مع إعداد العنوان والمتاجر المسموحة والأسرار، كما في ملف README داخل الحزمة.A Cloudflare account to deploy the Worker (wrangler deploy), with the address, allowed shops and secrets configured as described in the README inside the package.
  3. webhook «Order creation» في Shopify يشير إلى الـ Worker، وطريقة دفع «الدفع عند الاستلام».An “Order creation” webhook in Shopify pointing to the Worker, and a “Cash on Delivery” payment method.

الطلبات المدفوعة كلياً أونلاين، أو التي لا تطابق مدينتها قائمة مناطق كير، تُدرَج في قائمة «يدوي» لتسجّلها بنفسك؛ لا يُخمَّن شيء ولا يضيع طلب بصمت. التفاصيل الكاملة في README داخل الحزمة.Orders paid fully online, or whose city does not match Care's area list, are put on a “manual” list for you to register yourself; nothing is guessed and no order is dropped silently. Full details are in the README inside the package.

تحتاج تكاملاً آخر أو مساعدة في الربط؟ راسلنا على [email protected] أو واتساب.Need another integration or help connecting? Write to [email protected] or WhatsApp us.