Overview
After sending an internet top-up order, poll the/check-id endpoint to track status and retrieve card details when fulfilled. Most orders complete within 3-45 seconds, but some may be QUEUED for 12-48 hours.
Poll every 5-10 seconds until order reaches a final state: FULFILLED, REFUNDED, or QUEUED.
API Reference
GET /v3/internet/check-id/{id}
Complete endpoint documentation
Order Status Values
HANDLING
HANDLING
Order is processing with the operator. Typical time: 3-45 seconds. Continue polling every 5-10 seconds.
FULFILLED
FULFILLED
Success! Card delivered.
card_code, num_trans, and date_traitement available. Deliver to customer immediately.QUEUED
QUEUED
Scheduled for later. Order will be processed within 12-48 hours. Not a failure - schedule recheck after 24 hours and inform customer.
REFUNDED
REFUNDED
Failed. Order cancelled and refunded automatically. Notify customer of failure.
Basic Status Check
async function checkTopupStatus(topupId) {
const response = await fetch(
`https://api.oneclickdz.com/v3/internet/check-id/${topupId}`,
{
headers: {
"X-Access-Token": process.env.API_KEY,
},
}
);
if (!response.ok) {
throw new Error(`Failed to check status: ${response.status}`);
}
const result = await response.json();
return result.data;
}
// Usage
const topupId = "6901616fe9e88196b4eb64b2";
const order = await checkTopupStatus(topupId);
console.log(`Status: ${order.status}`);
console.log(`Type: ${order.type}`);
console.log(`Number: ${order.number}`);
if (order.card_code) {
console.log(`Card Code: ${order.card_code}`);
console.log(`Transaction: ${order.num_trans}`);
}
import requests
import os
def check_topup_status(topup_id):
response = requests.get(
f'https://api.oneclickdz.com/v3/internet/check-id/{topup_id}',
headers={'X-Access-Token': os.getenv('API_KEY')}
)
response.raise_for_status()
return response.json()['data']
# Usage
topup_id = '6901616fe9e88196b4eb64b2'
order = check_topup_status(topup_id)
print(f"Status: {order['status']}")
print(f"Type: {order['type']}")
print(f"Number: {order['number']}")
if 'card_code' in order:
print(f"Card Code: {order['card_code']}")
print(f"Transaction: {order['num_trans']}")
<?php
function checkTopupStatus($topupId) {
$url = "https://api.oneclickdz.com/v3/internet/check-id/{$topupId}";
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'X-Access-Token: ' . getenv('API_KEY')
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode !== 200) {
throw new Exception("Failed to check status: " . $httpCode);
}
$result = json_decode($response, true);
return $result['data'];
}
// Usage
$topupId = '6901616fe9e88196b4eb64b2';
$order = checkTopupStatus($topupId);
echo "Status: {$order['status']}\n";
echo "Type: {$order['type']}\n";
echo "Number: {$order['number']}\n";
if (isset($order['card_code'])) {
echo "Card Code: {$order['card_code']}\n";
echo "Transaction: {$order['num_trans']}\n";
}
?>
curl https://api.oneclickdz.com/v3/internet/check-id/6901616fe9e88196b4eb64b2 \
-H "X-Access-Token: YOUR_API_KEY"
Response Examples
Handling (Processing)
{
"success": true,
"data": {
"_id": "6901616fe9e88196b4eb64b2",
"ref": "order-123456",
"status": "HANDLING",
"type": "ADSL",
"number": "036362608",
"topup_amount": 1000,
"created_at": "2025-11-01T12:00:00.000Z"
}
}
Fulfilled (Success)
{
"success": true,
"data": {
"_id": "6901616fe9e88196b4eb64b2",
"ref": "order-123456",
"status": "FULFILLED",
"type": "ADSL",
"number": "036362608",
"topup_amount": 1000,
"card_code": "123456789012",
"num_trans": "AT-2025-12345",
"date_traitement": "2025-11-01T12:00:45.000Z",
"created_at": "2025-11-01T12:00:00.000Z"
}
}
Queued (Scheduled)
{
"success": true,
"data": {
"_id": "6901616fe9e88196b4eb64b2",
"ref": "order-123456",
"status": "QUEUED",
"type": "ADSL",
"number": "036362608",
"topup_amount": 1000,
"created_at": "2025-11-01T12:00:00.000Z"
}
}
Basic Polling Implementation
async function pollTopupUntilComplete(topupId, maxAttempts = 60) {
const pollInterval = 5000; // 5 seconds
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
console.log(`Polling attempt ${attempt}/${maxAttempts}`);
const order = await checkTopupStatus(topupId);
// Check if order reached final state
const finalStates = ['FULFILLED', 'REFUNDED', 'QUEUED'];
if (finalStates.includes(order.status)) {
console.log(`Order completed with status: ${order.status}`);
return order;
}
// Wait before next poll
if (attempt < maxAttempts) {
await new Promise(resolve => setTimeout(resolve, pollInterval));
}
}
throw new Error('Polling timeout - order still processing');
}
// Usage
try {
const order = await pollTopupUntilComplete('6901616fe9e88196b4eb64b2');
if (order.status === 'FULFILLED') {
console.log('✅ Card delivered:', order.card_code);
} else if (order.status === 'QUEUED') {
console.log('⏰ Order scheduled for later');
} else if (order.status === 'REFUNDED') {
console.log('❌ Order failed and refunded');
}
} catch (error) {
console.error('Polling failed:', error.message);
}
import time
def poll_topup_until_complete(topup_id, max_attempts=60):
poll_interval = 5 # 5 seconds
for attempt in range(1, max_attempts + 1):
print(f"Polling attempt {attempt}/{max_attempts}")
order = check_topup_status(topup_id)
# Check if order reached final state
final_states = ['FULFILLED', 'REFUNDED', 'QUEUED']
if order['status'] in final_states:
print(f"Order completed with status: {order['status']}")
return order
# Wait before next poll
if attempt < max_attempts:
time.sleep(poll_interval)
raise Exception('Polling timeout - order still processing')
# Usage
try:
order = poll_topup_until_complete('6901616fe9e88196b4eb64b2')
if order['status'] == 'FULFILLED':
print(f"✅ Card delivered: {order['card_code']}")
elif order['status'] == 'QUEUED':
print('⏰ Order scheduled for later')
elif order['status'] == 'REFUNDED':
print('❌ Order failed and refunded')
except Exception as e:
print(f"Polling failed: {e}")
<?php
function pollTopupUntilComplete($topupId, $maxAttempts = 60) {
$pollInterval = 5; // 5 seconds
for ($attempt = 1; $attempt <= $maxAttempts; $attempt++) {
error_log("Polling attempt {$attempt}/{$maxAttempts}");
$order = checkTopupStatus($topupId);
// Check if order reached final state
$finalStates = ['FULFILLED', 'REFUNDED', 'QUEUED'];
if (in_array($order['status'], $finalStates)) {
error_log("Order completed with status: {$order['status']}");
return $order;
}
// Wait before next poll
if ($attempt < $maxAttempts) {
sleep($pollInterval);
}
}
throw new Exception('Polling timeout - order still processing');
}
// Usage
try {
$order = pollTopupUntilComplete('6901616fe9e88196b4eb64b2');
if ($order['status'] === 'FULFILLED') {
echo "✅ Card delivered: {$order['card_code']}\n";
} elseif ($order['status'] === 'QUEUED') {
echo "⏰ Order scheduled for later\n";
} elseif ($order['status'] === 'REFUNDED') {
echo "❌ Order failed and refunded\n";
}
} catch (Exception $e) {
echo "Polling failed: " . $e->getMessage() . "\n";
}
?>
Adaptive Polling Strategy
Adjust polling frequency based on elapsed time:async function pollTopupAdaptive(topupId, maxDuration = 5 * 60 * 1000) {
const startTime = Date.now();
let pollInterval = 3000; // Start with 3 seconds
while (Date.now() - startTime < maxDuration) {
const order = await checkTopupStatus(topupId);
// Check for final state
const finalStates = ['FULFILLED', 'REFUNDED', 'QUEUED'];
if (finalStates.includes(order.status)) {
return order;
}
// Adaptive interval: increase as time passes
const elapsed = Date.now() - startTime;
if (elapsed > 60000) {
pollInterval = 10000; // 10 seconds after 1 minute
} else if (elapsed > 30000) {
pollInterval = 5000; // 5 seconds after 30 seconds
}
await new Promise(resolve => setTimeout(resolve, pollInterval));
}
throw new Error('Order processing timeout');
}
// Usage
const order = await pollTopupAdaptive('6901616fe9e88196b4eb64b2');
Handling Order Results
async function handleTopupResult(topupId, order) {
switch (order.status) {
case 'FULFILLED':
console.log(`✅ Order fulfilled`);
console.log(`Card: ${order.card_code}`);
console.log(`Transaction: ${order.num_trans}`);
// Update database
await db.internetOrders.updateOne(
{ topupId },
{
$set: {
status: 'FULFILLED',
cardCode: order.card_code,
numTrans: order.num_trans,
dateTraitement: order.date_traitement,
fulfilledAt: new Date()
}
}
);
// Deliver card to customer
await deliverCard(order);
break;
case 'QUEUED':
console.log(`⏰ Order scheduled for later delivery`);
// Update database
await db.internetOrders.updateOne(
{ topupId },
{
$set: {
status: 'SCHEDULED',
message: 'Card will be delivered within 48 hours',
nextCheckAt: new Date(Date.now() + 24 * 60 * 60 * 1000)
}
}
);
// Schedule recheck after 24 hours
await scheduleRecheck(topupId, 24 * 60 * 60 * 1000);
// Notify customer
await notifyCustomer(order,
'Your order is scheduled and will be delivered within 48 hours.'
);
break;
case 'REFUNDED':
console.log(`❌ Order failed and refunded`);
// Update database
await db.internetOrders.updateOne(
{ topupId },
{
$set: {
status: 'REFUNDED',
refundedAt: new Date()
}
}
);
// Notify customer of failure
await notifyCustomer(order,
'Your order could not be completed. A full refund has been issued.'
);
break;
}
}
from datetime import datetime, timedelta
async def handle_topup_result(topup_id, order):
if order['status'] == 'FULFILLED':
print('✅ Order fulfilled')
print(f"Card: {order['card_code']}")
print(f"Transaction: {order['num_trans']}")
# Update database
db.internet_orders.update_one(
{'topupId': topup_id},
{
'$set': {
'status': 'FULFILLED',
'cardCode': order['card_code'],
'numTrans': order['num_trans'],
'dateTraitement': order['date_traitement'],
'fulfilledAt': datetime.now()
}
}
)
# Deliver card to customer
await deliver_card(order)
elif order['status'] == 'QUEUED':
print('⏰ Order scheduled for later delivery')
# Update database
db.internet_orders.update_one(
{'topupId': topup_id},
{
'$set': {
'status': 'SCHEDULED',
'message': 'Card will be delivered within 48 hours',
'nextCheckAt': datetime.now() + timedelta(hours=24)
}
}
)
# Schedule recheck after 24 hours
await schedule_recheck(topup_id, 24 * 60 * 60 * 1000)
# Notify customer
await notify_customer(order,
'Your order is scheduled and will be delivered within 48 hours.'
)
elif order['status'] == 'REFUNDED':
print('❌ Order failed and refunded')
# Update database
db.internet_orders.update_one(
{'topupId': topup_id},
{
'$set': {
'status': 'REFUNDED',
'refundedAt': datetime.now()
}
}
)
# Notify customer of failure
await notify_customer(order,
'Your order could not be completed. A full refund has been issued.'
)
<?php
function handleTopupResult($topupId, $order) {
switch ($order['status']) {
case 'FULFILLED':
error_log('✅ Order fulfilled');
error_log("Card: {$order['card_code']}");
error_log("Transaction: {$order['num_trans']}");
// Update database
updateOrderStatus($topupId, 'FULFILLED', [
'cardCode' => $order['card_code'],
'numTrans' => $order['num_trans'],
'dateTraitement' => $order['date_traitement'],
'fulfilledAt' => date('Y-m-d H:i:s')
]);
// Deliver card to customer
deliverCard($order);
break;
case 'QUEUED':
error_log('⏰ Order scheduled for later delivery');
// Update database
updateOrderStatus($topupId, 'SCHEDULED', [
'message' => 'Card will be delivered within 48 hours',
'nextCheckAt' => date('Y-m-d H:i:s', time() + 24 * 60 * 60)
]);
// Schedule recheck after 24 hours
scheduleRecheck($topupId, 24 * 60 * 60);
// Notify customer
notifyCustomer($order,
'Your order is scheduled and will be delivered within 48 hours.'
);
break;
case 'REFUNDED':
error_log('❌ Order failed and refunded');
// Update database
updateOrderStatus($topupId, 'REFUNDED', [
'refundedAt' => date('Y-m-d H:i:s')
]);
// Notify customer of failure
notifyCustomer($order,
'Your order could not be completed. A full refund has been issued.'
);
break;
}
}
?>
Handling QUEUED Status
QUEUED orders are not failures! They’re scheduled for delivery within 12-48 hours.
async function scheduleRecheck(topupId, delayMs) {
// Using a job queue (e.g., Bull)
await recheckQueue.add(
'recheck-topup',
{ topupId },
{
delay: delayMs,
attempts: 3,
backoff: {
type: 'exponential',
delay: 3600000, // 1 hour
},
}
);
console.log(`Scheduled recheck for ${topupId} in ${delayMs / 1000 / 60 / 60} hours`);
}
// Worker to process rechecks
recheckQueue.process('recheck-topup', async (job) => {
const { topupId } = job.data;
const order = await checkTopupStatus(topupId);
if (order.status === 'QUEUED') {
// Still queued, schedule another check
await scheduleRecheck(topupId, 12 * 60 * 60 * 1000); // 12 hours
} else {
// Order completed
await handleTopupResult(topupId, order);
}
});
Testing Every Status in Sandbox
With a sandbox key, the number you send decides how the order behaves — so you can test each branch of your polling code without waiting on a real order. Statuses advance on their own as time passes; poll exactly as you would in production.| Number | Timeline | Use it to test |
|---|---|---|
030000001 | HANDLING → REFUNDED after 3s | Your failure/refund path |
030000002 | HANDLING → QUEUED after 3s → FULFILLED 15s later | Your QUEUED recheck path |
| any other valid number | HANDLING → FULFILLED after 3s | The happy path and card delivery |
030000000 | rejected at /send with ERR_PHONE | Your validation error path |
// Same polling loop as production — only the number changes
const { data } = await sendTopup({ type: 'ADSL', number: '030000002', value: 1000 });
await pollTopupStatus(data.topupId);
// t=0s HANDLING
// t=4s QUEUED → your recheck scheduler fires here
// t=19s FULFILLED card_code: "TESTCARD", num_trans: "TESTTRANS"
A fulfilled sandbox order returns
card_code: "TESTCARD" and num_trans: "TESTTRANS" instead of real values. Everything else — response shape, status names, polling behaviour — is identical to production.Best Practices
Poll Every 5-10 Seconds
Balance between responsiveness and API load
Handle QUEUED Properly
Don’t treat QUEUED as failure - schedule rechecks
Set Timeout Limits
Fail gracefully after 5 minutes of polling
Update Database
Store status changes and card details
Next Steps
Deliver Cards
Securely deliver card codes to customers
Send Top-Ups
Submit orders with validation
API Reference
Complete endpoint documentation
Overview
Back to integration overview
Validate Numbers
Verify phone numbers
Load Products
Fetch available cards

