Handle Failed Payments
What happens when a customer's payment fails and how they can reactivate from the Customer Portal.
When a payment fails, the subscription moves to past_due status and feature access is revoked immediately. Customers can reactivate their subscription from the Customer Portal by retrying payment or updating their card.
What happens when a payment fails
- The subscription status changes to
past_due - Feature access is revoked immediately
- The customer receives an email notification
- The failed invoice is marked as
uncollectible
The subscription stays in past_due until the customer reactivates from the portal or an admin cancels it manually.
Check subscription status
const { data } = await commet.subscriptions.get('user_123')
if (data.status === 'past_due') {
// Payment failed — prompt customer to reactivate from the portal
}response = commet.subscriptions.get(customer_id='user_123')
if response.data['status'] == 'past_due':
# Payment failed — prompt customer to reactivate from the portal
passresult, err := client.Subscriptions.Get(ctx, "user_123")
if result.Data.Status == "past_due" {
// Payment failed — prompt customer to reactivate from the portal
}ApiResponse<Subscription> result = commet.subscriptions().get("user_123");
if ("past_due".equals(result.getData().getStatus())) {
// Payment failed — prompt customer to reactivate from the portal
}$result = $commet->subscriptions->get('user_123');
if ($result->data['status'] === 'past_due') {
// Payment failed — prompt customer to reactivate from the portal
}curl "https://commet.co/api/subscriptions/active?customerId=user_123" \
-H "x-api-key: $COMMET_API_KEY"Gate access based on status
Only active and trialing subscriptions have feature access. past_due subscriptions are blocked until the customer reactivates from the portal.
const { data } = await commet.subscriptions.get('user_123')
const hasAccess = data.status === 'active' || data.status === 'trialing'response = commet.subscriptions.get(customer_id='user_123')
has_access = response.data['status'] in ('active', 'trialing')result, err := client.Subscriptions.Get(ctx, "user_123")
status := result.Data.Status
hasAccess := status == "active" || status == "trialing"ApiResponse<Subscription> result = commet.subscriptions().get("user_123");
String status = result.getData().getStatus();
boolean hasAccess = "active".equals(status) || "trialing".equals(status);$result = $commet->subscriptions->get('user_123');
$hasAccess = in_array($result->data['status'], ['active', 'trialing'], true);curl "https://commet.co/api/subscriptions/active?customerId=user_123" \
-H "x-api-key: $COMMET_API_KEY"Customer Portal reactivation
Customers in past_due see their subscription in the Customer Portal with a Reactivate Subscription button. They can choose:
- Retry with their current card — useful when the failure was temporary (insufficient funds that are now available, a bank hold that cleared).
- Update their payment method — enter a new card via Stripe and retry in the same step.
A successful retry moves the subscription back to active, voids the failed invoices, and emits a payment.recovered event. Retry attempts are rate-limited to 3 per day per customer.
Prompt payment update
Redirect customers to the Customer Portal to reactivate:
const portal = await commet.portal.getUrl({ customerId: 'user_123' })
redirect(portal.data.portalUrl)portal = commet.portal.get_url(customer_id='user_123')
redirect(portal.data['portal_url'])portal, err := client.Portal.GetURL(ctx, &commet.GetPortalURLParams{
CustomerID: "user_123",
})
// redirect(portal.Data.PortalURL)ApiResponse<PortalSession> portal = commet.portal().getUrl("user_123", null, null);
// redirect(portal.getData().getPortalUrl())$portal = $commet->portal->getUrl(customerId: 'user_123');
redirect($portal->data['portalUrl']);curl -X POST https://commet.co/api/portal/request-access \
-H "x-api-key: $COMMET_API_KEY" \
-H "Content-Type: application/json" \
-d '{"customerId": "user_123"}'Related
- Invoices and Billing Cycles — Invoice types and charge timing
- Manage Subscriptions — Create and manage customer subscriptions
- Customer Portal — Self-service billing portal for customers
How is this guide?