Encaisser un paiement (panier)
Fonctionnalité en cours de déploiement. L'interface décrite ici est celle de la prochaine livraison : elle peut encore évoluer, et n'est pas forcément activée sur votre tenant.
À quoi ça sert
Pour un achat ponctuel, votre application envoie un panier : le client, les lignes, les prix et la TVA. La plateforme renvoie un lien de paiement vers une page à vos couleurs. Votre client paie par carte (Stripe) ou PayPal ; la facture est émise automatiquement.
Il n'y a aucun catalogue : chaque panier porte ses propres lignes.
Prérequis
- Un compte de paiement prêt (
ready: true), avecone_timedansbillingModes. - Un jeton de l'application déclarée dans votre compte, avec le scope
carts.
1. Créer le panier
curl -s -X POST https://billing-api.dev.stackngo.fr/v1/carts \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: order-10042" \
-d '{
"mode": "one_time",
"currency": "EUR",
"customer": {
"external_ref": "user-381",
"name": "Dupont Conseil",
"email": "compta@dupont.example",
"siren": "552100554",
"address": { "line1": "3 place Bellecour", "postal_code": "69002", "city": "Lyon", "country": "FR" }
},
"lines": [
{ "label": "Formation Go (1 jour)", "quantity": "1", "unit_amount": "490.00", "tax_category": "S", "tax_rate": "20.00" },
{ "label": "Support de cours", "quantity": "2", "unit_amount": "15.00", "tax_category": "S", "tax_rate": "5.50" }
],
"success_url": "https://shop.acme.example/merci",
"cancel_url": "https://shop.acme.example/panier",
"tags": { "shop": "formations", "order": "10042" }
}'
| Champ | Rôle |
|---|---|
mode | one_time ici ; voir Abonnements et Paiement à l'usage |
currency | une devise ISO 4217 par panier |
customer | votre client ; external_ref est votre identifiant : le même external_ref retrouve le même client |
lines[] | label, quantity, unit_amount, tax_category, tax_rate ; facultatifs : description, unit_code (C62 unité, HUR heure…), period_start, period_end, tags |
success_url, cancel_url | retour vers votre site ; doivent figurer dans carts.allowedReturnURLs |
ttl_seconds | durée de vie du lien (300 s minimum, carts.maxTTL maximum, carts.defaultTTL par défaut) |
providers | restreindre les fournisseurs proposés (["stripe"]) ; par défaut tous ceux du compte |
tags | étiquettes libres (20 au plus) pour savoir à qui appartient l'argent, voir plus bas |
Catégories de TVA (tax_category) : S taux normal, Z taux zéro, E exonéré, AE
autoliquidation, K livraison intracommunautaire, G export, O hors champ.
Ce que vous obtenez
{
"id": "cart_01J9ZQ4K7M2V8X3N5P6R",
"status": "open",
"mode": "one_time",
"currency": "EUR",
"lines": [
{ "label": "Formation Go (1 jour)", "quantity": "1", "unit_amount": "490.00", "tax_category": "S", "tax_rate": "20.00", "amount": "490.00" },
{ "label": "Support de cours", "quantity": "2", "unit_amount": "15.00", "tax_category": "S", "tax_rate": "5.50", "amount": "30.00" }
],
"totals": {
"subtotal": "520.00",
"tax": "99.65",
"total": "619.65",
"taxes": [
{ "category": "S", "rate": "20.00", "basis": "490.00", "amount": "98.00" },
{ "category": "S", "rate": "5.50", "basis": "30.00", "amount": "1.65" }
]
},
"payment_url": "https://pay.dev.stackngo.fr/acme/…",
"expires_at": "2026-10-09T10:15:00Z",
"created_at": "2026-10-08T10:15:00Z",
"tags": { "shop": "formations", "order": "10042" }
}
2. Envoyer le lien à votre client
Redirigez votre client vers payment_url, ou envoyez-lui le lien par e-mail. Il voit votre
logo, vos couleurs, le détail du panier et les moyens de paiement proposés. Il n'a pas de
compte à créer.
Après le paiement, il est renvoyé vers success_url ; s'il abandonne, vers cancel_url.
3. Suivre le paiement
Le plus simple est d'écouter le webhook payment.succeeded (voir Webhooks).
Vous pouvez aussi relire le panier :
curl -s https://billing-api.dev.stackngo.fr/v1/carts/cart_01J9ZQ4K7M2V8X3N5P6R \
-H "Authorization: Bearer $TOKEN"
status | Signification |
|---|---|
open | en attente du paiement |
processing | paiement en cours de confirmation par le fournisseur |
paid | payé : payment_id est renseigné, la facture est émise |
expired | lien expiré sans paiement |
Pour retirer un lien envoyé par erreur : DELETE /v1/carts/{id} (refusé avec 409 si le
panier est déjà payé).
Savoir à qui appartient l'argent
Chaque paiement retient l'application qui l'a demandé (source_app, l'identifiant client
de l'application) et vos étiquettes (tags). Le rapport d'encaissement les regroupe :
curl -s "https://billing-api.dev.stackngo.fr/v1/reports/payments?from=2026-10-01&to=2026-10-31&group_by=source_app,tag:shop" \
-H "Authorization: Bearer $TOKEN"
{
"from": "2026-10-01",
"to": "2026-10-31",
"group_by": ["source_app", "tag:shop"],
"rows": [
{ "keys": { "source_app": "6f1c…", "tag:shop": "formations" }, "currency": "EUR", "gross": "12450.00", "refunded": "490.00", "net": "11960.00", "count": 31 },
{ "keys": { "source_app": "6f1c…", "tag:shop": "librairie" }, "currency": "EUR", "gross": "1830.40", "refunded": "0.00", "net": "1830.40", "count": 112 }
]
}
group_by accepte source_app, currency, mode et tag:<clé>, séparés par des virgules.
Pour la liste détaillée : GET /v1/payments?tag=shop:formations.
Ce que vous pouvez en attendre
- Un panier non payé n'est pas conservé : passé
expires_at, le lien ne fonctionne plus et le panier disparaît. Seul le paiement crée une commande et une facture. - Rejouer la même création avec la même
Idempotency-Keyrenvoie le même panier, sans doublon. - Les montants sont recalculés par la plateforme :
amountde chaque ligne, puis TVA par catégorie et par taux. Ce sont ces montants qui figurent sur la facture. - L'argent arrive sur votre compte Stripe ou PayPal, selon le moyen choisi par votre client.
Si ça ne marche pas
| Ce que vous voyez | Cause | Correction |
|---|---|---|
422 avec errors[] | champ manquant ou invalide (montant non décimal, devise, pays sur deux lettres…) | corriger le champ indiqué |
403 à la création | one_time absent de billingModes | l'ajouter au BillingAccount |
422 sur success_url | adresse absente de carts.allowedReturnURLs | l'ajouter |
422 sur ttl_seconds | au-delà de carts.maxTTL | réduire, ou augmenter maxTTL |
| Le client voit « lien expiré » | panier expiré | créer un nouveau panier |
Voir aussi Dépannage des paiements.