Développeurs/Intégrer
Recharge mobile
La recharge mobile crédite directement un numéro de téléphone prépayé. Votre client reçoit du crédit d'appel ou des données sur sa ligne. Il n'y a aucun code à lui remettre. Vous payez avec votre portefeuille CardV, comme pour les autres commandes.
Voir aussi : Authentification · Conventions · Webhooks
#Fonctionnement
GET /recharge/countries pays que vous pouvez recharger
GET /recharge/operators?country=US opérateurs, types de recharge et montants
POST /recharge/quote votre prix, et un quote_token valable 300 s
POST /recharge/orders passer la commande, payée avec votre portefeuille
GET /recharge/orders/{order_id} consulter le statut, ou attendre un webhook- Tous les chemins commencent par
/api/v1. Envoyez les mêmes en-têtes que pour tout autre appel. - Les deux appels
POSTdoivent être signés. Signez-les commePOST/orders, mais avec leur propre chemin, par exemple/api/v1/recharge/quote. - Les commandes de recharge sont distinctes des commandes de cartes cadeaux. Consultez-les avec les endpoints
/recharge. - Seules les recharges directes sont proposées. Les produits à PIN (un code que le client saisit) ne le sont pas.
#Pays
GET/api/v1/recharge/countries liste les pays que vous pouvez recharger actuellement.
{
"count": 2,
"results": [
{"code": "MX", "name": "Mexico", "currency_codes": ["MXN"], "operator_count": 4, "offer_count": 37},
{"code": "US", "name": "United States", "currency_codes": ["USD"], "operator_count": 6, "offer_count": 52}
]
}codeest le code pays ISO 3166-1 alpha-2. Envoyez-le danscountrylors des appels suivants.currency_codessont les devises locales dans lesquelles vendent les opérateurs de ce pays.- La liste change quand des opérateurs sont ajoutés ou deviennent indisponibles. Rechargez-la toutes les quelques heures.
#Opérateurs
GET/api/v1/recharge/operators?country=US liste les opérateurs d'un pays.
Ajoutez search=att pour filtrer sur le nom de l'opérateur.
{
"count": 1,
"results": [
{
"operator_key": "us-att",
"name": "AT&T",
"country": "US",
"country_name": "United States",
"logo_url": "https://b2b.cardv.net/api/v1/catalog-assets/3f5c...a1.png",
"subtypes": ["airtime", "data"],
"amount_model": "range",
"currency_codes": ["USD"],
"amounts": [
{"min": "5.0000", "max": "100.0000", "currency": "USD", "subtype": "airtime", "label": "5.0000-100.0000 USD"},
{"min": "15.0000", "max": "15.0000", "currency": "USD", "subtype": "data", "label": "15.0000 USD"}
],
"offer_count": 3
}
]
}| Champ | Signification |
|---|---|
operator_key | L'identifiant à envoyer pour obtenir le prix et commander, par exemple us-att. Enregistrez-le sous forme de texte. |
subtypes | Ce que vous pouvez acheter : airtime (crédit d'appel), data ou bundle (appels et données). |
amount_model | fixed si tous les montants sont des valeurs fixes, range si au moins un montant est une fourchette. |
amounts[] | Chaque option. Si min est égal à max, c'est un montant fixe. Sinon, tout montant compris entre les deux. |
amounts[].currency | La devise locale de cette option. Envoyez-la dans local_currency. |
logo_url | Image hébergée par CardV, ou "". |
- Les montants sont des montants locaux : ce que reçoit la ligne, dans la devise locale.
- Un
countryinconnu ou mal formé renvoie HTTP 400.
#Prix
POST/api/v1/recharge/quote vous donne votre prix pour une recharge. Cet appel doit être signé.
{
"country": "US",
"operator_key": "us-att",
"amount": "10.00",
"local_currency": "USD",
"subtype": "airtime"
}| Champ | Obligatoire | Signification |
|---|---|---|
country | Oui | Code pays issu de la liste des pays. |
operator_key | Oui | Issu de la liste des opérateurs. |
amount | Oui | Montant local, sous forme de chaîne. Fixe : une des valeurs listées. Fourchette : entre min et max. |
local_currency | Recommandé | Code ISO 4217 de amount, issu de amounts[].currency. Envoyez-le quand un opérateur propose plusieurs devises. |
subtype | Non | airtime (par défaut), data ou bundle. |
La réponse :
{
"country": "US",
"country_name": "United States",
"operator": {"operator_key": "us-att", "name": "AT&T", "logo_url": ""},
"subtype": "airtime",
"local_amount": "10.0000",
"local_currency": "USD",
"merchant_price": "9.6200",
"merchant_currency": "USD",
"expires_at": "2026-09-30T08:20:30.123456+00:00",
"quote_token": "eyJ2ZXJzaW9uIjox...:1uXyZa:8c1f..."
}merchant_priceest le montant débité de votre portefeuille, enmerchant_currency.quote_tokenbloque ce prix pendant 300 secondes, jusqu'àexpires_at. Renvoyez-le tel quel avec la commande.- Le jeton est lié à votre compte et à ce pays, cet opérateur, ce type et ce montant.
- Vérifiez que
local_currencyest bien la devise attendue avant de commander. - Une demande de prix ne bloque aucun argent. Vous pouvez redemander un prix à tout moment.
#Passer une commande de recharge
POST/api/v1/recharge/orders recharge le téléphone et paie avec votre portefeuille. Cet appel doit être signé.
{
"external_order_id": "SHOP-RC-20260930-0001",
"country": "US",
"operator_key": "us-att",
"amount": "10.00",
"local_currency": "USD",
"subtype": "airtime",
"account": "12125550100",
"quote_token": "eyJ2ZXJzaW9uIjox...:1uXyZa:8c1f..."
}| Champ | Obligatoire | Signification |
|---|---|---|
external_order_id | Oui | Votre numéro de commande. Unique parmi toutes vos commandes, y compris les commandes de cartes cadeaux. |
country, operator_key, amount, local_currency, subtype | Oui | Les mêmes valeurs que celles envoyées pour le prix. |
account | Oui | Le numéro de téléphone à recharger : chiffres uniquement, avec l'indicatif du pays, sans + ni espaces. |
quote_token | Oui | Issu de la demande de prix, avant son expiration. |
Exemples de numéros : 12125550100 (États-Unis), 525512345678 (Mexique).
Vérifiez que le numéro appartient bien à l'opérateur choisi. Une recharge envoyée au mauvais numéro ne peut pas être annulée.
CardV vérifie le prix, débite immédiatement merchant_price de votre portefeuille et lance la recharge en arrière-plan.
Une nouvelle commande renvoie HTTP 201 :
{
"idempotent_replay": false,
"order": {
"order_id": "O-00005678",
"external_order_id": "SHOP-RC-20260930-0001",
"status": "accepted",
"status_title": "Recharge accepted",
"poll_after_seconds": 12,
"account": "12***00",
"local_amount": "10.0000",
"local_currency": "USD",
"merchant_price": "9.6200",
"merchant_currency": "USD",
"...": "more fields"
}
}- Enregistrez
order.order_id. - Le numéro de téléphone est renvoyé masqué, jamais en entier.
#Renvoyer sans risque
external_order_id vous évite de recharger deux fois.
| Vous envoyez | Vous recevez |
|---|---|
| Un nouveau numéro de commande | HTTP 201. Une nouvelle commande. Votre portefeuille est débité. |
| Le même numéro et la même recharge | HTTP 200 et "idempotent_replay": true. La commande existante. Aucun débit. |
| Le même numéro mais une recharge différente | HTTP 400 sur external_order_id. Il ne se passe rien. |
« La même recharge » signifie le même pays, le même opérateur, le même type, le même montant et le même numéro de téléphone.
Une commande en double est détectée avant la vérification du prix : un quote_token expiré renvoie donc quand même la première commande.
- Après un délai dépassé, une erreur 5xx ou une connexion perdue, renvoyez le même corps avec le même numéro de commande. Signez-le à nouveau avec un nouvel horodatage et un nouveau nonce.
- Ne créez jamais un nouveau numéro de commande parce qu'une réponse s'est perdue. Le téléphone pourrait être rechargé deux fois.
#Consulter les commandes de recharge
GET/api/v1/recharge/orders/{order_id} renvoie une commande.
Vous pouvez utiliser le numéro de commande CardV (O-00005678).
{
"order_id": "O-00005678",
"external_order_id": "SHOP-RC-20260930-0001",
"status": "processing",
"order_status": "processing",
"status_title": "Recharge processing",
"status_message": "The recharge request is being processed. Delivery is not confirmed yet.",
"next_step": "Keep this order open and wait for confirmation before placing another recharge.",
"poll_after_seconds": 12,
"country": "US",
"operator": {"operator_key": "us-att", "name": "AT&T", "logo_url": ""},
"subtype": "airtime",
"account": "12***00",
"local_amount": "10.0000",
"local_currency": "USD",
"merchant_price": "9.6200",
"merchant_currency": "USD",
"attempts": [{"attempt_no": 1, "status": "processing", "error_message": "", "submitted_at": "2026-09-30T08:16:02.511201Z", "completed_at": null}],
"created_at": "2026-09-30T08:16:01.004211Z",
"updated_at": "2026-09-30T08:16:02.611978Z",
"...": "more fields"
}- Un numéro de commande inconnu, ou la commande d'un autre compte, renvoie HTTP 404.
status_title,status_messageetnext_stepsont des textes en anglais que vous pouvez montrer à votre équipe.poll_after_secondsindique combien de temps attendre avant la prochaine vérification.0signifie que la commande est terminée.
#Lister les commandes de recharge
GET/api/v1/recharge/orders liste vos commandes de recharge, des plus récentes aux plus anciennes.
GET /api/v1/recharge/orders?status=processing&limit=50&offset=0{"count": 3, "limit": 50, "results": ["..."]}- Filtres :
statusetsearch(numéro de commande CardV, votre numéro de commande ou nom de l'opérateur). limitvaut 20 par défaut, 100 au maximum. Une valeur plus grande est ramenée à 100.- Un
limitou unoffsetnégatif ou non numérique renvoie HTTP 400.
#Statut
accepted ──► processing ──► succeeded
│
├──► manual_review ──► succeeded ou refunded
│
└──► failed ──► refunded (argent rendu à votre portefeuille)| Statut | Terminée ? | Que faire |
|---|---|---|
accepted | Non | Attendez. Le portefeuille est débité, la recharge n'a pas commencé. |
processing | Non | Attendez. Cela peut prendre plusieurs minutes. Ne repassez pas la commande. |
manual_review | Non | CardV vérifie le résultat auprès de l'opérateur. Attendez. |
succeeded | Oui | Le téléphone a été rechargé. Prévenez votre client. |
failed | Pas encore | La recharge n'a pas abouti. Attendez refunded. |
refunded | Oui | L'argent est revenu dans votre portefeuille. Vous pouvez passer une nouvelle commande. |
- Interrogez l'API après
poll_after_seconds, puis espacez : 30 s, 60 s, puis toutes les 5 minutes. Restez sous la limite de requêtes. - Considérez un statut inconnu comme « pas encore terminée ».
- Tant qu'une commande n'est pas terminée, n'envoyez pas d'autre recharge vers le même numéro avec un nouveau numéro de commande. Si la première aboutit aussi, le téléphone est rechargé deux fois.
#Webhooks et remboursements
Les commandes de recharge envoient les mêmes webhooks que les autres commandes :
order.succeeded, order.failed et order.refunded.
Le webhook contient le numéro de commande CardV et votre numéro de commande, avec une liste items vide.
Après un webhook, consultez la commande avec GET/api/v1/recharge/orders/{order_id}.
Les remboursements sont automatiques. Quand l'opérateur confirme un échec, CardV rend l'intégralité du
merchant_price à votre portefeuille et la commande passe à refunded.
Le remboursement apparaît sur la page des transactions du Portail.
Une recharge réussie ne peut être ni remboursée ni annulée.
#Erreurs
Les erreurs suivent les Conventions. Une demande de prix ou une commande refusée renvoie HTTP 400 et rien n'est débité.
| Clé | Où | Que faire |
|---|---|---|
detail | Prix, commande | Pays, opérateur, type ou montant indisponible. Vérifiez la liste des opérateurs. |
amount | Prix, commande | Pas un nombre, zéro ou hors limites. |
local_currency | Prix, commande | Pas un code ISO 4217 à 3 lettres. |
account | Commande | Numéro de téléphone manquant. |
quote_token | Commande | Manquant, expiré, modifié ou ne correspondant pas. Consultez code, puis redemandez le prix. |
balance | Commande | Ajoutez des fonds dans le Portail. |
risk | Commande | Vous avez atteint un plafond de commande. Contactez CardV. |
external_order_id | Commande | Déjà utilisé pour une autre commande. Voir Renvoyer sans risque. |
wallet | Commande | Aucun portefeuille actif. Contactez CardV. |
Les erreurs quote_token sont accompagnées d'un code :
{"code": "quote_expired", "quote_token": "This quote expired. Refresh the price and confirm again."}code | Signification |
|---|---|
quote_required | Aucun quote_token n'a été envoyé. |
quote_expired | Plus de 300 secondes se sont écoulées. Redemandez le prix. |
quote_invalid | Modifié, ou prévu pour une autre recharge. Redemandez le prix. |
price_changed | Votre prix a changé depuis la demande. Redemandez le prix et confirmez le nouveau prix. |
HTTP 403 signale un problème d'identifiants, de signature, d'IP ou de validation. Voir Authentification.
Une question sur votre intégration ? Écrivez à [email protected] en indiquant votre Merchant ID et l’identifiant de commande ou de requête.