تخطّ إلى المحتوى الرئيسي

نظرة عامة على API

توفّر Joryio REST API وصولًا برمجيًا إلى جميع ميزات المنصة.

عنوان الأساس

https://api-eu1.joryio.com

تُخدَم جميع مساحات العمل حاليًا من منطقة واحدة؛ وستوثق نقاط النهاية الخاصة بالمناطق عند إطلاق مناطق إضافية.

المصادقة

تتطلب جميع طلبات API المصادقة عبر مفتاح API. يرتبط المفتاح بمساحة عمل واحدة ويحمل مجموعة صلاحيات صريحة ويمكن تقييده بقائمة IPs. راجع مفاتيح API لكتالوج النطاقات الكامل وسلوك قائمة سماح IP.

GET /users/by-user-id/user_123
Host: api-eu1.joryio.com
Authorization: Bearer jry_live_your_api_key_here
Content-Type: application/json

مرّر المفتاح كـ bearer token في رأس Authorization مع كل طلب. تبدأ المفاتيح دائمًا بـ jry_live_ للإنتاج أو jry_test_ للاختبار. ويمكن تسجيل بادئة المفتاح المرئية، مثل jry_live_98f31a72، بأمان؛ أما الباقي فهو سري.

الحصول على مفتاح API

  1. سجّل الدخول إلى لوحة Joryio.
  2. انتقل إلى Settings ← API Keys.
  3. انقر Create API Key، واختر النطاقات التي يحتاجها التكامل، ثم انسخ القيمة التي تظهر مرة واحدة.
حافظ على سرية مفاتيح API

لا ترفع مفاتيح API إلى التحكم بالإصدارات ولا تكشفها في كود جهة العميل. تظهر القيمة الكاملة مرة واحدة فقط بعد الإنشاء؛ خزّنها فورًا في مدير الأسرار لديك.

مجموعة Postman

أسرع طريقة لاستكشاف API: استورد المجموعة الرسمية إلى Postman. تتضمن كل نقطة نهاية عامة ونص مثالًا، ومضبوطة مسبقًا على متغير {{baseUrl}} ومصادقة bearer token.

  1. نزّل المجموعة.
  2. في Postman: Import ثم أسقط الملف.
  3. اضبط متغيرات المجموعة: baseUrl = https://api-eu1.joryio.com وtoken = مفتاح API، jry_live_....

صيغة الطلب

تستخدم جميع الطلبات والاستجابات JSON:

POST /users
Content-Type: application/json

{
"userId": "user_123",
"email": "user@example.com",
"attributes": {
"plan": "premium"
}
}

صيغة الاستجابة

تعيد نقاط النهاية JSON للمورد مباشرة؛ لا يوجد غلاف { "success": true, "data": ... }.

استجابة نجاح

مثلًا، يعيد GET /users/by-user-id/user_123 كائن المستخدم نفسه:

{
"id": "665f1e2a9b3c4d5e6f7a8b9c",
"userId": "665f1e2a9b3c4d5e6f7a8b9c",
"externalId": "user_123",
"email": "user@example.com",
"phone": "+14155550123",
"attributes": { "plan": "premium" },
"createdAt": "2026-01-15T10:30:00.000Z",
"updatedAt": "2026-01-15T10:30:00.000Z"
}

id / userId هو معرّف Joryio الداخلي؛ أما المعرّف الذي قدمته فيظهر كـ externalId.

استجابة خطأ

تشترك كل الأخطاء في شكل واحد ينتجه مرشح استثناءات عام:

{
"statusCode": 400,
"message": "Cannot create user without a valid identifier (userId, externalId, or email)",
"timestamp": "2026-01-15T10:30:00.000Z",
"path": "/users"
}

تحمل أخطاء تحقق الطلب، 400، أيضًا مصفوفة errors برسالة لكل حقل فاشل:

{
"statusCode": 400,
"message": "Bad Request Exception",
"timestamp": "2026-01-15T10:30:00.000Z",
"path": "/events/track",
"errors": [
"eventName must be shorter than or equal to 500 characters"
]
}

رموز حالة HTTP

الرمزالمعنىالوصف
200OKنجح الطلب
201Createdأُنشئ المورد بنجاح
204No Contentنجح الحذف، نص استجابة فارغ
400Bad Requestمعاملات طلب غير صالحة
401Unauthorizedمفتاح API مفقود أو غير صالح
403Forbiddenلا يملك مفتاح API الصلاحيات المطلوبة
404Not Foundالمورد غير موجود
409Conflictالمورد موجود مسبقًا
429Too Many Requestsتجاوز حد المعدل
500Internal Server Errorحدث خطأ في الخادم
503Service Unavailableالخدمة غير متاحة مؤقتًا

تحديد المعدل

لا تفرض نقاط API الأساسية، المستخدمون والأحداث والشرائح والحملات، حدودًا ثابتة لكل نقطة نهاية حاليًا. يطبق التقييد على الأسطح المعرضة للإساءة، مثل نقاط المصادقة ومستقبِلات Webhook الواردة، باستخدام نوافذ ثابتة لكل دقيقة.

عند تقييد الطلب، يعيد API الخطأ 429 Too Many Requests مع الرأس Retry-After، أي ثوانٍ حتى إعادة ضبط النافذة:

HTTP/1.1 429 Too Many Requests
Retry-After: 42
{
"statusCode": 429,
"message": "Too Many Requests",
"timestamp": "2026-01-15T10:30:00.000Z",
"path": "/auth/login"
}

التعامل مع حدود المعدل

قد تُدخل الحدود أو تُشدد بمرور الوقت. عامل 429 دائمًا كقابل لإعادة المحاولة، واحترم Retry-After ونفذ تراجعًا أسيًا:

async function makeRequestWithRetry(url, options, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
const response = await fetch(url, options);

if (response.status === 429) {
const retryAfter = response.headers.get('Retry-After') || Math.pow(2, i);
await sleep(retryAfter * 1000);
continue;
}

return response;
}
}

ترقيم الصفحات

تستخدم نقاط نهاية السرد معاملات الاستعلام limit / offset:

GET /users?limit=50&offset=100

المعاملات:

  • limit: النتائج في الصفحة؛ تختلف القيم الافتراضية والقصوى حسب نقطة النهاية. المستخدمون: الافتراضي 50 والحد 200؛ الشرائح: الافتراضي والحد 100؛ استعلام الأحداث: الافتراضي 100 والحد 1000.
  • offset: عدد العناصر التي يجب تخطيها؛ الافتراضي 0.

الاستجابة:

تغلّف استجابات السرد المرقمة الصفحة في مصفوفة data وكائن pagination:

{
"data": [...],
"pagination": {
"total": 1234,
"limit": 50,
"offset": 100,
"hasMore": true
}
}

تتضمن بعض النقاط حقول ترقيم إضافية، مثل page / totalPages، وتعید بعض القوائم الأصغر مصفوفة JSON مباشرة. توثق صفحة كل نقطة شكلها الدقيق.

الفلترة

لا توجد صيغة استعلام عامة مثل filter[field] أو sort. تعرض نقاط السرد معاملات فلترة خاصة بها، مثل:

GET /events/query?eventName=Order+Completed&startDate=2026-01-01&endDate=2026-01-31
GET /segments?q=vip&status=active&tags=onboarding
GET /users/search?query=jane

تعاد النتائج بترتيب ثابت: الأحدث أولًا.

عدم التكرار

لا يوجد رأس طلب عام Idempotency-Key. تُوفّر سلامة إعادة المحاولة لكل نقطة نهاية:

  • POST /users عملية upsert تعتمد userId لديك؛ إعادة الطلب نفسه تحدّث الملف نفسه بدل إنشاء تكرار.
  • POST /events/track يقبل clientEventId اختياريًا ويستخدمه كمعرّف للحدث المخزن، لذلك تُزال تكرارات الطلب المعاد بالمعرف نفسه.
  • POST /campaigns/transactional/send يقبل idempotencyKey اختياريًا في النص؛ إعادة المحاولة بالمفتاح نفسه لا ترسل مرتين.

الطوابع الزمنية

تستخدم جميع الطوابع ISO 8601 مع المنطقة الزمنية UTC:

{
"createdAt": "2024-01-15T10:30:00.000Z",
"updatedAt": "2024-01-15T14:45:30.000Z"
}

نقاط API

Users API

الطريقةنقطة النهايةالوصف
POST/usersإنشاء مستخدم أو تحديثه، نص كائن واحد أو مصفوفة مجردة لعدة مستخدمين حتى 1000
GET/usersسرد المستخدمين، limit / offset
GET/users/searchالبحث عن المستخدمين بالبريد أو الاسم أو الهاتف أو المعرّف
GET/users/:userIdجلب المستخدم بالمعرّف الداخلي لـ Joryio
GET/users/by-user-id/:userIdجلب المستخدم بـ userId الخاص بك
PUT/users/:userIdتحديث المستخدم بالمعرّف الداخلي
PUT/users/by-user-id/:userIdتحديث المستخدم بـ userId الخاص بك
DELETE/users/:userIdحذف المستخدم، يعيد 204

Events API

الطريقةنقطة النهايةالوصف
POST/events/trackتتبع حدث واحد أو عدة أحداث، مصفوفة مجردة حتى 500
GET/events/queryالاستعلام عن الأحداث بفلاتر
POST/events/aggregateتجميع مقاييس الأحداث بمرور الوقت

Campaigns API

الطريقةنقطة النهايةالوصف
POST/campaignsإنشاء حملة
GET/campaigns/:idجلب حملة
PUT/campaigns/:idتحديث حملة
DELETE/campaigns/:idحذف حملة
POST/campaigns/:id/sendإرسال حملة
GET/campaigns/:id/statsجلب إحصاءات حملة

Segments API

الطريقةنقطة النهايةالوصف
POST/segmentsإنشاء شريحة
GET/segmentsسرد الشرائح
GET/segments/:idجلب شريحة
PUT/segments/:idتحديث شريحة
POST/segments/:id/archiveأرشفة شريحة؛ لا يمكن حذف الشرائح حذفًا نهائيًا
GET/segments/:id/usersجلب مستخدمي شريحة
GET/segments/:id/sizeجلب حجم الشريحة

Apps API

الطريقةنقطة النهايةالوصف
POST/appsإنشاء تطبيق
GET/apps/:idجلب تطبيق
PUT/apps/:idتحديث تطبيق
DELETE/apps/:idحذف تطبيق
POST/apps/:id/regenerate-keyإعادة إنشاء مفتاح SDK
GET/apps/:id/statsجلب إحصاءات التطبيق

SDKs

لتكامل أسهل، استخدم SDKs الرسمية:

أمثلة

إنشاء مستخدم

curl -X POST https://api-eu1.joryio.com/users \
-H "Authorization: Bearer jry_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"userId": "user_123",
"email": "user@example.com",
"attributes": {
"firstName": "John",
"lastName": "Doe",
"plan": "premium"
}
}'

تتبع حدث

curl -X POST https://api-eu1.joryio.com/events/track \
-H "Authorization: Bearer jry_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"userId": "user_123",
"eventName": "Order Completed",
"properties": {
"orderId": "order_456",
"total": 99.99,
"currency": "USD"
}
}'

إنشاء شريحة

curl -X POST https://api-eu1.joryio.com/segments \
-H "Authorization: Bearer jry_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"name": "Premium Users",
"description": "Users on premium plan",
"filterGroups": [{
"filters": [{
"type": "attribute",
"field": "plan",
"operator": "equals",
"value": "premium"
}],
"operator": "AND"
}],
"groupOperator": "AND"
}'

إرسال حملة

لا تحتاج نقطة الإرسال إلى نص طلب: إذ يحدد إعداد الحملة المحفوظ ما يُرسل.

curl -X POST https://api-eu1.joryio.com/campaigns/:id/send \
-H "Authorization: Bearer jry_live_your_api_key"

الأخطاء

لا توجد مفردات منفصلة لرموز أخطاء قابلة للقراءة آليًا. استخدم رمز HTTP مع حقل message في نص الخطأ القياسي، راجع صيغة الاستجابة:

{
"statusCode": 404,
"message": "Segment with ID 3f9d2c1e-7a54-4b2e-9c1d-8e6f5a4b3c2d not found",
"timestamp": "2026-01-15T10:30:00.000Z",
"path": "/segments/3f9d2c1e-7a54-4b2e-9c1d-8e6f5a4b3c2d"
}

الاختبار

يمكن إنشاء المفاتيح بتسمية test، مثل jry_test_...، لتمييز مفاتيح التكامل عن مفاتيح الإنتاج سريعًا؛ ولا تغير التسمية ما يمكن للمفتاح فعله. للتجارب الآمنة، أنشئ مساحة عمل منفصلة للاختبار: تعزل مساحات العمل الملفات والأحداث والحملات تمامًا، لذلك لا يلامس ما تجربه بيانات أو مستلمين في الإنتاج. تتوفر إرسالات اختبار القناة، مثل Email وSMS، داخل محررات الحملات.

الدعم

هل تحتاج إلى مساعدة؟