API reference
Events
The record of everything that happened in an app, and every event type.
An event records something that happened in your app, like a paid invoice. Abuna records every event, and also sends it to your webhook URL if you set one.
The event object
Attributes
idstringUnique identifier for the event. A webhook for the event carries the same ID.event_typestringThe event's type.payloadobjectThe event's data. A webhook sends the same object asdata.created_attimestampWhen the event happened, in Unix seconds.
{
"id": "01M4047EV16DJZJQKM0ADM4T99",
"event_type": "invoice.paid",
"payload": {
"kind": "period",
"amount": 5000,
"credit": 0,
"paid_at": 1791005801,
"currency": "XAF",
"entry_id": "01M4047ETRRSRY6EY5FH0X9XCG",
"metadata": {
"user_id": "42"
},
"invoice_id": "01M4047ETS17EJ5ZR31PWQBWF2",
"period_end": 1793684201,
"period_start": 1791005801,
"invoice_number": "01M4047ETSAJKDQ118H6TN7XG0",
"subscription_id": "01M4047ETPMMZ6EWNJQBD1S7W6"
},
"created_at": 1791005801
}List events
GET/v1/apps/{appID}/events
Lists the app's 50 newest events, newest first.
Query parameters
typestringReturns only events of this type, likeinvoice.paid.
Returns an array of event objects. There is no way to page past the newest 50.
curl 'https://api.abuna.app/v1/apps/01J9ZQ4Y7R3T6V8W2X5B1C0DEF/events?type=invoice.paid' \
-H "Authorization: Bearer sk_test_..."[
{
"id": "01M4047EV16DJZJQKM0ADM4T99",
"event_type": "invoice.paid",
"payload": {
"kind": "period",
"amount": 5000,
"credit": 0,
"paid_at": 1791005801,
"currency": "XAF",
"entry_id": "01M4047ETRRSRY6EY5FH0X9XCG",
"metadata": {
"user_id": "42"
},
"invoice_id": "01M4047ETS17EJ5ZR31PWQBWF2",
"period_end": 1793684201,
"period_start": 1791005801,
"invoice_number": "01M4047ETSAJKDQ118H6TN7XG0",
"subscription_id": "01M4047ETPMMZ6EWNJQBD1S7W6"
},
"created_at": 1791005801
}
]Event types
Each type below lists the fields in its payload. IDs are strings, amounts are integers in the currency's smallest unit, and times are Unix seconds.
Subscription, invoice, and plan offer events carry the subscription's metadata when the event was recorded. Session events carry the session's own metadata, not the subscription's. Pass metadata on every session you create. Without it, session events carry {}. The lists below leave metadata out unless noted.
session.completed
A session completed. A session completes at most once, and an expired session never completes. The payload depends on the session's type. Every type has session_id, type, subscription_id, customer_id, metadata (the metadata you passed when you created the session), and completed_at.
checkout(Start a subscription): the first payment succeeded and the subscription is nowactive.subscription.paidis recorded at the same moment. Addsprice_id, the subscription's price.payment(Pay an invoice): the invoice was paid through the session.invoice.paidis also sent. Addsinvoice_id.plan_change(Change plan): the customer confirmed the change, and paid it if it was an upgrade with something to pay. Adds the fields below.cancel(Request a cancel): the customer confirmed the cancel, scheduled or immediate.subscription.updated(scheduled) orsubscription.canceled(immediate) is also sent. Adds the fields below.portal(Open the customer portal): the customer opened the customer portal for the first time. It doesn't mean they changed anything. What they do there sends its own events, likesubscription.updated,subscription.canceled,invoice.paid, andcustomer.updated. Adds nothing.
plan_change payload adds
plan_offer_idstringThe plan offer the session created.previous_price_idstringThe price before the change.price_idstringThe new price.directionstringupgradeordowngrade.effective_attimestampWhen the new price starts. For a downgrade, the end of the paid period:subscription.updatedfires with the price change then.
cancel payload adds
cancel_attimestampnullableWhen the subscription ends.subscription.canceledfires then. Null when it ended right away.immediatebooleantruewhen the subscription ended right away.
session.expired
An open session ran out at its expires_at, or you expired it. Abuna doesn't expire a checkout session on its own while its payment is pending. A pending subscription a checkout session started stays, and ends with checkout_expired if it isn't paid in time.
A payment session also expires when its invoice is paid another way, voided, or its subscription ends. A plan_change session also expires when its offer is replaced, canceled, or expires, or when an upgrade it started lapses unpaid. A cancel session expires 24 hours after creation if the customer doesn't confirm, and a portal session 1 hour after creation if nobody opens it. See Session types.
Payload
session_idstringThe session.typestringThe session's type:checkout,payment,plan_change,cancel, orportal.subscription_idstringnullableThe subscription the session started or acts on. For checkout, null if the customer didn't get that far.customer_idstringnullableThe customer you passed, or the one the customer's details created. Null if neither.price_idstringnullableThe session's price, or null for payment, cancel, and portal sessions.invoice_idstringnullableThe payment session's invoice, or null for other types.plan_offer_idstringnullableThe plan change session's offer, or null for other types.metadataobjectThe metadata you passed when you created the session.expired_attimestampWhen the session expired.
{
"type": "cancel",
"metadata": {
"user_id": "42"
},
"price_id": null,
"expired_at": 1791005801,
"invoice_id": null,
"session_id": "01M4047EV7TVR4KQQJXTVRX36B",
"customer_id": "01M4047ETN25J0H6E8P8ZX9QGZ",
"plan_offer_id": null,
"subscription_id": "01M4047ETPMMZ6EWNJQBD1S7W6"
}subscription.created
A subscription was created, through the API, a checkout session, or a checkout link. It is still pending.
Payload
subscription_idstringThe new subscription.customer_idstringIts customer.price_idstringIts price.entry_idstringIts first billing period.
subscription.paid
The first billing period was paid, so the subscription is now active. Later payments send only invoice.paid.
Payload
subscription_idstringThe subscription.customer_idstringIts customer.price_idstringIts price.entry_idstringThe paid billing period.activated_attimestampWhen the subscription became active.
subscription.renewed
A paid billing period ended, and Abuna started the next one. The customer now owes it.
Payload
subscription_idstringThe subscription.entry_idstringThe new billing period.amountintegerThe amount due for the new period.currencystringXAForXOF.
subscription.updated
Something scheduled or changed on an active subscription. It fires when a cancel at the end of the paid period is scheduled or undone, when the price changes (an upgrade takes effect, or a scheduled downgrade starts), when a downgrade is scheduled or undone, when an upgrade waiting for payment lapses, and when a new change clears an earlier one. For a scheduled cancel, subscription.canceled follows when it ends. See Changing plan.
Payload
subscription_idstringThe subscription.price_idstringThe price the subscription is on now.cancel_attimestampnullableWhen the subscription will end, if a cancel is scheduled. Null otherwise.scheduled_price_changeobjectnullableThe downgrade scheduled for the end of the paid period. Null when none is.Show child attributesHide child attributes
price_idstringThe price the subscription moves to.effective_attimestampWhen it moves.
changeobjectWhat happened to the price. Present only when the price changed or a downgrade was scheduled or undone. A lapsed upgrade, a cancel at the end of the period, and an upgrade that starts waiting for payment have none.Show child attributesHide child attributes
typestringprice_changed,downgrade_scheduled, ordowngrade_undone.old_price_idstringThe price before.new_price_idstringThe new price, or the scheduled one.effective_attimestampWhen the change took effect, or when the scheduled one will.
updated_bystringmerchantwhen you changed it, orcustomerwhen they changed it in the customer portal. When a plan change is carried out later (a paid upgrade, a downgrade that starts, an upgrade that lapses), it is whoever asked for it:customerfrom the portal, ormerchantwhen they confirmed a change you sent them to.
subscription.canceled
The subscription ended. It fires when the subscription really ends: right away for a cancel now, or at the end of the paid period for a scheduled cancel. Scheduling a cancel sends subscription.updated instead.
Payload
subscription_idstringThe subscription.reasonstringWhy it ended:merchant(you canceled it),customer(they canceled in the customer portal),non_payment(a renewal passed its pay-by date), orcheckout_expired(the first period was never paid). A scheduled cancel that ends keeps who scheduled it,merchantorcustomer.
plan_offer.created
A Change plan session made a plan offer, or you offered a change from the dashboard and Abuna sent the customer the link. A session sends nothing to the customer. Resending the link from the dashboard doesn't fire it again. The four plan_offer events share one payload.
Payload
offer_idstringThe offer.subscription_idstringThe subscription.price_idstringThe price offered.expires_attimestampWhen the offer stops working.
plan_offer.confirmed
The customer accepted the offer. A downgrade is now scheduled, or an upgrade is applied or waiting for payment. subscription.updated fires when the price changes or the downgrade is scheduled.
plan_offer.canceled
The offer stopped before the customer accepted it. The payload adds reason: merchant when you canceled it, or replaced when a new offer or the customer's own plan change took its place.
plan_offer.expired
The offer reached its expires_at without being accepted.
invoice.created
Abuna issued an invoice for a new billing period, or for an upgrade. An upgrade waiting for payment gets its period dates when it is paid, and invoice.paid carries them.
Payload
invoice_idstringThe invoice.invoice_numberstringIts number.subscription_idstringIts subscription.entry_idstringThe billing period it bills.kindstringperiodfor a billing period, orplan_changefor the first period of an upgrade.amountintegerThe amount due.creditintegerThe unused time of the current period taken off the new price.0on aperiodinvoice.currencystringXAForXOF.period_starttimestampWhen the period starts.period_endtimestampWhen the period ends.
invoice.paid
An invoice was paid. The payload has every invoice.created field, plus one.
Payload
paid_attimestampWhen it was paid.
invoice.payment_failed
A payment on an invoice failed. The invoice stays open, so the customer can try again before the pay-by date.
Payload
subscription_idstringThe subscription.entry_idstringThe billing period.invoice_idstringThe invoice.invoice_numberstringIts number.provider_referencestringThe provider's ID for the charge. Empty if it gave none.messagestringThe provider's message. Empty if it gave none.
customer.updated
A customer's name, email, or phone number changed.
Payload
customer_idstringThe customer.namestringnullableTheir name now.emailstringTheir email address now.phone_numberstringTheir phone number now.updated_bystringmerchantwhen you changed it, orcustomerwhen they changed it in the customer portal.
price_change.scheduled
You scheduled a new amount for a price, or replaced the one that was pending. The three price_change events share one payload.
Payload
price_change_idstringThe change.price_idstringThe price.amountintegerThe new amount.previous_amountintegerThe amount before the change.currencystringXAForXOF.effective_attimestampThe start of the day the new amount applies from, in your app's time zone.keep_current_subscribersbooleantruewhen everyone subscribed on that day keeps the old amount.
price_change.canceled
A pending change stopped before its day. The payload adds reason: merchant when you canceled it, or replaced when you scheduled a new change in its place. A replacement also sends price_change.scheduled.
price_change.applied
The price's amount switched to the new one on its effective_at. From then on, checkouts and new subscriptions pay it. Current subscribers move to it at their next renewal, unless keep_current_subscribers is true.
notification.captured
Test mode only. Abuna wrote a notice to a Test customer and kept it instead of sending it. This event never goes to your webhook URL.
Payload
customer_idstringThe customer.kindstringWhat the notice is about. See notice kinds.channelstringemailortelegram.recipientstringThe email address or Telegram chat it would have gone to.subjectstringThe subject line.textstringThe message, as plain text.sentbooleanAlwaysfalse.