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

# Partenaires et comptes

> Vérifiez la disponibilité des facturiers et construisez un identifiant de compte valide

## Vue d'ensemble

Avant de pouvoir découvrir quoi que ce soit, deux choses doivent être correctes : le facturier doit être disponible, et l'identifiant de compte doit être celui que ce facturier comprend. Cette étape couvre les deux, ainsi que la différence entre les deux erreurs que vous verrez lorsque le second est erroné.

<Note>
  Tout sur cette page utilise `https://billapi.oneclickdz.com` et l'en-tête `X-Access-Token`. Si vous n'avez pas confirmé à quel environnement appartient votre clé, commencez par [Valider la clé API](/fr/api-reference/bill-payment/validate-key).
</Note>

## Vérifier la disponibilité

`GET /v3/partners` renvoie une entrée par facturier, chacune avec un unique champ `status`.

<CodeGroup>
  ```bash cURL theme={null}
  curl https://billapi.oneclickdz.com/v3/partners \
    -H "X-Access-Token: YOUR_API_KEY"
  ```

  ```javascript Node.js theme={null}
  const response = await fetch("https://billapi.oneclickdz.com/v3/partners", {
    headers: { "X-Access-Token": process.env.ONECLICKDZ_API_KEY },
  });

  const body = await response.json();
  if (!body.success) throw new Error(body.error.code);

  const available = Object.entries(body.data)
    .filter(([, partner]) => partner.status === "ACTIVE")
    .map(([name]) => name);

  console.log(available);
  ```

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

  response = requests.get(
      'https://billapi.oneclickdz.com/v3/partners',
      headers={'X-Access-Token': os.getenv('ONECLICKDZ_API_KEY')}
  )

  body = response.json()
  if not body['success']:
      raise RuntimeError(body['error']['code'])

  available = [
      name for name, partner in body['data'].items()
      if partner['status'] == 'ACTIVE'
  ]

  print(available)
  ```

  ```php PHP theme={null}
  <?php
  $ch = curl_init('https://billapi.oneclickdz.com/v3/partners');
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  curl_setopt($ch, CURLOPT_HTTPHEADER, [
      'X-Access-Token: ' . getenv('ONECLICKDZ_API_KEY')
  ]);

  $body = json_decode(curl_exec($ch), true);
  curl_close($ch);

  if (!$body['success']) {
      throw new Exception($body['error']['code']);
  }

  $available = array_keys(array_filter(
      $body['data'],
      fn($partner) => $partner['status'] === 'ACTIVE'
  ));

  print_r($available);
  ?>
  ```
</CodeGroup>

```json theme={null}
{
  "success": true,
  "data": {
    "ADE": { "status": "ACTIVE" },
    "SONELGAZ": { "status": "ACTIVE" },
    "SEAAL": { "status": "UNAVAILABLE" },
    "AADL": { "status": "UNAVAILABLE" },
    "Algérie Télécom": { "status": "ACTIVE" }
  },
  "meta": { "timestamp": "2026-08-31T10:15:32.194Z" },
  "requestId": "req_9f3a1c72e0b84d51aB3xZq07"
}
```

Un facturier marqué `UNAVAILABLE` répond `503 PARTNER_UNAVAILABLE` à la découverte comme au paiement. `SEAAL` et `AADL` sont actuellement `UNAVAILABLE` en sandbox comme en production — c'est le réglage actuel de l'opérateur, pas une limitation permanente, alors gardez-les dans votre code et laissez la carte décider de ce qu'il faut afficher.

<Warning>
  Une clé `PRODUCTION` voit la disponibilité réelle ; une clé `SANDBOX` voit une carte figée, parce qu'une requête sandbox n'atteint jamais un facturier. N'utilisez pas le sandbox pour tester la réaction de votre application à la panne d'un facturier — utilisez les [scénarios sandbox](/fr/bill-payment-guides/6-sandbox-testing) dédiés pour cela.
</Warning>

## L'identifiant de chaque facturier

Envoyez exactement un identifiant, et envoyez le champ qui correspond au facturier que vous interrogez. L'API renvoie ce même champ dans `account` sur chaque transaction pour ce facturier.

| Partenaire        | Champ            | Format                                                   | Exemple valide                |
| ----------------- | ---------------- | -------------------------------------------------------- | ----------------------------- |
| `ADE`             | `reference`      | Jusqu'à 50 caractères                                    | `"0123456789012345678901234"` |
| `SEAAL`           | `reference`      | Jusqu'à 50 caractères                                    | `"0123456789012340000000000"` |
| `SONELGAZ`        | `contractNumber` | Jusqu'à 50 caractères                                    | `"9876543210"`                |
| `AADL`            | `aadlNumber`     | Jusqu'à 50 caractères                                    | `"1112223334"`                |
| `Algérie Télécom` | `phoneNumber`    | `0` ou `+213`, puis un chiffre de 2 à 4, puis 7 chiffres | `"023456789"`                 |

```json theme={null}
{
  "partner": "ADE",
  "account": { "reference": "0123456789012345678901234" },
  "ref": "disc-inv-2026-0042"
}
```

<Note>
  Envoyez `Algérie Télécom` avec ses accents. La valeur est comparée caractère par caractère, et c'est aussi la clé que vous relisez dans la carte des partenaires.
</Note>

### Numéros de téléphone fixe

`phoneNumber` est un **fixe** algérien, pas un numéro mobile.

**Valide :**

* `"023456789"` — zéro de tête, puis un chiffre compris entre 2 et 4
* `"+213023456789"` n'est pas valide ; utilisez `"+21323456789"` ou la forme locale `"023456789"`

**Invalide :**

* `"0778037340"` — un numéro mobile, pas un fixe
* `"23456789"` — zéro de tête manquant
* `"023 45 67 89"` — contient des espaces
* `23456789` — un nombre au lieu d'une chaîne

### Les formes d'identifiant plus riches

Deux facturiers acceptent un objet plus complet lorsqu'un seul numéro ne suffit pas à identifier une facture précise. Chaque champ à l'intérieur de ces objets est obligatoire.

<AccordionGroup>
  <Accordion title="SONELGAZ — forme facture" icon="bolt">
    ```json theme={null}
    {
      "partner": "SONELGAZ",
      "account": {
        "sonelgaz": {
          "invoice_number": "9876543210",
          "amount_without_stamp": "15000",
          "ebb_key": "ABC123"
        }
      },
      "ref": "disc-inv-2026-0042"
    }
    ```

    `invoice_number` jusqu'à 20 caractères, `amount_without_stamp` jusqu'à 20, `ebb_key` jusqu'à 30.
  </Accordion>

  <Accordion title="ADE — forme facture" icon="file-lines">
    ```json theme={null}
    {
      "partner": "ADE",
      "account": {
        "ade": {
          "sub_id": "000123456789",
          "period": "07/2026",
          "amount": "12000",
          "pay_key": "1234567"
        }
      },
      "ref": "disc-inv-2026-0043"
    }
    ```

    `sub_id` exactement 12 caractères, `period` au format `MM/YYYY`, `amount` jusqu'à 20 caractères, `pay_key` exactement 7 caractères.
  </Accordion>

  <Accordion title="ADE et SEAAL — clé de 25 caractères" icon="key">
    `electronic_payment_key` est accepté comme alternative à `reference`, et doit faire **exactement 25 caractères**.

    ```json theme={null}
    {
      "partner": "ADE",
      "account": { "electronic_payment_key": "0123456789012345678901234" },
      "ref": "disc-inv-2026-0044"
    }
    ```
  </Accordion>
</AccordionGroup>

## Exactement un identifiant

L'objet `account` doit porter **un seul** identifiant, pas plus. Les champs se regroupent en quatre emplacements :

| Emplacement           | Champs                                                                |
| --------------------- | --------------------------------------------------------------------- |
| Clé de type référence | `reference`, `contractNumber`, `aadlNumber`, `electronic_payment_key` |
| Fixe                  | `phoneNumber`, `phone_number`                                         |
| Facture SONELGAZ      | `sonelgaz`                                                            |
| Facture ADE           | `ade`                                                                 |

Exactement un emplacement doit être rempli. Zéro ou deux est rejeté avant que quoi que ce soit d'autre ne se produise.

```json theme={null}
{
  "partner": "ADE",
  "account": {
    "reference": "0123456789012345678901234",
    "phoneNumber": "023456789"
  },
  "ref": "disc-inv-2026-0045"
}
```

```json theme={null}
{
  "success": false,
  "error": {
    "code": "ERR_VALIDATION",
    "message": "account must contain exactly one identifier (electronic_payment_key, phone_number, sonelgaz, or ade)",
    "details": [
      "account must contain exactly one identifier (electronic_payment_key, phone_number, sonelgaz, or ade)"
    ]
  },
  "requestId": "req_9f3a1c72e0b84d51aB3xZq07"
}
```

Valider cela de votre côté tient en une ligne, et transforme un aller-retour en une erreur de formulaire instantanée :

```javascript theme={null}
const SLOTS = [
  ["reference", "contractNumber", "aadlNumber", "electronic_payment_key"],
  ["phoneNumber", "phone_number"],
  ["sonelgaz"],
  ["ade"],
];

function hasExactlyOneIdentifier(account) {
  const filled = SLOTS.filter((slot) =>
    slot.some((field) => {
      const value = account[field];
      return value !== undefined && value !== null && value !== "";
    }),
  );

  return filled.length === 1;
}
```

## `ERR_VALIDATION` ou `INVALID_ACCOUNT` ?

Les deux sont des `400`, et ils signifient des choses très différentes.

|                           | `ERR_VALIDATION`                                                                                                      | `INVALID_ACCOUNT`                                     |
| ------------------------- | --------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------- |
| Cause                     | La requête ne correspond pas au schéma                                                                                | L'identifiant est bien formé mais inutilisable        |
| Exemples                  | Pas de `ref` ; deux identifiants ; un `electronic_payment_key` de 24 caractères ; un numéro mobile dans `phoneNumber` | Un numéro de compte que le facturier ne reconnaît pas |
| À qui la faute            | À votre intégration                                                                                                   | À la saisie de votre client                           |
| Montrer au client         | Non — journalisez-la                                                                                                  | Oui — « vérifiez le numéro sur votre facture »        |
| Réessayer sans changement | Jamais                                                                                                                | Uniquement après que le client a corrigé le numéro    |

<Warning>
  N'affichez pas les messages `ERR_VALIDATION` aux clients finaux. Ils citent des noms de champs internes comme `electronic_payment_key`, ce qui ne signifie rien pour quelqu'un qui tient une facture papier.
</Warning>

## Mettre la carte des partenaires en cache

La disponibilité change rarement, alors rafraîchissez-la sur un minuteur plutôt qu'avant chaque découverte — et continuez à servir la dernière copie valide si un rafraîchissement échoue. Une liste de facturiers vide est pire pour vos clients qu'une liste légèrement périmée.

```javascript theme={null}
let cache = { map: null, fetchedAt: 0 };
const TTL_MS = 5 * 60 * 1000;

async function getPartners() {
  if (cache.map && Date.now() - cache.fetchedAt < TTL_MS) return cache.map;

  try {
    const response = await fetch("https://billapi.oneclickdz.com/v3/partners", {
      headers: { "X-Access-Token": process.env.ONECLICKDZ_API_KEY },
    });

    const body = await response.json();
    if (body.success) cache = { map: body.data, fetchedAt: Date.now() };
  } catch {
    // Serve the previous map rather than blocking the customer.
  }

  return cache.map ?? {};
}
```

<Note>
  Le cache ne dispense pas de gérer `503 PARTNER_UNAVAILABLE` à la découverte. Un facturier peut tomber en panne entre votre dernier rafraîchissement et le moment où le client appuie sur le bouton.
</Note>

## Bonnes pratiques

<CardGroup cols={2}>
  <Card title="Validez avant d'envoyer" icon="circle-check">
    Vérifiez la règle d'emplacement et le format du fixe côté client. Cela économise un aller-retour et donne un meilleur message d'erreur.
  </Card>

  <Card title="Mettez la carte en cache pour des minutes, pas des heures" icon="database">
    Cinq minutes suffisent largement. Rafraîchissez en arrière-plan, jamais sur le chemin critique du client.
  </Card>

  <Card title="Gardez les facturiers indisponibles dans votre code" icon="toggle-on">
    `SEAAL` et `AADL` reviendront. Pilotez l'interface depuis la carte, pas depuis une liste codée en dur.
  </Card>

  <Card title="Séparez les deux 400" icon="arrows-split">
    `INVALID_ACCOUNT` est un message pour votre client. `ERR_VALIDATION` est un message pour vos logs.
  </Card>
</CardGroup>

## Étape suivante

<Card title="Étape 2 : Découverte des factures" icon="magnifying-glass-dollar" href="/fr/bill-payment-guides/2-discovering-bills">
  Envoyez une découverte, interrogez-la jusqu'à `READY`, et lisez ce qui est payable
</Card>

## Pages liées

<CardGroup cols={2}>
  <Card title="Lister les partenaires" icon="building-columns" href="/fr/api-reference/bill-payment/list-partners">
    La référence de l'endpoint
  </Card>

  <Card title="Découvrir les factures" icon="magnifying-glass-dollar" href="/fr/api-reference/bill-payment/discover-bills">
    Où l'objet account est envoyé
  </Card>

  <Card title="Vue d'ensemble du Paiement de Factures" icon="file-invoice-dollar" href="/fr/bill-payment-guides/overview">
    La carte en cinq étapes
  </Card>

  <Card title="Tests en sandbox" icon="flask" href="/fr/bill-payment-guides/6-sandbox-testing">
    Les identifiants qui produisent un résultat choisi
  </Card>
</CardGroup>
