Skip to content
ABUNA
DocumentationFactures et paiements

Référence de l'API

Factures et paiements

Périodes de facturation, leurs factures et les paiements associés, et comment lister et lire les factures.

Un abonnement facture une période de facturation à la fois. Chaque période a une facture, et chaque tentative de paiement de celle-ci est un paiement. Vous lisez les trois en récupérant un abonnement. Pour parcourir les factures de tous les abonnements, listez les factures. Pour envoyer un client vers une page hébergée afin de payer une facture ouverte, utilisez Créer une session de paiement.

L'objet billing period

Créer un abonnement renvoie sa première période de facturation dans period. Abuna crée la suivante quand une période payée se termine, et émet sa facture.

Attributs

  • idstring

    Identifiant unique de la période de facturation.
  • subscription_idstring

    L'abonnement auquel appartient la période.
  • price_idstring

    Le tarif facturé pour la période.
  • pay_tokenstring

    Le jeton du lien de paiement de la période.
  • starts_attimestamp

    Quand la période commence, en secondes Unix.
  • ends_attimestamp

    Quand la période se termine, en secondes Unix.
  • period_indexinteger

    La position de la période dans l'abonnement, à partir de 0.
  • grace_period_ends_attimestamp

    La date limite de paiement  : le délai de grâce de l'application après le début de la période, mais jamais après sa fin. S'il passe sans paiement, Abuna annule l'abonnement.
  • paid_attimestampnullable

    Quand la période a été payée.
  • paused_attimestampnullable

    Réservé aux périodes en pause. Toujours null.
  • in_forceboolean

    false pour la période d'une mise à niveau pendant qu'elle attend le paiement, et définitivement si la mise à niveau échoue. Une telle période ne compte pas parmi les périodes de l'abonnement, et la période suivante réutilise son period_index.
  • created_attimestamp

    Quand la période a été créée, en secondes Unix.
L'objet billing period
{
  "id": "T6yVr3Dp",
  "subscription_id": "x9QbL2sK",
  "price_id": "Zt6YbN3q",
  "pay_token": "3a7e1c9f5b2d8a4e6c0f7b3d9a1e5c8f2b6d",
  "starts_at": 1727600000,
  "ends_at": 1730192000,
  "period_index": 0,
  "grace_period_ends_at": 1727686400,
  "paid_at": null,
  "paused_at": null,
  "in_force": true,
  "created_at": 1727600000
}

L'objet invoice

Une facture conserve le montant, l'acheteur et le vendeur tels qu'ils étaient quand Abuna l'a émise. Les changements ultérieurs ne la modifient pas.

Les numéros de facture se présentent comme MYST-000124  : le préfixe invoice_prefix de l'application, puis le nombre de factures de l'application, complété à 6 chiffres et plus long au-delà de 999999. Chaque facture émise par l'application prend le numéro suivant, donc les numéros ne se répètent jamais et aucun n'est sauté. Le mode Réel et le mode Test comptent séparément. Un numéro ne change jamais une fois émis, même si vous modifiez le préfixe.

Attributs

  • idstring

    Identifiant unique de la facture.
  • app_idstring

    L'application qui a émis la facture.
  • period_idstring

    La période de facturation facturée.
  • subscription_idstring

    L'abonnement auquel appartient la facture.
  • numberstring

    Le numéro de facture, comme MYST-000124. Voir numéros de facture.
  • statusstring

    open jusqu'au paiement, puis paid. void quand l'abonnement a été annulé avant le paiement, ou qu'un changement de formule l'a remplacée. Une facture annulée devient paid si un paiement que le client avait déjà approuvé passe après son annulation. Voir Paiements qui arrivent en retard.
  • kindstring

    period pour une période de facturation, ou plan_change pour la première période d'une mise à niveau. Voir Mises à niveau.
  • amountinteger

    Le montant dû, dans la plus petite unité de la devise.
  • creditinteger

    Le temps inutilisé de la période précédente déduit du tarif. 0 sauf si kind vaut plan_change.
  • currencystring

    XAF.
  • item_labelstring

    Le nom du tarif.
  • buyer_namestringnullable

    Le nom du client.
  • buyer_emailstringnullable

    L'adresse e-mail du client.
  • seller_namestring

    Le nom de l'application.
  • period_starttimestamp

    Quand la période facturée commence.
  • period_endtimestamp

    Quand la période facturée se termine.
  • due_attimestamp

    La date limite de paiement.
  • created_attimestamp

    Quand la facture a été émise, en secondes Unix.
  • paid_attimestampnullable

    Quand la facture a été payée.
  • voided_attimestampnullable

    Quand la facture a été annulée. Null de nouveau dès qu'un paiement tardif la rend payée.
L'objet invoice
{
  "id": "V2nC8xEi",
  "app_id": "8ddhXCDW",
  "period_id": "T6yVr3Dp",
  "subscription_id": "x9QbL2sK",
  "number": "MYST-000124",
  "status": "open",
  "kind": "period",
  "amount": 5000,
  "credit": 0,
  "currency": "XAF",
  "item_label": "Monthly",
  "buyer_name": "Jane Doe",
  "buyer_email": "jane@example.com",
  "seller_name": "My store",
  "period_start": 1727600000,
  "period_end": 1730192000,
  "due_at": 1727686400,
  "created_at": 1727600000,
  "paid_at": null,
  "voided_at": null
}

L'objet payment

Attributs

  • idstring

    Identifiant unique du paiement.
  • app_idstring

    L'application à laquelle appartient le paiement.
  • period_idstring

    La période de facturation concernée par le paiement.
  • driverstring

    Le prestataire de paiement, comme pawapay. sandbox pour un paiement Test simulé, et manual pour un paiement que vous avez marqué payé.
  • providerstring

    Le réseau que le prestataire a débité, comme MTN_MOMO_CMR. manual pour un paiement que vous avez marqué payé.
  • provider_referencestringnullable

    L'identifiant propre au prestataire pour le débit.
  • amountinteger

    Le montant débité, dans la plus petite unité de la devise.
  • currencystring

    XAF.
  • statusstring

    pending, succeeded ou failed.
  • messagestringnullable

    Le code d'échec, comme insufficient_funds, ou null quand le paiement n'a pas échoué.
  • created_attimestamp

    Quand le paiement a commencé, en secondes Unix.
  • feeintegernullable

    Les frais du prestataire, dans la plus petite unité de la devise. En mode Réel, ils valent null jusqu'à ce que le prestataire les communique. En mode Test, c'est une estimation.
  • session_idstringnullable

    La session utilisée pour ce paiement, ou null pour un paiement effectué autrement.
  • notestringnullable

    Pour un paiement que vous avez marqué payé, la note que vous avez donnée sur la façon dont le client a payé. Les clients ne la voient jamais. Null sinon.
  • marked_by_user_idstringnullable

    Pour un paiement marqué payé depuis le tableau de bord, l'identifiant du membre de l'équipe qui l'a marqué. Null sinon.
  • marked_by_api_key_idstringnullable

    Pour un paiement marqué payé avec une clé secrète, l'identifiant de cette clé. Null sinon.
  • method_labelstring

    Le nom du réseau, en toutes lettres. Paid outside Abuna pour un paiement que vous avez marqué payé.
L'objet payment
{
  "amount": 5000,
  "app_id": "VyYjSLf1",
  "created_at": 1791143442,
  "currency": "XAF",
  "driver": "sandbox",
  "fee": 100,
  "id": "lzI2RSXG",
  "marked_by_api_key_id": null,
  "marked_by_user_id": null,
  "message": null,
  "method_label": "Successful payment (test)",
  "note": null,
  "period_id": "tKhKXYjr",
  "provider": "test",
  "provider_reference": "test_92070010bbf2fcf61894",
  "session_id": null,
  "status": "succeeded"
}

L'objet invoice summary

Les endpoints de facture renvoient les factures sous cette forme. Elle ajoute le client et indique si la facture est en retard, et omet app_id, period_id et seller_name.

Attributs

  • idstring

    Identifiant unique de la facture.
  • numberstring

    Le numéro de facture, comme MYST-000124. Voir numéros de facture.
  • statusstring

    open jusqu'au paiement, puis paid. void quand l'abonnement a été annulé avant le paiement, ou qu'un changement de formule l'a remplacée. Une facture annulée devient paid si un paiement que le client avait déjà approuvé passe après son annulation. Voir Paiements qui arrivent en retard.
  • overdueboolean

    true quand la facture est open et que sa due_at est passée. Abuna le calcule chaque fois que vous le demandez. Ce n'est pas un statut.
  • kindstring

    period ou plan_change, comme sur l'objet invoice.
  • amountinteger

    Le montant dû, dans la plus petite unité de la devise.
  • creditinteger

    Le temps inutilisé déduit du tarif, comme sur l'objet invoice.
  • currencystring

    XAF.
  • item_labelstring

    Le nom du tarif.
  • buyer_namestringnullable

    Le nom du client.
  • buyer_emailstringnullable

    L'adresse e-mail du client.
  • subscription_idstring

    L'abonnement auquel appartient la facture.
  • customer_idstring

    Le client de l'abonnement.
  • period_starttimestamp

    Quand la période facturée commence.
  • period_endtimestamp

    Quand la période facturée se termine.
  • due_attimestamp

    La date limite de paiement de la période de facturation (grace_period_ends_at), telle qu'elle est maintenant. Elle peut différer de la due_at de l'objet invoice, qui est fixée à l'émission de la facture.
  • created_attimestamp

    Quand la facture a été émise, en secondes Unix.
  • paid_attimestampnullable

    Quand la facture a été payée.
  • voided_attimestampnullable

    Quand la facture a été annulée. Null de nouveau dès qu'un paiement tardif la rend payée.
L'objet invoice summary
{
  "id": "V2nC8xEi",
  "number": "MYST-000124",
  "status": "open",
  "overdue": false,
  "kind": "period",
  "amount": 5000,
  "credit": 0,
  "currency": "XAF",
  "item_label": "Monthly",
  "buyer_name": "Jane Doe",
  "buyer_email": "jane@example.com",
  "subscription_id": "x9QbL2sK",
  "customer_id": "Cu5tM8rA",
  "period_start": 1727600000,
  "period_end": 1730192000,
  "due_at": 1727686400,
  "created_at": 1727600000,
  "paid_at": null,
  "voided_at": null
}

Lister les factures

GET/v1/apps/{appID}/invoices

Liste les factures de l'application, de la plus récente à la plus ancienne, une page à la fois. Le mode Test et le mode Réel ont des factures distinctes, donc une liste ne montre que le mode de l'application demandée. Tous les paramètres sont facultatifs, et un paramètre vide est ignoré.

Paramètres

  • statusstring

    open, paid, void ou overdue. open inclut les factures en retard. overdue renvoie les factures ouvertes dont la date limite de paiement est passée.
  • searchstring

    Une partie du numéro de facture, du nom de l'acheteur ou de son e-mail. Ignore la casse.
  • fromtimestamp

    Uniquement les factures émises à cette date ou après, en secondes Unix.
  • totimestamp

    Uniquement les factures émises avant cette date, en secondes Unix.
  • customer_idstring

    Uniquement les factures de ce client.
  • limitinteger

    Combien de factures 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.

Attributs de la réponse

  • itemsarray

    Les factures de la page. Vide quand rien ne correspond.
  • next_cursorstringnullable

    Passez-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.

GET /v1/apps/{appID}/invoices
curl "https://api.abuna.app/v1/apps/8ddhXCDW/invoices?status=overdue&limit=50" \
  -H "Authorization: Bearer sk_test_..."
Réponse
{
  "items": [
    {
      "id": "V2nC8xEi",
      "number": "MYST-000124",
      "status": "open",
      "overdue": false,
      "kind": "period",
      "amount": 5000,
      "credit": 0,
      "currency": "XAF",
      "item_label": "Monthly",
      "buyer_name": "Jane Doe",
      "buyer_email": "jane@example.com",
      "subscription_id": "x9QbL2sK",
      "customer_id": "Cu5tM8rA",
      "period_start": 1727600000,
      "period_end": 1730192000,
      "due_at": 1727686400,
      "created_at": 1727600000,
      "paid_at": null,
      "voided_at": null
    }
  ],
  "next_cursor": "MTcyNzYwMDAwMDAwMDAwMC4wMUo5WlE3VjFXMlgzWTRaNUE2QjdDOEQ5RQ"
}

Récupérer une facture

GET/v1/apps/{appID}/invoices/{id}

Récupère une facture avec ses liens et son historique, depuis son émission jusqu'à son paiement ou son annulation.

Attributs de la réponse

  • invoiceobject

  • pay_urlstringnullable

    Le lien de paiement de la période de facturation. Il vaut null dès que la facture est payée ou annulée, ou quand l'abonnement est annulé.
  • invoice_urlstring

    Un lien vers la page de facture du client, qui affiche aussi les factures payées et annulées. Il expire au bout de 7 jours.
  • timelinearray

    Ce qui est arrivé à la facture, du plus ancien au plus récent. Les événements de la même seconde arrivent dans l'ordre ci-dessous.
    Afficher les attributsMasquer les attributs
    • typestring

      • issued  : Abuna a émis la facture.
      • reminder  : Abuna a mis un rappel en file d'attente.
      • notice  : un message au client à propos de la facture.
      • payment  : une tentative de paiement, qu'elle ait réussi, échoué ou soit encore en attente.
      • paid  : la facture a été payée.
      • voided  : la facture a été annulée.
    • attimestamp

      Quand c'est arrivé, en secondes Unix. Pour une notification, quand elle a été envoyée, ou créée si elle n'est pas encore envoyée.
    • noticeobject

      Sur un événement notice  : l'objet notice. Son recipient est vide pour Telegram.
    • paymentobject

      Sur un événement payment  : l'objet payment. Ses status et message indiquent comment la tentative s'est terminée.
    • reminderobject

      Sur un événement reminder  : un objet avec kind, l'une des valeurs renewal_upcoming, payment_overdue ou payment_final_notice.

Renvoie 200. Si l'application n'a aucune facture avec cet identifiant, renvoie 404 avec le code not_found.

GET /v1/apps/{appID}/invoices/{id}
curl https://api.abuna.app/v1/apps/8ddhXCDW/invoices/V2nC8xEi \
  -H "Authorization: Bearer sk_test_..."
Réponse
{
  "invoice": {
    "id": "V2nC8xEi",
    "number": "MYST-000124",
    "status": "open",
    "overdue": false,
    "kind": "period",
    "amount": 5000,
    "credit": 0,
    "currency": "XAF",
    "item_label": "Monthly",
    "buyer_name": "Jane Doe",
    "buyer_email": "jane@example.com",
    "subscription_id": "x9QbL2sK",
    "customer_id": "Cu5tM8rA",
    "period_start": 1727600000,
    "period_end": 1730192000,
    "due_at": 1727686400,
    "created_at": 1727600000,
    "paid_at": null,
    "voided_at": null
  },
  "pay_url": "https://app.abuna.app/pay/3a7e1c9f5b2d8a4e6c0f7b3d9a1e5c8f2b6d",
  "invoice_url": "https://app.abuna.app/invoice/V2nC8xEi?exp=1728204800&sig=b4e1c8f2a7d3960e5b1f8c4a2d7e3b9f6a0c5e8d1b4f7a2c9e6d3b0f8a5c1e7d",
  "timeline": [
    { "type": "issued", "at": 1727600000 },
    {
      "type": "notice",
      "at": 1727600002,
      "notice": {
        "id": "e7JpT4cN",
        "customer_id": "Cu5tM8rA",
        "subscription_id": "x9QbL2sK",
        "kind": "subscription_started",
        "channel": "email",
        "recipient": "jane@example.com",
        "subject": "Pay FCFA 5,000 to start your Pro · Monthly plan with My store",
        "status": "sent",
        "attempts": 1,
        "last_error": null,
        "next_attempt_at": 1727600000,
        "created_at": 1727600000,
        "sent_at": 1727600002
      }
    },
    {
      "type": "payment",
      "at": 1727600090,
      "payment": {
        "id": "m7Yw4NcJ",
        "app_id": "8ddhXCDW",
        "period_id": "T6yVr3Dp",
        "driver": "pawapay",
        "provider": "MTN_MOMO_CMR",
        "provider_reference": "9f3b7d1a-5c2e-8f4b-6d0a-3e7c1b5a9d2f",
        "amount": 5000,
        "currency": "XAF",
        "status": "failed",
        "message": "insufficient_funds",
        "created_at": 1727600090,
        "fee": 100,
        "session_id": null,
        "method_label": "MTN Mobile Money Cameroon"
      }
    },
    { "type": "reminder", "at": 1727686400, "reminder": { "kind": "payment_overdue" } }
  ]
}

Débiter une facture

POST/v1/apps/{appID}/invoices/{id}/charge

Accepte un en-tête Idempotency-Key.

Débite le numéro de téléphone enregistré du client pour une facture ouverte. Le client approuve le paiement sur son téléphone. La requête part vers le réseau auquel appartient le numéro, comme Orange Money pour un numéro camerounais commençant par 69. Quand le préfixe n'indique pas le réseau, elle part vers le réseau avec lequel le client a payé en dernier ; avec pawaPay, pawaPay détermine le réseau à partir du numéro. Avec les paiements Test simulés, le débit réussit toujours. Pour que le client paie plutôt sur une page hébergée, utilisez Créer une session de paiement.

Attributs de la réponse

  • statusstring

    succeeded, ou pending pendant que le client approuve le débit sur son téléphone.
  • paidboolean

    true quand status vaut succeeded.
  • periodobject

    La période de facturation de la facture.

Renvoie 200. Un débit refusé renvoie 402 avec la raison comme code, comme insufficient_funds ou payment_declined. Ces cas échouent aussi  :

  • 403 plan_limit  : le premier paiement du client dépasserait la limite d'abonnés Réels de votre forfait.
  • 404 not_found  : l'application n'a aucune facture avec cet identifiant.
  • 409 already_paid  : la facture est payée.
  • 409 invoice_not_open  : la facture est annulée, parce que l'abonnement a été annulé.
  • 409 payment_in_progress  : un autre paiement pour la facture est encore en attente.
  • 422 not_accepting_payments  : une application Réelle ne peut pas encore encaisser de paiements.
  • 422 payment_unavailable  : votre prestataire n'a aucun réseau capable de débiter le numéro du client dans la devise de la facture.
POST /v1/apps/{appID}/invoices/{id}/charge
curl -X POST https://api.abuna.app/v1/apps/8ddhXCDW/invoices/V2nC8xEi/charge \
  -H "Authorization: Bearer sk_test_..."
Réponse
{
  "status": "succeeded",
  "paid": true,
  "period": {
    "id": "T6yVr3Dp",
    "subscription_id": "x9QbL2sK",
    "price_id": "Zt6YbN3q",
    "pay_token": "3a7e1c9f5b2d8a4e6c0f7b3d9a1e5c8f2b6d",
    "starts_at": 1727600000,
    "ends_at": 1730192000,
    "period_index": 0,
    "grace_period_ends_at": 1727686400,
    "paid_at": 1727600100,
    "paused_at": null,
    "in_force": true,
    "created_at": 1727600000
  }
}

Marquer une facture payée

POST/v1/apps/{appID}/invoices/{id}/mark-paid

Accepte un en-tête Idempotency-Key.

Enregistre que le client a payé une facture ouverte en dehors d'Abuna, par exemple en espèces, par virement bancaire, ou directement sur votre propre numéro de mobile money. Abuna ne débite rien. La facture est alors payée comme n'importe quelle autre  : l'abonnement démarre, se renouvelle ou revient de past_due, vous recevez invoice.paid et les événements d'abonnement qui suivent, et le client reçoit un reçu indiquant que vous avez enregistré son paiement. Un renouvellement marqué payé avant son démarrage conserve ses dates.

Paramètres

  • notestringobligatoire

    Comment le client a payé, pour vos propres archives, comme un reçu ou une référence de virement. De 1 à 500 caractères, les espaces étant retirés aux deux extrémités. Les clients ne la voient jamais.

Attributs de la réponse

  • statusstring

    Toujours succeeded.
  • paidboolean

    Toujours true.
  • periodobject

    La période de facturation de la facture, désormais payée.
  • paymentobject

    Le paiement enregistré  : le montant de la facture, driver et provider à manual, aucun frais, et votre note.

Renvoie 200. Ces cas échouent  :

  • 403 plan_limit  : le premier paiement du client dépasserait la limite d'abonnés Réels de votre forfait.
  • 404 not_found  : l'application n'a aucune facture avec cet identifiant.
  • 409 already_paid  : la facture est payée.
  • 409 invoice_not_open  : la facture est annulée, par exemple parce que l'abonnement a été annulé.
  • 409 payment_in_progress  : un paiement par mobile money pour la facture attend l'approbation du client. Réessayez une fois qu'il a réussi ou échoué.
  • 422 invalid  : la note est manquante ou vide (required) ou dépasse 500 caractères (too_long), dans errors.
POST /v1/apps/{appID}/invoices/{id}/mark-paid
curl https://api.abuna.app/v1/apps/8ddhXCDW/invoices/V2nC8xEi/mark-paid \
  -H "Authorization: Bearer sk_test_..." \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: cash-V2nC8xEi" \
  -d '{
    "note": "Paid cash at the shop, receipt 0042"
  }'
Réponse
{
  "status": "succeeded",
  "paid": true,
  "period": {
    "id": "T6yVr3Dp",
    "subscription_id": "x9QbL2sK",
    "price_id": "Zt6YbN3q",
    "pay_token": "3a7e1c9f5b2d8a4e6c0f7b3d9a1e5c8f2b6d",
    "starts_at": 1727600000,
    "ends_at": 1730192000,
    "period_index": 0,
    "grace_period_ends_at": 1727686400,
    "paid_at": 1727600100,
    "paused_at": null,
    "in_force": true,
    "created_at": 1727600000
  },
  "payment": {
    "amount": 5000,
    "app_id": "VyYjSLf1",
    "created_at": 1791143442,
    "currency": "XAF",
    "driver": "manual",
    "fee": null,
    "id": "lzI2RSXG",
    "marked_by_api_key_id": "01J9ZQ5K2M3N4P5Q6R7S8T9V0W",
    "marked_by_user_id": null,
    "message": null,
    "method_label": "Paid outside Abuna",
    "note": "Paid cash at the shop, receipt 0042",
    "period_id": "tKhKXYjr",
    "provider": "manual",
    "provider_reference": null,
    "session_id": null,
    "status": "succeeded"
  }
}

Étapes suivantes