نظرة عامة على 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
- سجّل الدخول إلى لوحة Joryio.
- انتقل إلى Settings ← API Keys.
- انقر Create API Key، واختر النطاقات التي يحتاجها التكامل، ثم انسخ القيمة التي تظهر مرة واحدة.
لا ترفع مفاتيح API إلى التحكم بالإصدارات ولا تكشفها في كود جهة العميل. تظهر القيمة الكاملة مرة واحدة فقط بعد الإنشاء؛ خزّنها فورًا في مدير الأسرار لديك.
مجموعة Postman
أسرع طريقة لاستكشاف API: استورد المجموعة الرسمية إلى Postman. تتضمن كل نقطة نهاية عامة ونص مثالًا، ومضبوطة مسبقًا على متغير {{baseUrl}} ومصادقة bearer token.
- نزّل المجموعة.
- في Postman: Import ثم أسقط الملف.
- اضبط متغيرات المجموعة:
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
| الرمز | المعنى | الوصف |
|---|---|---|
200 | OK | نجح الطلب |
201 | Created | أُنشئ المورد بنجاح |
204 | No Content | نجح الحذف، نص استجابة فارغ |
400 | Bad Request | معاملات طلب غير صالحة |
401 | Unauthorized | مفتاح API مفقود أو غير صالح |
403 | Forbidden | لا يملك مفتاح API الصلاحيات المطلوبة |
404 | Not Found | المورد غير موجود |
409 | Conflict | المورد موجود مسبقًا |
429 | Too Many Requests | تجاوز حد المعدل |
500 | Internal Server Error | حدث خطأ في الخادم |
503 | Service 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 الرسمية:
- Web SDK: npm install @joryio/web-sdk
- iOS SDK: Swift Package / CocoaPods
- Android SDK: Gradle
- React Native SDK: npm install @joryio/react-native-sdk
أمثلة
إنشاء مستخدم
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، داخل محررات الحملات.
الدعم
هل تحتاج إلى مساعدة؟