Subscription and payment events through webhooks

Webhooks notify an external system when Alunta records a change. They are useful when a customer portal, CRM, or accounting system needs to follow subscriptions without polling Alunta continuously. An event is a signal about Alunta's state; it does not confirm that your own system has completed its follow-up action.

All product updates

Historical retrospective: November 2025 to August 2026; changed since February to August 2026

This article was written afterwards and describes the feature as it was expanded during the stated period. Webhook events grew from the basic subscription lifecycle to include resumption, payment failures, and payment outcomes. See the public API and webhooks guide (Markdown file, AI agent-friendly) for the current event list and contract.

Webhooks notify an external system when Alunta records a change. They are useful when a customer portal, CRM, or accounting system needs to follow subscriptions without polling Alunta continuously. An event is a signal about Alunta’s state; it does not confirm that your own system has completed its follow-up action.

The main events

The lifecycle can include subscription.started, subscription.ended, and subscription.resumed. Cancellation and ending are different: cancellation can schedule or mark that an agreement should stop, while ending says that the subscription has actually ended. Later, subscription.payment_succeeded and subscription.payment_failed were added so an integration can react to each payment outcome. payment_succeeded confirms the payment itself, but a partial payment or installment can leave an invoice balance. An invoice.paid event describes the invoice’s payment state and should not be treated as proof that a subscription is active.

Use the documented event type and the deduplication key provided for that event type. subscription.started, subscription.ended, subscription.payment_succeeded, and invoice.paid have a stable data.event_id for retries and replays. subscription.payment_failed can arrive more than once for separate retry attempts and has no stable event_id; retain each delivery and use the documented webhook_uuid, where available, as the delivery key. Subscribe only to events the integration needs, and always use the current public API reference for fields and status values.

Getting started

  1. Enable the API/webhook capability for the team and create an HTTPS receiver.
  2. Register the endpoint and choose the required subscription and payment events.
  3. Verify the signature against the raw request body before processing the payload.
  4. Store the key documented for the specific event type and process it idempotently. Use data.event_id for event types that provide a stable key, retain separate subscription.payment_failed attempts, and use webhook_uuid as delivery identity where available. A repeated delivery must produce the same final state as the first without merging distinct payment attempts.
  5. Return a successful HTTP status quickly, then perform longer processing afterwards.

When a subscription starts, ends, resumes, or has a payment failure, use the relevant stable key and the payload’s subscription and invoice relations to update your local view. Use the event type together with those relations; do not use delivery order alone as a business rule.

Common questions

Why did the same event arrive again? Deliveries may be repeated after an error or timeout. Deduplicate data.event_id when the specific event type documents it, or use webhook_uuid as delivery identity where available. Retain separate payment-failure attempts even when they concern the same subscription.

Is payment_failed the same as cancellation? No. It is a payment outcome. Read the current subscription status separately.

What if the receiver was unavailable? Open the delivery log, fix the receiver, and replay the failed delivery when the integration is ready.

See the public API and webhooks guide (Markdown file, AI agent-friendly) for the current workflow.

Choose the event for the business need

A customer portal can listen for subscription.started to show access, subscription.ended to close an agreement, and subscription.resumed to open it again. An accounting system can listen for invoice.paid to mark a receivable as paid. A support or payment system can use subscription.payment_succeeded and subscription.payment_failed to show payment outcomes. Do not conflate the events: a partial payment is not necessarily a paid invoice, and a payment failure is not itself a cancellation.

Store a local receipt with the event type, relevant key, and receipt time. Only process the business action after signature verification. If the same stable event_id arrives again, the receiver still returns a successful response but skips the completed action. Do not merge separate payment-failure deliveries only because they share a subscription UUID. If events arrive in an unexpected order, fetch current subscription or invoice state before changing local status.

Why did no event arrive? Check the endpoint, selected event, team’s API access, and delivery log. A product capability is not automatically a webhook until the event exists in the public contract.

Can a webhook trigger an action? Yes, in your system, but make the action idempotent and show which Alunta status it relies on.

Bo Møller
Bo Møller
Emil Højbjerg
Emil Højbjerg

The people and AI helpers behind the updates

Bo Møller and Emil Højbjerg are the primary developers behind Alunta. They spend most of their time coding, so they have delegated the wording of these explanations to our AI helpers.

The AI helpers write from the updates we have deployed to the product. Bo and Emil are behind the changes and remain responsible for ensuring the information reflects what was actually released.