Fired when a subscription charge fails, including resume charges and recovery attempts
All webhook payloads follow a consistent top-level structure with event-specific data nested within the data object.
The original reason for a charge and how this attempt was initiated. Recovery never replaces the original reason. Context can be null when it was not captured, including retries of historical invoices.
The invoice ID, if available.
The human-readable invoice number, if available.
The customer ID. Returns your externalId if you provided one when creating the customer, otherwise returns the Commet publicId.
The subscription ID, if the invoice is linked to a subscription.
The payment provider the charge was routed to: stripe, commet, or dlocal.
The payment method: card, oxxo, or mercado_pago. Null when unknown.
The source of funds for this charge, when reported by the provider. Null when unavailable or unknown.
The failure code from the payment processor.
A human-readable failure message.
A ready-to-use link the customer can follow to retry this payment, or null when no recovery path applies. For a first failed charge (pending_payment) it is the checkout URL; for a failed renewal (past_due) it is a signed recovery link — no separate createRecoveryLink call needed.
The original charge attempt, before recovery.
{
"event": "payment.failed",
"timestamp": "2026-06-23T14:30:00.000Z",
"organizationId": "8f14e45f-ceea-4e7a-9c3d-1c2b3a4d5e6f",
"mode": "live",
"apiVersion": "2026-08-27",
"data": {
"paymentContext": {
"reason": "recurring_billing",
"paymentLinkId": null,
"recovery": null
},
"invoiceId": "inv_n4o5p6",
"invoiceNumber": "INV-0043",
"customerId": "user_123",
"subscriptionId": "sub_1a2b3c4d",
"provider": "stripe",
"paymentMethod": "card",
"subPaymentMethod": null,
"failureCode": "card_declined",
"failureMessage": "Your card was declined.",
"recoveryUrl": "https://pay.commet.co/recover/tok_9f8e7d6c"
}
}How is this guide?