Référence de l'API
Sessions
Envoyez un client vers une page hébergée pour démarrer un abonnement, payer une facture, changer de formule, annuler ou ouvrir son espace client. Puis listez, lisez et expirez ces sessions.
Une session est une page hébergée que vous créez pour un client. Vous envoyez le client vers son url, et Abuna indique à votre serveur comment elle s'est terminée avec un événement session.completed ou session.expired. Le guide Sessions décrit tout le déroulement.
Vous créez chaque session avec POST /v1/apps/{appID}/sessions. Le type du corps indique ce que fait le client, et détermine les autres champs que le corps accepte :
checkout: une page de paiement hébergée qui vend un tarif. Envoyezprice_id.payment: une page de paiement pour une facture ouverte. Envoyezinvoice_id.plan_change: le client confirme le passage à un autre tarif. Envoyezsubscription_idetprice_id.cancel: le client confirme une annulation. Envoyezsubscription_id.portal: l'espace client avec un lien de retour vers votre application. Envoyezsubscription_idetreturn_url.
Chaque type renvoie le même objet session. Vous listez, récupérez et expirez les sessions de tout type avec les mêmes endpoints. Un type qu'Abuna ne connaît pas renvoie 422 avec le code invalid et un élément errors pour type.
Ces endpoints n'acceptent qu'une clé secrète. Une clé publiable ou une connexion au tableau de bord reçoit 403 avec le code forbidden. Un champ du corps que le type de la session n'accepte pas renvoie 400 avec le code invalid_json.
L'objet session
Attributs
idstringIdentifiant unique de la session.typestringCe à quoi sert la session :checkout,payment,plan_change,cancelouportal, tel que vous l'avez envoyé à la création.statusstringopenjusqu'à sa fin.completeddès que le client termine, selon la définition de chaque type, ouexpiredlorsqu'elle expire ou que vous l'expirez. Une session terminée ne change plus jamais.urlstringLa page hébergée vers laquelle envoyer le client. Elle appartient à ce client, ne la partagez pas.success_urlstringnullableOù va le client après avoir terminé, tel que vous l'avez envoyé, ou l'URL de succès de votre application si vous n'en avez pas envoyé. Les jetons comme{SESSION_ID}apparaissent tels quels. Null quand ni l'un ni l'autre n'est défini, et toujours null pourportal. Voir Jetons de l'URL de succès.cancel_urlstringnullableOù va le client s'il part avant de payer, ou si la session expire. L'URL d'annulation de votre application si vous n'en avez pas envoyé. Null quand ni l'une ni l'autre n'est définie, et toujours null pour portal.return_urlstringnullablePourportal, où mène le lien « Retour » de l'espace client. Null pour les autres types.metadataobjectVos propres clés et valeurs, telles que vous les avez envoyées.{}quand vous n'en avez pas envoyé.customer_idstringnullableLe client que vous avez transmis, ou celui créé par les coordonnées du client. Pour les autres types, le client de l'abonnement. Null tant qu'il est inconnu.price_idstringnullablePourcheckout, le tarif que vend la session. Pourplan_change, le nouveau tarif. Null pour les autres types.subscription_idstringnullablePourcheckout, l'abonnement que la session a démarré, défini dès que le client envoie ses coordonnées. Pour les autres types, l'abonnement sur lequel agit la session. Null tant qu'il est inconnu.invoice_idstringnullablePourpayment, la facture que paie le client. Null pour les autres types.plan_offer_idstringnullablePourplan_change, l'offre de formule créée par la session. Null pour les autres types.at_period_endbooleannullablePourcancel, si l'annulation attend la fin de la période payée (true) ou met fin à l'abonnement immédiatement (false). Défini à la création de la session, d'après votre requête ou lecustomer_cancelde l'application. Null pour les autres types.expires_attimestampQuand la session expire, en secondes Unix. 24 heures après sa création pourcheckout,paymentetcancel. 7 jours, ou la fin de la période en cours si elle arrive avant, pourplan_change. 1 heure pourportal, qui doit être ouvert avant.completed_attimestampnullableQuand la session s'est terminée.created_attimestampQuand la session a été créée, en secondes Unix.
{
"id": "A4kN1oSs",
"type": "checkout",
"status": "open",
"url": "https://app.abuna.app/checkout/7f2c9e4a1b8d3f6e0c5a9d2b7e4f1a8c3d6b",
"success_url": "https://example.com/welcome",
"cancel_url": "https://example.com/pricing",
"return_url": null,
"metadata": {
"user_id": "42"
},
"customer_id": null,
"price_id": "Zt6YbN3q",
"subscription_id": null,
"invoice_id": null,
"plan_offer_id": null,
"at_period_end": null,
"expires_at": 1727686400,
"completed_at": null,
"created_at": 1727600000
}Créer une session checkout
POST/v1/apps/{appID}/sessions
Accepte un en-tête Idempotency-Key.
Crée une session checkout : une page de paiement hébergée qui vend un tarif à un nouvel abonné. Envoyez le client vers son url. Pour démarrer un abonnement sans page de paiement, utilisez Créer un abonnement.
Paramètres du corps
typestringobligatoirecheckout.price_idstringobligatoireLe tarif à vendre. Il ne doit pas être archivé.customer_idstringUn client existant à facturer. La page de paiement affiche ses coordonnées en lecture seule. Ne l'envoyez pas aveccustomer.customerobjectCoordonnées à préremplir pour un nouveau client. La page de paiement affiche en lecture seule chacune de celles que vous envoyez, et le client remplit le reste. Ne l'envoyez pas aveccustomer_id.Afficher les paramètresMasquer les paramètres
emailstringSon adresse e-mail. Elle doit contenir@.namestringSon nom.phone_numberstringSon numéro de téléphone avec son indicatif pays, comme+237671234567.
success_urlstringOù envoyer le client une fois la session terminée. Abuna remplit ses jetons, ou ajoute les identifiants en paramètres de requête si elle n'en a aucun. Par défaut, l'URL de succès de votre application.cancel_urlstringOù envoyer le client s'il part avant de payer. Par défaut, l'URL d'annulation de votre application.metadataobjectVos propres clés et valeurs, renvoyées dans les événements de la session. L'abonnement que démarre la session les reçoit aussi. Jusqu'à 20 clés. Chaque clé fait de 1 à 40 caractères, et chaque valeur est une chaîne de 500 caractères maximum.
Renvoie la session avec le statut 201. Elle peut aussi renvoyer :
422avec le codeinvalidquand un champ échoue. Chaque élémenterrorsnomme le champ : pas deprice_id(required), unprice_idoucustomer_idque l'application n'a pas (not_found),customerenvoyé aveccustomer_id(invalid), un e-mail invalide (invalid) ou un numéro de téléphone (phone_invalid), un numéro d'un pays que votre prestataire de paiement ne peut pas débiter (phone_country_unsupported), une URL qui enfreint les règles d'URL (url_invalid), ou desmetadataau-delà de leurs limites (invalid).410avec le codeprice_archivedquand le tarif est archivé.422avec le codenot_accepting_paymentsquand une application Réelle ne peut pas encore encaisser de paiements.422avec le codeidempotency_key_reusedou409avec le codeidempotency_in_progress. Voir Requêtes idempotentes.
curl https://api.abuna.app/v1/apps/8ddhXCDW/sessions \
-H "Authorization: Bearer sk_test_..." \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 6f1c2b9e-4d3a-4c8e-9a7f-2e5b8d1c0a43" \
-d '{
"type": "checkout",
"price_id": "Zt6YbN3q",
"customer": {"email": "ana@example.com"},
"success_url": "https://example.com/welcome",
"cancel_url": "https://example.com/pricing",
"metadata": {"user_id": "42"}
}'{
"id": "A4kN1oSs",
"type": "checkout",
"status": "open",
"url": "https://app.abuna.app/checkout/7f2c9e4a1b8d3f6e0c5a9d2b7e4f1a8c3d6b",
"success_url": "https://example.com/welcome",
"cancel_url": "https://example.com/pricing",
"return_url": null,
"metadata": {
"user_id": "42"
},
"customer_id": null,
"price_id": "Zt6YbN3q",
"subscription_id": null,
"invoice_id": null,
"plan_offer_id": null,
"at_period_end": null,
"expires_at": 1727686400,
"completed_at": null,
"created_at": 1727600000
}Créer une session de paiement
POST/v1/apps/{appID}/sessions
Accepte un en-tête Idempotency-Key.
Crée une session payment : une page de paiement pour une facture ouverte. Rien n'est débité tant que le client n'a pas payé sur la page. Pour débiter depuis votre serveur le numéro de téléphone enregistré du client, utilisez Débiter une facture.
Trouvez les factures ouvertes avec Lister les factures et status=open, ou conservez l'invoice_id de l'événement invoice.created.
Paramètres du corps
typestringobligatoirepayment.invoice_idstringobligatoireLa facture ouverte que paie le client.success_urlstringOù envoyer le client une fois la session terminée. Abuna remplit ses jetons, ou ajoute les identifiants en paramètres de requête si elle n'en a aucun. Par défaut, l'URL de succès de votre application.cancel_urlstringOù envoyer le client s'il part sans payer. Par défaut, l'URL d'annulation de votre application.metadataobjectVos propres clés et valeurs, renvoyées dans les événements de la session. Jusqu'à 20 clés. Chaque clé fait de 1 à 40 caractères, et chaque valeur est une chaîne de 500 caractères maximum.
Renvoie la session avec le statut 201. Elle peut aussi renvoyer :
422avec le codeinvalidquand un champ échoue : pas d'invoice_id(required), uninvoice_idque l'application n'a pas (not_found), une URL qui enfreint les règles d'URL (url_invalid), ou desmetadataau-delà de leurs limites (invalid).409avec le codealready_paidquand la facture est déjà payée, ou409avec le codeinvoice_not_openquand elle est annulée, y compris la facture d'un abonnement annulé.422avec le codenot_accepting_paymentsquand une application Réelle ne peut pas encore encaisser de paiements.422avec le codeidempotency_key_reusedou409avec le codeidempotency_in_progress. Voir Requêtes idempotentes.
curl https://api.abuna.app/v1/apps/8ddhXCDW/sessions \
-H "Authorization: Bearer sk_test_..." \
-H "Content-Type: application/json" \
-d '{
"type": "payment",
"invoice_id": "V2nC8xEi",
"success_url": "https://example.com/billing/paid",
"cancel_url": "https://example.com/billing",
"metadata": {"user_id": "42"}
}'{
"id": "z8TmY5Pq",
"type": "payment",
"status": "open",
"url": "https://app.abuna.app/pay/3a8d1f6c9e2b5a7d0f4c8e1b6a9d3f7c2e5b",
"success_url": "https://example.com/billing/paid",
"cancel_url": "https://example.com/billing",
"return_url": null,
"metadata": {
"user_id": "42"
},
"customer_id": "Cu5tM8rA",
"price_id": null,
"subscription_id": "x9QbL2sK",
"invoice_id": "V2nC8xEi",
"plan_offer_id": null,
"at_period_end": null,
"expires_at": 1727686400,
"completed_at": null,
"created_at": 1727600000
}Créer une session de changement de formule
POST/v1/apps/{appID}/sessions
Accepte un en-tête Idempotency-Key.
Crée une session plan_change : une page où le client confirme le passage à un autre tarif, et paie une mise à niveau. Rien ne change tant qu'il n'a pas confirmé. Abuna n'envoie ni e-mail ni message au client, envoyez-le vous-même vers l'url. Changer de formule explique les mises à niveau, les rétrogradations et leur coût.
Paramètres du corps
typestringobligatoireplan_change.subscription_idstringobligatoireL'abonnement à déplacer. Il doit êtreactiveoupast_due.price_idstringobligatoireLe nouveau tarif. Il doit faire partie des options de formule de l'abonnement.success_urlstringOù envoyer le client une fois la session terminée. Abuna remplit ses jetons, ou ajoute les identifiants en paramètres de requête si elle n'en a aucun. Par défaut, l'URL de succès de votre application.cancel_urlstringLe lien « Retour » des étapes de confirmation et de paiement. Par défaut, l'URL d'annulation de votre application.metadataobjectVos propres clés et valeurs, renvoyées dans les événements de la session. Jusqu'à 20 clés. Chaque clé fait de 1 à 40 caractères, et chaque valeur est une chaîne de 500 caractères maximum.
Renvoie la session avec le statut 201. Elle peut aussi renvoyer :
422avec le codeinvalidquand un champ échoue : pas desubscription_idouprice_id(required), unsubscription_idque l'application n'a pas (not_found), une URL qui enfreint les règles d'URL (url_invalid), ou desmetadataau-delà de leurs limites (invalid).422avec le codeprice_not_eligiblequand le tarif ne fait pas partie des options de formule.409avec le codeplan_change_unavailablequand l'abonnement n'est pasactiveoupast_due.422avec le codeidempotency_key_reusedou409avec le codeidempotency_in_progress. Voir Requêtes idempotentes.
curl https://api.abuna.app/v1/apps/8ddhXCDW/sessions \
-H "Authorization: Bearer sk_test_..." \
-H "Content-Type: application/json" \
-d '{
"type": "plan_change",
"subscription_id": "x9QbL2sK",
"price_id": "Hc8LmV2s",
"success_url": "https://example.com/plan/changed",
"cancel_url": "https://example.com/plan",
"metadata": {"user_id": "42"}
}'{
"id": "G2wP6hCs",
"type": "plan_change",
"status": "open",
"url": "https://app.abuna.app/plan-change/5d2b8e1f4a7c0d3e6b9f2a5c8e1d4b7a0f3c",
"success_url": "https://example.com/plan/changed",
"cancel_url": "https://example.com/plan",
"return_url": null,
"metadata": {
"user_id": "42"
},
"customer_id": "Cu5tM8rA",
"price_id": "Hc8LmV2s",
"subscription_id": "x9QbL2sK",
"invoice_id": null,
"plan_offer_id": "q2WkR5oF",
"at_period_end": null,
"expires_at": 1728204800,
"completed_at": null,
"created_at": 1727600000
}Créer une session d'annulation
POST/v1/apps/{appID}/sessions
Accepte un en-tête Idempotency-Key.
Crée une session cancel : une page où le client confirme une annulation. Rien ne change tant qu'il n'a pas confirmé. Pour annuler sans demander au client, utilisez Annuler un abonnement.
Paramètres du corps
typestringobligatoirecancel.subscription_idstringobligatoireL'abonnement à annuler. Il doit êtreactiveoupast_due.at_period_endbooleantruemet fin à l'abonnement à la fin de la période payée, etfalsey met fin immédiatement. Par défaut, lecustomer_cancelde votre application, lu à la création de la session.success_urlstringOù envoyer le client une fois la session terminée. Abuna remplit ses jetons, ou ajoute les identifiants en paramètres de requête si elle n'en a aucun. Par défaut, l'URL de succès de votre application.cancel_urlstringLe lien « Retour » de la page de confirmation. Par défaut, l'URL d'annulation de votre application.metadataobjectVos propres clés et valeurs, renvoyées dans les événements de la session. Jusqu'à 20 clés. Chaque clé fait de 1 à 40 caractères, et chaque valeur est une chaîne de 500 caractères maximum.
Renvoie la session avec le statut 201. Elle peut aussi renvoyer :
422avec le codeinvalidquand un champ échoue : pas desubscription_id(required), unsubscription_idque l'application n'a pas (not_found), une URL qui enfreint les règles d'URL (url_invalid), ou desmetadataau-delà de leurs limites (invalid).409avec le codesubscription_canceledquand l'abonnement a pris fin,409avec le codesubscription_not_activequand il estpending, sa première période n'étant pas encore payée, ou409avec le codecancel_already_scheduledquand une annulation est déjà programmée.422avec le codeidempotency_key_reusedou409avec le codeidempotency_in_progress. Voir Requêtes idempotentes.
curl https://api.abuna.app/v1/apps/8ddhXCDW/sessions \
-H "Authorization: Bearer sk_test_..." \
-H "Content-Type: application/json" \
-d '{
"type": "cancel",
"subscription_id": "x9QbL2sK",
"at_period_end": true,
"success_url": "https://example.com/account/canceled",
"cancel_url": "https://example.com/account",
"metadata": {"user_id": "42"}
}'{
"id": "n9RcL3Xu",
"type": "cancel",
"status": "open",
"url": "https://app.abuna.app/cancel/9e4b7a1d3f6c0e8b2d5a9f1c4e7b0d3a6f2c",
"success_url": "https://example.com/account/canceled",
"cancel_url": "https://example.com/account",
"return_url": null,
"metadata": {
"user_id": "42"
},
"customer_id": "Cu5tM8rA",
"price_id": null,
"subscription_id": "x9QbL2sK",
"invoice_id": null,
"plan_offer_id": null,
"at_period_end": true,
"expires_at": 1727686400,
"completed_at": null,
"created_at": 1727600000
}Créer une session d'espace client
POST/v1/apps/{appID}/sessions
Accepte un en-tête Idempotency-Key.
Crée une session portal : l'espace client d'un abonnement, avec un lien « Retour » vers votre application. L'abonnement peut avoir n'importe quel statut. Créez-en une nouvelle chaque fois que le client demande à gérer sa facturation.
Paramètres du corps
typestringobligatoireportal.subscription_idstringobligatoireL'abonnement à gérer.return_urlstringobligatoireOù mène le lien « Retour » de l'espace client.metadataobjectVos propres clés et valeurs, renvoyées dans les événements de la session. Jusqu'à 20 clés. Chaque clé fait de 1 à 40 caractères, et chaque valeur est une chaîne de 500 caractères maximum.
Une session portal ne prend ni success_url ni cancel_url. Renvoie la session avec le statut 201. Elle peut aussi renvoyer :
422avec le codeinvalidquand un champ échoue : pas desubscription_idoureturn_url(required), unsubscription_idque l'application n'a pas (not_found), unereturn_urlqui enfreint les règles d'URL (url_invalid), ou desmetadataau-delà de leurs limites (invalid).422avec le codeidempotency_key_reusedou409avec le codeidempotency_in_progress. Voir Requêtes idempotentes.
curl https://api.abuna.app/v1/apps/8ddhXCDW/sessions \
-H "Authorization: Bearer sk_test_..." \
-H "Content-Type: application/json" \
-d '{
"type": "portal",
"subscription_id": "x9QbL2sK",
"return_url": "https://example.com/account",
"metadata": {"user_id": "42"}
}'{
"id": "D1vT7rQf",
"type": "portal",
"status": "open",
"url": "https://app.abuna.app/portal/2c7f0a3d6b9e1c4f8a2d5b7e0c3f6a9d1b4e",
"success_url": null,
"cancel_url": null,
"return_url": "https://example.com/account",
"metadata": {
"user_id": "42"
},
"customer_id": "Cu5tM8rA",
"price_id": null,
"subscription_id": "x9QbL2sK",
"invoice_id": null,
"plan_offer_id": null,
"at_period_end": null,
"expires_at": 1727603600,
"completed_at": null,
"created_at": 1727600000
}Lister les sessions
GET/v1/apps/{appID}/sessions
Liste les sessions de l'application, de la plus récente à la plus ancienne, une page à la fois. Tous les paramètres sont facultatifs, et un paramètre vide est ignoré.
Paramètres
typestringUniquement les sessions de ce type :checkout,payment,plan_change,cancelouportal.statusstringopen,completedouexpired.subscription_idstringUniquement les sessions de cet abonnement.limitintegerCombien de sessions renvoyer, de 1 à 100. Par défaut : 50.cursorstringLa valeurnext_cursorde la page précédente. Envoyez les mêmes filtres avec.
Attributs de la réponse
itemsarrayLes sessions de la page. Vide quand rien ne correspond.next_cursorstringnullablePassez-le en cursor pour obtenir la page suivante. Il vaut null sur la dernière page. Traitez-le comme opaque.
Renvoie 200. Une valeur non autorisée renvoie 422 avec le code invalid et le nom du paramètre dans errors.
curl "https://api.abuna.app/v1/apps/8ddhXCDW/sessions?status=completed&limit=50" \
-H "Authorization: Bearer sk_test_..."{
"items": [
{
"id": "A4kN1oSs",
"type": "checkout",
"status": "completed",
"url": "https://app.abuna.app/checkout/7f2c9e4a1b8d3f6e0c5a9d2b7e4f1a8c3d6b",
"success_url": "https://example.com/welcome",
"cancel_url": "https://example.com/pricing",
"return_url": null,
"metadata": {
"user_id": "42"
},
"customer_id": "Cu5tM8rA",
"price_id": "Zt6YbN3q",
"subscription_id": "x9QbL2sK",
"invoice_id": null,
"plan_offer_id": null,
"at_period_end": null,
"expires_at": 1727686400,
"completed_at": 1727600600,
"created_at": 1727600000
}
],
"next_cursor": null
}Récupérer une session
GET/v1/apps/{appID}/sessions/{id}
Récupère une session.
Renvoie la session. Si l'application n'a aucune session avec cet identifiant, renvoie 404 avec le code not_found.
curl https://api.abuna.app/v1/apps/8ddhXCDW/sessions/A4kN1oSs \
-H "Authorization: Bearer sk_test_..."{
"id": "A4kN1oSs",
"type": "checkout",
"status": "completed",
"url": "https://app.abuna.app/checkout/7f2c9e4a1b8d3f6e0c5a9d2b7e4f1a8c3d6b",
"success_url": "https://example.com/welcome",
"cancel_url": "https://example.com/pricing",
"return_url": null,
"metadata": {
"user_id": "42"
},
"customer_id": "Cu5tM8rA",
"price_id": "Zt6YbN3q",
"subscription_id": "x9QbL2sK",
"invoice_id": null,
"plan_offer_id": null,
"at_period_end": null,
"expires_at": 1727686400,
"completed_at": 1727600600,
"created_at": 1727600000
}Expirer une session
POST/v1/apps/{appID}/sessions/{id}/expire
Accepte un en-tête Idempotency-Key.
Met fin immédiatement à une session open, avant son expires_at. Sa page indique au client que la session a expiré, et Abuna envoie session.expired. Un abonnement qu'une session checkout a déjà démarré reste pending, comme décrit dans le guide Sessions. Expirer une session plan_change retire aussi son offre de formule, et Abuna envoie plan_offer.canceled.
Renvoie la session. Si elle est déjà completed ou expired, renvoie 409 avec le code session_not_open. Si l'application n'a aucune session avec cet identifiant, renvoie 404 avec le code not_found.
curl -X POST https://api.abuna.app/v1/apps/8ddhXCDW/sessions/A4kN1oSs/expire \
-H "Authorization: Bearer sk_test_..."{
"id": "A4kN1oSs",
"type": "checkout",
"status": "expired",
"url": "https://app.abuna.app/checkout/7f2c9e4a1b8d3f6e0c5a9d2b7e4f1a8c3d6b",
"success_url": "https://example.com/welcome",
"cancel_url": "https://example.com/pricing",
"return_url": null,
"metadata": {
"user_id": "42"
},
"customer_id": null,
"price_id": "Zt6YbN3q",
"subscription_id": null,
"invoice_id": null,
"plan_offer_id": null,
"at_period_end": null,
"expires_at": 1727686400,
"completed_at": null,
"created_at": 1727600000
}Types de session
Chaque type a sa propre page, sa propre règle de fin et ses propres données session.completed. Tous envoient session.expired avec les données de la référence des événements.
checkout
Créée par Créer une session checkout. L'url est une page de paiement hébergée pour price_id. La session se termine quand le premier paiement réussit et que l'abonnement devient active. Elle expire 24 heures après sa création. Ses données session.completed contiennent session_id, type, subscription_id, customer_id, price_id, metadata et completed_at.
payment
Créée par Créer une session de paiement. L'url est une page de paiement pour invoice_id. La session se termine quand cette facture est payée par son intermédiaire. Elle expire 24 heures après sa création, ou plus tôt dès que la facture ne peut plus être payée par ce biais : payée autrement, annulée, ou son abonnement terminé. Une facture payée autrement expire la session, alors utilisez invoice.paid pour savoir qu'une facture est réglée. Les liens de paiement qu'Abuna envoie par e-mail et sur Telegram continuent de fonctionner seuls.
session.completed data
session_idstringLa session.typestringToujourspayment.invoice_idstringLa facture payée par le client.subscription_idstringSon abonnement.customer_idstringSon client.metadataobjectLes métadonnées transmises à la création de la session.completed_attimestampQuand la session s'est terminée.
{
"session_id": "z8TmY5Pq",
"type": "payment",
"invoice_id": "V2nC8xEi",
"subscription_id": "x9QbL2sK",
"customer_id": "Cu5tM8rA",
"metadata": {
"user_id": "42"
},
"completed_at": 1727600600,
"subscription": {
"id": "x9QbL2sK",
"app_id": "8ddhXCDW",
"customer_id": "Cu5tM8rA",
"price_id": "Zt6YbN3q",
"status": "active",
"starts_at": 1727600000,
"activated_at": 1727600100,
"canceled_at": null,
"cancel_at": null,
"current_period_start": 1727600000,
"current_period_end": 1730192000,
"ended_reason": null,
"metadata": {
"user_id": "42"
},
"created_at": 1727600000,
"manage_token": "8c1f4a7d2e9b3c6f0a5d8e1b4c7f2a9d3e6b"
}
}plan_change
Créée par Créer une session de changement de formule. L'url est la page de confirmation du passage de subscription_id à price_id. Créer la session crée une offre de formule en arrière-plan et envoie plan_offer.created, mais Abuna n'envoie ni e-mail ni message au client. Elle remplace toute offre ou session plan_change en attente, et la session plus ancienne reçoit session.expired.
La session se termine quand le changement est effectué :
- Une rétrogradation : quand le client confirme. Elle est programmée pour la fin de la période payée.
- Une mise à niveau : quand son paiement réussit. Une mise à niveau qui coûte
0s'applique, et se termine, à la confirmation.
Elle expire 7 jours après sa création, ou à la fin de la période en cours si elle arrive avant. Elle expire aussi quand son offre est remplacée, annulée ou expire, ou quand une mise à niveau qu'elle a démarrée reste impayée et échoue. Une mise à niveau confirmée en attente de paiement reste open jusqu'à son paiement ou son échec.
Les événements plan_offer.*, subscription.updated et invoice.* se déclenchent toujours comme pour tout changement de formule. Utilisez session.completed pour savoir que le client a terminé le parcours que vous avez démarré, et subscription.updated pour savoir que le tarif a changé. Une rétrogradation change le tarif à la fin de la période, après la fin de la session.
session.completed data
session_idstringLa session.typestringToujoursplan_change.subscription_idstringL'abonnement.customer_idstringSon client.metadataobjectLes métadonnées transmises à la création de la session.completed_attimestampQuand la session s'est terminée.plan_offer_idstringL'offre de formule créée par la session.previous_price_idstringLe tarif avant le changement.price_idstringLe nouveau tarif.directionstringupgradeoudowngrade.effective_attimestampQuand le nouveau tarif commence : au moment où la mise à niveau s'applique, ou à la fin de la période payée pour une rétrogradation.
{
"session_id": "G2wP6hCs",
"type": "plan_change",
"subscription_id": "x9QbL2sK",
"customer_id": "Cu5tM8rA",
"metadata": {
"user_id": "42"
},
"completed_at": 1727600900,
"plan_offer_id": "q2WkR5oF",
"previous_price_id": "Zt6YbN3q",
"price_id": "Hc8LmV2s",
"direction": "upgrade",
"effective_at": 1727600900,
"subscription": {
"id": "x9QbL2sK",
"app_id": "8ddhXCDW",
"customer_id": "Cu5tM8rA",
"price_id": "Hc8LmV2s",
"status": "active",
"starts_at": 1727600000,
"activated_at": 1727600100,
"canceled_at": null,
"cancel_at": null,
"current_period_start": 1727600900,
"current_period_end": 1730192900,
"ended_reason": null,
"metadata": {
"user_id": "42"
},
"created_at": 1727600000,
"manage_token": "8c1f4a7d2e9b3c6f0a5d8e1b4c7f2a9d3e6b"
}
}cancel
Créée par Créer une session d'annulation. L'url est une page de confirmation pour annuler subscription_id. Elle montre ce qui se passe et la date de fin, avec un bouton de confirmation et un lien « Retour » vers cancel_url. L'abonnement doit être active ou past_due, et pas déjà programmé pour annulation. Vous ne pouvez pas en créer une pour un abonnement pending : vous obtenez 409 avec le code subscription_not_active.
at_period_end est défini à la création de la session : la valeur que vous avez envoyée, ou le réglage customer_cancel de l'application. L'annulation suit les règles d'annulation habituelles :
- À la fin de la période, l'abonnement reste
activeet le client garde l'accès jusqu'à la fin de la période payée. - Si la période en cours n'est pas payée, comme pendant que l'abonnement est
past_due, ou est déjà terminée, l'abonnement prend fin immédiatement à la place. La page l'indique au client avant qu'il confirme. - Une annulation qui prend effet immédiatement annule les factures ouvertes de l'abonnement.
La session se termine quand le client confirme, que l'annulation soit programmée ou immédiate. Elle expire 24 heures après sa création sinon. subscription.updated (programmée) ou subscription.canceled (immédiate) se déclenchent toujours comme pour toute annulation. Pour une annulation programmée, subscription.canceled se déclenche plus tard, à cancel_at. Fiez-vous à ces événements pour changer l'accès.
session.completed data
session_idstringLa session.typestringToujourscancel.subscription_idstringL'abonnement.customer_idstringSon client.metadataobjectLes métadonnées transmises à la création de la session.completed_attimestampQuand le client a confirmé.cancel_attimestampnullableQuand l'abonnement prend fin. Null quand il a pris fin immédiatement.immediatebooleantruequand l'abonnement a pris fin immédiatement.
{
"session_id": "n9RcL3Xu",
"type": "cancel",
"subscription_id": "x9QbL2sK",
"customer_id": "Cu5tM8rA",
"metadata": {
"user_id": "42"
},
"completed_at": 1727600300,
"cancel_at": 1730192000,
"immediate": false,
"subscription": {
"id": "x9QbL2sK",
"app_id": "8ddhXCDW",
"customer_id": "Cu5tM8rA",
"price_id": "Zt6YbN3q",
"status": "active",
"starts_at": 1727600000,
"activated_at": 1727600100,
"canceled_at": null,
"cancel_at": 1730192000,
"current_period_start": 1727600000,
"current_period_end": 1730192000,
"ended_reason": null,
"metadata": {
"user_id": "42"
},
"created_at": 1727600000,
"manage_token": "8c1f4a7d2e9b3c6f0a5d8e1b4c7f2a9d3e6b"
}
}portal
Créée par Créer une session d'espace client. L'url est l'espace client de subscription_id, avec un lien « Retour » vers return_url en haut. L'abonnement peut avoir n'importe quel statut. Le lien reste valable pendant que le client change de formule, paie, connecte Telegram ou met à jour ses coordonnées. Sur la page de paiement, les liens de retour et de fin mènent à return_url, et « Gérer l'abonnement » revient à l'espace client. Chacun de ces liens est votre return_url exactement tel que vous l'avez envoyé. Abuna n'y ajoute aucun paramètre de requête ni identifiant.
Ce que l'espace client affiche dépend du statut de l'abonnement :
pending: la première facture avec sa date limite de paiement et un bouton Payer, ainsi qu'un bouton Annuler qui met fin à l'abonnement immédiatement. Il n'y a pas de changement de formule.activeoupast_due: la formule, les factures, les coordonnées, un bouton Annuler et les tarifs vers lesquels le client peut changer, le cas échéant. Un abonnementpast_dueaffiche aussi sa facture impayée avec un bouton Payer.canceled: la formule, la date d'annulation, les factures et les coordonnées du client, qu'il peut encore mettre à jour. Il n'y a rien à payer, ni changement de formule ni annulation.
L'url doit être ouverte dans l'heure suivant sa création, sinon elle affiche un lien invalide. Une fois ouverte, elle continue de fonctionner comme l'espace client. Créez une nouvelle session chaque fois que le client demande à gérer sa facturation.
La session se termine quand le client l'ouvre pour la première fois. Cela ne signifie pas qu'il a changé quelque chose : ce qu'il fait dans l'espace client envoie ses propres événements, comme subscription.updated, subscription.canceled, invoice.paid et customer.updated. Une session que personne n'ouvre expire au bout d'une heure. Le subscription_page_url de l'abonnement continue de fonctionner comme avant, sans lien de retour vers votre application.
session.completed data
session_idstringLa session.typestringToujoursportal.subscription_idstringL'abonnement.customer_idstringSon client.metadataobjectLes métadonnées transmises à la création de la session.completed_attimestampQuand le client a ouvert l'espace client pour la première fois.
{
"session_id": "D1vT7rQf",
"type": "portal",
"subscription_id": "x9QbL2sK",
"customer_id": "Cu5tM8rA",
"metadata": {
"user_id": "42"
},
"completed_at": 1727600020,
"subscription": {
"id": "x9QbL2sK",
"app_id": "8ddhXCDW",
"customer_id": "Cu5tM8rA",
"price_id": "Zt6YbN3q",
"status": "active",
"starts_at": 1727600000,
"activated_at": 1727600100,
"canceled_at": null,
"cancel_at": null,
"current_period_start": 1727600000,
"current_period_end": 1730192000,
"ended_reason": null,
"metadata": {
"user_id": "42"
},
"created_at": 1727600000,
"manage_token": "8c1f4a7d2e9b3c6f0a5d8e1b4c7f2a9d3e6b"
}
}URL de redirection
success_url et cancel_url prennent par défaut l'URL de succès et l'URL d'annulation de votre application. Abuna les copie sur la session à sa création, donc modifier le réglage plus tard ne change pas les sessions existantes. Une session portal prend return_url à la place, et n'a ni l'une ni l'autre.
Chaque URL doit être une URL https absolue avec un hôte. En mode Test, http fonctionne aussi pour localhost, 127.0.0.1 et [::1]. Cela vaut pour l'URL de succès et l'URL d'annulation par défaut de l'application Test, pour chaque type de session. Toute autre URL renvoie 422 avec le code invalid et un élément errors avec le code url_invalid.
Jetons de l'URL de succès
Les sessions d'annulation et les changements de formule sans paiement dû envoient le client directement à success_url. Les sessions checkout, payment et les mises à niveau payantes affichent à la place un bouton « Retour ». Les deux utilisent success_url avec ces jetons remplis :
{SESSION_ID}: tous les types.{SUBSCRIPTION_ID}: tous les types.{INVOICE_ID}:paymentuniquement.
Si l'URL n'a aucun jeton, Abuna ajoute les mêmes identifiants en paramètres de requête : session_id, subscription_id, et pour payment, invoice_id. Elle conserve vos propres paramètres de requête et le fragment #. Rien n'est ajouté à cancel_url. Une session portal n'a pas de success_url ; son lien « Retour » mène à return_url.
Étapes suivantes
- SessionsEnvoyez un client depuis votre application pour s'abonner, payer une facture, changer de formule, annuler ou gérer sa facturation, ramenez-le, et sachez avec certitude quand il a terminé.
- AbonnementsDémarrez, listez, lisez, mettez à jour, annulez, conservez et changez la formule de l'abonnement d'un client à un tarif.
- ÉvénementsLe journal de tout ce qui s'est passé dans une application, et chaque type d'événement.
- ErreursCodes de statut, codes d'erreur, erreurs de champ, limites de débit, identifiants de requête, et comment réessayer sans risque.