> ## 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.

# Status Tracking & Polling

> Monitor internet top-up fulfillment with efficient polling strategies

## 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.

<Info>
  Poll every **5-10 seconds** until order reaches a final state: FULFILLED, REFUNDED, or QUEUED.
</Info>

## API Reference

<Card title="GET /v3/internet/check-id/{id}" icon="magnifying-glass" href="/en/api-reference/internet/check-by-id">
  Complete endpoint documentation
</Card>

## Order Status Values

<AccordionGroup>
  <Accordion title="HANDLING" icon="spinner">
    Order is processing with the operator. Typical time: 3-45 seconds. Continue polling every 5-10 seconds.
  </Accordion>

  <Accordion title="FULFILLED" icon="check-circle">
    **Success!** Card delivered. `card_code`, `num_trans`, and `date_traitement` available. Deliver to customer immediately.
  </Accordion>

  <Accordion title="QUEUED" icon="clock">
    **Scheduled for later.** Order will be processed within 12-48 hours. Not a failure - schedule recheck after 24 hours and inform customer.
  </Accordion>

  <Accordion title="REFUNDED" icon="rotate-left">
    **Failed.** Order cancelled and refunded automatically. Notify customer of failure.
  </Accordion>
</AccordionGroup>

## Basic Status Check

<CodeGroup>
  ```javascript Node.js theme={null}
  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}`);
  }
  ```

  ```python Python theme={null}
  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 PHP theme={null}
  <?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";
  }
  ?>
  ```

  ```bash cURL theme={null}
  curl https://api.oneclickdz.com/v3/internet/check-id/6901616fe9e88196b4eb64b2 \
    -H "X-Access-Token: YOUR_API_KEY"
  ```
</CodeGroup>

## Response Examples

### Handling (Processing)

```json theme={null}
{
  "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)

```json theme={null}
{
  "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)

```json theme={null}
{
  "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

<CodeGroup>
  ```javascript Node.js theme={null}
  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);
  }
  ```

  ```python Python theme={null}
  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 PHP theme={null}
  <?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";
  }
  ?>
  ```
</CodeGroup>

## Adaptive Polling Strategy

Adjust polling frequency based on elapsed time:

```javascript theme={null}
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

<CodeGroup>
  ```javascript Node.js theme={null}
  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;
    }
  }
  ```

  ```python Python theme={null}
  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 PHP theme={null}
  <?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;
      }
  }
  ?>
  ```
</CodeGroup>

## Handling QUEUED Status

<Info>
  **QUEUED orders are not failures!** They're scheduled for delivery within 12-48 hours.
</Info>

```javascript theme={null}
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);
  }
});
```

## Best Practices

<CardGroup cols={2}>
  <Card title="Poll Every 5-10 Seconds" icon="clock">
    Balance between responsiveness and API load
  </Card>

  <Card title="Handle QUEUED Properly" icon="calendar">
    Don't treat QUEUED as failure - schedule rechecks
  </Card>

  <Card title="Set Timeout Limits" icon="stopwatch">
    Fail gracefully after 5 minutes of polling
  </Card>

  <Card title="Update Database" icon="database">
    Store status changes and card details
  </Card>
</CardGroup>

## Next Steps

<CardGroup cols={3}>
  <Card title="Deliver Cards" icon="file-code" href="/en/internet-topup-guides/5-card-delivery">
    Securely deliver card codes to customers
  </Card>

  <Card title="Send Top-Ups" icon="paper-plane" href="/en/internet-topup-guides/3-sending-topups">
    Submit orders with validation
  </Card>

  <Card title="API Reference" icon="book" href="/en/api-reference/internet/check-by-id">
    Complete endpoint documentation
  </Card>

  <Card title="Overview" icon="book-open" href="/en/internet-topup-guides/overview">
    Back to integration overview
  </Card>

  <Card title="Validate Numbers" icon="check" href="/en/internet-topup-guides/2-validation">
    Verify phone numbers
  </Card>

  <Card title="Load Products" icon="list" href="/en/internet-topup-guides/1-loading-products">
    Fetch available cards
  </Card>
</CardGroup>
