đŗ Subscription & Payments
Stripe-powered subscription management. Supports Stripe Checkout (redirect flow) and direct card payment (PaymentMethod ID flow). Webhooks handle all async payment state changes.
POST /api/webhook/stripe. After checkout completion, allow a few seconds for the webhook to finalize the subscription.
Get All Plans
âļReturns all active subscription plans ordered by plan.order. Each plan includes its available price options (monthly, quarterly, annual).
{
"success": true,
"data": {
"plans": [
{
"id": "plan_basic",
"name": "Basic",
"description": "Perfect for individuals getting started",
"currency": "usd",
"order": 1,
"status": "active",
"color": "#6366f1",
"isTrialAllowed": true,
"trialDays": 14,
"settings": { "max_tools": 5 },
"metadata": ["5 tool listings", "Basic analytics"],
"planPrices": [
{
"id": "pp_basic_monthly",
"priceId": "price_1ABC...",
"name": "Monthly",
"months": 1,
"price": 1900,
"discount": 0
}
]
}
]
}
}
Get Plan by ID
âļ| Param | Type | Description |
|---|---|---|
| id | string | Plan ID |
{ "success": true, "data": { "plan": { /* same shape as above */ } } }
{ "success": false, "errorCode": "PLAN_NOT_FOUND", "message": "Plan not found." }
My Subscription
đ Auth Required âļReturns the current user's active subscription, including plan details and current billing price. Returns null if no subscription exists.
{
"success": true,
"data": {
"subscription": {
"id": "sub_xyz",
"stripeSubscriptionId": "sub_1ABC...",
"status": "active",
"amount": 1900,
"currency": "usd",
"periodStart": "2026-04-01T00:00:00.000Z",
"periodEnd": "2026-05-01T00:00:00.000Z",
"cancelAtPeriodEnd": false,
"plan": { "id": "plan_basic", "name": "Basic", "settings": { "max_tools": 5 } },
"currentPlanPrice": { "name": "Monthly", "months": 1, "price": 1900 }
}
}
}
Create Checkout Session
đ Auth Required âļCreates a Stripe Checkout session. Redirects the user to Stripe's hosted payment page. On success, Stripe redirects to {APP_ORIGIN}/subscription/success?session_id=....
| Param | Type | Description |
|---|---|---|
| planId | string | The plan ID to subscribe to |
{
"success": true,
"message": "Checkout session created.",
"data": {
"url": "https://checkout.stripe.com/pay/cs_test_...",
"sessionId": "cs_test_abc123"
}
}
Direct Card Payment
đ Auth Required âļCreates a subscription using a Stripe PaymentMethod ID (tokenized by Stripe.js on the frontend). Card details are never sent to this server.
| Param | Type | Description |
|---|---|---|
| planId | string | The plan ID to subscribe to |
| Field | Type | Required | Description |
|---|---|---|---|
| paymentMethodId | string | required | Stripe PaymentMethod ID â must start with pm_ |
{
"success": true,
"message": "Subscription initiated. Confirm payment on the client.",
"data": {
"subscriptionId": "sub_1ABC...",
"status": "incomplete",
"clientSecret": "pi_abc_secret_xyz"
}
}
// clientSecret is passed to stripe.confirmCardPayment() on the frontend for 3DS
Cancel Subscription
đ Auth Required âļSchedules the subscription to cancel at the end of the current billing period. Access continues until periodEnd. Does not immediately cut off access.
{
"success": true,
"message": "Subscription will be canceled at the end of the current billing period.",
"data": { "cancelAtPeriodEnd": true }
}
Reactivate Subscription
đ Auth Required âļReverses a pending cancellation. Only valid when cancelAtPeriodEnd = true and the subscription has not yet been fully canceled.
{
"success": true,
"message": "Subscription reactivated. It will continue after the current billing period.",
"data": { "cancelAtPeriodEnd": false }
}
Upgrade Plan
đ Auth Required âļInitiates a plan upgrade. Proration is applied automatically via Stripe (always_invoice). The plan change is finalized asynchronously when the prorated invoice's webhook fires.
| Param | Type | Description |
|---|---|---|
| planId | string | The new plan ID to upgrade to |
{
"success": true,
"data": {
"message": "Plan upgrade initiated. Prorated invoice will be charged.",
"newPlanId": "plan_premium"
}
}
Poll Upgrade Status
đ Auth Required âļPolls whether a pending plan upgrade has been finalized by the Stripe webhook. Poll every few seconds after initiating an upgrade.
{
"success": true,
"data": {
"upgradeStatus": "pending",
"currentPlanId": "plan_basic",
"pendingPlanId": "plan_premium"
}
}
{
"success": true,
"data": {
"upgradeStatus": "completed",
"currentPlanId": "plan_premium",
"currentPlanName": "Premium",
"pendingPlanId": null
}
}
Billing Portal
đ Auth Required âļCreates a Stripe Customer Portal session URL. Redirect the user to this URL to let them manage payment methods, download invoices, and cancel subscriptions directly in Stripe's hosted UI.
{
"success": true,
"data": {
"url": "https://billing.stripe.com/session/..."
}
}
My Invoices
đ Auth Required âļ| Param | Type | Default | Description |
|---|---|---|---|
| page | number | 1 | Page number |
| limit | number | 10 | Results per page |
{
"success": true,
"data": {
"invoices": [
{
"id": "inv_abc",
"invoiceId": "in_1ABC...",
"amountPaid": 1900,
"amountDue": 1900,
"currency": "usd",
"status": "paid",
"pdfUrl": "https://pay.stripe.com/invoice/in_1ABC/pdf",
"hostedInvoiceUrl": "https://invoice.stripe.com/i/acct_.../in_1ABC",
"createdAt": "2026-04-01T00:00:00.000Z"
}
],
"pagination": { "total": 5, "page": 1, "limit": 10, "totalPages": 1 }
}
}
All Subscriptions
đĄ Admin Only âļReturns all subscriptions across all users with a summary metrics block. Powers the admin billing dashboard. No caching â always live data.
| Param | Type | Default | Description |
|---|---|---|---|
| page | number | 1 | Page number |
| limit | number | 20 | Results per page (max 200) |
| status | string | â | active | past_due | canceled | trialing |
| search | string | â | Filter by username or email (partial match) |
{
"success": true,
"data": {
"summary": {
"totalActive": 3,
"monthlyRevenue": 377, // USD, sum of active subscription amounts
"pastDue": 1,
"cancelled": 1
},
"subscriptions": [
{
"id": "sub_abc",
"stripeSubscriptionId": "sub_1ABC...",
"status": "active",
"amount": 29900, // cents
"currency": "usd",
"periodStart": "2026-04-24T00:00:00.000Z",
"periodEnd": "2026-05-24T00:00:00.000Z",
"cancelAtPeriodEnd": false,
"canceledAt": null,
"intervalId": "1-month",
"pendingPlanId": null,
"createdAt": "2026-04-24T00:00:00.000Z",
"user": {
"id": "usr_1",
"username": "lawfirmABC",
"email": "abc@law.com",
"avatar": "https://..."
},
"plan": {
"id": "plan_enterprise",
"name": "Enterprise",
"color": "#a855f7"
}
}
],
"pagination": { "total": 5, "page": 1, "limit": 20, "totalPages": 1 }
}
}
status or search query params. The paginated list is filtered; the summary is not.
All Plans (Admin)
đĄ Admin Only âļReturns all plans regardless of status (including inactive / draft). Includes plan prices and live subscriber count per plan. No pagination â plan count is small.
{
"success": true,
"data": {
"plans": [
{
"id": "plan_basic",
"name": "Basic",
"description": "For individuals",
"currency": "usd",
"color": "#6366f1",
"status": "active",
"order": 1,
"isTrialAllowed": true,
"trialDays": 14,
"settings": { "max_tools": 5 },
"metadata": ["5 tool listings", "Basic analytics"],
"subscriberCount": 42,
"planPrices": [
{
"id": "pp_basic_monthly",
"priceId": "price_1ABC...",
"name": "Monthly",
"months": 1,
"price": 2900,
"discount": 0
}
]
}
]
}
}
GET /plans which only returns status = active, this endpoint returns all plans including inactive ones. Use it to manage plan visibility in the admin dashboard.
All Invoices (Admin)
đĄ Admin Only âļReturns all invoices across all users. Includes user info and plan name via the subscription relation. Ordered by newest first.
| Param | Type | Default | Description |
|---|---|---|---|
| page | number | 1 | Page number |
| limit | number | 20 | Results per page (max 200) |
| status | string | â | paid | open | void | uncollectible |
| search | string | â | Filter by username or email (partial match) |
{
"success": true,
"data": {
"invoices": [
{
"id": "inv_abc",
"invoiceId": "in_1ABC...",
"stripeSubscriptionId": "sub_1ABC...",
"amountPaid": 29900,
"amountDue": 29900,
"currency": "usd",
"status": "paid",
"pdfUrl": "https://pay.stripe.com/invoice/.../pdf",
"hostedInvoiceUrl": "https://invoice.stripe.com/i/...",
"createdAt": "2026-04-24T00:00:00.000Z",
"user": {
"id": "usr_1",
"username": "lawfirmABC",
"email": "abc@law.com",
"avatar": "https://..."
},
"subscription": {
"plan": {
"id": "plan_enterprise",
"name": "Enterprise",
"color": "#a855f7"
}
}
}
],
"pagination": { "total": 18, "page": 1, "limit": 20, "totalPages": 1 }
}
}
Update Plan Settings
đĄ Admin Only âļ| Param | Type | Description |
|---|---|---|
| id | string | Plan ID |
| Field | Type | Required | Description |
|---|---|---|---|
| max_tools | integer | required | Max tools allowed. -1 = unlimited |
| default_order_type | "ASC" | "DESC" | optional | Default sort order for the plan |
{
"success": true,
"message": "Plan settings updated.",
"data": { "plan": { /* plan object with new settings */ } }
}