Skip to content
ABUNA
DocumentationTarifs

Référence de l'API

Tarifs

Définissez le prix d'un produit et sa fréquence de renouvellement.

Un tarif définit combien coûte un produit et à quelle fréquence il se renouvelle. Un produit peut avoir plusieurs tarifs, comme un mensuel et un annuel.

L'objet price

Attributs

  • idstring

    Identifiant unique du tarif.
  • product_idstring

    Le produit auquel appartient le tarif.
  • namestring

    Le nom du tarif, comme Monthly.
  • currencystring

    XAF.
  • amountinteger

    Ce que le client paie à chaque période de facturation, dans la plus petite unité de la devise.
  • intervalstring

    L'unité d'une période de facturation : day, week, month ou year.
  • interval_countinteger

    Combien d'intervalles composent une période de facturation. month avec 3 facture tous les trois mois.
  • created_attimestamp

    Quand le tarif a été créé, en secondes Unix.
  • archived_attimestampnullable

    Quand le tarif a été archivé. Un tarif archivé ne démarre aucun nouvel abonnement.
  • pending_changeobjectnullable

    Le changement de montant programmé pour le tarif, ou null quand il n'y en a pas. Un tarif en a au plus un.
    Afficher les attributsMasquer les attributs
    • idstring

      Identifiant unique du changement. Les événements de changement de tarif le portent comme price_change_id.
    • amountinteger

      Le nouveau montant, dans la plus petite unité de la devise.
    • previous_amountinteger

      Le montant avant le changement.
    • currencystring

      La devise du tarif, XAF.
    • effective_attimestamp

      Minuit au début du jour à partir duquel le nouveau montant s'applique, dans timezone.
    • timezonestring

      Le fuseau horaire de votre application, comme Africa/Douala, le même que le timezone de l'application. effective_at est minuit dans ce fuseau.
    • keep_current_subscribersboolean

      true quand toutes les personnes abonnées ce jour-là gardent l'ancien montant.
    • created_attimestamp

      Quand le changement a été programmé, en secondes Unix.
L'objet price
{
  "id": "Zt6YbN3q",
  "product_id": "pR4dWx9K",
  "name": "Monthly",
  "currency": "XAF",
  "amount": 5000,
  "interval": "month",
  "interval_count": 1,
  "created_at": 1727600000,
  "archived_at": null,
  "pending_change": null
}

Créer un tarif

POST/v1/apps/{appID}/prices

Accepte un en-tête Idempotency-Key.

Crée un tarif pour l'un des produits de l'application.

Paramètres

  • product_idstringobligatoire

    Le produit à tarifer.
  • namestringobligatoire

    Le nom du tarif, comme Monthly.
  • currencystringobligatoire

    XAF. Les minuscules fonctionnent aussi.
  • amountintegerobligatoire

    Ce que le client paie à chaque période de facturation, dans la plus petite unité de la devise. Doit être supérieur à 0.
  • intervalstringobligatoire

    day, week, month ou year.
  • interval_countinteger

    Combien d'intervalles composent une période de facturation. Par défaut 1. Au plus 365 jours, 52 semaines, 12 mois ou 1 an.

Renvoie le tarif avec le statut 201. Un champ invalide renvoie 422 avec le code invalid. Si l'application n'a aucun produit avec ce product_id, renvoie 404 avec le code not_found.

POST /v1/apps/{appID}/prices
curl https://api.abuna.app/v1/apps/8ddhXCDW/prices \
  -H "Authorization: Bearer sk_test_..." \
  -H "Content-Type: application/json" \
  -d '{"product_id": "pR4dWx9K", "name": "Monthly", "currency": "XAF", "amount": 5000, "interval": "month"}'
Réponse
{
  "id": "Zt6YbN3q",
  "product_id": "pR4dWx9K",
  "name": "Monthly",
  "currency": "XAF",
  "amount": 5000,
  "interval": "month",
  "interval_count": 1,
  "created_at": 1727600000,
  "archived_at": null,
  "pending_change": null
}

Lister les tarifs

GET/v1/apps/{appID}/prices

Liste les tarifs de l'application, tous produits confondus et archivés compris, du plus récent au plus ancien, une page à la fois.

Paramètres de requête

  • limitinteger

    Combien de tarifs renvoyer, de 1 à 100. Par défaut : 50.
  • cursorstring

    La valeur next_cursor de la page précédente. Envoyez les mêmes filtres avec.

Renvoie items et next_cursor, comme décrit dans Listes et filtres. Une valeur non autorisée, comme un limit supérieur à 100, renvoie 422 avec le code invalid et le nom du paramètre dans errors.

GET /v1/apps/{appID}/prices
curl https://api.abuna.app/v1/apps/8ddhXCDW/prices \
  -H "Authorization: Bearer sk_test_..."
Réponse
{
  "items": [
    {
      "id": "Zt6YbN3q",
      "product_id": "pR4dWx9K",
      "name": "Monthly",
      "currency": "XAF",
      "amount": 5000,
      "interval": "month",
      "interval_count": 1,
      "created_at": 1727600000,
      "archived_at": null,
      "pending_change": null
    }
  ],
  "next_cursor": null
}

Mettre à jour un tarif

PATCH/v1/apps/{appID}/prices/{id}

Renomme le tarif. Son montant, sa devise, sa période de facturation et son lien de paiement restent les mêmes. Pour changer ce que paient les clients, programmez un changement de tarif.

Paramètres

  • namestringobligatoire

    Le nouveau nom, comme Monthly plan.

Renvoie le tarif. Un nom vide renvoie 422 avec le code invalid. Si l'application n'a aucun tarif avec cet ID, renvoie 404 avec le code not_found.

PATCH /v1/apps/{appID}/prices/{id}
curl https://api.abuna.app/v1/apps/8ddhXCDW/prices/Zt6YbN3q \
  -X PATCH \
  -H "Authorization: Bearer sk_test_..." \
  -H "Content-Type: application/json" \
  -d '{"name": "Monthly plan"}'
Réponse
{
  "id": "Zt6YbN3q",
  "product_id": "pR4dWx9K",
  "name": "Monthly plan",
  "currency": "XAF",
  "amount": 5000,
  "interval": "month",
  "interval_count": 1,
  "created_at": 1727600000,
  "archived_at": null,
  "pending_change": null
}

Archiver un tarif

POST/v1/apps/{appID}/prices/{id}/archive

Accepte un en-tête Idempotency-Key.

Archive le tarif. Il ne démarre aucun nouvel abonnement, et les abonnements déjà dessus continuent de se renouveler. Archiver un tarif déjà archivé ne change rien. Pour l'annuler, désarchivez le tarif.

Renvoie le tarif. Si l'application n'a aucun tarif avec cet ID, renvoie 404 avec le code not_found.

POST /v1/apps/{appID}/prices/{id}/archive
curl https://api.abuna.app/v1/apps/8ddhXCDW/prices/Zt6YbN3q/archive \
  -X POST \
  -H "Authorization: Bearer sk_test_..."
Réponse
{
  "id": "Zt6YbN3q",
  "product_id": "pR4dWx9K",
  "name": "Monthly",
  "currency": "XAF",
  "amount": 5000,
  "interval": "month",
  "interval_count": 1,
  "created_at": 1727600000,
  "archived_at": 1727686400,
  "pending_change": null
}

Désarchiver un tarif

POST/v1/apps/{appID}/prices/{id}/unarchive

Accepte un en-tête Idempotency-Key.

Désarchive le tarif. Il peut de nouveau démarrer de nouveaux abonnements, et son lien de paiement fonctionne de nouveau. Désarchiver un tarif qui n'est pas archivé ne change rien.

Renvoie le tarif. Si l'application n'a aucun tarif avec cet ID, renvoie 404 avec le code not_found.

POST /v1/apps/{appID}/prices/{id}/unarchive
curl https://api.abuna.app/v1/apps/8ddhXCDW/prices/Zt6YbN3q/unarchive \
  -X POST \
  -H "Authorization: Bearer sk_test_..."
Réponse
{
  "id": "Zt6YbN3q",
  "product_id": "pR4dWx9K",
  "name": "Monthly",
  "currency": "XAF",
  "amount": 5000,
  "interval": "month",
  "interval_count": 1,
  "created_at": 1727600000,
  "archived_at": null,
  "pending_change": null
}

Programmer un changement de tarif

POST/v1/apps/{appID}/prices/{id}/change

Accepte un en-tête Idempotency-Key.

Programme un nouveau montant pour le tarif, à partir d'un jour situé au moins 14 jours plus loin. Le montant ne change jamais tout de suite. La devise et la période de facturation ne peuvent pas changer. Pour une autre, créez un nouveau tarif.

À partir du début de ce jour dans le fuseau horaire de votre application, les paiements et les nouveaux abonnements paient le nouveau montant. Chaque abonné en cours le paie à partir de son premier renouvellement à cette date ou après. Abuna leur envoie tous un e-mail maintenant avec le nouveau montant et la date à laquelle il s'applique pour la première fois, et leur envoie un message sur Telegram s'ils l'ont connecté. Les clients qui s'abonnent pendant que le changement est en attente reçoivent le même avis au moment de s'abonner.

Avec keep_current_subscribers, toutes les personnes abonnées ce jour-là continuent de payer l'ancien montant tant qu'elles restent abonnées, et seuls les abonnés suivants paient le nouveau. Un abonné qui passe à un autre tarif puis revient paie le montant du tarif à ce moment-là.

Un tarif a un seul changement en attente. En programmer un autre le remplace. Si le remplacement garde les abonnés en cours sur l'ancien montant, ceux qui ont été informés du changement précédent reçoivent un e-mail disant que leur tarif reste. Abuna enregistre un price_change.scheduled événement, et price_change.applied quand le nouveau montant démarre.

Paramètres

  • amountintegerobligatoire

    Le nouveau montant, dans la plus petite unité de la devise. Doit être supérieur à 0 et différent du montant actuel.
  • effective_attimestampobligatoire

    N'importe quelle heure du jour où le nouveau montant démarre, en secondes Unix. Abuna la ramène au début de ce jour dans le fuseau horaire de votre application. Ce jour doit être au moins 14 jours après aujourd'hui dans ce fuseau.
  • keep_current_subscribersboolean

    Garder toutes les personnes abonnées ce jour-là sur l'ancien montant. Par défaut false.

Renvoie le tarif avec pending_change défini. Une vérification échouée renvoie 422 avec le code invalid, et chaque élément errors nomme le champ : amount avec invalid ou unchanged, ou effective_at avec required ou too_soon. Tout autre champ, comme currency ou interval, renvoie 400 avec le code invalid_json. Si l'application n'a aucun tarif avec cet ID, renvoie 404 avec le code not_found. Une fois que le changement en attente atteint son effective_at, il ne peut plus être remplacé avant d'être appliqué, et la requête renvoie 409 avec le code change_in_effect. Voir Quand le changement prend effet.

POST /v1/apps/{appID}/prices/{id}/change
curl https://api.abuna.app/v1/apps/8ddhXCDW/prices/Zt6YbN3q/change \
  -X POST \
  -H "Authorization: Bearer sk_test_..." \
  -H "Content-Type: application/json" \
  -d '{"amount": 6000, "effective_at": 1730458800, "keep_current_subscribers": false}'
Réponse
{
  "id": "Zt6YbN3q",
  "product_id": "pR4dWx9K",
  "name": "Monthly",
  "currency": "XAF",
  "amount": 5000,
  "interval": "month",
  "interval_count": 1,
  "created_at": 1727600000,
  "archived_at": null,
  "pending_change": {
    "id": "W4hN7gPc",
    "amount": 6000,
    "previous_amount": 5000,
    "currency": "XAF",
    "effective_at": 1730415600,
    "timezone": "Africa/Douala",
    "keep_current_subscribers": false,
    "created_at": 1727700000
  }
}

Annuler un changement de tarif

POST/v1/apps/{appID}/prices/{id}/change/cancel

Accepte un en-tête Idempotency-Key.

Annule le changement en attente du tarif, donc le montant reste tel quel. Si des abonnés en cours devaient passer au nouveau montant, Abuna leur envoie un e-mail disant que leur tarif reste. Abuna enregistre un price_change.canceled événement.

Renvoie le tarif avec pending_change à null. Si l'application n'a aucun tarif avec cet ID, renvoie 404 avec le code not_found. Sans changement en attente, renvoie 409 avec le code no_pending_change. Une fois que le changement atteint son effective_at, il ne peut plus être annulé, et la requête renvoie 409 avec le code change_in_effect.

POST /v1/apps/{appID}/prices/{id}/change/cancel
curl https://api.abuna.app/v1/apps/8ddhXCDW/prices/Zt6YbN3q/change/cancel \
  -X POST \
  -H "Authorization: Bearer sk_test_..."
Réponse
{
  "id": "Zt6YbN3q",
  "product_id": "pR4dWx9K",
  "name": "Monthly",
  "currency": "XAF",
  "amount": 5000,
  "interval": "month",
  "interval_count": 1,
  "created_at": 1727600000,
  "archived_at": null,
  "pending_change": null
}

Quand le changement prend effet

Un changement prend effet à son effective_at, et Abuna enregistre price_change.applied dans la minute environ qui suit. Entre-temps, pending_change montre encore le changement, et l'annuler ou le remplacer renvoie 409 avec le code change_in_effect. Une fois price_change.applied enregistré, pending_change est null et vous pouvez programmer un nouveau changement.

Étapes suivantes