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.

RouteMethodsAuthPurpose
/api/stripe/check-sessionGETSessionInspect a Stripe Checkout session by session_id
/api/stripe/create-checkout-sessionPOSTSessionCreate a checkout flow from one or more purchase keys and return a client secret
/api/stripe/create-customerPOSTSessionCreate or reuse the caller's Stripe customer record and customer mapping
/api/stripe/cancel-subscriptionPOSTSessionCancel a subscription by subscriptionId
/api/stripe/resume-subscriptionPOSTSessionResume a paused or canceled subscription by subscriptionId
/api/stripe/reconcile-sessionPOSTSessionVerify checkout by sessionId, dedupe repeat processing, reconcile billing snapshots, and return the final entitlement state after purchase
/api/stripe/verify-and-update-rolePOSTSessionCompatibility alias to the same reconcile-session handler for older success flows
/api/stripe/webhookPOSTStripe signatureProcess 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.

RouteMethodsAuthPurpose
/api-dashboard/keys/generatePOSTSessionCreate a named API key for the authenticated user and return the plaintext apiKey once
/api-dashboard/keys/deactivatePOSTSession + key ownershipDeactivate an owned API key by keyId
Generate an API key from the signed-in Console session
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"}'
Deactivate an owned key
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

RouteMethodsAuthPurpose
/api/admin/billing-entitlement-discrepanciesGET POSTAdmin sessionAudit billing entitlement drift versus local billing snapshots and trigger safe recompute-based repairs
/api/admin/stripe-role-discrepanciesGET POSTAdmin sessionCompatibility alias that currently reuses the billing-entitlement-discrepancies handler
/api/admin/backfill-milestonesPOSTSession plus member-role checkRun 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.

Related links