Operations
Billing and admin routes
Stripe lifecycle routes, Console-adjacent account flows, webhook processing, and admin-only maintenance endpoints.
The billing and admin layer sits behind the Parchment Console and subscription flows. These routes are operational, not public APIs.
Most billing routes require a user session. The Stripe webhook requires a valid Stripe signature. Admin routes should be treated as support and maintenance surfaces.
Stripe and Console-adjacent routes
create-checkout-session accepts purchaseKey or purchaseKeys, rejects unknown or non-self-serve entries, and returns 409 when the request mixes same-family plans or conflicts with an existing active subscription.
cancel-subscription and resume-subscription are intentionally limited to membership subscriptions and return 409 when the same Stripe subscription also bundles API or Parchment Intelligence products.
| Route | Methods | Auth | Purpose |
|---|---|---|---|
| /api/stripe/check-session | GET | Session | Inspect a Stripe Checkout session by session_id |
| /api/stripe/create-checkout-session | POST | Session | Create a checkout flow from one or more purchase keys and return a client secret |
| /api/stripe/create-customer | POST | Session | Create or reuse the caller's Stripe customer record and customer mapping |
| /api/stripe/cancel-subscription | POST | Session | Cancel a subscription by subscriptionId |
| /api/stripe/resume-subscription | POST | Session | Resume a paused or canceled subscription by subscriptionId |
| /api/stripe/reconcile-session | POST | Session | Verify checkout by sessionId, dedupe repeat processing, reconcile billing snapshots, and return the final entitlement state after purchase |
| /api/stripe/verify-and-update-role | POST | Session | Compatibility alias to the same reconcile-session handler for older success flows |
| /api/stripe/webhook | POST | Stripe signature | Process checkout and subscription lifecycle events |
Console key management routes
These are Console control-plane routes, not public API contracts. A browser session is required because key creation and deactivation mutate the signed-in account.
generate requires a non-empty JSON name field and returns apiKey only in the creation response. Store it immediately; later Console views should show metadata, not the secret.
deactivate requires keyId and verifies ownership before marking a key inactive. There is no public delete-by-secret flow.
| Route | Methods | Auth | Purpose |
|---|---|---|---|
| /api-dashboard/keys/generate | POST | Session | Create a named API key for the authenticated user and return the plaintext apiKey once |
| /api-dashboard/keys/deactivate | POST | Session + key ownership | Deactivate an owned API key by keyId |
curl -X POST https://purveyors.io/api-dashboard/keys/generate -H "Content-Type: application/json" -H "Cookie: <signed-in session cookie>" -d '{"name":"local sync job"}'curl -X POST https://purveyors.io/api-dashboard/keys/deactivate -H "Content-Type: application/json" -H "Cookie: <signed-in session cookie>" -d '{"keyId":"api_key_row_id"}'Admin routes
| Route | Methods | Auth | Purpose |
|---|---|---|---|
| /api/admin/billing-entitlement-discrepancies | GET POST | Admin session | Audit billing entitlement drift versus local billing snapshots and trigger safe recompute-based repairs |
| /api/admin/stripe-role-discrepancies | GET POST | Admin session | Compatibility alias that currently reuses the billing-entitlement-discrepancies handler |
| /api/admin/backfill-milestones | POST | Session plus member-role check | Run milestone backfill logic for roast-related calculations |
Admin namespace does not mean uniform admin enforcement
Today, /api/admin/billing-entitlement-discrepancies uses centralized admin validation, but /api/admin/backfill-milestones currently checks for a member role rather than admin. Keep docs truthful about the current behavior and treat that mismatch as implementation debt, not documentation ambiguity.
Operational notes
- Billing docs should always cross-link to /api-dashboard because that is the user-facing surface for keys, usage, and subscription state.
- Webhook routes are machine-to-machine infrastructure and should never be presented as browser-consumable product APIs.
- GET /api/docs and GET /api-dashboard/docs are legacy docs handoff routes that redirect to /docs/api/overview.
- When role-sync behavior changes, review subscription success flows, webhook docs, Console key-management docs, and admin discrepancy tooling together.