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

# Phone Number Validation

> Validate ADSL and 4G phone numbers before processing orders

## Overview

Always validate phone numbers before submitting internet top-up orders. This prevents errors, reduces refunds, and improves user experience by catching format issues immediately.

<Warning>
  **Critical Step:** Validation prevents 90% of order failures. Never skip this step.
</Warning>

## API Reference

<Card title="GET /v3/internet/check-number" icon="check" href="/en/api-reference/internet/validate-number">
  Complete endpoint documentation
</Card>

## Phone Number Formats

<Tabs>
  <Tab title="ADSL">
    **Pattern:** `^0[0-9]{8}$`

    **Description:** 9 digits starting with 0

    **Valid Examples:**

    * ✅ `036362608`
    * ✅ `031417237`
    * ✅ `021123456`

    **Invalid Examples:**

    * ❌ `36362608` - Missing leading zero
    * ❌ `0363626081` - Too long (10 digits)
    * ❌ `213636362608` - Wrong format (has country code)
    * ❌ `+213636362608` - Wrong format (has +)
  </Tab>

  <Tab title="4G LTE">
    **Pattern:** `^213[0-9]{9}$`

    **Description:** 12 digits starting with 213 (country code)

    **Valid Examples:**

    * ✅ `213472731602`
    * ✅ `213665983439`
    * ✅ `213778037340`

    **Invalid Examples:**

    * ❌ `0665983439` - Missing country code
    * ❌ `665983439` - Missing country code
    * ❌ `+213665983439` - Has + symbol
    * ❌ `2136659834399` - Too long
  </Tab>
</Tabs>

## Basic Validation

<CodeGroup>
  ```javascript Node.js theme={null}
  async function validateInternetNumber(type, number) {
    const response = await fetch(
      `https://api.oneclickdz.com/v3/internet/check-number?type=${type}&number=${number}`,
      {
        headers: {
          "X-Access-Token": process.env.API_KEY,
        },
      }
    );

    if (!response.ok) {
      const error = await response.json();
      throw new Error(error.error.message);
    }

    const result = await response.json();
    return result.data;
  }

  // Usage
  try {
    await validateInternetNumber('ADSL', '036362608');
    console.log('✅ Number is valid');
  } catch (error) {
    console.error('❌ Validation failed:', error.message);
  }
  ```

  ```python Python theme={null}
  import requests
  import os

  def validate_internet_number(service_type, number):
      response = requests.get(
          'https://api.oneclickdz.com/v3/internet/check-number',
          headers={'X-Access-Token': os.getenv('API_KEY')},
          params={'type': service_type, 'number': number}
      )
      
      if not response.ok:
          error = response.json()
          raise ValueError(error['error']['message'])
      
      return response.json()['data']

  # Usage
  try:
      validate_internet_number('ADSL', '036362608')
      print('✅ Number is valid')
  except ValueError as e:
      print(f'❌ Validation failed: {e}')
  ```

  ```php PHP theme={null}
  <?php

  function validateInternetNumber($type, $number) {
      $url = "https://api.oneclickdz.com/v3/internet/check-number";
      $url .= "?type=" . urlencode($type) . "&number=" . urlencode($number);
      
      $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) {
          $error = json_decode($response, true);
          throw new Exception($error['error']['message']);
      }
      
      return json_decode($response, true)['data'];
  }

  // Usage
  try {
      validateInternetNumber('ADSL', '036362608');
      echo "✅ Number is valid\n";
  } catch (Exception $e) {
      echo "❌ Validation failed: " . $e->getMessage() . "\n";
  }
  ?>
  ```

  ```bash cURL theme={null}
  # Validate ADSL number
  curl "https://api.oneclickdz.com/v3/internet/check-number?type=ADSL&number=036362608" \
    -H "X-Access-Token: YOUR_API_KEY"

  # Validate 4G number
  curl "https://api.oneclickdz.com/v3/internet/check-number?type=4G&number=213665983439" \
    -H "X-Access-Token: YOUR_API_KEY"
  ```
</CodeGroup>

## Client-Side Format Validation

Validate format client-side first for instant feedback:

<CodeGroup>
  ```javascript Node.js theme={null}
  function validateADSLFormat(number) {
    const pattern = /^0[0-9]{8}$/;
    return pattern.test(number);
  }

  function validate4GFormat(number) {
    const pattern = /^213[0-9]{9}$/;
    return pattern.test(number);
  }

  function validateFormat(type, number) {
    if (type === 'ADSL') {
      return validateADSLFormat(number);
    } else if (type === '4G') {
      return validate4GFormat(number);
    }
    return false;
  }

  // Usage
  const number = '036362608';
  const type = 'ADSL';

  if (!validateFormat(type, number)) {
    console.error('Invalid format. Please check the number.');
  } else {
    // Format is correct, now validate with API
    await validateInternetNumber(type, number);
  }
  ```

  ```python Python theme={null}
  import re

  def validate_adsl_format(number):
      pattern = r'^0[0-9]{8}$'
      return bool(re.match(pattern, number))

  def validate_4g_format(number):
      pattern = r'^213[0-9]{9}$'
      return bool(re.match(pattern, number))

  def validate_format(service_type, number):
      if service_type == 'ADSL':
          return validate_adsl_format(number)
      elif service_type == '4G':
          return validate_4g_format(number)
      return False

  # Usage
  number = '036362608'
  service_type = 'ADSL'

  if not validate_format(service_type, number):
      print('Invalid format. Please check the number.')
  else:
      # Format is correct, now validate with API
      validate_internet_number(service_type, number)
  ```

  ```php PHP theme={null}
  <?php

  function validateADSLFormat($number) {
      return preg_match('/^0[0-9]{8}$/', $number) === 1;
  }

  function validate4GFormat($number) {
      return preg_match('/^213[0-9]{9}$/', $number) === 1;
  }

  function validateFormat($type, $number) {
      if ($type === 'ADSL') {
          return validateADSLFormat($number);
      } elseif ($type === '4G') {
          return validate4GFormat($number);
      }
      return false;
  }

  // Usage
  $number = '036362608';
  $type = 'ADSL';

  if (!validateFormat($type, $number)) {
      echo "Invalid format. Please check the number.\n";
  } else {
      // Format is correct, now validate with API
      validateInternetNumber($type, $number);
  }
  ?>
  ```
</CodeGroup>

## Complete Validation Flow

<CodeGroup>
  ```javascript Node.js theme={null}
  async function validateCompleteFlow(type, number) {
    // Step 1: Validate service type
    if (!['ADSL', '4G'].includes(type)) {
      return {
        valid: false,
        error: 'INVALID_TYPE',
        message: 'Service type must be ADSL or 4G'
      };
    }

    // Step 2: Client-side format check
    if (!validateFormat(type, number)) {
      return {
        valid: false,
        error: 'INVALID_FORMAT',
        message: type === 'ADSL' 
          ? 'ADSL numbers must be 9 digits starting with 0 (e.g., 036362608)'
          : '4G numbers must be 12 digits starting with 213 (e.g., 213665983439)'
      };
    }

    // Step 3: API validation
    try {
      await validateInternetNumber(type, number);
      return {
        valid: true,
        type,
        number
      };
    } catch (error) {
      return {
        valid: false,
        error: 'API_VALIDATION_FAILED',
        message: error.message
      };
    }
  }

  // Usage
  const result = await validateCompleteFlow('ADSL', '036362608');

  if (!result.valid) {
    console.error(`Validation failed: ${result.message}`);
  } else {
    console.log('✅ Ready to place order');
  }
  ```

  ```python Python theme={null}
  async def validate_complete_flow(service_type, number):
      # Step 1: Validate service type
      if service_type not in ['ADSL', '4G']:
          return {
              'valid': False,
              'error': 'INVALID_TYPE',
              'message': 'Service type must be ADSL or 4G'
          }
      
      # Step 2: Client-side format check
      if not validate_format(service_type, number):
          message = (
              'ADSL numbers must be 9 digits starting with 0 (e.g., 036362608)'
              if service_type == 'ADSL'
              else '4G numbers must be 12 digits starting with 213 (e.g., 213665983439)'
          )
          return {
              'valid': False,
              'error': 'INVALID_FORMAT',
              'message': message
          }
      
      # Step 3: API validation
      try:
          validate_internet_number(service_type, number)
          return {
              'valid': True,
              'type': service_type,
              'number': number
          }
      except Exception as e:
          return {
              'valid': False,
              'error': 'API_VALIDATION_FAILED',
              'message': str(e)
          }

  # Usage
  result = await validate_complete_flow('ADSL', '036362608')

  if not result['valid']:
      print(f"Validation failed: {result['message']}")
  else:
      print('✅ Ready to place order')
  ```

  ```php PHP theme={null}
  <?php

  function validateCompleteFlow($type, $number) {
      // Step 1: Validate service type
      if (!in_array($type, ['ADSL', '4G'])) {
          return [
              'valid' => false,
              'error' => 'INVALID_TYPE',
              'message' => 'Service type must be ADSL or 4G'
          ];
      }
      
      // Step 2: Client-side format check
      if (!validateFormat($type, $number)) {
          $message = $type === 'ADSL'
              ? 'ADSL numbers must be 9 digits starting with 0 (e.g., 036362608)'
              : '4G numbers must be 12 digits starting with 213 (e.g., 213665983439)';
          
          return [
              'valid' => false,
              'error' => 'INVALID_FORMAT',
              'message' => $message
          ];
      }
      
      // Step 3: API validation
      try {
          validateInternetNumber($type, $number);
          return [
              'valid' => true,
              'type' => $type,
              'number' => $number
          ];
      } catch (Exception $e) {
          return [
              'valid' => false,
              'error' => 'API_VALIDATION_FAILED',
              'message' => $e->getMessage()
          ];
      }
  }

  // Usage
  $result = validateCompleteFlow('ADSL', '036362608');

  if (!$result['valid']) {
      echo "Validation failed: {$result['message']}\n";
  } else {
      echo "✅ Ready to place order\n";
  }
  ?>
  ```
</CodeGroup>

## Validation Caching

Cache successful validations briefly to reduce API calls:

```javascript theme={null}
class ValidationCache {
  constructor(ttlSeconds = 300) { // 5 minutes
    this.cache = new Map();
    this.ttl = ttlSeconds * 1000;
  }

  async validate(type, number) {
    const key = `${type}:${number}`;
    const cached = this.cache.get(key);
    const now = Date.now();

    // Return cached if valid
    if (cached && (now - cached.timestamp) < this.ttl) {
      return cached.result;
    }

    // Validate with API
    try {
      const result = await validateInternetNumber(type, number);
      this.cache.set(key, {
        result: { valid: true, ...result },
        timestamp: now,
      });
      return { valid: true, ...result };
    } catch (error) {
      // Don't cache failures
      throw error;
    }
  }

  invalidate(type, number) {
    const key = `${type}:${number}`;
    this.cache.delete(key);
  }
}

// Usage
const validationCache = new ValidationCache(300); // 5 minutes

// First call - validates with API
const result1 = await validationCache.validate('ADSL', '036362608');

// Second call within 5 minutes - returns cached
const result2 = await validationCache.validate('ADSL', '036362608');
```

## User-Friendly Error Messages

Provide clear feedback based on error type:

```javascript theme={null}
function getValidationErrorMessage(type, error) {
  const messages = {
    INVALID_TYPE: 'Please select either ADSL or 4G service type.',
    
    INVALID_FORMAT: {
      ADSL: 'Please enter a valid ADSL number (9 digits starting with 0).\nExample: 036362608',
      '4G': 'Please enter a valid 4G number (12 digits starting with 213).\nExample: 213665983439'
    },
    
    API_VALIDATION_FAILED: {
      default: 'This number is not valid for the selected service type.',
      'ERR_PHONE': 'This number cannot be used for internet recharge.'
    }
  };
  
  if (error === 'INVALID_FORMAT') {
    return messages.INVALID_FORMAT[type];
  }
  
  if (error === 'API_VALIDATION_FAILED') {
    return messages.API_VALIDATION_FAILED.default;
  }
  
  return messages[error] || 'Unable to validate number. Please try again.';
}
```

## Best Practices

<CardGroup cols={2}>
  <Card title="Validate Early" icon="bolt">
    Check format client-side before API call
  </Card>

  <Card title="Clear Messages" icon="message">
    Show specific, helpful error messages
  </Card>

  <Card title="Cache Results" icon="database">
    Cache valid numbers for 5 minutes
  </Card>

  <Card title="Visual Feedback" icon="eye">
    Show real-time validation status as user types
  </Card>
</CardGroup>

## Testing Validation

```javascript theme={null}
async function testValidation() {
  const testCases = [
    // ADSL tests
    { type: 'ADSL', number: '036362608', expected: true },
    { type: 'ADSL', number: '031417237', expected: true },
    { type: 'ADSL', number: '36362608', expected: false },  // Missing 0
    { type: 'ADSL', number: '0363626081', expected: false }, // Too long
    
    // 4G tests
    { type: '4G', number: '213665983439', expected: true },
    { type: '4G', number: '213472731602', expected: true },
    { type: '4G', number: '0665983439', expected: false },   // Wrong format
    { type: '4G', number: '+213665983439', expected: false }, // Has +
  ];

  console.log('🧪 Testing validation...\n');

  for (const test of testCases) {
    const result = await validateCompleteFlow(test.type, test.number);
    const passed = result.valid === test.expected;
    
    console.log(
      `${passed ? '✅' : '❌'} ${test.type} ${test.number}: ${result.valid ? 'VALID' : 'INVALID'}`
    );
    
    if (!passed) {
      console.log(`  Expected: ${test.expected}, Got: ${result.valid}`);
      if (!result.valid) {
        console.log(`  Error: ${result.message}`);
      }
    }
  }
}
```

## Next Steps

<CardGroup cols={3}>
  <Card title="Send Top-Ups" icon="paper-plane" href="/en/internet-topup-guides/3-sending-topups">
    Submit validated orders
  </Card>

  <Card title="Track Status" icon="chart-line" href="/en/internet-topup-guides/4-status-tracking">
    Monitor order fulfillment
  </Card>

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

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

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

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