X Enterprises
fastify-xadmin

Stripe Routes

Admin Stripe billing endpoints — customers, subscriptions, invoices, payment methods, and webhook logs under /api/admin/stripe, backed by the fastify.stripe decorator from xStripe.

Stripe Routes

Admin endpoints for reading and acting on Stripe billing state: customers, subscriptions, invoices, payment methods, and webhook event logs.

These routes reuse the fastify.stripe decorator registered by @xenterprises/fastify-xstripe — xAdmin never creates Stripe clients and never sees a Stripe secret key. Whether the routes are active is controlled by the stripe.enabled option, which auto-detects: it defaults to true when a fastify.stripe decorator exists and false otherwise. Explicitly passing stripe: { enabled: true } without the decorator logs a registration warning, and every Stripe route then returns 503 (Stripe is not configured. Register xStripe plugin first.). The consumer sets any Stripe env vars (e.g. STRIPE_SECRET_KEY) and passes them to xStripe's registration options — never to xAdmin.

await app.register(xStripe, { secretKey: process.env.STRIPE_SECRET_KEY }); // consumer-owned env access
await app.register(xAdmin); // stripe.enabled auto-detects fastify.stripe

Routes

MethodPathPermissionDescription
GET/api/admin/stripe/customersbilling:readList customers
GET/api/admin/stripe/customers/:idbilling:readGet customer (expanded)
POST/api/admin/stripe/customers/:id/syncbilling:manageSync from Stripe
GET/api/admin/stripe/subscriptionsbilling:readList subscriptions
POST/api/admin/stripe/subscriptions/:id/cancelbilling:manageCancel subscription
GET/api/admin/stripe/invoicesinvoices:readList invoices
POST/api/admin/stripe/invoices/:id/refundinvoices:refundRefund invoice
POST/api/admin/stripe/invoices/:id/voidbilling:manageVoid invoice
GET/api/admin/stripe/payment-methodsbilling:readList payment methods
GET/api/admin/stripe/webhook-logsbilling:readList webhook events (requires StripeWebhookLog model)

All routes except /webhook-logs run a Stripe-availability preHandler and return 503 when fastify.stripe is missing. /webhook-logs reads from the database only and simply returns an empty list when the optional StripeWebhookLog model does not exist.


GET /api/admin/stripe/customers

List Stripe customers.

Query Parameters

NameTypeDefaultDescription
limitnumber20Results to return (1–100).
starting_afterstringStripe cursor for the next page.
searchstringFilter by email.

Response data is a flattened customer shape (id, email, name, phone, balance, currency, defaultPaymentMethodId, created, metadata); meta.hasMore indicates another page.


GET /api/admin/stripe/customers/:id

Retrieve a single customer with subscriptions and invoice_settings.default_payment_method expanded. Returns the raw Stripe customer object in data.


POST /api/admin/stripe/customers/:id/sync

Re-fetch a customer from Stripe and record a sync audit entry. Returns { id, syncedAt, changes } (changes is currently always []).


GET /api/admin/stripe/subscriptions

List subscriptions with customer expanded.

Query Parameters

NameTypeDefaultDescription
limitnumber20Results to return (1–100).
starting_afterstringStripe cursor for the next page.
customerIdstringFilter by Stripe customer ID.
statusstringFilter by subscription status.

POST /api/admin/stripe/subscriptions/:id/cancel

Cancel a subscription.

Body Fields

FieldTypeRequiredDescription
immediatelybooleanNotrue cancels now; default false sets cancel_at_period_end.
reasonstringNoRecorded in the audit entry metadata.

GET /api/admin/stripe/invoices

List invoices with customer expanded. Same query parameters as /subscriptions (limit, starting_after, customerId, status). Response data includes amounts, hostedInvoiceUrl, and invoicePdf.


POST /api/admin/stripe/invoices/:id/refund

Refund a paid invoice via its payment intent.

Body Fields

FieldTypeRequiredDescription
amountnumberNoPartial refund amount in cents (integer ≥ 1). Omit for a full refund.
reasonstringNoRecorded in the audit entry; sent to Stripe as requested_by_customer when present.

Returns 400 (Can only refund paid invoices) unless the invoice status is paid.


POST /api/admin/stripe/invoices/:id/void

Void an invoice. Returns 400 (Can only void draft or open invoices) unless the invoice status is draft or open.


GET /api/admin/stripe/payment-methods

List a customer's payment methods, flagging the default.

Query Parameters

NameTypeDefaultDescription
customerIdstringRequiredStripe customer ID.
typestringcardPayment method type.
limitnumber20Results to return (1–100).

Missing customerId is rejected with a 400 by querystring validation.


GET /api/admin/stripe/webhook-logs

Paginated list of processed webhook events from the StripeWebhookLog Prisma model. Returns an empty list when the model does not exist.

Query Parameters

NameTypeDefaultDescription
pagenumber1Page number (1-indexed).
limitnumberResults per page (1–100).
eventTypestringFilter by event type (contains).
statusstringFilter by processing status.

AI Context

package: "@xenterprises/fastify-xadmin"
routes:
  - GET /api/admin/stripe/customers — list; query: limit, starting_after, search (email)
  - GET /api/admin/stripe/customers/:id — retrieve with subscriptions + default PM expanded
  - POST /api/admin/stripe/customers/:id/sync — re-fetch + audit entry
  - GET /api/admin/stripe/subscriptions — list; query: limit, starting_after, customerId, status
  - POST /api/admin/stripe/subscriptions/:id/cancel — body: immediately (bool), reason
  - GET /api/admin/stripe/invoices — list; query: limit, starting_after, customerId, status
  - POST /api/admin/stripe/invoices/:id/refund — body: amount (cents), reason; 400 unless paid
  - POST /api/admin/stripe/invoices/:id/void — 400 unless draft/open
  - GET /api/admin/stripe/payment-methods — query: customerId (required), type, limit
  - GET /api/admin/stripe/webhook-logs — DB list; query: page, limit, eventType, status; [] without StripeWebhookLog model
permissions: billing:read, billing:manage, invoices:read, invoices:refund
requires: fastify.stripe decorator from xStripe (auto-detected via stripe.enabled); routes 503 without it
env: none on xAdmin — consumer passes Stripe keys to xStripe registration, not xAdmin

See Also

Copyright © 2026