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

# Transactions

> Collectes, dépôts, vérification de statut et consultation des soldes via /api/v1/transaction.

<Note>
  **Authentification requise** : tous ces endpoints nécessitent les headers `apiKey`, `apiId` et `Authorization: Bearer <token>`.
</Note>

***

## Opérateurs disponibles

| Code       | Opérateur        | Pays          | Indicatif |
| ---------- | ---------------- | ------------- | --------- |
| `OMCM`     | Orange Money     | Cameroun      | +237      |
| `MOMOCM`   | MTN Mobile Money | Cameroun      | +237      |
| `CIWAVE`   | Wave             | Côte d'Ivoire | +225      |
| `CIOM`     | Orange Money     | Côte d'Ivoire | +225      |
| `SNWAVE`   | Wave             | Sénégal       | +221      |
| `SNOM`     | Orange Money     | Sénégal       | +221      |
| `SNFREE`   | Free             | Sénégal       | +221      |
| `BFOM`     | Orange Money     | Burkina Faso  | +226      |
| `MLMOOV`   | Moov             | Mali          | +223      |
| `BJMTN`    | MTN              | Bénin         | +229      |
| `BJMOOV`   | Moov             | Bénin         | +229      |
| `UGMTN`    | MTN              | Ouganda       | +256      |
| `UGAIRTEL` | Airtel           | Ouganda       | +256      |

***

## Corps de requête commun

Les endpoints `collect` et `deposit` utilisent le même corps :

```json theme={null}
{
  "transferMethod": "OMCM",
  "customerName": "Jean Dupont",
  "externalId": "550e8400-e29b-41d4-a716-446655440000",
  "phoneNumber": "237690000000",
  "amount": 5000,
  "webhookUrl": "https://votre-serveur.com/callback",
  "countryName": "CAMEROON"
}
```

| Champ            | Type       | Obligatoire | Description                                                                     |
| ---------------- | ---------- | ----------- | ------------------------------------------------------------------------------- |
| `transferMethod` | String     | Oui         | Code opérateur (ex : `OMCM`, `MOMOCM`)                                          |
| `customerName`   | String     | Oui         | Nom complet du client                                                           |
| `externalId`     | UUID       | Oui         | Identifiant unique côté votre système (UUID v4)                                 |
| `phoneNumber`    | String     | Oui         | Numéro en format international sans `+` (ex : `237690000000`)                   |
| `amount`         | BigDecimal | Oui         | Montant dans la devise locale (XAF, XOF, UGX…)                                  |
| `webhookUrl`     | String     | Oui         | URL de callback pour recevoir le résultat asynchrone                            |
| `countryName`    | String     | Oui         | `CAMEROON`, `IVORY_COAST`, `SENEGAL`, `BURKINA_FASO`, `MALI`, `BENIN`, `UGANDA` |

<Warning>
  `transferMethod` et `countryName` doivent être cohérents. Ex : `OMCM` + `CAMEROON`. Toute combinaison invalide retourne `400 Bad Request`.
</Warning>

***

## POST /api/v1/transaction/collect

Initie une **collecte** — débite le compte mobile money du client vers votre compte.

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://api.remita.cm/api/v1/transaction/collect \
    -H "Content-Type: application/json" \
    -H "apiKey: YOUR_API_KEY" \
    -H "apiId: YOUR_API_ID" \
    -H "Authorization: Bearer YOUR_JWT_TOKEN" \
    -d '{
      "transferMethod": "OMCM",
      "customerName": "Jean Dupont",
      "externalId": "550e8400-e29b-41d4-a716-446655440000",
      "phoneNumber": "237690000000",
      "amount": 5000,
      "webhookUrl": "https://votre-serveur.com/callback",
      "countryName": "CAMEROON"
    }'
  ```

  ```python Python theme={null}
  import requests, uuid

  response = requests.post(
      "https://api.remita.cm/api/v1/transaction/collect",
      headers={
          "apiKey": "YOUR_API_KEY",
          "apiId": "YOUR_API_ID",
          "Authorization": "Bearer YOUR_JWT_TOKEN",
      },
      json={
          "transferMethod": "OMCM",
          "customerName": "Jean Dupont",
          "externalId": str(uuid.uuid4()),
          "phoneNumber": "237690000000",
          "amount": 5000,
          "webhookUrl": "https://votre-serveur.com/callback",
          "countryName": "CAMEROON",
      }
  )
  print(response.json())
  ```

  ```php PHP theme={null}
  <?php
  $ch = curl_init('https://api.remita.cm/api/v1/transaction/collect');
  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_JWT_TOKEN',
      ],
      CURLOPT_POSTFIELDS => json_encode([
          'transferMethod' => 'OMCM',
          'customerName'   => 'Jean Dupont',
          'externalId'     => uniqid('', true),
          'phoneNumber'    => '237690000000',
          'amount'         => 5000,
          'webhookUrl'     => 'https://votre-serveur.com/callback',
          'countryName'    => 'CAMEROON',
      ]),
  ]);
  print_r(json_decode(curl_exec($ch), true));
  curl_close($ch);
  ```

  ```java Java theme={null}
  String body = """
      {
        "transferMethod": "OMCM",
        "customerName": "Jean Dupont",
        "externalId": "550e8400-e29b-41d4-a716-446655440000",
        "phoneNumber": "237690000000",
        "amount": 5000,
        "webhookUrl": "https://votre-serveur.com/callback",
        "countryName": "CAMEROON"
      }
      """;
  HttpRequest request = HttpRequest.newBuilder()
      .uri(URI.create("https://api.remita.cm/api/v1/transaction/collect"))
      .header("Content-Type", "application/json")
      .header("apiKey", "YOUR_API_KEY")
      .header("apiId", "YOUR_API_ID")
      .header("Authorization", "Bearer YOUR_JWT_TOKEN")
      .POST(HttpRequest.BodyPublishers.ofString(body))
      .build();
  System.out.println(client.send(request, HttpResponse.BodyHandlers.ofString()).body());
  ```
</CodeGroup>

### Réponse (200)

```json theme={null}
{
  "transactionId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "externalId": "550e8400-e29b-41d4-a716-446655440000",
  "transferMethod": "OMCM",
  "customerName": "Jean Dupont",
  "customerPhone": "237690000000",
  "payToken": "abc123xyz",
  "amount": 5000,
  "feesSystem": 50,
  "feesApp": 25,
  "transactionStatus": "PENDING"
}
```

***

## POST /api/v1/transaction/deposit

Initie un **dépôt** — envoie de l'argent depuis votre compte vers le mobile money d'un bénéficiaire.

Même corps de requête que `/collect`. Seul le sens du transfert change.

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://api.remita.cm/api/v1/transaction/deposit \
    -H "Content-Type: application/json" \
    -H "apiKey: YOUR_API_KEY" \
    -H "apiId: YOUR_API_ID" \
    -H "Authorization: Bearer YOUR_JWT_TOKEN" \
    -d '{
      "transferMethod": "MOMOCM",
      "customerName": "Marie Martin",
      "externalId": "660e9500-f30c-52e5-b827-557766551111",
      "phoneNumber": "237670000000",
      "amount": 10000,
      "webhookUrl": "https://votre-serveur.com/callback",
      "countryName": "CAMEROON"
    }'
  ```

  ```python Python theme={null}
  import requests, uuid

  response = requests.post(
      "https://api.remita.cm/api/v1/transaction/deposit",
      headers={
          "apiKey": "YOUR_API_KEY",
          "apiId": "YOUR_API_ID",
          "Authorization": "Bearer YOUR_JWT_TOKEN",
      },
      json={
          "transferMethod": "MOMOCM",
          "customerName": "Marie Martin",
          "externalId": str(uuid.uuid4()),
          "phoneNumber": "237670000000",
          "amount": 10000,
          "webhookUrl": "https://votre-serveur.com/callback",
          "countryName": "CAMEROON",
      }
  )
  print(response.json())
  ```
</CodeGroup>

Réponse identique à `/collect` avec `transactionStatus: "PENDING"`.

***

## POST /api/v1/transaction/depositMultiple

Initie plusieurs dépôts en une seule requête (batch).

### Corps de la requête

```json theme={null}
[
  {
    "transferMethod": "MOMOCM",
    "customerName": "Alice",
    "externalId": "uuid-1",
    "phoneNumber": "237670000001",
    "amount": 5000,
    "webhookUrl": "https://votre-serveur.com/callback",
    "countryName": "CAMEROON"
  },
  {
    "transferMethod": "OMCM",
    "customerName": "Bob",
    "externalId": "uuid-2",
    "phoneNumber": "237690000002",
    "amount": 3000,
    "webhookUrl": "https://votre-serveur.com/callback",
    "countryName": "CAMEROON"
  }
]
```

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://api.remita.cm/api/v1/transaction/depositMultiple \
    -H "Content-Type: application/json" \
    -H "apiKey: YOUR_API_KEY" \
    -H "apiId: YOUR_API_ID" \
    -H "Authorization: Bearer YOUR_JWT_TOKEN" \
    -d '[{...}, {...}]'
  ```

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

  response = requests.post(
      "https://api.remita.cm/api/v1/transaction/depositMultiple",
      headers={
          "apiKey": "YOUR_API_KEY",
          "apiId": "YOUR_API_ID",
          "Authorization": "Bearer YOUR_JWT_TOKEN",
      },
      json=[
          {
              "transferMethod": "MOMOCM", "customerName": "Alice",
              "externalId": "uuid-1", "phoneNumber": "237670000001",
              "amount": 5000, "webhookUrl": "https://votre-serveur.com/callback",
              "countryName": "CAMEROON"
          },
          {
              "transferMethod": "OMCM", "customerName": "Bob",
              "externalId": "uuid-2", "phoneNumber": "237690000002",
              "amount": 3000, "webhookUrl": "https://votre-serveur.com/callback",
              "countryName": "CAMEROON"
          }
      ]
  )
  print(response.json())
  ```
</CodeGroup>

***

## POST /api/v1/transaction/transaction-status

Vérifie le statut d'une transaction par son `transactionId`.

### Paramètres query

| Paramètre | Type | Obligatoire | Description                                    |
| --------- | ---- | ----------- | ---------------------------------------------- |
| `id`      | UUID | Oui         | `transactionId` retourné par collect / deposit |

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST "https://api.remita.cm/api/v1/transaction/transaction-status?id=3fa85f64-5717-4562-b3fc-2c963f66afa6" \
    -H "apiKey: YOUR_API_KEY" \
    -H "apiId: YOUR_API_ID" \
    -H "Authorization: Bearer YOUR_JWT_TOKEN"
  ```

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

  response = requests.post(
      "https://api.remita.cm/api/v1/transaction/transaction-status",
      headers={
          "apiKey": "YOUR_API_KEY",
          "apiId": "YOUR_API_ID",
          "Authorization": "Bearer YOUR_JWT_TOKEN",
      },
      params={"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6"}
  )
  print(response.json())
  ```
</CodeGroup>

### Réponse (200)

```json theme={null}
{
  "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "externalId": "550e8400-e29b-41d4-a716-446655440000",
  "amount": 5000,
  "feesSystem": 50,
  "feesApp": 25,
  "phoneReceiver": "237690000000",
  "receiverName": "Jean Dupont",
  "status": "SUCCESS",
  "transferMethod": "OMCM",
  "transactionType": "COLLECT",
  "countryName": "CAMEROON",
  "payToken": "abc123xyz"
}
```

### Statuts possibles

| Statut             | Description                               |
| ------------------ | ----------------------------------------- |
| `PENDING`          | Transaction initiée, en attente opérateur |
| `PENDING_APPROVAL` | En attente d'approbation interne          |
| `SUCCESS`          | Transaction réussie                       |
| `FAILED`           | Transaction échouée                       |

***

## POST /api/v1/transaction/chekTransactionStatus

Vérifie et synchronise le statut d'une transaction en interrogeant directement l'opérateur. Utile si le webhook n'a pas été reçu et que `transaction-status` retourne encore `PENDING`.

### Paramètres query

| Paramètre       | Type | Obligatoire | Description                   |
| --------------- | ---- | ----------- | ----------------------------- |
| `transactionId` | UUID | Oui         | Identifiant de la transaction |

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST "https://api.remita.cm/api/v1/transaction/chekTransactionStatus?transactionId=3fa85f64-5717-4562-b3fc-2c963f66afa6" \
    -H "apiKey: YOUR_API_KEY" \
    -H "apiId: YOUR_API_ID" \
    -H "Authorization: Bearer YOUR_JWT_TOKEN"
  ```

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

  response = requests.post(
      "https://api.remita.cm/api/v1/transaction/chekTransactionStatus",
      headers={
          "apiKey": "YOUR_API_KEY",
          "apiId": "YOUR_API_ID",
          "Authorization": "Bearer YOUR_JWT_TOKEN",
      },
      params={"transactionId": "3fa85f64-5717-4562-b3fc-2c963f66afa6"}
  )
  print(response.json())
  ```
</CodeGroup>

***

## POST /api/v1/transaction/validateTransaction

Valide et approuve une transaction en attente (`PENDING_APPROVAL`).

### Paramètres query

| Paramètre       | Type   | Obligatoire | Description                   |
| --------------- | ------ | ----------- | ----------------------------- |
| `checkerId`     | UUID   | Oui         | Identifiant du validateur     |
| `transactionId` | UUID   | Oui         | Identifiant de la transaction |
| `payeeNote`     | String | Oui         | Note de validation            |

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST "https://api.remita.cm/api/v1/transaction/validateTransaction?checkerId=<uuid>&transactionId=<uuid>&payeeNote=Approuv%C3%A9" \
    -H "apiKey: YOUR_API_KEY" \
    -H "apiId: YOUR_API_ID" \
    -H "Authorization: Bearer YOUR_JWT_TOKEN"
  ```

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

  response = requests.post(
      "https://api.remita.cm/api/v1/transaction/validateTransaction",
      headers={
          "apiKey": "YOUR_API_KEY",
          "apiId": "YOUR_API_ID",
          "Authorization": "Bearer YOUR_JWT_TOKEN",
      },
      params={
          "checkerId": "checker-uuid",
          "transactionId": "txn-uuid",
          "payeeNote": "Approuvé après vérification"
      }
  )
  print(response.json())
  ```
</CodeGroup>

***

## POST /api/v1/transaction/rejectTransaction

Rejette une transaction en attente.

### Paramètres query

| Paramètre       | Type   | Obligatoire | Description                   |
| --------------- | ------ | ----------- | ----------------------------- |
| `checkerId`     | UUID   | Oui         | Identifiant du validateur     |
| `transactionId` | UUID   | Oui         | Identifiant de la transaction |
| `reason`        | String | Oui         | Motif du rejet                |

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST "https://api.remita.cm/api/v1/transaction/rejectTransaction?checkerId=<uuid>&transactionId=<uuid>&reason=Fraude+suspect%C3%A9e" \
    -H "apiKey: YOUR_API_KEY" \
    -H "apiId: YOUR_API_ID" \
    -H "Authorization: Bearer YOUR_JWT_TOKEN"
  ```

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

  response = requests.post(
      "https://api.remita.cm/api/v1/transaction/rejectTransaction",
      headers={
          "apiKey": "YOUR_API_KEY",
          "apiId": "YOUR_API_ID",
          "Authorization": "Bearer YOUR_JWT_TOKEN",
      },
      params={
          "checkerId": "checker-uuid",
          "transactionId": "txn-uuid",
          "reason": "Fraude suspectée"
      }
  )
  print(response.json())
  ```
</CodeGroup>

***

## GET /api/v1/transaction/getByApplicationProduct

Liste toutes les transactions de votre application avec pagination.

### Paramètres query

| Paramètre | Type    | Obligatoire | Description                |
| --------- | ------- | ----------- | -------------------------- |
| `page`    | Integer | Oui         | Numéro de page (0-indexé)  |
| `size`    | Integer | Oui         | Nombre d'éléments par page |

<CodeGroup>
  ```bash cURL theme={null}
  curl -X GET "https://api.remita.cm/api/v1/transaction/getByApplicationProduct?page=0&size=20" \
    -H "apiKey: YOUR_API_KEY" \
    -H "apiId: YOUR_API_ID" \
    -H "Authorization: Bearer YOUR_JWT_TOKEN"
  ```

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

  response = requests.get(
      "https://api.remita.cm/api/v1/transaction/getByApplicationProduct",
      headers={
          "apiKey": "YOUR_API_KEY",
          "apiId": "YOUR_API_ID",
          "Authorization": "Bearer YOUR_JWT_TOKEN",
      },
      params={"page": 0, "size": 20}
  )
  print(response.json())
  ```
</CodeGroup>

### Réponse (200)

```json theme={null}
{
  "content": [
    {
      "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "externalId": "550e8400-e29b-41d4-a716-446655440000",
      "amount": 5000,
      "feesSystem": 50,
      "feesApp": 25,
      "phoneReceiver": "237690000000",
      "receiverName": "Jean Dupont",
      "status": "SUCCESS",
      "transferMethod": "OMCM",
      "transactionType": "COLLECT",
      "countryName": "CAMEROON"
    }
  ],
  "totalElements": 150,
  "totalPages": 8,
  "size": 20,
  "number": 0
}
```

***

## GET /api/v1/transaction/getByApplicationProductAndPhoneReceiver

Filtre les transactions par numéro de téléphone du bénéficiaire.

| Paramètre     | Type    | Obligatoire | Description                    |
| ------------- | ------- | ----------- | ------------------------------ |
| `phoneNumber` | String  | Oui         | Numéro en format international |
| `page`        | Integer | Oui         | Numéro de page (0-indexé)      |
| `size`        | Integer | Oui         | Nombre d'éléments par page     |

***

## GET /api/v1/transaction/getByApplicationProductAndStatus

Filtre les transactions par statut.

| Paramètre           | Type    | Obligatoire | Description                                        |
| ------------------- | ------- | ----------- | -------------------------------------------------- |
| `transactionStatus` | String  | Oui         | `PENDING`, `PENDING_APPROVAL`, `SUCCESS`, `FAILED` |
| `page`              | Integer | Oui         | Numéro de page                                     |
| `size`              | Integer | Oui         | Taille de la page                                  |

***

## GET /api/v1/transaction/getTotalAmountByApplicationProductAndDateRange

Calcule le montant total des transactions sur une plage de dates.

| Paramètre   | Type   | Obligatoire | Description                             |
| ----------- | ------ | ----------- | --------------------------------------- |
| `startDate` | String | Oui         | Date début ISO 8601 (ex : `2026-01-01`) |
| `endDate`   | String | Oui         | Date fin ISO 8601 (ex : `2026-03-31`)   |
| `status`    | String | Oui         | Statut à filtrer                        |

### Réponse

```json theme={null}
75000.00
```

***

## GET /api/v1/transaction/getTotalAmountByApplicationProduct

Retourne le montant total de toutes les transactions de votre application.

```bash theme={null}
curl -X GET "https://api.remita.cm/api/v1/transaction/getTotalAmountByApplicationProduct" \
  -H "apiKey: YOUR_API_KEY" \
  -H "apiId: YOUR_API_ID" \
  -H "Authorization: Bearer YOUR_JWT_TOKEN"
```

***

## GET /api/v1/transaction/getByApplicationProductBalances

Retourne les soldes disponibles de votre application par opérateur et type (collect / deposit).

<CodeGroup>
  ```bash cURL theme={null}
  curl -X GET "https://api.remita.cm/api/v1/transaction/getByApplicationProductBalances" \
    -H "apiKey: YOUR_API_KEY" \
    -H "apiId: YOUR_API_ID" \
    -H "Authorization: Bearer YOUR_JWT_TOKEN"
  ```

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

  response = requests.get(
      "https://api.remita.cm/api/v1/transaction/getByApplicationProductBalances",
      headers={
          "apiKey": "YOUR_API_KEY",
          "apiId": "YOUR_API_ID",
          "Authorization": "Bearer YOUR_JWT_TOKEN",
      }
  )
  print(response.json())
  ```

  ```java Java theme={null}
  HttpRequest request = HttpRequest.newBuilder()
      .uri(URI.create("https://api.remita.cm/api/v1/transaction/getByApplicationProductBalances"))
      .header("apiKey", "YOUR_API_KEY")
      .header("apiId", "YOUR_API_ID")
      .header("Authorization", "Bearer YOUR_JWT_TOKEN")
      .GET()
      .build();
  System.out.println(client.send(request, HttpResponse.BodyHandlers.ofString()).body());
  ```

  ```php PHP theme={null}
  <?php
  $ch = curl_init('https://api.remita.cm/api/v1/transaction/getByApplicationProductBalances');
  curl_setopt_array($ch, [
      CURLOPT_RETURNTRANSFER => true,
      CURLOPT_HTTPHEADER     => [
          'apiKey: YOUR_API_KEY',
          'apiId: YOUR_API_ID',
          'Authorization: Bearer YOUR_JWT_TOKEN',
      ],
  ]);
  print_r(json_decode(curl_exec($ch), true));
  curl_close($ch);
  ```
</CodeGroup>

### Réponse (200)

```json theme={null}
[
  {
    "serviceType": "OMCM",
    "balanceCollect": 250000.00,
    "balanceDeposit": 120000.00
  },
  {
    "serviceType": "MOMOCM",
    "balanceCollect": 180000.00,
    "balanceDeposit": 95000.00
  }
]
```

***

## Flux recommandé

```
1. POST /collect  ou  /deposit
         ↓
2. Recevoir transactionId + statut initial (PENDING)
         ↓
3. Attendre le callback webhook (asynchrone)
       OU
   POST /transaction-status  (polling)
       OU
   POST /chekTransactionStatus  (force sync opérateur)
         ↓
4. Traiter le statut final (SUCCESS / FAILED)
```

<Tip>
  Utilisez toujours un `externalId` unique (UUID v4) par transaction. En cas de retry sur timeout réseau, réutilisez le **même** `externalId` — Remita détectera le doublon et retournera la transaction existante.

  ```python theme={null}
  import uuid

  def idempotent_external_id(order_id: str) -> str:
      """UUID déterministe à partir de votre ID de commande."""
      return str(uuid.uuid5(uuid.NAMESPACE_DNS, f"order:{order_id}"))
  ```
</Tip>
