Pay a mobile wallet in CFA francs
Pay a mobile wallet in Côte d'Ivoire or Benin in XOF, with the payee's country set and the phone number's leading zero kept.
Use this recipe to pay a mobile wallet in Côte d'Ivoire or Benin in XOF. You set the payee's country and keep the leading zero of the phone number.
Who it is for. This recipe is for a New York cocoa buyer whose app pays a cooperative treasurer's mobile wallet in Abidjan and a field agent in Cotonou.
Status. Available on the operator rows MTN MoMo Cote d'Ivoire and MTN MoMo Benin. Other wallet operators in Côte d'Ivoire, Senegal, Burkina Faso, Mali and Togo, and XOF or XAF bank accounts, are not yet available.
Money example
- The buyer sends 120.00 USD. Say the fee on your plan is 1.00 USD.
- Say the rate is 605.00 XOF per USD. The transfer response prices 72,600 XOF for the treasurer.
- The treasurer's wallet receives the CFA francs.
Before you start
- The sender's name and country are on the profile, or in
additional_information(remitter_full_name,remitter_country). - The USD account is
activeand funded.
Find out what is required
- The pair.
GET /v1/transfer/supported-currencieslists pairs such asUSD_XOF. A pair is not a country. - The operator row. Call
GET /v1/external-accounts/institutions?country_iso_code=CI&institution_type=mobile_money. Côte d'Ivoire's row isMTN MoMo Cote d'Ivoire(6c5cf000-ec15-4c95-98ee-b1a1077a31e0), and Benin's isMTN MoMo Benin(8adf9a8f-7fa9-4875-aff4-ee7a7624de3c). Other operators in the list are not confirmed, so ask support before you promise them. - The rate.
GET /v1/transfer/rates?currency=XOFreturns one item per XOF country, such ascurrency_pairUSD_US_XOF_CIorUSD_US_XOF_BJ. Pick the one for the payee's country. - The country. Eight countries share XOF, so the currency does not tell Gravv the country. Pick an operator row, which carries
country_iso_code, and also sendinstitution_country_iso_code. - The phone number. A Côte d'Ivoire number is
225plus 10 digits, and a Benin number is229plus 10 digits. Both keep their leading 0, as in+2250708123456and+2290197123456.
Steps
1. Save the payee
curl --request POST \
--url https://api.gravv.xyz/v1/external-accounts \
--header 'Api-Key: <API_KEY>' \
--header 'Content-Type: application/json' \
--header 'Idempotency-Key: 9401411b-9038-4982-9804-504d4396dad9' \
--data '
{
"customer_id": "adfc44c6-3bf4-4c4c-8e53-4bc255cdba4b",
"payee_type": "mobile_money",
"currency": "XOF",
"account_name": "Awa Kone",
"phone_number": "+2250708123456",
"institution_id": "6c5cf000-ec15-4c95-98ee-b1a1077a31e0",
"institution_country_iso_code": "CI"
}
'
const response = await fetch("https://api.gravv.xyz/v1/external-accounts", {
method: "POST",
headers: {
"Api-Key": process.env.GRAVV_API_KEY,
"Content-Type": "application/json",
"Idempotency-Key": "9401411b-9038-4982-9804-504d4396dad9",
},
body: JSON.stringify({
"customer_id": "adfc44c6-3bf4-4c4c-8e53-4bc255cdba4b",
"payee_type": "mobile_money",
"currency": "XOF",
"account_name": "Awa Kone",
"phone_number": "+2250708123456",
"institution_id": "6c5cf000-ec15-4c95-98ee-b1a1077a31e0",
"institution_country_iso_code": "CI"
}),
});
console.log(response.status, await response.json());
import os
import requests
response = requests.post(
"https://api.gravv.xyz/v1/external-accounts",
headers={
"Api-Key": os.environ["GRAVV_API_KEY"],
"Content-Type": "application/json",
"Idempotency-Key": "9401411b-9038-4982-9804-504d4396dad9",
},
json={
"customer_id": "adfc44c6-3bf4-4c4c-8e53-4bc255cdba4b",
"payee_type": "mobile_money",
"currency": "XOF",
"account_name": "Awa Kone",
"phone_number": "+2250708123456",
"institution_id": "6c5cf000-ec15-4c95-98ee-b1a1077a31e0",
"institution_country_iso_code": "CI",
},
)
print(response.status_code, response.json())
{
"data": {
"id": "c0407de2-db05-4385-8138-682b326c4b6e",
"institution_id": "6c5cf000-ec15-4c95-98ee-b1a1077a31e0",
"payee_type": "mobile_money",
"institution_type": "mobile_money",
"institution_name": "MTN MoMo Cote d'Ivoire",
"account_name": "AWA KONE",
"customer_id": "adfc44c6-3bf4-4c4c-8e53-4bc255cdba4b",
"currency": "XOF",
"institution_country_iso_code": "CI",
"status": "active",
"phone_number": "+2250708123456",
"date_created": "2026-10-13T12:20:00.000Z"
},
"error": null
}
2. Send
curl --request POST \
--url https://api.gravv.xyz/v1/transfer \
--header 'Api-Key: <API_KEY>' \
--header 'Content-Type: application/json' \
--header 'Idempotency-Key: 734ac97d-d945-415f-a75b-9384e21cb7a4' \
--data '
{
"customer_id": "adfc44c6-3bf4-4c4c-8e53-4bc255cdba4b",
"source": {
"source_type": "internal_account",
"id": "9a29e7f8-a3e8-4907-8dfd-1fee0169ee96"
},
"destination": {
"destination_type": "external_account",
"id": "c0407de2-db05-4385-8138-682b326c4b6e"
},
"amount": "120.00",
"description": "Lot 118 advance",
"client_reference": "cocoa-ci-lot-118",
"additional_information": {
"remitter_full_name": "Grace Whitfield",
"remitter_country": "US"
}
}
'
const response = await fetch("https://api.gravv.xyz/v1/transfer", {
method: "POST",
headers: {
"Api-Key": process.env.GRAVV_API_KEY,
"Content-Type": "application/json",
"Idempotency-Key": "734ac97d-d945-415f-a75b-9384e21cb7a4",
},
body: JSON.stringify({
"customer_id": "adfc44c6-3bf4-4c4c-8e53-4bc255cdba4b",
"source": {
"source_type": "internal_account",
"id": "9a29e7f8-a3e8-4907-8dfd-1fee0169ee96"
},
"destination": {
"destination_type": "external_account",
"id": "c0407de2-db05-4385-8138-682b326c4b6e"
},
"amount": "120.00",
"description": "Lot 118 advance",
"client_reference": "cocoa-ci-lot-118",
"additional_information": {
"remitter_full_name": "Grace Whitfield",
"remitter_country": "US"
}
}),
});
console.log(response.status, await response.json());
import os
import requests
response = requests.post(
"https://api.gravv.xyz/v1/transfer",
headers={
"Api-Key": os.environ["GRAVV_API_KEY"],
"Content-Type": "application/json",
"Idempotency-Key": "734ac97d-d945-415f-a75b-9384e21cb7a4",
},
json={
"customer_id": "adfc44c6-3bf4-4c4c-8e53-4bc255cdba4b",
"source": {
"source_type": "internal_account",
"id": "9a29e7f8-a3e8-4907-8dfd-1fee0169ee96",
},
"destination": {
"destination_type": "external_account",
"id": "c0407de2-db05-4385-8138-682b326c4b6e",
},
"amount": "120.00",
"description": "Lot 118 advance",
"client_reference": "cocoa-ci-lot-118",
"additional_information": {
"remitter_full_name": "Grace Whitfield",
"remitter_country": "US",
},
},
)
print(response.status_code, response.json())
{
"data": {
"amount": "120",
"amount_currency": "USD",
"reference": "b3ee69b6-37e7-4e69-9236-b2dbef3f9790",
"date_created": "2026-10-13T12:22:15.019Z",
"transfer_status": "pending",
"transaction_id": "6791bb33-7239-4a40-8749-69ed17e72701",
"local_amount": "72600",
"local_currency": "XOF",
"fee": "1",
"fee_currency": "USD",
"requires_approval": false
},
"error": null
}
3. Follow it
Follow the transfer as described in the East and Central Africa recipe.
What can go wrong
| Response | Why | Fix |
|---|---|---|
400 destination country is required for international transfers |
The XOF payee has no country | Save it again with an institution_id and institution_country_iso_code |
400 WAEMU account numbers must be exactly 24 alphanumeric characters |
A bank payee in SN, CI, BJ, BF, GW, ML, NE or TG needs the 24-character account number (RIB) | Ask for the full number. XOF bank payouts are not yet available |
400 transfers to SN/XOF are not available at this time |
The route is not open | Contact support |
transfer.status.failed after acceptance |
The phone lost its leading 0, or the sender's name or country is missing | Save a new payee with the full number, and add the sender details |
transfer.status.failed, but the transaction is still pending |
The transfer is in manual review | Do not send it again. Contact support with the reference |
Webhooks you will receive
You receive the same webhooks as in the East and Central Africa recipe.
Testing in sandbox
You cannot test this route in sandbox today. In sandbox, saving a Côte d'Ivoire or Benin payee on these rows returns account verification temporarily unavailable; please retry: invalid input. Payouts to other XOF operators return the payee is missing required information for this transfer type — please update the payee details.