Apache-3 BidOps · Docs · 05
Webhook events (Stripe)
Event types Apache-3's payment pipeline handles and the corresponding Supabase table writes.
Stripe webhook endpoint: https://learntrainai.com/api/webhooks/stripe. All payment events flow through it.
Subscribed events
| Stripe event | Trigger | Supabase write |
|---|---|---|
checkout.session.completed (metadata.product = "prompt_to_product_book") |
Direct book purchase ($19.95) | book_orders upsert |
checkout.session.completed (metadata.product = "cohort_qualifying_deposit") |
$1k cohort deposit | cohort_deposits upsert |
checkout.session.completed (metadata.product = "alumni_coaching_subscription") |
Initial subscription | alumni_subscriptions upsert |
customer.subscription.created |
Subscription created (often duplicates checkout.session.completed) | alumni_subscriptions update |
customer.subscription.updated |
Plan change, status change, cancel-at-period-end | alumni_subscriptions update |
customer.subscription.deleted |
Subscription canceled at period end or hard-canceled | alumni_subscriptions update (status = canceled) |
Required env (Vercel)
STRIPE_SECRET_KEY(sk_test_... or sk_live_...)STRIPE_WEBHOOK_SECRET(whsec_... from Stripe Dashboard webhook configuration)SUPABASE_SERVICE_ROLE_KEY(service role for the learntrainai Supabase project)NEXT_PUBLIC_SUPABASE_URLRESEND_API_KEY(for confirmation emails)
Idempotency
All inserts use upsert with onConflict: stripe_session_id (for checkout-derived rows) or stripe_subscription_id (for subscription lifecycle). Stripe retries on 5xx responses; the upsert ensures repeated processing is safe.
Email side-effects
Each successful webhook event triggers Resend emails:
- Book order: confirmation to buyer with fulfillment timeline (24h digital, 5 business days paperback)
- Cohort deposit: confirmation to buyer + notification to
apache3corp@gmail.comfor fit-call scheduling - Alumni subscription: welcome to subscriber + admin notification
RLS posture
All three tables are RLS-locked:
- No anon access
authenticatedusers can SELECT only if their JWT email is on the admin allowlist (s@apache-3.com,naveen@apache-3.com,apache3corp@gmail.com,snake@apache-3.com)- Writes are exclusively via the service-role key in the webhook handler
How to test locally
stripe listen --forward-to localhost:3000/api/webhooks/stripe
# In a separate shell:
curl -X POST localhost:3000/api/checkout/book -d '{}' -H 'content-type: application/json'
# Click the resulting URL in a browser and use card 4242 4242 4242 4242
Production webhook URL
Configure at: https://dashboard.stripe.com/test/webhooks (test mode) or https://dashboard.stripe.com/webhooks (live).
Endpoint: https://learntrainai.com/api/webhooks/stripe
Events to subscribe to (minimum):
checkout.session.completedcustomer.subscription.createdcustomer.subscription.updatedcustomer.subscription.deleted