Abonnements
Un abonnement facture un client à une cadence fixe en utilisant un token de paiement précédemment enregistré. Genius Checkout possède le calendrier — nous facturons à chaque renouvellement, retentons les refus et émettons des webhooks. Pas besoin de cron.
Un abonnement a besoin de deux choses : un customer_id (retourné par tout checkout précédent) et un token_id (pt_…). Les deux sont isolés par marchand.
Cycle de vie
trial ─▶ active ─▶ past_due ─▶ cancelled
└▶ suspended ─▶ active
└▶ cancelled
└▶ expired (total_cycles atteint)| Statut | Signification |
|---|---|
trial | Créé avec trial_period_days. Pas de débit — le premier débit a lieu à la fin de l'essai. |
active | Facturation en cours. Chaque cycle émet subscription.charged en cas de succès. |
past_due | Le dernier renouvellement a échoué. Le job de dunning relance selon le calendrier du marchand. |
suspended | Mis en pause par le marchand via POST /subscriptions/{id}/pause. |
cancelled | Terminal. Plus aucun débit. Défini via POST /subscriptions/{id}/cancel. |
expired | Terminal. total_cycles atteint (abonnements à durée fixe). |
Créer un abonnement
POST /api/v1/subscriptions| Champ | Type | Requis | Description |
|---|---|---|---|
customer_id | string | Oui | ID externe client (cus_…) |
token_id | string | Oui | ID externe du token (pt_…). Doit être active. |
amount | integer | Oui | Montant par cycle en unités mineures (voir Devises) |
currency | string | Oui | Code alpha ISO 4217 |
interval | string | Oui | day, week, month, year |
interval_count | integer | Non | Multiplicateur d'interval. Défaut 1. Plage 1–365. |
trial_period_days | integer | Non | Si défini, le premier débit a lieu après l'essai. |
setup_fee | integer | Non | Frais uniques facturés à la création. |
total_cycles | integer | Non | Abonnement à durée fixe. Le statut passe à expired après le dernier cycle. |
start_date | date | Non | Date ISO 8601 future. Défaut : aujourd'hui. |
metadata | object | Non | Renvoyé sur chaque webhook subscription.*. |
curl -X POST https://app.geniuscheckout.com/api/v1/subscriptions \
-H "Authorization: Bearer gc_test_..." \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{
"customer_id": "cus_abc123",
"token_id": "pt_xyz789",
"amount": 2999,
"currency": "USD",
"interval": "month",
"trial_period_days": 14,
"metadata": {"plan": "pro"}
}'Réponse (201)
{
"id": "sub_abc123",
"status": "trial",
"amount": 2999,
"currency": "USD",
"interval": "month",
"interval_count": 1,
"setup_fee": null,
"trial_ends_at": "2026-06-05T12:00:00+00:00",
"current_period_start": "2026-05-22T12:00:00+00:00",
"current_period_end": "2026-06-22T12:00:00+00:00",
"next_charge_at": "2026-06-05T12:00:00+00:00",
"total_cycles": null,
"completed_cycles": 0,
"dunning_attempts": 0,
"cancelled_at": null,
"cancel_reason": null,
"customer": {"id": "cus_abc123", "name": "Jane Doe", "email": "[email protected]"},
"payment_method": {"id": "pt_xyz789", "brand": "Visa", "last4": "0071"},
"created_at": "2026-05-22T12:00:00+00:00"
}Lister les abonnements
GET /api/v1/subscriptions?status=active&limit=20&offset=0Filtres : status, customer_id. Pagination en limit/offset (max limit=100). Voir Pagination.
{
"data": [ /* objets abonnement */ ],
"total": 142,
"limit": 20,
"offset": 0
}Récupérer un abonnement
GET /api/v1/subscriptions/{id}Renvoie l'objet complet plus un tableau events des événements de cycle récents (status_changed, charged, charge_failed).
Annuler
POST /api/v1/subscriptions/{id}/cancel{ "reason": "Demande du client", "immediate": true }Quand immediate est false, l'annulation est programmée à current_period_end (le client conserve l'accès jusque-là). Par défaut true.
Pause / reprise
POST /api/v1/subscriptions/{id}/pause
POST /api/v1/subscriptions/{id}/resumeMettre en pause fait passer le statut à suspended et arrête tous les débits futurs. Reprendre revient à active et recalcule next_charge_at.
Mettre à jour le moyen de paiement
PUT /api/v1/subscriptions/{id}/payment-method{ "token_id": "pt_new_card" }Le nouveau token doit être active et appartenir au même marchand. À utiliser quand une carte expire et que le client en ajoute une nouvelle via votre portail.
Webhooks
Chaque cycle et transition d'état émet un webhook — voir Webhooks pour la liste complète. Les plus communs :
subscription.created— créé (entrialouactive)subscription.charged— renouvellement réussisubscription.charge_failed— renouvellement refusé ; le dunning relancesubscription.cancelled— annulation terminalesubscription.updated— moyen de paiement ou calendrier modifié
Exemples de code
// Node — créer un abonnement avec essai de 14 jours
const res = await fetch('https://app.geniuscheckout.com/api/v1/subscriptions', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.GC_API_KEY}`,
'Content-Type': 'application/json',
'Idempotency-Key': crypto.randomUUID(),
},
body: JSON.stringify({
customer_id: 'cus_abc123',
token_id: 'pt_xyz789',
amount: 2999,
currency: 'USD',
interval: 'month',
trial_period_days: 14,
}),
})
const subscription = await res.json()// PHP (Guzzle) — annuler en fin de période
$client = new \GuzzleHttp\Client();
$client->post("https://app.geniuscheckout.com/api/v1/subscriptions/{$id}/cancel", [
'headers' => [
'Authorization' => 'Bearer ' . getenv('GC_API_KEY'),
'Content-Type' => 'application/json',
],
'json' => [
'reason' => 'Demande du client',
'immediate' => false,
],
]);Suite
- Tokens de paiement — lister / désactiver les cartes enregistrées
- Webhooks — écouter les événements de renouvellement
- Tokenisation et récurrence — capture initiale de la carte
