> ## Documentation Index
> Fetch the complete documentation index at: https://docs.remita.finance/llms.txt
> Use this file to discover all available pages before exploring further.

# Erreurs

> Codes d'erreur HTTP, format des réponses et guide de débogage.

## Format des erreurs

Toutes les erreurs sont retournées en JSON :

```json theme={null}
{
  "timestamp": "2026-03-19T10:00:00Z",
  "status": 400,
  "error": "Bad Request",
  "message": "Description détaillée de l'erreur",
  "path": "/api/v1/transaction/collect"
}
```

***

## 400 — Bad Request

La requête est malformée ou contient des données invalides.

| Cause                                                              | Solution                                                        |
| ------------------------------------------------------------------ | --------------------------------------------------------------- |
| Champ obligatoire manquant (`phoneNumber`, `amount`, `externalId`) | Vérifiez que tous les champs requis sont présents               |
| `amount` négatif ou nul                                            | Le montant doit être strictement positif                        |
| `externalId` non unique                                            | Chaque transaction doit avoir un UUID unique                    |
| Format de `phoneNumber` invalide                                   | Format international sans `+` (ex : `237690000000`)             |
| `transferMethod` invalide                                          | Voir la liste des opérateurs dans [Transactions](/transactions) |
| `countryName` incohérent avec `transferMethod`                     | Ex : `OMCM` requiert `countryName: "CAMEROON"`                  |

```json theme={null}
{
  "status": 400,
  "error": "Bad Request",
  "message": "Le champ 'phoneNumber' est obligatoire",
  "path": "/api/v1/transaction/collect"
}
```

***

## 401 — Unauthorized

L'authentification a échoué.

| Cause                                   | Solution                                           |
| --------------------------------------- | -------------------------------------------------- |
| Header `apiKey` absent                  | Ajoutez le header `apiKey` à votre requête         |
| Header `apiId` absent                   | Ajoutez le header `apiId` à votre requête          |
| Token Bearer manquant ou expiré         | Renouvelez via `POST /public/refresh_token`        |
| `apiKey` invalide ou révoquée           | Régénérez votre clé API depuis l'espace partenaire |
| `apiId` ne correspond pas à la `apiKey` | Vérifiez que vous utilisez la bonne paire clé/ID   |

```json theme={null}
{
  "status": 401,
  "error": "Unauthorized",
  "message": "apiKey manquante ou invalide",
  "path": "/api/v1/transaction/collect"
}
```

***

## 403 — Forbidden

Accès refusé, même avec une authentification valide.

| Cause                                         | Solution                                                |
| --------------------------------------------- | ------------------------------------------------------- |
| Adresse IP non autorisée                      | Ajoutez votre IP à la liste blanche (espace partenaire) |
| Compte utilisateur bloqué                     | Contactez le support Remita                             |
| Application produit désactivée                | Vérifiez le statut de votre application                 |
| Service de transfert désactivé pour ce compte | Contactez le support pour activer le service            |

```json theme={null}
{
  "status": 403,
  "error": "Forbidden",
  "message": "L'adresse IP 203.0.113.42 n'est pas autorisée",
  "path": "/api/v1/transaction/collect"
}
```

***

## 404 — Not Found

La ressource demandée n'existe pas.

| Cause                                      | Solution                                        |
| ------------------------------------------ | ----------------------------------------------- |
| Transaction introuvable avec l'`id` fourni | Vérifiez l'identifiant de la transaction        |
| Endpoint inexistant                        | Vérifiez l'URL (majuscules/minuscules, slashes) |

```json theme={null}
{
  "status": 404,
  "error": "Not Found",
  "message": "Transaction 'txn_xxx' introuvable",
  "path": "/api/v1/transaction/transaction-status"
}
```

***

## 500 — Internal Server Error

Erreur interne côté Remita.

| Cause                                     | Solution                                              |
| ----------------------------------------- | ----------------------------------------------------- |
| Erreur temporaire opérateur (Orange, MTN) | Réessayez après quelques secondes                     |
| Erreur système Remita                     | Contactez le support avec le `timestamp` et le `path` |

```json theme={null}
{
  "status": 500,
  "error": "Internal Server Error",
  "message": "Erreur de communication avec l'opérateur MTN",
  "path": "/api/v1/transaction/deposit"
}
```

***

## Statuts de transaction échoués

Quand une transaction atteint le statut `FAILED` :

| Message                             | Cause probable                                               |
| ----------------------------------- | ------------------------------------------------------------ |
| `Solde insuffisant`                 | Le client n'a pas assez de solde sur son compte mobile money |
| `Numéro invalide`                   | Le numéro n'existe pas chez l'opérateur                      |
| `Transaction annulée par le client` | Le client a refusé la confirmation sur son téléphone         |
| `Timeout opérateur`                 | L'opérateur n'a pas répondu dans le délai imparti            |
| `Compte non inscrit`                | Le numéro n'est pas enregistré au service mobile money       |

***

## Gestion des erreurs — Exemples

<CodeGroup>
  ```java Java theme={null}
  HttpResponse<String> response = client.send(request,
      HttpResponse.BodyHandlers.ofString());

  switch (response.statusCode()) {
      case 200 -> System.out.println("Succès: " + response.body());
      case 400 -> System.err.println("Requête invalide: " + response.body());
      case 401 -> System.err.println("Non authentifié: vérifiez apiKey/apiId/token");
      case 403 -> System.err.println("Accès refusé: vérifiez votre IP whitelist");
      case 404 -> System.err.println("Ressource introuvable");
      case 500 -> System.err.println("Erreur serveur: réessayez plus tard");
      default  -> System.err.println("Erreur inattendue: " + response.statusCode());
  }
  ```

  ```python Python theme={null}
  def remita_collect(payload: dict) -> dict:
      response = requests.post(
          "https://api.remita.cm/api/v1/transaction/collect",
          headers={
              "apiKey": "YOUR_API_KEY",
              "apiId": "YOUR_API_ID",
              "Authorization": "Bearer YOUR_TOKEN",
          },
          json=payload
      )
      if response.status_code == 200:
          return response.json()
      elif response.status_code == 400:
          raise ValueError(f"Requête invalide: {response.json().get('message')}")
      elif response.status_code == 401:
          raise PermissionError("Non authentifié: vérifiez apiKey/apiId/token")
      elif response.status_code == 403:
          raise PermissionError("Accès refusé: vérifiez votre IP whitelist")
      elif response.status_code == 404:
          raise LookupError("Ressource introuvable")
      else:
          raise RuntimeError(f"Erreur serveur ({response.status_code}): {response.text}")
  ```

  ```php PHP theme={null}
  function remitaRequest(string $endpoint, array $data): array {
      $ch = curl_init("https://api.remita.cm$endpoint");
      curl_setopt_array($ch, [
          CURLOPT_RETURNTRANSFER => true,
          CURLOPT_POST           => true,
          CURLOPT_HTTPHEADER     => [
              'Content-Type: application/json',
              'apiKey: YOUR_API_KEY',
              'apiId: YOUR_API_ID',
              'Authorization: Bearer YOUR_TOKEN',
          ],
          CURLOPT_POSTFIELDS => json_encode($data),
      ]);
      $response = curl_exec($ch);
      $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
      curl_close($ch);
      $result = json_decode($response, true);

      match(true) {
          $httpCode === 200 => null,
          $httpCode === 400 => throw new InvalidArgumentException("Requête invalide: " . $result['message']),
          $httpCode === 401 => throw new RuntimeException("Non authentifié"),
          $httpCode === 403 => throw new RuntimeException("Accès refusé"),
          $httpCode === 404 => throw new RuntimeException("Ressource introuvable"),
          $httpCode >= 500  => throw new RuntimeException("Erreur serveur Remita"),
          default           => throw new RuntimeException("Erreur HTTP $httpCode"),
      };

      return $result;
  }
  ```
</CodeGroup>

***

## Checklist de débogage

<Check>Les headers `apiKey` et `apiId` sont présents et corrects</Check>
<Check>Le header `Authorization: Bearer <token>` est présent et non expiré</Check>
<Check>L'IP de votre serveur est dans la liste blanche</Check>
<Check>Le corps de la requête est du JSON valide (`Content-Type: application/json`)</Check>
<Check>Tous les champs obligatoires sont présents</Check>
<Check>L'`externalId` est un UUID valide et unique</Check>
<Check>Le `phoneNumber` est au format international (ex : `237690000000`)</Check>
<Check>Le `amount` est un nombre strictement positif</Check>
<Check>`transferMethod` et `countryName` sont cohérents</Check>

***

## Support

Si le problème persiste, contactez le support Remita en fournissant :

* Le `timestamp` de l'erreur
* Le `path` concerné
* Votre `apiId` (**jamais** votre `apiKey`)
* Le corps de votre requête (sans données sensibles)
