AgentFlow Enterprise Docs

Stripe Webhook Events

Stripe lifecycle events are verified from the raw body, persisted in Supabase, and used to update checkout, customer, subscription, billing, audit, email, and analytics records.

Endpoint and Signature Verification

PathBehavior
/api/webhooks/stripePrimary implemented webhook route.
/api/stripe/webhookCompatibility route that re-exports the same POST handler.

The handler requires STRIPE_WEBHOOK_SECRET, reads the raw body with request.text(), and calls stripe.webhooks.constructEvent(rawBody, signature, webhookSecret). Requests without stripe-signature return 400.

Idempotency and Persistence

TablePurpose
billing_eventsStores stripe_event_id, event type, raw provider payload, processing_status, error_message, and processed_at. Unique event ids provide idempotency.
checkout_sessionsCheckout route writes created sessions; webhook marks successful sessions as completed.
customersStores organization to Stripe customer mapping.
subscriptionsMirrors Stripe subscription id, customer id, price id, plan, status, period dates, cancellation flags, and cancellation timestamp.
audit_eventsRecords billing lifecycle events for operator review.

If an event already exists and has processed_at, the route returns { "received": true, "duplicate": true }. If an existing event has not finished processing, the handler can mark it back to processing and retry. Handler failures mark the billing event as failed with a truncated safe error message and return 500 so Stripe can retry.

Handled Events

EventSourcePurposeSupabase updateFailure and retry behavior
checkout.session.completedStripe CheckoutActivates the paid checkout lifecycle after successful payment.Resolves checkout_sessions, upserts customers, upserts subscriptions, marks checkout completed, writes audit event, sends confirmation email when SES is configured.Failure marks billing_events.processing_status = failed and returns 500 for Stripe retry.
customer.subscription.createdStripe BillingCreates subscription state from Stripe.Upserts subscriptions and related customers by subscription/customer identifiers.Unknown organization or plan fails when persistence is required.
customer.subscription.updatedStripe BillingKeeps subscription status, price, period, and cancellation flags current.Upserts subscriptions with current Stripe state.Duplicate processed events are skipped; failed events are retryable.
customer.subscription.deletedStripe BillingReflects cancellation/deletion state.Upserts subscriptions with Stripe status and canceled_at where available.Failure is stored on billing_events and retried by Stripe.
invoice.payment_succeededStripe BillingRefreshes subscription state after successful renewal/payment.Retrieves the subscription, upserts subscription/customer, writes billing audit event.Invoices without subscription ids are skipped with a warning.
invoice.payment_failedStripe BillingRefreshes subscription state and triggers payment-failure notification path.Retrieves subscription, upserts state, writes billing audit event, sends payment-failure email when SES is configured, tracks Amplitude event.Failure marks event failed and returns 500.

Sanitized Payload Fragments

checkout.session.completed fragmentjson
{
  "id": "evt_placeholder_checkout",
  "type": "checkout.session.completed",
  "data": {
    "object": {
      "id": "cs_test_placeholder",
      "object": "checkout.session",
      "mode": "subscription",
      "customer": "cus_placeholder",
      "subscription": "sub_placeholder",
      "client_reference_id": "organization_uuid_placeholder",
      "metadata": {
        "organization_id": "organization_uuid_placeholder",
        "user_id": "user_uuid_placeholder",
        "plan_key": "growth",
        "provider": "stripe"
      }
    }
  }
}
customer.subscription.updated fragmentjson
{
  "id": "evt_placeholder_subscription",
  "type": "customer.subscription.updated",
  "data": {
    "object": {
      "id": "sub_placeholder",
      "object": "subscription",
      "customer": "cus_placeholder",
      "status": "active",
      "cancel_at_period_end": false,
      "items": {
        "data": [
          {
            "price": {
              "id": "price_placeholder_growth"
            }
          }
        ]
      },
      "metadata": {
        "organization_id": "organization_uuid_placeholder",
        "plan_key": "growth"
      }
    }
  }
}

Live-mode verification

Live-mode payment, webhook delivery, subscription persistence, failed-payment handling, email delivery, and dashboard access should be tested before public commercial launch if they have not been proven in the target production environment.

These docs describe implementation readiness and configuration. They are not a SOC 2, ISO 27001, penetration test, or contractual SLA claim.