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

# Airtel Money

> Airtel Africa Open API — sandbox openapiuat.airtel.africa

<div style={{ display: "inline-block", width: "1rem", height: "1rem", background: "#ED1C24", borderRadius: "2px", marginRight: "0.5rem", verticalAlign: "middle" }} />

**Airtel Money** — Open API merchant payments.

## Covered countries

| Country | Code | Currency |
| ------- | ---- | -------- |
| Rwanda  | RW   | RWF      |

Additional Airtel markets (Uganda, Tanzania, DRC…) will be added post-launch.

## URLs

| Type        | URL                                                          |
| ----------- | ------------------------------------------------------------ |
| Dev portal  | [developers.airtel.africa](https://developers.airtel.africa) |
| Sandbox UAT | `https://openapiuat.airtel.africa`                           |
| OAuth token | `https://openapiuat.airtel.africa/auth/oauth2/token`         |
| Payment     | `https://openapiuat.airtel.africa/merchant/v1/payments/`     |
| USSD client | `*185#`                                                      |

## Required credentials

Enter these in **Settings → Stores → Airtel**:

| Field           | Type     | Description                                      |
| --------------- | -------- | ------------------------------------------------ |
| `client_id`     | text     | OAuth `client_id` for your Airtel Developer app. |
| `client_secret` | password | Associated OAuth secret.                         |

## Specifics

* **OAuth client\_credentials with JSON body**: unlike Orange (which expects `x-www-form-urlencoded`), Airtel requires a JSON body `{ "client_id": ..., "client_secret": ..., "grant_type": "client_credentials" }` on the token endpoint. SandPay handles this variant via `oauthClientCredentialsJsonBody`.
* The `X-Country` and `X-Currency` headers are required on the `POST /merchant/v1/payments/` call — they are derived from the MSISDN or explicitly passed via the `country` field.
* `msisdn` is sent **without the `+`** in the subscriber object.
* The Airtel payload separates `subscriber` (the payer) and `transaction` (the movement) — SandPay copies `reference` into both `id` fields to remain idempotent.
* Nested response: `data.transaction.id` — this value is stored as `provider_tx_id`.

## See also

* [Scenarios](/en/scenarios) — result driver independent of the operator
* [MTN](/en/operators/mtn), [Orange](/en/operators/orange), [Moov](/en/operators/moov)
