الانتقال إلى المحتوى الرئيسي

Documentation Index

Fetch the complete documentation index at: https://docs.oneclickdz.com/llms.txt

Use this file to discover all available pages before exploring further.

نظرة عامة

يُوضِّح هذا الدليل بالضبط ما يجب تغييره عند الانتقال من OneClickDz Flexy API الإصدار v2 إلى v3. يعرض كل مثال الكود الحالي في v2 ويسرد التغييرات المطلوبة ويُظهر النتيجة في v3.متاح بعدة لغات: أمثلة JavaScript/Node.js وPHP وPython متضمَّنة.
إيقاف API v2: سيُوقَف API v2 في 30 أكتوبر 2026. يرجى الانتقال قبل هذا التاريخ لتجنب انقطاع الخدمة.

الجديد في v3

استجابات موحّدة

جميع الاستجابات مُغلَّفة في هيكل {(success, data, meta, requestId)}

معالجة أخطاء أفضل

أخطاء منظّمة مع أكواد ورسائل وتفاصيل لتصحيح أسهل

تصحيح أخطاء محسَّن

كل استجابة تتضمن طوابع زمنية ومعرّفات طلب فريدة

endpoints أوضح

تجميع منطقي: /mobile/* و/internet/* و/gift-cards/* و/account/*

مفاتيح API منفصلة

أنشئ مفاتيح sandbox مخصصة للاختبار مع الحفاظ على مفتاح الإنتاج

القائمة البيضاء لعناوين IP

أضف قيود IP مباشرة من صفحة الإعدادات لأمان معزّز

قائمة التحقق السريع للهجرة

1

إنشاء مفتاح API للـ sandbox (اختياري)

أنشئ مفتاح API للـ sandbox من صفحة إعدادات لوحة التحكم لاختبار v3 قبل نقل الإنتاج
2

تهيئة القائمة البيضاء لعناوين IP (اختياري)

أضف قيود IP لأمان معزّز مباشرة من الإعدادات
3

تحديث رأس المصادقة

غيِّر من authorization إلى X-Access-Token في جميع طلبات API
4

تحديث معالجة الاستجابة

ادخل إلى البيانات عبر result.data بدلاً من الوصول المباشر
5

تحديث معالجة الأخطاء

تحقق من القيمة المنطقية result.success وتعامل مع كائن result.error المنظّم
6

تحديث مسارات الـ endpoints

رسِّم مسارات v2 على المسارات الجديدة في v3 (راجع جدول المرجع الكامل أدناه)
7

تحديث منطق ترقيم الصفحات

ادخل إلى معلومات الترقيم من result.data.pagination بدلاً من المستوى الجذري

اختر استراتيجية الهجرة الخاصة بك

خبر جيد: كلا API الإصداريْن v2 وv3 يعملان في آنٍ واحد حتى إيقاف v2. مفتاح API الإنتاجي الحالي يعمل مع endpoints كلٍّ من v2 وv3، مما يمنحك مرونة في كيفية الانتقال.
تغيير عنوان URL الأساسي: يستخدم v3 عنوان URL أساسياً جديداً: - v2: https://flexy-api.oneclickdz.com/v2 - v3: https://api.oneclickdz.com/v3
اختر النهج الذي يناسب احتياجاتك:

🆕 بداية جديدة

الأنسب لـ: إعادة البناء الكاملة أو المشاريع الجديدة
  • أنشئ مفتاح sandbox للاختبار من الإعدادات
  • هيِّئ القائمة البيضاء لعناوين IP لمفتاح الإنتاج
  • اختبر كل شيء في sandbox مع v3
  • استخدم مفتاح الإنتاج عند الاستعداد
✅ صفحة بيضاء، لا كود موروث ✅ أمان معزّز مع قيود IP

🔄 هجرة تدريجية

الأنسب لـ: أنظمة الإنتاج الحالية
  • استمر في استخدام مفتاح الإنتاج الحالي لـ endpoints v2
  • أنشئ مفتاح sandbox لاختبار v3 بأمان
  • انقل الـ endpoints واحداً تلو الآخر إلى v3
  • شغِّل v2 وv3 جنباً إلى جنب بنفس مفتاح الإنتاج
✅ صفر توقف، مخاطر أقل ✅ انتقل بالسرعة التي تناسبك
موصى به: معظم الفرق تختار الهجرة التدريجية لتقليل المخاطر. يمكنك تحديث الـ endpoints الحرجة أولاً مع إبقاء البقية على v2.

هجرة ذكية: ابدأ ببطاقات الهدايا

نصيحة احترافية: إذا كنت مهتماً ببطاقات الهدايا، ادمجها على v3 أولاً! لا تحتاج إلى نقل شحنات الجوال والإنترنت الحالية لتبدأ استخدام بطاقات الهدايا على v3. هذه طريقة منخفضة المخاطر لاختبار v3 مع إبقاء عملياتك الحرجة على v2. استخدم مفتاح sandbox للاختبار، ثم انتقل للإنتاج عند الاستعداد.
ترتيب الهجرة المقترح:
  1. المرحلة 1: دمج بطاقات الهدايا على v3 (إذا كان ذلك مناسباً)
    • أنشئ مفتاح sandbox للاختبار
    • استخدم endpoints /v3/gift-cards/* في sandbox
    • اختبر بدقة، ثم استخدم مفتاح الإنتاج
    • أبقِ الجوال/الإنترنت على v2
  2. المرحلة 2: نقل endpoints الحساب والتحقق
    • /v3/validate
    • /v3/account/balance
    • /v3/account/transactions
  3. المرحلة 3: نقل شحنات الجوال تدريجياً
    • اختبر بعمليات منخفضة الحجم أولاً
    • راقب المشكلات
    • وسِّع نطاق الهجرة تدريجياً
  4. المرحلة 4: نقل شحنات الإنترنت
    • أكمل قبل الموعد النهائي للإيقاف
هذا النهج يتيح لك الانتقال بالسرعة التي تناسبك حتى تاريخ الإيقاف مع الاستفادة من ميزات v3 الجديدة.

التغييرات الثلاثة الرئيسية

1. رأس المصادقة

ما يجب تغييره: أعِد تسمية الرأس من authorization إلى X-Access-Token
إدارة المفاتيح الجديدة: يتيح لك v3 إنشاء مفتاح API sandbox منفصل للاختبار من إعدادات لوحة التحكم. يمكنك أيضاً إضافة قيود القائمة البيضاء لعناوين IP لأمان معزّز. مفتاح API الإنتاجي الحالي يعمل مع endpoints كلٍّ من v2 وv3.
// Your current v2 code:
fetch("https://flexy-api.oneclickdz.com/v2/plans/listAll", {
  headers: {
    authorization: "YOUR_API_KEY",
  },
});
Changes needed:
  • ❌ Remove: authorization: "YOUR_API_KEY"
  • ✅ Add: X-Access-Token: "YOUR_API_KEY"
  • ✅ Update: Base URL to https://api.oneclickdz.com/v3
The authentication mechanism remains the same - only the header name changes. Your existing API key works with both v2 and v3.
// Updated v3 code:
fetch("https://api.oneclickdz.com/v3/mobile/plans", {
  headers: {
    "X-Access-Token": "YOUR_API_KEY",
  },
});
التغييرات المطلوبة:
  • ❌ احذف: authorization: "YOUR_API_KEY"
  • ✅ أضف: X-Access-Token: "YOUR_API_KEY"
  • ✅ حدِّث: عنوان URL الأساسي إلى https://api.oneclickdz.com/v3
آلية المصادقة تبقى كما هي - فقط اسم الرأس يتغير. مفتاح API الحالي يعمل مع v2 وv3.
# Updated v3 code:
import requests

response = requests.get(
'https://api.oneclickdz.com/v3/mobile/plans',
headers={'X-Access-Token': 'YOUR_API_KEY'}
)


2. Response Structure

What to change: All responses are now wrapped in a standard structure
// Your current v2 code:
const response = await fetch("https://flexy-api.oneclickdz.com/v2/account/balance", {
  headers: { authorization: API_KEY },
});
const data = await response.json();
console.log("Balance:", data.balance); // Direct access

3. Error Handling

What to change: Errors are now structured objects with codes
// Your current v2 code:
const response = await fetch("https://flexy-api.oneclickdz.com/v2/topup/sendTopup", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    authorization: API_KEY,
  },
  body: JSON.stringify(data),
});

const result = await response.json();
if (result.error) {
  console.error("Error:", result.message); // Simple string
}
Changes needed:
  • ❌ Remove: Checking result.error string
  • ✅ Add: Check result.success === false
  • ✅ Add: Access result.error.code and result.error.message
  • ✅ Add: Handle different error codes with switch/if statements
  • ✅ Add: Log result.requestId for support tickets
Pro Tip: Always save the requestId when logging errors. Our support team needs this to trace issues in our system.
// Updated v3 code:
const response = await fetch("https://api.oneclickdz.com/v3/mobile/send", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "X-Access-Token": API_KEY,
  },
  body: JSON.stringify(data),
});

const result = await response.json();

if (!result.success) {
console.error(`Error [${result.error.code}]: ${result.error.message}`);
console.log("Request ID:", result.requestId);

// Handle specific errors
switch (result.error.code) {
case "INSUFFICIENT_BALANCE":
alert("Please top up your account");
break;
case "ERR_PHONE":
alert(`Invalid phone number: ${result.error.message}`);
if (result.error.details?.pattern) {
console.log("Expected format:", result.error.details.pattern);
}
break;
case "DUPLICATED_REF":
alert("This order reference was already used");
break;
default:
alert("An error occurred. Please try again.");
}
}


Step-by-Step Migration Examples

Example 1: Get Mobile Plans

Step 1 - Your current v2 code:
const response = await fetch("https://flexy-api.oneclickdz.com/v2/plans/listAll", {
  headers: {
    authorization: API_KEY,
  },
});

const data = await response.json();
const dynamicPlans = data.dymanicPlans; // Note: typo in v2
const fixedPlans = data.fixedPlans;
Step 2 - What to change:
  1. Change base URL: https://flexy-api.oneclickdz.comhttps://api.oneclickdz.com
  2. Change endpoint: /v2/plans/listAll/v3/mobile/plans
  3. Change header: authorizationX-Access-Token
  4. Add success check: if (result.success)
  5. Access through data: data.dymanicPlansresult.data.dynamicPlans (typo fixed!)
MUST Fix: v3 fixes the typo in “dymanicPlans” to “dynamicPlans”. Update your code to use the correct spelling.
Step 3 - Your new v3 code:
const response = await fetch("https://api.oneclickdz.com/v3/mobile/plans", {
  headers: {
    "X-Access-Token": API_KEY,
  },
});

const result = await response.json();
if (result.success) {
const dynamicPlans = result.data.dynamicPlans; // Typo fixed!
const fixedPlans = result.data.fixedPlans;
}


Example 2: Send Mobile Top-Up

Step 1 - Your current v2 code:
const response = await fetch("https://flexy-api.oneclickdz.com/v2/topup/sendTopup", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    authorization: API_KEY,
  },
  body: JSON.stringify({
    plan_code: "PREPAID_DJEZZY",
    MSSIDN: "0778037340",
    amount: 500,
    ref: "order-123",
  }),
});

const data = await response.json();
console.log("Topup ID:", data.topupId);
console.log("New Balance:", data.newBalance);
Step 2 - What to change:
  1. Change base URL: https://flexy-api.oneclickdz.comhttps://api.oneclickdz.com
  2. Change endpoint: /v2/topup/sendTopup/v3/mobile/send
  3. Change header: authorizationX-Access-Token
  4. Add success check: if (result.success)
  5. Access through data: data.topupIdresult.data.topupId
  6. Add comprehensive error handling
Important: Always handle errors when sending top-ups. Network issues, insufficient balance, or invalid data can cause failures. Save the requestId for tracking.
Step 3 - Your new v3 code:
const response = await fetch("https://api.oneclickdz.com/v3/mobile/send", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "X-Access-Token": API_KEY,
  },
  body: JSON.stringify({
    plan_code: "PREPAID_DJEZZY",
    MSSIDN: "0778037340",
    amount: 500,
    ref: "order-123",
  }),
});

const result = await response.json();
if (result.success) {
console.log("✅ Top-up sent successfully!");
console.log("Topup ID:", result.data.topupId);
console.log("New Balance:", result.data.newBalance);
console.log("Request ID:", result.requestId);
} else {
console.error(`❌ Error [${result.error.code}]: ${result.error.message}`);
console.error("Request ID:", result.requestId);
}


Example 3: Check Top-Up Status

Step 1 - Your current v2 code:
const response = await fetch(
  "https://flexy-api.oneclickdz.com/v2/topup/checkStatus/REF/order-123",
  {
    headers: { authorization: API_KEY },
  }
);

const data = await response.json();
console.log("Status:", data.topup.status);
console.log("Phone:", data.topup.MSSIDN);
Step 2 - What to change:
  1. Change base URL: https://flexy-api.oneclickdz.comhttps://api.oneclickdz.com
  2. Change endpoint: /v2/topup/checkStatus/REF/:ref/v3/mobile/check-ref/:ref
  3. Change header: authorizationX-Access-Token
  4. Add success check: if (result.success)
  5. Access directly: data.topup.statusresult.data.status (no more nested topup object)
  6. Handle new refund information fields
New Feature: v3 includes detailed refund information with suggested alternative offers when a top-up is refunded.
Step 3 - Your new v3 code:
const response = await fetch(
  "https://api.oneclickdz.com/v3/mobile/check-ref/order-123",
  {
    headers: { "X-Access-Token": API_KEY },
  }
);

const result = await response.json();
if (result.success) {
console.log("Status:", result.data.status);
console.log("Phone:", result.data.MSSIDN);

// New in v3: Enhanced refund information
if (result.data.status === "REFUNDED") {
console.log("❌ Top-up was refunded");
console.log("Reason:", result.data.refund_message);
if (result.data.suggested_offers) {
console.log("💡 Try these offers instead:");
console.log(result.data.suggested_offers);
}
} else if (result.data.status === "FULFILLED") {
console.log("✅ Top-up completed successfully");
}
}


Example 4: List Transactions with Pagination

Step 1 - Your current v2 code:
const response = await fetch(
  "https://flexy-api.oneclickdz.com/v2/account/transactions?page=1&pageSize=20",
  {
    headers: { authorization: API_KEY },
  }
);

const data = await response.json();
console.log("Transactions:", data.transactions);
console.log("Total:", data.totalResults);
console.log("Page:", data.currentPage);
console.log("Pages:", data.totalPages);
Step 2 - What to change:
  1. Change base URL: https://flexy-api.oneclickdz.comhttps://api.oneclickdz.com
  2. Change version: /v2/account/transactions/v3/account/transactions
  3. Change header: authorizationX-Access-Token
  4. Add success check: if (result.success)
  5. Access items: data.transactionsresult.data.items
  6. Access pagination: Root level fields → result.data.pagination object
Breaking Change: Pagination structure has moved from root level to data.pagination. Update all list/pagination logic.
Step 3 - Your new v3 code:
const response = await fetch(
  "https://api.oneclickdz.com/v3/account/transactions?page=1&pageSize=20",
  {
    headers: { "X-Access-Token": API_KEY },
  }
);

const result = await response.json();
if (result.success) {
console.log("Transactions:", result.data.items);
console.log("Total:", result.data.pagination.totalResults);
console.log("Page:", result.data.pagination.page);
console.log("Pages:", result.data.pagination.totalPages);
console.log("Page Size:", result.data.pagination.pageSize);
}


Example 5: Check Internet Products

Step 1 - Your current v2 code:
const response = await fetch(
  "https://flexy-api.oneclickdz.com/v2/internet/checkCards/ADSL",
  {
    headers: { authorization: API_KEY },
  }
);

const cards = await response.json(); // Direct array
cards.forEach((card) => {
  console.log(`${card.value} DA - Available: ${card.available}`);
});
Step 2 - What to change:
  1. Change base URL: https://flexy-api.oneclickdz.comhttps://api.oneclickdz.com
  2. Change endpoint: /v2/internet/checkCards/:type/v3/internet/products?type=:type
  3. Change from path param to query param: /ADSL?type=ADSL
  4. Change header: authorizationX-Access-Token
  5. Add success check: if (result.success)
  6. Access array: Direct array → result.data.products
API Design: v3 uses query parameters instead of path parameters for type selection, making it easier to add filters in the future.
Step 3 - Your new v3 code:
const response = await fetch(
  "https://api.oneclickdz.com/v3/internet/products?type=ADSL",
  {
    headers: { "X-Access-Token": API_KEY },
  }
);

const result = await response.json();
if (result.success) {
result.data.products.forEach((card) => {
console.log(`${card.value} DA - Available: ${card.available}`);
});
}


Migrate Your API Client

Here’s how to update your API client wrapper:Step 1 - Your current v2 client:
class FlexyAPI {
  constructor(apiKey) {
    this.apiKey = apiKey;
    this.baseUrl = "https://flexy-api.oneclickdz.com";
  }

  async request(endpoint, options = {}) {
    const response = await fetch(`${this.baseUrl}${endpoint}`, {
      ...options,
      headers: {
        ...options.headers,
        authorization: this.apiKey,
      },
    });
    return response.json();
  }

  async getBalance() {
    const data = await this.request("/v2/account/balance");
    return data.balance;
  }

  async sendTopup(params) {
    return await this.request("/v2/topup/sendTopup", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify(params),
    });
  }
}
Step 2 - What to change:
  1. Change base URL: https://flexy-api.oneclickdz.comhttps://api.oneclickdz.com
  2. Change header: authorizationX-Access-Token
  3. Add response wrapper handling in request() method
  4. Check result.success and handle errors
  5. Update all endpoint paths to v3
  6. Throw structured errors with codes and request IDs
Best Practice: Centralize error handling in your API client. This makes it easier to add logging, monitoring, and user notifications.
Step 3 - Your new v3 client:
class FlexyAPI {
  constructor(apiKey) {
    this.apiKey = apiKey;
    this.baseUrl = "https://api.oneclickdz.com";
  }

async request(endpoint, options = {}) {
const response = await fetch(`${this.baseUrl}${endpoint}`, {
...options,
headers: {
...options.headers,
"X-Access-Token": this.apiKey, // Changed header name
},
});

    const result = await response.json();

    // Handle v3 response wrapper
    if (!result.success) {
      const error = new Error(result.error.message);
      error.code = result.error.code;
      error.details = result.error.details;
      error.requestId = result.requestId;
      throw error;
    }

    return result.data; // Return unwrapped data

}

async getBalance() {
const data = await this.request("/v3/account/balance"); // Updated path
return data.balance;
}

async sendTopup(params) {
return await this.request("/v3/mobile/send", { // Updated path
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(params),
});
}
}


Complete Endpoint Reference

Servicev2 Endpointv3 EndpointNotes
Authentication
Headerauthorization: KEYX-Access-Token: KEYHeader name changed
ValidateGET /v2/validateGET /v3/validateResponse wrapped
Mobile
List PlansGET /v2/plans/listAllGET /v3/mobile/plansPath changed, typo fixed
Send Top-UpPOST /v2/topup/sendTopupPOST /v3/mobile/sendPath simplified
Check by RefGET /v2/topup/checkStatus/REF/:refGET /v3/mobile/check-ref/:refPath simplified, refund info added
Check by IDGET /v2/topup/checkStatus/ID/:idGET /v3/mobile/check-id/:idPath simplified
List Top-UpsGET /v2/topup/listGET /v3/mobile/listPagination moved to data.pagination
Internet
ProductsGET /v2/internet/checkCards/:typeGET /v3/internet/products?type=Path param → query param
Check NumberGET /v2/internet/checkNumber/:t/:nGET /v3/internet/check-number?type=&number=Path params → query params
SendPOST /v2/internet/sendTopupPOST /v3/internet/sendPath simplified
Check by RefGET /v2/internet/checkStatus/REF/:refGET /v3/internet/check-ref/:refPath simplified
Check by IDGET /v2/internet/checkStatus/ID/:idGET /v3/internet/check-id/:idPath simplified
ListGET /v2/internet/listGET /v3/internet/listPagination moved
Gift Cards
CatalogGET /v2/gift-cards/catalogueGET /v3/gift-cards/catalogSpelling fixed
Check ProductGET /v2/gift-cards/checkProduct/:idGET /v3/gift-cards/checkProduct/:idResponse wrapped
Place OrderPOST /v2/gift-cards/placeOrderPOST /v3/gift-cards/placeOrderResponse wrapped
Check OrderGET /v2/gift-cards/checkOrder/:idGET /v3/gift-cards/checkOrder/:idResponse wrapped
List OrdersGET /v2/gift-cards/listGET /v3/gift-cards/listPagination moved
Account
BalanceGET /v2/account/balanceGET /v3/account/balanceResponse wrapped
TransactionsGET /v2/account/transactionsGET /v3/account/transactionsPagination moved

Error Code Reference

Common v2 errors and their v3 equivalents:
v2 Errorv3 Error CodeWhat Changed
"NO-BALANCE"INSUFFICIENT_BALANCENow a code with structured message
"DUPLICATED-REF"DUPLICATED_REFSame code, now with details object
"ERR_VALIDATION"ERR_VALIDATIONIncludes details.field and `details.pattern
"ERR_PHONE"ERR_PHONEIncludes validation pattern in details
"ERR_STOCK"ERR_STOCKProduct availability information
"Forbidden"ERR_AUTHMore descriptive, unified auth errors
"Access token missing"ERR_AUTHSame code for all auth errors
"NOT_FOUND"NOT_FOUNDResource not found (order, product, etc.)
How to handle v3 errors:
// v2 way:
if (result.error === "NO-BALANCE") {
  // handle
}

// v3 way:
if (!result.success && result.error.code === "INSUFFICIENT_BALANCE") {
  console.log("Request ID:", result.requestId); // Save for support
  // handle with more context
  if (result.error.details?.currentBalance) {
    console.log("Current balance:", result.error.details.currentBalance);
  }
}

Critical Deadline: After October 30, 2026, all v2 API requests will fail. Plan your migration accordingly to avoid service disruption.

Common Migration Issues & Solutions

Problem: Changed endpoint but forgot to update header name.Solution: Replace authorization with X-Access-Token in ALL requests.
// ❌ Wrong
headers: { authorization: API_KEY }

// ✅ Correct
headers: { "X-Access-Token": API_KEY }
Problem: Trying to access data directly instead of through result.data. Solution: Always access response data through the data property.
❌ Wrong const balance = result.balance; ✅ Correct const
balance = result.data.balance; ```
</Accordion>

{" "}

<Accordion title="Issue: Pagination Not Working" icon="circle-exclamation">
**Problem**: Looking for pagination fields at root level. **Solution**: Access
pagination through `data.pagination`. ```javascript // ❌ Wrong const total =
result.totalResults; const page = result.currentPage; // ✅ Correct const
total = result.data.pagination.totalResults; const page =
result.data.pagination.page; ```
</Accordion>

<Accordion title="Issue: Error Handling Not Working" icon="circle-exclamation">
  **Problem**: Checking for old error format.
  
  **Solution**: Check `success` boolean and access structured error object.
  
  ```javascript
  // ❌ Wrong
  if (result.error) {
    console.log(result.message);
  }
  
  // ✅ Correct
  if (!result.success) {
    console.log(result.error.code, result.error.message);
    console.log("Request ID:", result.requestId);
  }
Problem: Using old v2 endpoint paths.Solution: Update all paths according to the reference table above.
// ❌ Wrong
POST /v2/topup/sendTopup
GET /v2/internet/checkCards/ADSL

// ✅ Correct
POST /v3/mobile/send
GET /v3/internet/products?type=ADSL
التغييرات المطلوبة:
  • ❌ احذف: الوصول المباشر إلى data.balance
  • ✅ أضف: تحقق من result.success أولاً
  • ✅ أضف: الوصول عبر result.data.balance
  • ✅ إضافي: استخدم result.requestId لأغراض التصحيح
  • ✅ إضافي: استخدم result.meta.timestamp لمعلومات التوقيت
تغيير جوهري: في v3، يجب دائماً التحقق من القيمة المنطقية success قبل الوصول إلى البيانات. سيُسبِّب الوصول المباشر للحقول أخطاءً إذا فشل الطلب.
// Updated v3 code:
const response = await fetch("https://api.oneclickdz.com/v3/account/balance", {
  headers: { "X-Access-Token": API_KEY },
});
const result = await response.json();

if (result.success) {
  console.log("Balance:", result.data.balance);
  console.log("Request ID:", result.requestId);
  console.log("Timestamp:", result.meta.timestamp);
} else {
  console.error("Error:", result.error.message);
}

3. معالجة الأخطاء

ما يجب تغييره: الأخطاء الآن عبارة عن كائنات منظّمة مع أكواد
// Your current v2 code:
const response = await fetch("https://flexy-api.oneclickdz.com/v2/topup/sendTopup", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    authorization: API_KEY,
  },
  body: JSON.stringify(data),
});

const result = await response.json();
if (result.error) {
  console.error("Error:", result.message); // Simple string
}
التغييرات المطلوبة:
  • ❌ احذف: التحقق من سلسلة result.error
  • ✅ أضف: تحقق من result.success === false
  • ✅ أضف: ادخل إلى result.error.code وresult.error.message
  • ✅ أضف: تعامل مع أكواد الخطأ المختلفة باستخدام switch/if
  • ✅ أضف: سجِّل result.requestId لتذاكر الدعم
نصيحة احترافية: احفظ دائماً requestId عند تسجيل الأخطاء. يحتاج فريق الدعم لدينا إليه لتتبع المشكلات في نظامنا.
// Updated v3 code:
const response = await fetch("https://api.oneclickdz.com/v3/mobile/send", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "X-Access-Token": API_KEY,
  },
  body: JSON.stringify(data),
});

const result = await response.json();

if (!result.success) {
  console.error(`Error [${result.error.code}]: ${result.error.message}`);
  console.log("Request ID:", result.requestId);

  switch (result.error.code) {
    case "INSUFFICIENT_BALANCE":
      alert("Please top up your account");
      break;
    case "ERR_PHONE":
      alert(`Invalid phone number: ${result.error.message}`);
      if (result.error.details?.pattern) {
        console.log("Expected format:", result.error.details.pattern);
      }
      break;
    case "DUPLICATED_REF":
      alert("This order reference was already used");
      break;
    default:
      alert("Something went wrong. Please try again.");
  }
}

أمثلة الهجرة خطوة بخطوة

المثال 1: الحصول على الخطط المتنقلة

الخطوة 1 - كودك الحالي في v2:
const response = await fetch("https://flexy-api.oneclickdz.com/v2/plans/listAll", {
  headers: {
    authorization: API_KEY,
  },
});

const data = await response.json();
const dynamicPlans = data.dymanicPlans; // Note: typo in v2
const fixedPlans = data.fixedPlans;
الخطوة 2 - ما الذي يجب تغييره:
  1. غيّر عنوان URL الأساسي: https://flexy-api.oneclickdz.comhttps://api.oneclickdz.com
  2. غيّر الـ endpoint: /v2/plans/listAll/v3/mobile/plans
  3. غيّر الرأس: authorizationX-Access-Token
  4. أضف فحص النجاح: if (result.success)
  5. الوصول عبر data: data.dymanicPlansresult.data.dynamicPlans (تم تصحيح الخطأ المطبعي!)
إلزامي: يصحح v3 الخطأ المطبعي في “dymanicPlans” إلى “dynamicPlans”. قم بتحديث كودك لاستخدام الإملاء الصحيح.
الخطوة 3 - كودك الجديد في v3:
const response = await fetch("https://api.oneclickdz.com/v3/mobile/plans", {
  headers: {
    "X-Access-Token": API_KEY,
  },
});

const result = await response.json();
if (result.success) {
  const dynamicPlans = result.data.dynamicPlans; // Typo fixed!
  const fixedPlans = result.data.fixedPlans;
}

المثال 2: إرسال شحن متنقل

الخطوة 1 - كودك الحالي في v2:
const response = await fetch("https://flexy-api.oneclickdz.com/v2/topup/sendTopup", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    authorization: API_KEY,
  },
  body: JSON.stringify({
    plan_code: "PREPAID_DJEZZY",
    MSSIDN: "0778037340",
    amount: 500,
    ref: "order-123",
  }),
});

const data = await response.json();
console.log("Topup ID:", data.topupId);
console.log("New Balance:", data.newBalance);
الخطوة 2 - ما الذي يجب تغييره:
  1. غيّر عنوان URL الأساسي: https://flexy-api.oneclickdz.comhttps://api.oneclickdz.com
  2. غيّر الـ endpoint: /v2/topup/sendTopup/v3/mobile/send
  3. غيّر الرأس: authorizationX-Access-Token
  4. أضف فحص النجاح: if (result.success)
  5. الوصول عبر data: data.topupIdresult.data.topupId
  6. أضف معالجة شاملة للأخطاء
مهم: تعامل دائماً مع الأخطاء عند إرسال الشحن. مشاكل الشبكة أو الرصيد غير الكافي أو البيانات غير الصالحة قد تسبب الفشل. احفظ requestId للتتبع.
الخطوة 3 - كودك الجديد في v3:
const response = await fetch("https://api.oneclickdz.com/v3/mobile/send", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "X-Access-Token": API_KEY,
  },
  body: JSON.stringify({
    plan_code: "PREPAID_DJEZZY",
    MSSIDN: "0778037340",
    amount: 500,
    ref: "order-123",
  }),
});

const result = await response.json();
if (result.success) {
  console.log("✅ Top-up sent successfully!");
  console.log("Topup ID:", result.data.topupId);
  console.log("New Balance:", result.data.newBalance);
  console.log("Request ID:", result.requestId);
} else {
  console.error(`❌ Error [${result.error.code}]: ${result.error.message}`);
  console.error("Request ID:", result.requestId);
}

المثال 3: فحص حالة الشحن

الخطوة 1 - كودك الحالي في v2:
const response = await fetch(
  "https://flexy-api.oneclickdz.com/v2/topup/checkStatus/REF/order-123",
  {
    headers: { authorization: API_KEY },
  }
);

const data = await response.json();
console.log("Status:", data.topup.status);
console.log("Phone:", data.topup.MSSIDN);
الخطوة 2 - ما الذي يجب تغييره:
  1. غيّر عنوان URL الأساسي: https://flexy-api.oneclickdz.comhttps://api.oneclickdz.com
  2. غيّر الـ endpoint: /v2/topup/checkStatus/REF/:ref/v3/mobile/check-ref/:ref
  3. غيّر الرأس: authorizationX-Access-Token
  4. أضف فحص النجاح: if (result.success)
  5. الوصول المباشر: data.topup.statusresult.data.status (لا مزيد من كائن topup المتداخل)
  6. تعامل مع حقول معلومات الاسترداد الجديدة
ميزة جديدة: يتضمن v3 معلومات مفصلة عن الاسترداد مع عروض بديلة مقترحة عند استرداد الشحن.
الخطوة 3 - كودك الجديد في v3:
const response = await fetch(
  "https://api.oneclickdz.com/v3/mobile/check-ref/order-123",
  {
    headers: { "X-Access-Token": API_KEY },
  }
);

const result = await response.json();
if (result.success) {
  console.log("Status:", result.data.status);
  console.log("Phone:", result.data.MSSIDN);

  // New in v3: Enhanced refund information
  if (result.data.status === "REFUNDED") {
    console.log("❌ Top-up was refunded");
    console.log("Reason:", result.data.refund_message);
    if (result.data.suggested_offers) {
      console.log("💡 Try these offers instead:");
      console.log(result.data.suggested_offers);
    }
  } else if (result.data.status === "FULFILLED") {
    console.log("✅ Top-up completed successfully");
  }
}

المثال 4: قائمة المعاملات مع الترقيم

الخطوة 1 - كودك الحالي في v2:
const response = await fetch(
  "https://flexy-api.oneclickdz.com/v2/account/transactions?page=1&pageSize=20",
  {
    headers: { authorization: API_KEY },
  }
);

const data = await response.json();
console.log("Transactions:", data.transactions);
console.log("Total:", data.totalResults);
console.log("Page:", data.currentPage);
console.log("Pages:", data.totalPages);
الخطوة 2 - ما الذي يجب تغييره:
  1. غيّر عنوان URL الأساسي: https://flexy-api.oneclickdz.comhttps://api.oneclickdz.com
  2. غيّر الإصدار: /v2/account/transactions/v3/account/transactions
  3. غيّر الرأس: authorizationX-Access-Token
  4. أضف فحص النجاح: if (result.success)
  5. الوصول للعناصر: data.transactionsresult.data.items
  6. الوصول للترقيم: الحقول على مستوى الجذر ← كائن result.data.pagination
تغيير جذري: انتقلت بنية الترقيم من المستوى الجذري إلى data.pagination. قم بتحديث جميع منطق القوائم/الترقيم.
الخطوة 3 - كودك الجديد في v3:
const response = await fetch(
  "https://api.oneclickdz.com/v3/account/transactions?page=1&pageSize=20",
  {
    headers: { "X-Access-Token": API_KEY },
  }
);

const result = await response.json();
if (result.success) {
  console.log("Transactions:", result.data.items);
  console.log("Total:", result.data.pagination.totalResults);
  console.log("Page:", result.data.pagination.page);
  console.log("Pages:", result.data.pagination.totalPages);
  console.log("Page Size:", result.data.pagination.pageSize);
}

المثال 5: فحص منتجات الإنترنت

الخطوة 1 - كودك الحالي في v2:
const response = await fetch(
  "https://flexy-api.oneclickdz.com/v2/internet/checkCards/ADSL",
  {
    headers: { authorization: API_KEY },
  }
);

const cards = await response.json(); // Direct array
cards.forEach((card) => {
  console.log(`${card.value} DA - Available: ${card.available}`);
});
الخطوة 2 - ما الذي يجب تغييره:
  1. غيّر عنوان URL الأساسي: https://flexy-api.oneclickdz.comhttps://api.oneclickdz.com
  2. غيّر الـ endpoint: /v2/internet/checkCards/:type/v3/internet/products?type=:type
  3. من معامل المسار إلى معامل الاستعلام: /ADSL?type=ADSL
  4. غيّر الرأس: authorizationX-Access-Token
  5. أضف فحص النجاح: if (result.success)
  6. الوصول للمصفوفة: مصفوفة مباشرة ← result.data.products
تصميم API: يستخدم v3 معاملات الاستعلام بدلاً من معاملات المسار لاختيار النوع، مما يسهّل إضافة الفلاتر مستقبلاً.
الخطوة 3 - كودك الجديد في v3:
const response = await fetch(
  "https://api.oneclickdz.com/v3/internet/products?type=ADSL",
  {
    headers: { "X-Access-Token": API_KEY },
  }
);

const result = await response.json();
if (result.success) {
  result.data.products.forEach((card) => {
    console.log(`${card.value} DA - Available: ${card.available}`);
  });
}

هجرة عميل API الخاص بك

إليك كيفية تحديث wrapper عميل API الخاص بك:الخطوة 1 - عميلك الحالي في v2:
class FlexyAPI {
  constructor(apiKey) {
    this.apiKey = apiKey;
    this.baseUrl = "https://flexy-api.oneclickdz.com";
  }

  async request(endpoint, options = {}) {
    const response = await fetch(`${this.baseUrl}${endpoint}`, {
      ...options,
      headers: {
        ...options.headers,
        authorization: this.apiKey,
      },
    });
    return response.json();
  }

  async getBalance() {
    const data = await this.request("/v2/account/balance");
    return data.balance;
  }

  async sendTopup(params) {
    return await this.request("/v2/topup/sendTopup", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify(params),
    });
  }
}
الخطوة 2 - ما الذي يجب تغييره:
  1. غيّر عنوان URL الأساسي: https://flexy-api.oneclickdz.comhttps://api.oneclickdz.com
  2. غيّر الرأس: authorizationX-Access-Token
  3. أضف معالجة غلاف الاستجابة في الـ method request()
  4. تحقق من result.success وتعامل مع الأخطاء
  5. حدّث جميع مسارات الـ endpoint إلى v3
  6. ألقِ أخطاء منظّمة مع أكواد ومعرّفات الطلبات
أفضل الممارسات: مركِّز معالجة الأخطاء في عميل API الخاص بك. هذا يسهّل إضافة التسجيل والمراقبة وإشعارات المستخدم.
الخطوة 3 - عميلك الجديد في v3:
class FlexyAPI {
  constructor(apiKey) {
    this.apiKey = apiKey;
    this.baseUrl = "https://api.oneclickdz.com";
  }

  async request(endpoint, options = {}) {
    const response = await fetch(`${this.baseUrl}${endpoint}`, {
      ...options,
      headers: {
        ...options.headers,
        "X-Access-Token": this.apiKey,
      },
    });

    const result = await response.json();

    if (!result.success) {
      const error = new Error(result.error.message);
      error.code = result.error.code;
      error.details = result.error.details;
      error.requestId = result.requestId;
      throw error;
    }

    return result.data;
  }

  async getBalance() {
    const data = await this.request("/v3/account/balance");
    return data.balance;
  }

  async sendTopup(params) {
    return await this.request("/v3/mobile/send", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify(params),
    });
  }
}

مرجع أكواد الخطأ

أخطاء v2 الشائعة ومكافئاتها في v3:
خطأ v2كود خطأ v3ما الذي تغيّر
"NO-BALANCE"INSUFFICIENT_BALANCEالآن كود مع رسالة منظّمة
"DUPLICATED-REF"DUPLICATED_REFنفس الكود، الآن مع كائن details
"ERR_VALIDATION"ERR_VALIDATIONيتضمن details.field وdetails.pattern
"ERR_PHONE"ERR_PHONEيتضمن نمط التحقق في التفاصيل
"ERR_STOCK"ERR_STOCKمعلومات توفر المنتج
"Forbidden"ERR_AUTHأكثر وصفاً، أخطاء مصادقة موحّدة
"Access token missing"ERR_AUTHنفس الكود لجميع أخطاء المصادقة
"NOT_FOUND"NOT_FOUNDالمورد غير موجود (طلب، منتج، إلخ.)
كيفية التعامل مع أخطاء v3:
// v2 way:
if (result.error === "NO-BALANCE") {
  // handle
}

// v3 way:
if (!result.success && result.error.code === "INSUFFICIENT_BALANCE") {
  console.log("Request ID:", result.requestId); // Save for support
  if (result.error.details?.currentBalance) {
    console.log("Current balance:", result.error.details.currentBalance);
  }
}

موعد نهائي حرج: بعد 30 أكتوبر 2026، ستفشل جميع طلبات API v2. خطّط لهجرتك وفقاً لذلك لتجنب انقطاع الخدمة.

مشاكل الهجرة الشائعة وحلولها

المشكلة: تم تغيير الـ endpoint لكن لم يتم تحديث اسم الرأس.الحل: استبدل authorization بـ X-Access-Token في جميع الطلبات.
// ❌ Wrong
headers: { authorization: API_KEY }

// ✅ Correct
headers: { "X-Access-Token": API_KEY }
المشكلة: محاولة الوصول للبيانات مباشرة بدون المرور بـ result.data.الحل: الوصول دائماً لبيانات الاستجابة عبر خاصية data.
// ❌ Wrong
const balance = result.balance;

// ✅ Correct
const balance = result.data.balance;
المشكلة: البحث عن حقول الترقيم على المستوى الجذري.الحل: الوصول للترقيم عبر data.pagination.
// ❌ Wrong
const total = result.totalResults;
const page = result.currentPage;

// ✅ Correct
const total = result.data.pagination.totalResults;
const page = result.data.pagination.page;
المشكلة: التحقق من تنسيق الخطأ القديم.الحل: تحقق من البوليان success وادخل إلى كائن الخطأ المنظّم.
// ❌ Wrong
if (result.error) {
  console.log(result.message);
}

// ✅ Correct
if (!result.success) {
  console.log(result.error.code, result.error.message);
  console.log("Request ID:", result.requestId);
}
المشكلة: استخدام مسارات الـ endpoint القديمة في v2.الحل: حدّث جميع المسارات وفقاً لجدول المرجع أعلاه.
// ❌ Wrong
POST /v2/topup/sendTopup
GET /v2/internet/checkCards/ADSL

// ✅ Correct
POST /v3/mobile/send
GET /v3/internet/products?type=ADSL


مرجع الـ endpoints الكامل

الخدمةالـ endpoint في v2الـ endpoint في v3ملاحظات
المصادقة
الرأسauthorization: KEYX-Access-Token: KEYاسم الرأس تغيّر
التحققGET /v2/validateGET /v3/validateالاستجابة مُغلَّفة
الجوال
قائمة الخططGET /v2/plans/listAllGET /v3/mobile/plansالمسار تغيّر، خطأ إملائي مُصحَّح
إرسال شحنةPOST /v2/topup/sendTopupPOST /v3/mobile/sendالمسار مُبسَّط
التحقق بالمرجعGET /v2/topup/checkStatus/REF/:refGET /v3/mobile/check-ref/:refالمسار مُبسَّط، معلومات الاسترداد أُضيفت
التحقق بالمعرِّفGET /v2/topup/checkStatus/ID/:idGET /v3/mobile/check-id/:idالمسار مُبسَّط
قائمة الشحناتGET /v2/topup/listGET /v3/mobile/listالترقيم انتقل إلى data.pagination
الإنترنت
المنتجاتGET /v2/internet/checkCards/:typeGET /v3/internet/products?type=معامل المسار ← معامل الاستعلام
التحقق من الرقمGET /v2/internet/checkNumber/:t/:nGET /v3/internet/check-number?type=&number=معاملات المسار ← معاملات الاستعلام
الإرسالPOST /v2/internet/sendTopupPOST /v3/internet/sendالمسار مُبسَّط
التحقق بالمرجعGET /v2/internet/checkStatus/REF/:refGET /v3/internet/check-ref/:refالمسار مُبسَّط
التحقق بالمعرِّفGET /v2/internet/checkStatus/ID/:idGET /v3/internet/check-id/:idالمسار مُبسَّط
القائمةGET /v2/internet/listGET /v3/internet/listالترقيم انتقل
بطاقات الهدايا
الكتالوجGET /v2/gift-cards/catalogueGET /v3/gift-cards/catalogالإملاء مُصحَّح
التحقق من المنتجGET /v2/gift-cards/checkProduct/:idGET /v3/gift-cards/checkProduct/:idالاستجابة مُغلَّفة
تقديم الطلبPOST /v2/gift-cards/placeOrderPOST /v3/gift-cards/placeOrderالاستجابة مُغلَّفة
التحقق من الطلبGET /v2/gift-cards/checkOrder/:idGET /v3/gift-cards/checkOrder/:idالاستجابة مُغلَّفة
قائمة الطلباتGET /v2/gift-cards/listGET /v3/gift-cards/listالترقيم انتقل
الحساب
الرصيدGET /v2/account/balanceGET /v3/account/balanceالاستجابة مُغلَّفة
المعاملاتGET /v2/account/transactionsGET /v3/account/transactionsالترقيم انتقل

قائمة التحقق من الاختبار

قبل النشر في الإنتاج، تحقق من:
  • جميع رؤوس المصادقة غُيِّرت إلى X-Access-Token
  • جميع مسارات الـ endpoints حُدِّثت إلى v3
  • التحقق من النجاح/الخطأ مُطبَّق في كل مكان
  • البيانات يمكن الوصول إليها عبر result.data
  • الترقيم يمكن الوصول إليه عبر result.data.pagination
  • أكواد الخطأ مُعالَجة مع result.error.code
  • معرِّفات الطلبات مسجَّلة لأغراض التصحيح
  • تم الاختبار في وضع sandbox أولاً
  • جميع الوظائف الموجودة لا تزال تعمل
  • سيناريوهات الخطأ مختبَرة (رصيد غير كافٍ، بيانات غير صالحة، إلخ)

تحتاج مساعدة؟

وثائق API v3

مرجع v3 الكامل والأمثلة

دليل معالجة الأخطاء

أفضل الممارسات لمعالجة الأخطاء

إعدادات لوحة التحكم

الوصول: سجِّل الدخول إلى لوحة التحكمإنشاء مفتاح sandbox: أنشئ مفتاحاً للاختبار الآمنالقائمة البيضاء لعناوين IP: أضف قيود IP لأمان معزّز

الدعم

البريد الإلكتروني: [email protected]مهم: أدرج دائماً معرِّف الطلب عند الإبلاغ عن مشكلات
دعم الهجرة: فريقنا هنا للمساعدة! راسلنا بالبريد الإلكتروني مع “دعم هجرة API v3” في سطر الموضوع، وأدرج: - تفاصيل تطبيقك الحالي - الأخطاء المحددة (مع معرِّفات الطلبات) - نماذج الكود التي تُظهر المشكلة