Fix: payment_intent.created Webhook Now Fires Correctly
Fix: payment_intent.created Webhook Now Fires Correctly
Version: 1.0.90
Overview
Prior to this release, the payment_intent.created webhook event type was advertised as subscribable but never actually emitted. This post explains what was broken, why it matters, and what you need to do (if anything).
Background: Webhook Event Subscriptions
Calmony Pay allows you to register webhook endpoints and filter them by event type. The set of valid event types is defined server-side in the KNOWN_EVENT_TYPES constant. Registering for an unknown type is rejected; registering for a known type is accepted and stored.
As of v1.0.90, the following lifecycle events are emitted for payment intents:
| Event | Fired when |
|---|---|
payment_intent.created | A new payment intent resource is created via POST /v1/payment_intents |
payment_intent.succeeded | A payment intent is confirmed and the charge succeeds |
payment_intent.failed | A payment intent confirmation fails |
What Was Broken
payment_intent.created was listed in KNOWN_EVENT_TYPES, so the API accepted subscriptions for it. However, the POST /v1/payment_intents handler never called emitPayEvent with this type. The event was never dispatched — to any subscriber, under any circumstances.
This created a silently broken subscription: no error was returned when registering, but no events were ever delivered. The same gap existed for payment intents created internally by the subscription billing engine.
This is a deviation from the Calmony Pay REST API Contract, which requires webhook events to fire on all resource lifecycle transitions.
What Changed in v1.0.90
POST /v1/payment_intentsnow emitspayment_intent.createdimmediately after the payment intent resource is persisted.- Subscription billing (
subscription-billing.ts) also emitspayment_intent.createdfor any payment intent it creates internally, ensuring parity between manual and automated payment flows.
No changes were made to payment_intent.succeeded or payment_intent.failed — these were already firing correctly.
Migration Guide
If you were subscribed to payment_intent.created
Your endpoint will now start receiving events. No changes to your webhook registration are required.
Verify your handler can process a payload shaped like:
{
"type": "payment_intent.created",
"data": {
"object": {
"id": "pi_...",
"amount": 2500,
"currency": "gbp",
"status": "requires_confirmation"
}
}
}
If you were working around the missing event
Some integrations may have inferred payment intent creation indirectly — for example, by listening to payment_intent.succeeded and treating it as a proxy for creation. Now that payment_intent.created fires reliably, you can subscribe to it directly for a more accurate signal.
If you were not subscribed to payment_intent.created
No action needed. This fix has no effect on endpoints that do not include payment_intent.created in their event filter.
Affected Files
src/app/api/v1/payment_intents/route.tssrc/app/api/v1/payment_intents/[id]/confirm/route.tssrc/inngest/functions/subscription-billing.ts