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 مباشرة من صفحة الإعدادات لأمان معزّز
قائمة التحقق السريع للهجرة
إنشاء مفتاح API للـ sandbox (اختياري)
أنشئ مفتاح API للـ sandbox من صفحة إعدادات لوحة التحكم لاختبار v3 قبل نقل الإنتاج
تهيئة القائمة البيضاء لعناوين IP (اختياري)
أضف قيود IP لأمان معزّز مباشرة من الإعدادات
تحديث رأس المصادقة
غيِّر من authorization إلى X-Access-Token في جميع طلبات API
تحديث معالجة الاستجابة
ادخل إلى البيانات عبر result.data بدلاً من الوصول المباشر
تحديث معالجة الأخطاء
تحقق من القيمة المنطقية result.success وتعامل مع كائن result.error المنظّم
تحديث مسارات الـ endpoints
رسِّم مسارات v2 على المسارات الجديدة في v3 (راجع جدول المرجع الكامل أدناه)
تحديث منطق ترقيم الصفحات
ادخل إلى معلومات الترقيم من 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 : دمج بطاقات الهدايا على v3 (إذا كان ذلك مناسباً)
أنشئ مفتاح sandbox للاختبار
استخدم endpoints /v3/gift-cards/* في sandbox
اختبر بدقة، ثم استخدم مفتاح الإنتاج
أبقِ الجوال/الإنترنت على v2
المرحلة 2 : نقل endpoints الحساب والتحقق
/v3/validate
/v3/account/balance
/v3/account/transactions
المرحلة 3 : نقل شحنات الجوال تدريجياً
اختبر بعمليات منخفضة الحجم أولاً
راقب المشكلات
وسِّع نطاق الهجرة تدريجياً
المرحلة 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" ,
},
});
// Your current v2 code:
$ch = curl_init ( 'https://flexy-api.oneclickdz.com/v2/plans/listAll' );
curl_setopt ( $ch , CURLOPT_HTTPHEADER , [
'authorization: YOUR_API_KEY'
]);
curl_setopt ( $ch , CURLOPT_RETURNTRANSFER , true );
$response = curl_exec ( $ch );
# Your current v2 code:
import requests
response = requests.get(
'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" ,
},
});
// Updated v3 code:
$ch = curl_init ( 'https://api.oneclickdz.com/v3/mobile/plans' );
curl_setopt ( $ch , CURLOPT_HTTPHEADER , [
'X-Access-Token: YOUR_API_KEY'
]);
curl_setopt ( $ch , CURLOPT_RETURNTRANSFER , true );
$response = curl_exec ( $ch );
التغييرات المطلوبة :
❌ احذف: 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 JavaScript
PHP
PHP
Python
PHP
Python
// 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
// Your current v2 code:
$ch = curl_init ( 'https://flexy-api.oneclickdz.com/v2/account/balance' );
curl_setopt ( $ch , CURLOPT_HTTPHEADER , [ 'authorization: ' . $apiKey ]);
curl_setopt ( $ch , CURLOPT_RETURNTRANSFER , true );
$response = curl_exec ( $ch );
$data = json_decode ( $response , true );
echo "Balance: " . $data [ 'balance' ]; // Direct access
# Your current v2 code:
response = requests.get(
'https://flexy-api.oneclickdz.com/v2/account/balance' ,
headers = { 'authorization' : API_KEY }
)
data = response.json()
print ( f "Balance: { data[ 'balance' ] } " ) # Direct access
// 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 ); // For debugging
console . log ( "Timestamp:" , result . meta . timestamp ); // Response time
} else {
console . error ( "Error:" , result . error . message );
}
// Updated v3 code:
$ch = curl_init ( 'https://api.oneclickdz.com/v3/account/balance' );
curl_setopt ( $ch , CURLOPT_HTTPHEADER , [ 'X-Access-Token: ' . $apiKey ]);
curl_setopt ( $ch , CURLOPT_RETURNTRANSFER , true );
$response = curl_exec ( $ch );
$result = json_decode ( $response , true );
if ( $result [ 'success' ]) {
echo "Balance: " . $result [ 'data' ][ 'balance' ] . " \n " ;
echo "Request ID: " . $result [ 'requestId' ] . " \n " ;
echo "Timestamp: " . $result [ 'meta' ][ 'timestamp' ] . " \n " ;
} else {
error_log ( "Error: " . $result [ 'error' ][ 'message' ]);
}
# Updated v3 code:
response = requests.get(
'https://api.oneclickdz.com/v3/account/balance' ,
headers = { 'X-Access-Token' : API_KEY }
)
result = response.json()
if result[ 'success' ]:
print ( f "Balance: { result[ 'data' ][ 'balance' ] } " )
print ( f "Request ID: { result[ 'requestId' ] } " ) # For debugging
print ( f "Timestamp: { result[ 'meta' ][ 'timestamp' ] } " )
else :
print ( f "Error: { result[ 'error' ][ 'message' ] } " )
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
}
// Your current v2 code:
$ch = curl_init ( 'https://flexy-api.oneclickdz.com/v2/topup/sendTopup' );
curl_setopt ( $ch , CURLOPT_POST , true );
curl_setopt ( $ch , CURLOPT_POSTFIELDS , json_encode ( $data ));
curl_setopt ( $ch , CURLOPT_HTTPHEADER , [
'Content-Type: application/json' ,
'authorization: ' . $apiKey
]);
curl_setopt ( $ch , CURLOPT_RETURNTRANSFER , true );
$response = curl_exec ( $ch );
$result = json_decode ( $response , true );
if ( isset ( $result [ 'error' ])) {
error_log ( "Error: " . $result [ 'message' ]); // Simple string
}
# Your current v2 code:
response = requests.post(
'https://flexy-api.oneclickdz.com/v2/topup/sendTopup' ,
headers = {
'Content-Type' : 'application/json' ,
'authorization' : API_KEY
},
json = data
)
result = response.json()
if 'error' in result:
print ( f "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." );
}
}
// Updated v3 code:
$ch = curl_init ( 'https://api.oneclickdz.com/v3/mobile/send' );
curl_setopt ( $ch , CURLOPT_POST , true );
curl_setopt ( $ch , CURLOPT_POSTFIELDS , json_encode ( $data ));
curl_setopt ( $ch , CURLOPT_HTTPHEADER , [
'Content-Type: application/json' ,
'X-Access-Token: ' . $apiKey
]);
curl_setopt ( $ch , CURLOPT_RETURNTRANSFER , true );
$response = curl_exec ( $ch );
$result = json_decode ( $response , true );
if ( ! $result [ 'success' ]) {
$errorCode = $result [ 'error' ][ 'code' ];
$errorMessage = $result [ 'error' ][ 'message' ];
error_log ( "Error [{ $errorCode }]: { $errorMessage }" );
error_log ( "Request ID: " . $result [ 'requestId' ]);
// Handle specific errors
switch ( $errorCode ) {
case 'INSUFFICIENT_BALANCE' :
echo "Please top up your account \n " ;
break ;
case 'ERR_PHONE' :
echo "Invalid phone number: { $errorMessage } \n " ;
if ( isset ( $result [ 'error' ][ 'details' ][ 'pattern' ])) {
echo "Expected format: " . $result [ 'error' ][ 'details' ][ 'pattern' ] . " \n " ;
}
break ;
case 'DUPLICATED_REF' :
echo "This order reference was already used \n " ;
break ;
default :
echo "An error occurred. Please try again \n " ;
}
}
# Updated v3 code:
response = requests.post(
'https://api.oneclickdz.com/v3/mobile/send' ,
headers = {
'Content-Type' : 'application/json' ,
'X-Access-Token' : API_KEY
},
json = data
)
result = response.json()
if not result[ 'success' ]:
error_code = result[ 'error' ][ 'code' ]
error_message = result[ 'error' ][ 'message' ]
print ( f "Error [ { error_code } ]: { error_message } " )
print ( f "Request ID: { result[ 'requestId' ] } " )
# Handle specific errors
if error_code == 'INSUFFICIENT_BALANCE' :
print ( "Please top up your account" )
elif error_code == 'ERR_PHONE' :
print ( f "Invalid phone number: { error_message } " )
if 'pattern' in result[ 'error' ].get( 'details' , {}):
print ( f "Expected format: { result[ 'error' ][ 'details' ][ 'pattern' ] } " )
elif error_code == 'DUPLICATED_REF' :
print ( "This order reference was already used" )
else :
print ( "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 ;
$ch = curl_init ( 'https://flexy-api.oneclickdz.com/v2/plans/listAll' );
curl_setopt ( $ch , CURLOPT_HTTPHEADER , [ 'authorization: ' . $apiKey ]);
curl_setopt ( $ch , CURLOPT_RETURNTRANSFER , true );
$response = curl_exec ( $ch );
$data = json_decode ( $response , true );
$dynamicPlans = $data [ 'dymanicPlans' ]; // Note: typo in v2
$fixedPlans = $data [ 'fixedPlans' ];
response = requests.get(
'https://flexy-api.oneclickdz.com/v2/plans/listAll' ,
headers = { 'authorization' : API_KEY }
)
data = response.json()
dynamic_plans = data[ 'dymanicPlans' ] # Note: typo in v2
fixed_plans = data[ 'fixedPlans' ]
Step 2 - What to change:
Change base URL: https://flexy-api.oneclickdz.com → https://api.oneclickdz.com
Change endpoint: /v2/plans/listAll → /v3/mobile/plans
Change header: authorization → X-Access-Token
Add success check: if (result.success)
Access through data: data.dymanicPlans → result.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 ;
}
$ch = curl_init ( 'https://api.oneclickdz.com/v3/mobile/plans' );
curl_setopt ( $ch , CURLOPT_HTTPHEADER , [ 'X-Access-Token: ' . $apiKey ]);
curl_setopt ( $ch , CURLOPT_RETURNTRANSFER , true );
$response = curl_exec ( $ch );
$result = json_decode ( $response , true );
if ( $result [ 'success' ]) {
$dynamicPlans = $result [ 'data' ][ 'dynamicPlans' ]; // Typo fixed!
$fixedPlans = $result [ 'data' ][ 'fixedPlans' ];
}
response = requests.get(
'https://api.oneclickdz.com/v3/mobile/plans' ,
headers = { 'X-Access-Token' : API_KEY }
)
result = response.json()
if result[ 'success' ]:
dynamic_plans = result[ 'data' ][ 'dynamicPlans' ] # Typo fixed!
fixed_plans = 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 );
$data = [
'plan_code' => 'PREPAID_DJEZZY' ,
'MSSIDN' => '0778037340' ,
'amount' => 500 ,
'ref' => 'order-123'
];
$ch = curl_init ( 'https://flexy-api.oneclickdz.com/v2/topup/sendTopup' );
curl_setopt ( $ch , CURLOPT_POST , true );
curl_setopt ( $ch , CURLOPT_POSTFIELDS , json_encode ( $data ));
curl_setopt ( $ch , CURLOPT_HTTPHEADER , [
'Content-Type: application/json' ,
'authorization: ' . $apiKey
]);
curl_setopt ( $ch , CURLOPT_RETURNTRANSFER , true );
$response = curl_exec ( $ch );
$result = json_decode ( $response , true );
echo "Topup ID: " . $result [ 'topupId' ] . " \n " ;
echo "New Balance: " . $result [ 'newBalance' ] . " \n " ;
data = {
'plan_code' : 'PREPAID_DJEZZY' ,
'MSSIDN' : '0778037340' ,
'amount' : 500 ,
'ref' : 'order-123'
}
response = requests.post(
'https://flexy-api.oneclickdz.com/v2/topup/sendTopup' ,
headers = {
'Content-Type' : 'application/json' ,
'authorization' : API_KEY
},
json = data
)
result = response.json()
print ( f "Topup ID: { result[ 'topupId' ] } " )
print ( f "New Balance: { result[ 'newBalance' ] } " )
Step 2 - What to change:
Change base URL: https://flexy-api.oneclickdz.com → https://api.oneclickdz.com
Change endpoint: /v2/topup/sendTopup → /v3/mobile/send
Change header: authorization → X-Access-Token
Add success check: if (result.success)
Access through data: data.topupId → result.data.topupId
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 );
}
// ...existing code...
$ch = curl_init ( 'https://api.oneclickdz.com/v3/mobile/send' );
curl_setopt ( $ch , CURLOPT_POST , true );
curl_setopt ( $ch , CURLOPT_POSTFIELDS , json_encode ( $data ));
curl_setopt ( $ch , CURLOPT_HTTPHEADER , [
'Content-Type: application/json' ,
'X-Access-Token: ' . $apiKey
]);
curl_setopt ( $ch , CURLOPT_RETURNTRANSFER , true );
$response = curl_exec ( $ch );
$result = json_decode ( $response , true );
if ( $result [ 'success' ]) {
echo "✅ Top-up sent successfully! \n " ;
echo "Topup ID: " . $result [ 'data' ][ 'topupId' ] . " \n " ;
echo "New Balance: " . $result [ 'data' ][ 'newBalance' ] . " \n " ;
echo "Request ID: " . $result [ 'requestId' ] . " \n " ;
} else {
error_log ( "❌ Error [{ $result ['error']['code']}]: { $result ['error']['message']}" );
error_log ( "Request ID: " . $result [ 'requestId' ]);
}
# ...existing code...
response = requests.post(
'https://api.oneclickdz.com/v3/mobile/send' ,
headers = {
'Content-Type' : 'application/json' ,
'X-Access-Token' : API_KEY
},
json = data
)
result = response.json()
if result[ 'success' ]:
print ( "✅ Top-up sent successfully!" )
print ( f "Topup ID: { result[ 'data' ][ 'topupId' ] } " )
print ( f "New Balance: { result[ 'data' ][ 'newBalance' ] } " )
print ( f "Request ID: { result[ 'requestId' ] } " )
else :
print ( f "❌ Error [ { result[ 'error' ][ 'code' ] } ]: { result[ 'error' ][ 'message' ] } " )
print ( f "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 );
$ch = curl_init ( 'https://flexy-api.oneclickdz.com/v2/topup/checkStatus/REF/order-123' );
curl_setopt ( $ch , CURLOPT_HTTPHEADER , [ 'authorization: ' . $apiKey ]);
curl_setopt ( $ch , CURLOPT_RETURNTRANSFER , true );
$response = curl_exec ( $ch );
$data = json_decode ( $response , true );
echo "Status: " . $data [ 'topup' ][ 'status' ] . " \n " ;
echo "Phone: " . $data [ 'topup' ][ 'MSSIDN' ] . " \n " ;
response = requests.get(
'https://flexy-api.oneclickdz.com/v2/topup/checkStatus/REF/order-123' ,
headers = { 'authorization' : API_KEY }
)
data = response.json()
print ( f "Status: { data[ 'topup' ][ 'status' ] } " )
print ( f "Phone: { data[ 'topup' ][ 'MSSIDN' ] } " )
Step 2 - What to change:
Change base URL: https://flexy-api.oneclickdz.com → https://api.oneclickdz.com
Change endpoint: /v2/topup/checkStatus/REF/:ref → /v3/mobile/check-ref/:ref
Change header: authorization → X-Access-Token
Add success check: if (result.success)
Access directly: data.topup.status → result.data.status (no more nested topup object)
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" );
}
}
$ch = curl_init ( 'https://api.oneclickdz.com/v3/mobile/check-ref/order-123' );
curl_setopt ( $ch , CURLOPT_HTTPHEADER , [ 'X-Access-Token: ' . $apiKey ]);
curl_setopt ( $ch , CURLOPT_RETURNTRANSFER , true );
$response = curl_exec ( $ch );
$result = json_decode ( $response , true );
if ( $result [ 'success' ]) {
echo "Status: " . $result [ 'data' ][ 'status' ] . " \n " ;
echo "Phone: " . $result [ 'data' ][ 'MSSIDN' ] . " \n " ;
// New in v3: Enhanced refund information
if ( $result [ 'data' ][ 'status' ] === 'REFUNDED' ) {
echo "❌ Top-up was refunded \n " ;
echo "Reason: " . $result [ 'data' ][ 'refund_message' ] . " \n " ;
if ( isset ( $result [ 'data' ][ 'suggested_offers' ])) {
echo "💡 Try these offers instead: \n " ;
print_r ( $result [ 'data' ][ 'suggested_offers' ]);
}
} elseif ( $result [ 'data' ][ 'status' ] === 'FULFILLED' ) {
echo "✅ Top-up completed successfully \n " ;
}
}
response = requests.get(
'https://api.oneclickdz.com/v3/mobile/check-ref/order-123' ,
headers = { 'X-Access-Token' : API_KEY }
)
result = response.json()
if result[ 'success' ]:
print ( f "Status: { result[ 'data' ][ 'status' ] } " )
print ( f "Phone: { result[ 'data' ][ 'MSSIDN' ] } " )
# New in v3: Enhanced refund information
if result[ 'data' ][ 'status' ] == 'REFUNDED' :
print ( "❌ Top-up was refunded" )
print ( f "Reason: { result[ 'data' ][ 'refund_message' ] } " )
if 'suggested_offers' in result[ 'data' ]:
print ( "💡 Try these offers instead:" )
print (result[ 'data' ][ 'suggested_offers' ])
elif result[ 'data' ][ 'status' ] == 'FULFILLED' :
print ( "✅ Top-up completed successfully" )
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 );
$ch = curl_init ( 'https://flexy-api.oneclickdz.com/v2/account/transactions?page=1&pageSize=20' );
curl_setopt ( $ch , CURLOPT_HTTPHEADER , [ 'authorization: ' . $apiKey ]);
curl_setopt ( $ch , CURLOPT_RETURNTRANSFER , true );
$response = curl_exec ( $ch );
$data = json_decode ( $response , true );
echo "Transactions: " . count ( $data [ 'transactions' ]) . " \n " ;
echo "Total: " . $data [ 'totalResults' ] . " \n " ;
echo "Page: " . $data [ 'currentPage' ] . " \n " ;
echo "Pages: " . $data [ 'totalPages' ] . " \n " ;
response = requests.get(
'https://flexy-api.oneclickdz.com/v2/account/transactions?page=1&pageSize=20' ,
headers = { 'authorization' : API_KEY }
)
data = response.json()
print ( f "Transactions: { len (data[ 'transactions' ]) } " )
print ( f "Total: { data[ 'totalResults' ] } " )
print ( f "Page: { data[ 'currentPage' ] } " )
print ( f "Pages: { data[ 'totalPages' ] } " )
Step 2 - What to change:
Change base URL: https://flexy-api.oneclickdz.com → https://api.oneclickdz.com
Change version: /v2/account/transactions → /v3/account/transactions
Change header: authorization → X-Access-Token
Add success check: if (result.success)
Access items: data.transactions → result.data.items
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 );
}
$ch = curl_init ( 'https://api.oneclickdz.com/v3/account/transactions?page=1&pageSize=20' );
curl_setopt ( $ch , CURLOPT_HTTPHEADER , [ 'X-Access-Token: ' . $apiKey ]);
curl_setopt ( $ch , CURLOPT_RETURNTRANSFER , true );
$response = curl_exec ( $ch );
$result = json_decode ( $response , true );
if ( $result [ 'success' ]) {
echo "Transactions: " . count ( $result [ 'data' ][ 'items' ]) . " \n " ;
echo "Total: " . $result [ 'data' ][ 'pagination' ][ 'totalResults' ] . " \n " ;
echo "Page: " . $result [ 'data' ][ 'pagination' ][ 'page' ] . " \n " ;
echo "Pages: " . $result [ 'data' ][ 'pagination' ][ 'totalPages' ] . " \n " ;
echo "Page Size: " . $result [ 'data' ][ 'pagination' ][ 'pageSize' ] . " \n " ;
}
response = requests.get(
'https://api.oneclickdz.com/v3/account/transactions?page=1&pageSize=20' ,
headers = { 'X-Access-Token' : API_KEY }
)
result = response.json()
if result[ 'success' ]:
print ( f "Transactions: { len (result[ 'data' ][ 'items' ]) } " )
print ( f "Total: { result[ 'data' ][ 'pagination' ][ 'totalResults' ] } " )
print ( f "Page: { result[ 'data' ][ 'pagination' ][ 'page' ] } " )
print ( f "Pages: { result[ 'data' ][ 'pagination' ][ 'totalPages' ] } " )
print ( f "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 } ` );
});
$ch = curl_init ( 'https://flexy-api.oneclickdz.com/v2/internet/checkCards/ADSL' );
curl_setopt ( $ch , CURLOPT_HTTPHEADER , [ 'authorization: ' . $apiKey ]);
curl_setopt ( $ch , CURLOPT_RETURNTRANSFER , true );
$response = curl_exec ( $ch );
$cards = json_decode ( $response , true ); // Direct array
foreach ( $cards as $card ) {
echo $card [ 'value' ] . " DA - Available: " . $card [ 'available' ] . " \n " ;
}
response = requests.get(
'https://flexy-api.oneclickdz.com/v2/internet/checkCards/ADSL' ,
headers = { 'authorization' : API_KEY }
)
cards = response.json() # Direct array
for card in cards:
print ( f " { card[ 'value' ] } DA - Available: { card[ 'available' ] } " )
Step 2 - What to change:
Change base URL: https://flexy-api.oneclickdz.com → https://api.oneclickdz.com
Change endpoint: /v2/internet/checkCards/:type → /v3/internet/products?type=:type
Change from path param to query param: /ADSL → ?type=ADSL
Change header: authorization → X-Access-Token
Add success check: if (result.success)
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 } ` );
});
}
$ch = curl_init ( 'https://api.oneclickdz.com/v3/internet/products?type=ADSL' );
curl_setopt ( $ch , CURLOPT_HTTPHEADER , [ 'X-Access-Token: ' . $apiKey ]);
curl_setopt ( $ch , CURLOPT_RETURNTRANSFER , true );
$response = curl_exec ( $ch );
$result = json_decode ( $response , true );
if ( $result [ 'success' ]) {
foreach ( $result [ 'data' ][ 'products' ] as $card ) {
echo $card [ 'value' ] . " DA - Available: " . $card [ 'available' ] . " \n " ;
}
}
response = requests.get(
'https://api.oneclickdz.com/v3/internet/products?type=ADSL' ,
headers = { 'X-Access-Token' : API_KEY }
)
result = response.json()
if result[ 'success' ]:
for card in result[ 'data' ][ 'products' ]:
print ( f " { 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 ),
});
}
}
class FlexyAPI {
private $apiKey ;
private $baseUrl = 'https://flexy-api.oneclickdz.com' ;
public function __construct ( $apiKey ) {
$this -> apiKey = $apiKey ;
}
private function request ( $endpoint , $options = []) {
$ch = curl_init ( $this -> baseUrl . $endpoint );
curl_setopt ( $ch , CURLOPT_HTTPHEADER , [
'authorization: ' . $this -> apiKey
]);
curl_setopt ( $ch , CURLOPT_RETURNTRANSFER , true );
if ( isset ( $options [ 'method' ]) && $options [ 'method' ] === 'POST' ) {
curl_setopt ( $ch , CURLOPT_POST , true );
curl_setopt ( $ch , CURLOPT_POSTFIELDS , $options [ 'body' ]);
}
$response = curl_exec ( $ch );
return json_decode ( $response , true );
}
public function getBalance () {
$data = $this -> request ( '/v2/account/balance' );
return $data [ 'balance' ];
}
public function sendTopup ( $params ) {
return $this -> request ( '/v2/topup/sendTopup' , [
'method' => 'POST' ,
'body' => json_encode ( $params )
]);
}
}
import requests
class FlexyAPI :
def __init__ ( self , api_key ):
self .api_key = api_key
self .base_url = 'https://flexy-api.oneclickdz.com'
def request ( self , endpoint , method = 'GET' , data = None ):
headers = { 'authorization' : self .api_key}
url = f " { self .base_url }{ endpoint } "
if method == 'GET' :
response = requests.get(url, headers = headers)
else :
headers[ 'Content-Type' ] = 'application/json'
response = requests.post(url, headers = headers, json = data)
return response.json()
def get_balance ( self ):
data = self .request( '/v2/account/balance' )
return data[ 'balance' ]
def send_topup ( self , params ):
return self .request( '/v2/topup/sendTopup' , method = 'POST' , data = params)
Step 2 - What to change:
Change base URL: https://flexy-api.oneclickdz.com → https://api.oneclickdz.com
Change header: authorization → X-Access-Token
Add response wrapper handling in request() method
Check result.success and handle errors
Update all endpoint paths to v3
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 ),
});
}
}
class FlexyAPI {
private $apiKey ;
private $baseUrl = 'https://api.oneclickdz.com' ;
public function __construct ( $apiKey ) {
$this -> apiKey = $apiKey ;
}
private function request ( $endpoint , $options = []) {
$ch = curl_init ( $this -> baseUrl . $endpoint );
$headers = [ 'X-Access-Token: ' . $this -> apiKey ]; // Changed header name
if ( isset ( $options [ 'method' ]) && $options [ 'method' ] === 'POST' ) {
curl_setopt ( $ch , CURLOPT_POST , true );
curl_setopt ( $ch , CURLOPT_POSTFIELDS , $options [ 'body' ]);
$headers [] = 'Content-Type: application/json' ;
}
curl_setopt ( $ch , CURLOPT_HTTPHEADER , $headers );
curl_setopt ( $ch , CURLOPT_RETURNTRANSFER , true );
$response = curl_exec ( $ch );
$result = json_decode ( $response , true );
// Handle v3 response wrapper
if ( ! $result [ 'success' ]) {
$error = [
'message' => $result [ 'error' ][ 'message' ],
'code' => $result [ 'error' ][ 'code' ],
'details' => $result [ 'error' ][ 'details' ] ?? null ,
'requestId' => $result [ 'requestId' ]
];
throw new Exception ( json_encode ( $error ));
}
return $result [ 'data' ]; // Return unwrapped data
}
public function getBalance () {
$data = $this -> request ( '/v3/account/balance' ); // Updated path
return $data [ 'balance' ];
}
public function sendTopup ( $params ) {
return $this -> request ( '/v3/mobile/send' , [ // Updated path
'method' => 'POST' ,
'body' => json_encode ( $params )
]);
}
}
import requests
class FlexyAPIError ( Exception ):
"""Custom exception for API errors"""
def ** init ** ( self , message, code, details= None , request_id= None ):
super (). ** init ** (message)
self .code = code
self .details = details
self .request_id = request_id
class FlexyAPI :
def ** init ** ( self , api_key):
self .api_key = api_key
self .base_url = 'https://api.oneclickdz.com'
def request ( self , endpoint , method = 'GET' , data = None ):
headers = { 'X-Access-Token' : self .api_key} # Changed header name
url = f " { self .base_url }{ endpoint } "
if method == 'GET' :
response = requests.get(url, headers = headers)
else :
headers[ 'Content-Type' ] = 'application/json'
response = requests.post(url, headers = headers, json = data)
result = response.json()
# Handle v3 response wrapper
if not result[ 'success' ]:
raise FlexyAPIError(
result[ 'error' ][ 'message' ],
result[ 'error' ][ 'code' ],
result[ 'error' ].get( 'details' ),
result[ 'requestId' ]
)
return result[ 'data' ] # Return unwrapped data
def get_balance ( self ):
data = self .request( '/v3/account/balance' ) # Updated path
return data[ 'balance' ]
def send_topup ( self , params ):
return self .request( '/v3/mobile/send' , method = 'POST' , data = params) # Updated path
Complete Endpoint Reference Service v2 Endpoint v3 Endpoint Notes Authentication Header authorization: KEYX-Access-Token: KEYHeader name changed Validate GET /v2/validateGET /v3/validateResponse wrapped Mobile List Plans GET /v2/plans/listAllGET /v3/mobile/plansPath changed, typo fixed Send Top-Up POST /v2/topup/sendTopupPOST /v3/mobile/sendPath simplified Check by Ref GET /v2/topup/checkStatus/REF/:refGET /v3/mobile/check-ref/:refPath simplified, refund info added Check by ID GET /v2/topup/checkStatus/ID/:idGET /v3/mobile/check-id/:idPath simplified List Top-Ups GET /v2/topup/listGET /v3/mobile/listPagination moved to data.pagination Internet Products GET /v2/internet/checkCards/:typeGET /v3/internet/products?type=Path param → query param Check Number GET /v2/internet/checkNumber/:t/:nGET /v3/internet/check-number?type=&number=Path params → query params Send POST /v2/internet/sendTopupPOST /v3/internet/sendPath simplified Check by Ref GET /v2/internet/checkStatus/REF/:refGET /v3/internet/check-ref/:refPath simplified Check by ID GET /v2/internet/checkStatus/ID/:idGET /v3/internet/check-id/:idPath simplified List GET /v2/internet/listGET /v3/internet/listPagination moved Gift Cards Catalog GET /v2/gift-cards/catalogueGET /v3/gift-cards/catalogSpelling fixed Check Product GET /v2/gift-cards/checkProduct/:idGET /v3/gift-cards/checkProduct/:idResponse wrapped Place Order POST /v2/gift-cards/placeOrderPOST /v3/gift-cards/placeOrderResponse wrapped Check Order GET /v2/gift-cards/checkOrder/:idGET /v3/gift-cards/checkOrder/:idResponse wrapped List Orders GET /v2/gift-cards/listGET /v3/gift-cards/listPagination moved Account Balance GET /v2/account/balanceGET /v3/account/balanceResponse wrapped Transactions GET /v2/account/transactionsGET /v3/account/transactionsPagination moved
Error Code Reference Common v2 errors and their v3 equivalents: v2 Error v3 Error Code What 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 );
}
}
// v2 way:
if ( $result [ 'error' ] === 'NO-BALANCE' ) {
// handle
}
// v3 way:
if ( ! $result [ 'success' ] && $result [ 'error' ][ 'code' ] === 'INSUFFICIENT_BALANCE' ) {
error_log ( "Request ID: " . $result [ 'requestId' ]); // Save for support
// handle with more context
if ( isset ( $result [ 'error' ][ 'details' ][ 'currentBalance' ])) {
echo "Current balance: " . $result [ 'error' ][ 'details' ][ 'currentBalance' ] . " \n " ;
}
}
# v2 way:
if result.get( 'error' ) == 'NO-BALANCE' :
# handle
# v3 way:
if not result[ 'success' ] and result[ 'error' ][ 'code' ] == 'INSUFFICIENT_BALANCE' :
print ( f "Request ID: { result[ 'requestId' ] } " ) # Save for support
# handle with more context
if 'currentBalance' in result[ 'error' ].get( 'details' , {}):
print ( f "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
Issue: Getting 401 Unauthorized Errors
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 }
Issue: Getting 'undefined' When Accessing Data
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 );
}
Issue: 404 Not Found Errors
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 );
}
// Updated v3 code:
$ch = curl_init ( 'https://api.oneclickdz.com/v3/account/balance' );
curl_setopt ( $ch , CURLOPT_HTTPHEADER , [ 'X-Access-Token: ' . $apiKey ]);
curl_setopt ( $ch , CURLOPT_RETURNTRANSFER , true );
$response = curl_exec ( $ch );
$result = json_decode ( $response , true );
if ( $result [ 'success' ]) {
echo "Balance: " . $result [ 'data' ][ 'balance' ] . " \n " ;
echo "Request ID: " . $result [ 'requestId' ] . " \n " ;
echo "Timestamp: " . $result [ 'meta' ][ 'timestamp' ] . " \n " ;
} else {
error_log ( "Error: " . $result [ 'error' ][ 'message' ]);
}
# Updated v3 code:
response = requests.get(
'https://api.oneclickdz.com/v3/account/balance' ,
headers = { 'X-Access-Token' : API_KEY }
)
result = response.json()
if result[ 'success' ]:
print ( f "Balance: { result[ 'data' ][ 'balance' ] } " )
print ( f "Request ID: { result[ 'requestId' ] } " )
print ( f "Timestamp: { result[ 'meta' ][ 'timestamp' ] } " )
else :
print ( f "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
}
// Your current v2 code:
$ch = curl_init ( 'https://flexy-api.oneclickdz.com/v2/topup/sendTopup' );
curl_setopt ( $ch , CURLOPT_POST , true );
curl_setopt ( $ch , CURLOPT_POSTFIELDS , json_encode ( $data ));
curl_setopt ( $ch , CURLOPT_HTTPHEADER , [
'Content-Type: application/json' ,
'authorization: ' . $apiKey
]);
curl_setopt ( $ch , CURLOPT_RETURNTRANSFER , true );
$response = curl_exec ( $ch );
$result = json_decode ( $response , true );
if ( isset ( $result [ 'error' ])) {
error_log ( "Error: " . $result [ 'message' ]); // Simple string
}
# Your current v2 code:
response = requests.post(
'https://flexy-api.oneclickdz.com/v2/topup/sendTopup' ,
headers = {
'Content-Type' : 'application/json' ,
'authorization' : API_KEY
},
json = data
)
result = response.json()
if 'error' in result:
print ( f "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." );
}
}
// Updated v3 code:
$ch = curl_init ( 'https://api.oneclickdz.com/v3/mobile/send' );
curl_setopt ( $ch , CURLOPT_POST , true );
curl_setopt ( $ch , CURLOPT_POSTFIELDS , json_encode ( $data ));
curl_setopt ( $ch , CURLOPT_HTTPHEADER , [
'Content-Type: application/json' ,
'X-Access-Token: ' . $apiKey
]);
curl_setopt ( $ch , CURLOPT_RETURNTRANSFER , true );
$response = curl_exec ( $ch );
$result = json_decode ( $response , true );
if ( ! $result [ 'success' ]) {
$errorCode = $result [ 'error' ][ 'code' ];
$errorMessage = $result [ 'error' ][ 'message' ];
error_log ( "Error [{ $errorCode }]: { $errorMessage }" );
error_log ( "Request ID: " . $result [ 'requestId' ]);
switch ( $errorCode ) {
case 'INSUFFICIENT_BALANCE' :
echo "Please top up your account \n " ;
break ;
case 'ERR_PHONE' :
echo "Invalid phone number: { $errorMessage } \n " ;
if ( isset ( $result [ 'error' ][ 'details' ][ 'pattern' ])) {
echo "Expected format: " . $result [ 'error' ][ 'details' ][ 'pattern' ] . " \n " ;
}
break ;
case 'DUPLICATED_REF' :
echo "This order reference was already used \n " ;
break ;
default :
echo "An error occurred. Please try again \n " ;
}
}
# Updated v3 code:
response = requests.post(
'https://api.oneclickdz.com/v3/mobile/send' ,
headers = {
'Content-Type' : 'application/json' ,
'X-Access-Token' : API_KEY
},
json = data
)
result = response.json()
if not result[ 'success' ]:
error_code = result[ 'error' ][ 'code' ]
error_message = result[ 'error' ][ 'message' ]
print ( f "Error [ { error_code } ]: { error_message } " )
print ( f "Request ID: { result[ 'requestId' ] } " )
if error_code == 'INSUFFICIENT_BALANCE' :
print ( "Please top up your account" )
elif error_code == 'ERR_PHONE' :
print ( f "Invalid phone number: { error_message } " )
if 'pattern' in result[ 'error' ].get( 'details' , {}):
print ( f "Expected format: { result[ 'error' ][ 'details' ][ 'pattern' ] } " )
elif error_code == 'DUPLICATED_REF' :
print ( "This order reference was already used" )
else :
print ( "An error occurred. 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 ;
$ch = curl_init ( 'https://flexy-api.oneclickdz.com/v2/plans/listAll' );
curl_setopt ( $ch , CURLOPT_HTTPHEADER , [ 'authorization: ' . $apiKey ]);
curl_setopt ( $ch , CURLOPT_RETURNTRANSFER , true );
$response = curl_exec ( $ch );
$data = json_decode ( $response , true );
$dynamicPlans = $data [ 'dymanicPlans' ]; // Note: typo in v2
$fixedPlans = $data [ 'fixedPlans' ];
response = requests.get(
'https://flexy-api.oneclickdz.com/v2/plans/listAll' ,
headers = { 'authorization' : API_KEY }
)
data = response.json()
dynamic_plans = data[ 'dymanicPlans' ] # Note: typo in v2
fixed_plans = data[ 'fixedPlans' ]
الخطوة 2 - ما الذي يجب تغييره:
غيّر عنوان URL الأساسي: https://flexy-api.oneclickdz.com ← https://api.oneclickdz.com
غيّر الـ endpoint: /v2/plans/listAll ← /v3/mobile/plans
غيّر الرأس: authorization ← X-Access-Token
أضف فحص النجاح: if (result.success)
الوصول عبر data: data.dymanicPlans ← result.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 ;
}
$ch = curl_init ( 'https://api.oneclickdz.com/v3/mobile/plans' );
curl_setopt ( $ch , CURLOPT_HTTPHEADER , [ 'X-Access-Token: ' . $apiKey ]);
curl_setopt ( $ch , CURLOPT_RETURNTRANSFER , true );
$response = curl_exec ( $ch );
$result = json_decode ( $response , true );
if ( $result [ 'success' ]) {
$dynamicPlans = $result [ 'data' ][ 'dynamicPlans' ]; // Typo fixed!
$fixedPlans = $result [ 'data' ][ 'fixedPlans' ];
}
response = requests.get(
'https://api.oneclickdz.com/v3/mobile/plans' ,
headers = { 'X-Access-Token' : API_KEY }
)
result = response.json()
if result[ 'success' ]:
dynamic_plans = result[ 'data' ][ 'dynamicPlans' ] # Typo fixed!
fixed_plans = 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 );
$data = [
'plan_code' => 'PREPAID_DJEZZY' ,
'MSSIDN' => '0778037340' ,
'amount' => 500 ,
'ref' => 'order-123'
];
$ch = curl_init ( 'https://flexy-api.oneclickdz.com/v2/topup/sendTopup' );
curl_setopt ( $ch , CURLOPT_POST , true );
curl_setopt ( $ch , CURLOPT_POSTFIELDS , json_encode ( $data ));
curl_setopt ( $ch , CURLOPT_HTTPHEADER , [
'Content-Type: application/json' ,
'authorization: ' . $apiKey
]);
curl_setopt ( $ch , CURLOPT_RETURNTRANSFER , true );
$response = curl_exec ( $ch );
$result = json_decode ( $response , true );
echo "Topup ID: " . $result [ 'topupId' ] . " \n " ;
echo "New Balance: " . $result [ 'newBalance' ] . " \n " ;
data = {
'plan_code' : 'PREPAID_DJEZZY' ,
'MSSIDN' : '0778037340' ,
'amount' : 500 ,
'ref' : 'order-123'
}
response = requests.post(
'https://flexy-api.oneclickdz.com/v2/topup/sendTopup' ,
headers = {
'Content-Type' : 'application/json' ,
'authorization' : API_KEY
},
json = data
)
result = response.json()
print ( f "Topup ID: { result[ 'topupId' ] } " )
print ( f "New Balance: { result[ 'newBalance' ] } " )
الخطوة 2 - ما الذي يجب تغييره:
غيّر عنوان URL الأساسي: https://flexy-api.oneclickdz.com ← https://api.oneclickdz.com
غيّر الـ endpoint: /v2/topup/sendTopup ← /v3/mobile/send
غيّر الرأس: authorization ← X-Access-Token
أضف فحص النجاح: if (result.success)
الوصول عبر data: data.topupId ← result.data.topupId
أضف معالجة شاملة للأخطاء
مهم : تعامل دائماً مع الأخطاء عند إرسال الشحن. مشاكل الشبكة أو الرصيد غير الكافي أو البيانات غير الصالحة قد تسبب الفشل. احفظ 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 );
}
$ch = curl_init ( 'https://api.oneclickdz.com/v3/mobile/send' );
curl_setopt ( $ch , CURLOPT_POST , true );
curl_setopt ( $ch , CURLOPT_POSTFIELDS , json_encode ( $data ));
curl_setopt ( $ch , CURLOPT_HTTPHEADER , [
'Content-Type: application/json' ,
'X-Access-Token: ' . $apiKey
]);
curl_setopt ( $ch , CURLOPT_RETURNTRANSFER , true );
$response = curl_exec ( $ch );
$result = json_decode ( $response , true );
if ( $result [ 'success' ]) {
echo "✅ Top-up sent successfully! \n " ;
echo "Topup ID: " . $result [ 'data' ][ 'topupId' ] . " \n " ;
echo "New Balance: " . $result [ 'data' ][ 'newBalance' ] . " \n " ;
echo "Request ID: " . $result [ 'requestId' ] . " \n " ;
} else {
error_log ( "❌ Error [{ $result ['error']['code']}]: { $result ['error']['message']}" );
error_log ( "Request ID: " . $result [ 'requestId' ]);
}
response = requests.post(
'https://api.oneclickdz.com/v3/mobile/send' ,
headers = {
'Content-Type' : 'application/json' ,
'X-Access-Token' : API_KEY
},
json = data
)
result = response.json()
if result[ 'success' ]:
print ( "✅ Top-up sent successfully!" )
print ( f "Topup ID: { result[ 'data' ][ 'topupId' ] } " )
print ( f "New Balance: { result[ 'data' ][ 'newBalance' ] } " )
print ( f "Request ID: { result[ 'requestId' ] } " )
else :
print ( f "❌ Error [ { result[ 'error' ][ 'code' ] } ]: { result[ 'error' ][ 'message' ] } " )
print ( f "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 );
$ch = curl_init ( 'https://flexy-api.oneclickdz.com/v2/topup/checkStatus/REF/order-123' );
curl_setopt ( $ch , CURLOPT_HTTPHEADER , [ 'authorization: ' . $apiKey ]);
curl_setopt ( $ch , CURLOPT_RETURNTRANSFER , true );
$response = curl_exec ( $ch );
$data = json_decode ( $response , true );
echo "Status: " . $data [ 'topup' ][ 'status' ] . " \n " ;
echo "Phone: " . $data [ 'topup' ][ 'MSSIDN' ] . " \n " ;
response = requests.get(
'https://flexy-api.oneclickdz.com/v2/topup/checkStatus/REF/order-123' ,
headers = { 'authorization' : API_KEY }
)
data = response.json()
print ( f "Status: { data[ 'topup' ][ 'status' ] } " )
print ( f "Phone: { data[ 'topup' ][ 'MSSIDN' ] } " )
الخطوة 2 - ما الذي يجب تغييره:
غيّر عنوان URL الأساسي: https://flexy-api.oneclickdz.com ← https://api.oneclickdz.com
غيّر الـ endpoint: /v2/topup/checkStatus/REF/:ref ← /v3/mobile/check-ref/:ref
غيّر الرأس: authorization ← X-Access-Token
أضف فحص النجاح: if (result.success)
الوصول المباشر: data.topup.status ← result.data.status (لا مزيد من كائن topup المتداخل)
تعامل مع حقول معلومات الاسترداد الجديدة
ميزة جديدة : يتضمن 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" );
}
}
$ch = curl_init ( 'https://api.oneclickdz.com/v3/mobile/check-ref/order-123' );
curl_setopt ( $ch , CURLOPT_HTTPHEADER , [ 'X-Access-Token: ' . $apiKey ]);
curl_setopt ( $ch , CURLOPT_RETURNTRANSFER , true );
$response = curl_exec ( $ch );
$result = json_decode ( $response , true );
if ( $result [ 'success' ]) {
echo "Status: " . $result [ 'data' ][ 'status' ] . " \n " ;
echo "Phone: " . $result [ 'data' ][ 'MSSIDN' ] . " \n " ;
// New in v3: Enhanced refund information
if ( $result [ 'data' ][ 'status' ] === 'REFUNDED' ) {
echo "❌ Top-up was refunded \n " ;
echo "Reason: " . $result [ 'data' ][ 'refund_message' ] . " \n " ;
if ( isset ( $result [ 'data' ][ 'suggested_offers' ])) {
echo "💡 Try these offers instead: \n " ;
print_r ( $result [ 'data' ][ 'suggested_offers' ]);
}
} elseif ( $result [ 'data' ][ 'status' ] === 'FULFILLED' ) {
echo "✅ Top-up completed successfully \n " ;
}
}
response = requests.get(
'https://api.oneclickdz.com/v3/mobile/check-ref/order-123' ,
headers = { 'X-Access-Token' : API_KEY }
)
result = response.json()
if result[ 'success' ]:
print ( f "Status: { result[ 'data' ][ 'status' ] } " )
print ( f "Phone: { result[ 'data' ][ 'MSSIDN' ] } " )
# New in v3: Enhanced refund information
if result[ 'data' ][ 'status' ] == 'REFUNDED' :
print ( "❌ Top-up was refunded" )
print ( f "Reason: { result[ 'data' ][ 'refund_message' ] } " )
if 'suggested_offers' in result[ 'data' ]:
print ( "💡 Try these offers instead:" )
print (result[ 'data' ][ 'suggested_offers' ])
elif result[ 'data' ][ 'status' ] == 'FULFILLED' :
print ( "✅ 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 );
$ch = curl_init ( 'https://flexy-api.oneclickdz.com/v2/account/transactions?page=1&pageSize=20' );
curl_setopt ( $ch , CURLOPT_HTTPHEADER , [ 'authorization: ' . $apiKey ]);
curl_setopt ( $ch , CURLOPT_RETURNTRANSFER , true );
$response = curl_exec ( $ch );
$data = json_decode ( $response , true );
echo "Transactions: " . count ( $data [ 'transactions' ]) . " \n " ;
echo "Total: " . $data [ 'totalResults' ] . " \n " ;
echo "Page: " . $data [ 'currentPage' ] . " \n " ;
echo "Pages: " . $data [ 'totalPages' ] . " \n " ;
response = requests.get(
'https://flexy-api.oneclickdz.com/v2/account/transactions?page=1&pageSize=20' ,
headers = { 'authorization' : API_KEY }
)
data = response.json()
print ( f "Transactions: { len (data[ 'transactions' ]) } " )
print ( f "Total: { data[ 'totalResults' ] } " )
print ( f "Page: { data[ 'currentPage' ] } " )
print ( f "Pages: { data[ 'totalPages' ] } " )
الخطوة 2 - ما الذي يجب تغييره:
غيّر عنوان URL الأساسي: https://flexy-api.oneclickdz.com ← https://api.oneclickdz.com
غيّر الإصدار: /v2/account/transactions ← /v3/account/transactions
غيّر الرأس: authorization ← X-Access-Token
أضف فحص النجاح: if (result.success)
الوصول للعناصر: data.transactions ← result.data.items
الوصول للترقيم: الحقول على مستوى الجذر ← كائن 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 );
}
$ch = curl_init ( 'https://api.oneclickdz.com/v3/account/transactions?page=1&pageSize=20' );
curl_setopt ( $ch , CURLOPT_HTTPHEADER , [ 'X-Access-Token: ' . $apiKey ]);
curl_setopt ( $ch , CURLOPT_RETURNTRANSFER , true );
$response = curl_exec ( $ch );
$result = json_decode ( $response , true );
if ( $result [ 'success' ]) {
echo "Transactions: " . count ( $result [ 'data' ][ 'items' ]) . " \n " ;
echo "Total: " . $result [ 'data' ][ 'pagination' ][ 'totalResults' ] . " \n " ;
echo "Page: " . $result [ 'data' ][ 'pagination' ][ 'page' ] . " \n " ;
echo "Pages: " . $result [ 'data' ][ 'pagination' ][ 'totalPages' ] . " \n " ;
echo "Page Size: " . $result [ 'data' ][ 'pagination' ][ 'pageSize' ] . " \n " ;
}
response = requests.get(
'https://api.oneclickdz.com/v3/account/transactions?page=1&pageSize=20' ,
headers = { 'X-Access-Token' : API_KEY }
)
result = response.json()
if result[ 'success' ]:
print ( f "Transactions: { len (result[ 'data' ][ 'items' ]) } " )
print ( f "Total: { result[ 'data' ][ 'pagination' ][ 'totalResults' ] } " )
print ( f "Page: { result[ 'data' ][ 'pagination' ][ 'page' ] } " )
print ( f "Pages: { result[ 'data' ][ 'pagination' ][ 'totalPages' ] } " )
print ( f "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 } ` );
});
$ch = curl_init ( 'https://flexy-api.oneclickdz.com/v2/internet/checkCards/ADSL' );
curl_setopt ( $ch , CURLOPT_HTTPHEADER , [ 'authorization: ' . $apiKey ]);
curl_setopt ( $ch , CURLOPT_RETURNTRANSFER , true );
$response = curl_exec ( $ch );
$cards = json_decode ( $response , true ); // Direct array
foreach ( $cards as $card ) {
echo $card [ 'value' ] . " DA - Available: " . $card [ 'available' ] . " \n " ;
}
response = requests.get(
'https://flexy-api.oneclickdz.com/v2/internet/checkCards/ADSL' ,
headers = { 'authorization' : API_KEY }
)
cards = response.json() # Direct array
for card in cards:
print ( f " { card[ 'value' ] } DA - Available: { card[ 'available' ] } " )
الخطوة 2 - ما الذي يجب تغييره:
غيّر عنوان URL الأساسي: https://flexy-api.oneclickdz.com ← https://api.oneclickdz.com
غيّر الـ endpoint: /v2/internet/checkCards/:type ← /v3/internet/products?type=:type
من معامل المسار إلى معامل الاستعلام: /ADSL ← ?type=ADSL
غيّر الرأس: authorization ← X-Access-Token
أضف فحص النجاح: if (result.success)
الوصول للمصفوفة: مصفوفة مباشرة ← 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 } ` );
});
}
$ch = curl_init ( 'https://api.oneclickdz.com/v3/internet/products?type=ADSL' );
curl_setopt ( $ch , CURLOPT_HTTPHEADER , [ 'X-Access-Token: ' . $apiKey ]);
curl_setopt ( $ch , CURLOPT_RETURNTRANSFER , true );
$response = curl_exec ( $ch );
$result = json_decode ( $response , true );
if ( $result [ 'success' ]) {
foreach ( $result [ 'data' ][ 'products' ] as $card ) {
echo $card [ 'value' ] . " DA - Available: " . $card [ 'available' ] . " \n " ;
}
}
response = requests.get(
'https://api.oneclickdz.com/v3/internet/products?type=ADSL' ,
headers = { 'X-Access-Token' : API_KEY }
)
result = response.json()
if result[ 'success' ]:
for card in result[ 'data' ][ 'products' ]:
print ( f " { 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 ),
});
}
}
class FlexyAPI {
private $apiKey ;
private $baseUrl = 'https://flexy-api.oneclickdz.com' ;
public function __construct ( $apiKey ) {
$this -> apiKey = $apiKey ;
}
private function request ( $endpoint , $options = []) {
$ch = curl_init ( $this -> baseUrl . $endpoint );
curl_setopt ( $ch , CURLOPT_HTTPHEADER , [
'authorization: ' . $this -> apiKey
]);
curl_setopt ( $ch , CURLOPT_RETURNTRANSFER , true );
if ( isset ( $options [ 'method' ]) && $options [ 'method' ] === 'POST' ) {
curl_setopt ( $ch , CURLOPT_POST , true );
curl_setopt ( $ch , CURLOPT_POSTFIELDS , $options [ 'body' ]);
}
$response = curl_exec ( $ch );
return json_decode ( $response , true );
}
public function getBalance () {
$data = $this -> request ( '/v2/account/balance' );
return $data [ 'balance' ];
}
public function sendTopup ( $params ) {
return $this -> request ( '/v2/topup/sendTopup' , [
'method' => 'POST' ,
'body' => json_encode ( $params )
]);
}
}
import requests
class FlexyAPI :
def __init__ ( self , api_key ):
self .api_key = api_key
self .base_url = 'https://flexy-api.oneclickdz.com'
def request ( self , endpoint , method = 'GET' , data = None ):
headers = { 'authorization' : self .api_key}
url = f " { self .base_url }{ endpoint } "
if method == 'GET' :
response = requests.get(url, headers = headers)
else :
headers[ 'Content-Type' ] = 'application/json'
response = requests.post(url, headers = headers, json = data)
return response.json()
def get_balance ( self ):
data = self .request( '/v2/account/balance' )
return data[ 'balance' ]
def send_topup ( self , params ):
return self .request( '/v2/topup/sendTopup' , method = 'POST' , data = params)
الخطوة 2 - ما الذي يجب تغييره:
غيّر عنوان URL الأساسي: https://flexy-api.oneclickdz.com ← https://api.oneclickdz.com
غيّر الرأس: authorization ← X-Access-Token
أضف معالجة غلاف الاستجابة في الـ method request()
تحقق من result.success وتعامل مع الأخطاء
حدّث جميع مسارات الـ endpoint إلى v3
ألقِ أخطاء منظّمة مع أكواد ومعرّفات الطلبات
أفضل الممارسات : مركِّز معالجة الأخطاء في عميل 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 ),
});
}
}
class FlexyAPI {
private $apiKey ;
private $baseUrl = 'https://api.oneclickdz.com' ;
public function __construct ( $apiKey ) {
$this -> apiKey = $apiKey ;
}
private function request ( $endpoint , $options = []) {
$ch = curl_init ( $this -> baseUrl . $endpoint );
$headers = [ 'X-Access-Token: ' . $this -> apiKey ];
if ( isset ( $options [ 'method' ]) && $options [ 'method' ] === 'POST' ) {
curl_setopt ( $ch , CURLOPT_POST , true );
curl_setopt ( $ch , CURLOPT_POSTFIELDS , $options [ 'body' ]);
$headers [] = 'Content-Type: application/json' ;
}
curl_setopt ( $ch , CURLOPT_HTTPHEADER , $headers );
curl_setopt ( $ch , CURLOPT_RETURNTRANSFER , true );
$response = curl_exec ( $ch );
$result = json_decode ( $response , true );
if ( ! $result [ 'success' ]) {
throw new Exception ( json_encode ([
'message' => $result [ 'error' ][ 'message' ],
'code' => $result [ 'error' ][ 'code' ],
'details' => $result [ 'error' ][ 'details' ] ?? null ,
'requestId' => $result [ 'requestId' ]
]));
}
return $result [ 'data' ];
}
public function getBalance () {
$data = $this -> request ( '/v3/account/balance' );
return $data [ 'balance' ];
}
public function sendTopup ( $params ) {
return $this -> request ( '/v3/mobile/send' , [
'method' => 'POST' ,
'body' => json_encode ( $params )
]);
}
}
import requests
class FlexyAPIError ( Exception ):
def __init__ ( self , message , code , details = None , request_id = None ):
super (). __init__ (message)
self .code = code
self .details = details
self .request_id = request_id
class FlexyAPI :
def __init__ ( self , api_key ):
self .api_key = api_key
self .base_url = 'https://api.oneclickdz.com'
def request ( self , endpoint , method = 'GET' , data = None ):
headers = { 'X-Access-Token' : self .api_key}
url = f " { self .base_url }{ endpoint } "
if method == 'GET' :
response = requests.get(url, headers = headers)
else :
headers[ 'Content-Type' ] = 'application/json'
response = requests.post(url, headers = headers, json = data)
result = response.json()
if not result[ 'success' ]:
raise FlexyAPIError(
result[ 'error' ][ 'message' ],
result[ 'error' ][ 'code' ],
result[ 'error' ].get( 'details' ),
result[ 'requestId' ]
)
return result[ 'data' ]
def get_balance ( self ):
data = self .request( '/v3/account/balance' )
return data[ 'balance' ]
def send_topup ( self , params ):
return self .request( '/v3/mobile/send' , method = 'POST' , data = 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 );
}
}
// v2 way:
if ( $result [ 'error' ] === 'NO-BALANCE' ) {
// handle
}
// v3 way:
if ( ! $result [ 'success' ] && $result [ 'error' ][ 'code' ] === 'INSUFFICIENT_BALANCE' ) {
error_log ( "Request ID: " . $result [ 'requestId' ]);
if ( isset ( $result [ 'error' ][ 'details' ][ 'currentBalance' ])) {
echo "Current balance: " . $result [ 'error' ][ 'details' ][ 'currentBalance' ] . " \n " ;
}
}
# v2 way:
if result.get( 'error' ) == 'NO-BALANCE' :
# handle
# v3 way:
if not result[ 'success' ] and result[ 'error' ][ 'code' ] == 'INSUFFICIENT_BALANCE' :
print ( f "Request ID: { result[ 'requestId' ] } " )
if 'currentBalance' in result[ 'error' ].get( 'details' , {}):
print ( f "Current balance: { result[ 'error' ][ 'details' ][ 'currentBalance' ] } " )
موعد نهائي حرج : بعد 30 أكتوبر 2026، ستفشل جميع طلبات API v2. خطّط لهجرتك وفقاً لذلك لتجنب انقطاع الخدمة.
مشاكل الهجرة الشائعة وحلولها
مشكلة: أخطاء 401 غير مصرح به
المشكلة : تم تغيير الـ endpoint لكن لم يتم تحديث اسم الرأس.الحل : استبدل authorization بـ X-Access-Token في جميع الطلبات.// ❌ Wrong
headers : { authorization : API_KEY }
// ✅ Correct
headers : { "X-Access-Token" : API_KEY }
مشكلة: الحصول على 'undefined' عند الوصول للبيانات
المشكلة : محاولة الوصول للبيانات مباشرة بدون المرور بـ 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 );
}
مشكلة: أخطاء 404 غير موجود
المشكلة : استخدام مسارات الـ 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الترقيم انتقل
قائمة التحقق من الاختبار قبل النشر في الإنتاج، تحقق من: تحتاج مساعدة؟
وثائق API v3 مرجع v3 الكامل والأمثلة
دليل معالجة الأخطاء أفضل الممارسات لمعالجة الأخطاء
إعدادات لوحة التحكم الوصول : سجِّل الدخول إلى لوحة التحكمإنشاء مفتاح sandbox : أنشئ مفتاحاً للاختبار الآمنالقائمة البيضاء لعناوين IP : أضف قيود IP لأمان معزّز
الدعم البريد الإلكتروني : [email protected] مهم : أدرج دائماً معرِّف الطلب عند الإبلاغ عن مشكلاتدعم الهجرة : فريقنا هنا للمساعدة! راسلنا بالبريد الإلكتروني مع “دعم هجرة API v3” في سطر الموضوع، وأدرج: - تفاصيل تطبيقك الحالي - الأخطاء المحددة (مع معرِّفات الطلبات) - نماذج الكود التي تُظهر المشكلة