Webhooks
Dacard.ai uses Stripe webhooks to handle subscription lifecycle events. When a billing event occurs in Stripe, it sends a signed webhook to the platform, which processes the event and updates account state accordingly.Webhook endpoint
Supported events
| Event | Description |
|---|---|
checkout.session.completed | A customer completed a checkout session. Creates or upgrades the subscription. |
customer.subscription.updated | A subscription was modified (plan change, renewal, payment method update). |
customer.subscription.deleted | A subscription was cancelled or expired. Downgrades the account to the free plan. |
invoice.payment_succeeded | A payment was successfully processed. Resets monthly credit usage. |
invoice.payment_failed | A payment attempt failed. May trigger grace period or account restriction. |
Signature verification
Every incoming webhook is verified using the Stripe webhook signing secret. Requests with invalid signatures are rejected with a400 Bad Request.
The signing secret is stored as an environment variable (STRIPE_WEBHOOK_SECRET) and is never exposed to the client.
Subscription lifecycle
- User signs up on the Free plan (no Stripe involvement)
- User initiates upgrade via
POST /api/stripe/checkoutto create a Stripe Checkout Session - On successful payment,
checkout.session.completedfires and the account is upgraded - Monthly renewals trigger
invoice.payment_succeeded, resetting credit counters - Cancellation triggers
customer.subscription.deleted, downgrading to Free
Retry behavior
Stripe retries failed webhook deliveries with exponential backoff for up to 3 days. The webhook handler is idempotent, so duplicate deliveries are safe.Testing webhooks locally
Use the Stripe CLI to forward events to your local dev server:Related endpoints
- Create Checkout Session, Initiate a Stripe checkout
- Create Billing Portal Session, Manage existing subscriptions