/api/subscriptions
List all subscriptions with filtering and pagination (requires authentication)
Headers:
Authorization: Bearer ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr...
Query Parameters:
sort
- JSON array with interface name and direction
["interfaceName","ASC|DESC"]
sort=["createdAt","DESC"]
- Sort by creation date in descending order
page
- Page number (1-based)
page=1
- Get the first page
perPage
- Number of items per page
perPage=10
- Show 10 items per page
filter
- JSON object with interface name/value pairs for filtering
{"interfaceName1":"value1","interfaceName2":value2}
filter={"status":"active"}
- Filter subscriptions with active status
filter={"planName":"Pro Plan"}
- Filter by subscription plan name
filter={"interval":"month"}
- Filter by plan billing interval
filter={"currency":"usd"}
- Filter by currency
q
in the filter will search across all text columns:
filter={"q":"pro","status":"active"}
- Find active subscriptions with
"pro" in any text field
syncWithStripe
- Whether to sync with Stripe before fetching data (default: true)
Response (200 OK):
{ "data": [ { "id": 1, "userId": 1, "email": "user@example.com", "username": "user123", "plan": { "id": 1, "stripePriceId": "price_...", "name": "Pro Plan", "interval": "month", "amount": 999, "currency": "usd", "trialPeriodDays": 14, "isActive": true, "createdAt": "2023-01-15T08:30:00Z", "updatedAt": null }, "status": "active", "currentPeriodStart": "2023-06-01T00:00:00Z", "currentPeriodEnd": "2023-07-01T00:00:00Z", "trialStart": "2023-06-01T00:00:00Z", "trialEnd": "2023-06-15T00:00:00Z", "cancelAtPeriodEnd": false, "canceledAt": null, "createdAt": "2023-06-01T00:00:00Z", "updatedAt": null, "promotion": { "id": 5, "name": "Summer Sale 2023", "coupon": { "id": 3, "type": "DISC", "name": "Discount Percentage", "percentOff": 20, "trialDays": null } } } // Additional subscription objects... ], "total": 42 }
Notes:
planName
, interval
, amount
,
etc.syncWithStripe
parameter allows you to ensure that all subscription data is fresh
from Stripe before applying filters and pagination/api/subscriptions/me
Get the current user's subscription (requires authentication)
Headers:
Authorization: Bearer ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr...
Response (200 OK):
{ "id": 1, "userId": 1, "email": "user@example.com", "username": "user123", "plan": { "id": 1, "stripePriceId": "price_...", "name": "Pro Plan", "interval": "month", "amount": 999, "currency": "usd", "trialPeriodDays": 14, "isActive": true, "createdAt": "2023-01-15T08:30:00Z", "updatedAt": null }, "status": "active", "currentPeriodStart": "2023-06-01T00:00:00Z", "currentPeriodEnd": "2023-07-01T00:00:00Z", "trialStart": "2023-06-01T00:00:00Z", "trialEnd": "2023-06-15T00:00:00Z", "cancelAtPeriodEnd": false, "canceledAt": null, "createdAt": "2023-06-01T00:00:00Z", "updatedAt": null, "promotion": { "id": 5, "name": "Summer Sale 2023", "coupon": { "id": 3, "type": "DISC", "name": "Discount Percentage", "percentOff": 20, "trialDays": null } } }
/api/subscriptions/plans
List all available subscription plans (requires authentication)
Headers:
Authorization: Bearer ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr...
Query Parameters:
sort
- JSON array with interface name and direction
["interfaceName","ASC|DESC"]
sort=["amount","ASC"]
- Sort by price amount in ascending order
sort=["name","ASC"]
- Sort by plan name in ascending order
page
- Page number (1-based)
page=1
- Get the first page
perPage
- Number of items per page
perPage=10
- Show 10 items per page
filter
- JSON object with interface name/value pairs for filtering
{"interfaceName1":"value1","interfaceName2":value2}
filter={"isActive":true}
- Show only active subscription plans
filter={"interval":"month"}
- Filter by billing interval
filter={"currency":"usd"}
- Filter by currency
q
in the filter will search across all text columns:
filter={"q":"pro"}
- Find plans with "pro" in their name or description
syncWithStripe
- Whether to sync with Stripe before fetching data (default: true)
Response (200 OK):
{ "data": [ { "id": 1, "stripePriceId": "price_...", "name": "Basic Plan", "interval": "month", "amount": 499, "currency": "usd", "trialPeriodDays": 14, "isActive": true, "createdAt": "2023-01-15T08:30:00Z", "updatedAt": null }, { "id": 2, "stripePriceId": "price_...", "name": "Pro Plan", "interval": "month", "amount": 999, "currency": "usd", "trialPeriodDays": 14, "isActive": true, "createdAt": "2023-01-15T08:30:00Z", "updatedAt": null } // Additional plan objects... ], "total": 5 }
Notes:
syncWithStripe
parameter allows you to ensure that all subscription data is fresh
from Stripe before applying filters and pagination/api/subscriptions/verify-payment
Verify payment status for a subscription using payment intent ID (requires authentication)
Headers:
Authorization: Bearer ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr...
Query Parameters:
paymentIntentId
- The Stripe payment intent ID to verifyResponse (200 OK):
{ "id": 1, "userId": 1, "email": "user@example.com", "username": "user123", "plan": { "id": 1, "stripePriceId": "price_...", "name": "Pro Plan", "interval": "month", "amount": 999, "currency": "usd", "trialPeriodDays": 14, "isActive": true, "createdAt": "2023-01-15T08:30:00Z", "updatedAt": null }, "status": "active", "currentPeriodStart": "2023-06-01T00:00:00Z", "currentPeriodEnd": "2023-07-01T00:00:00Z", "trialStart": null, "trialEnd": null, "cancelAtPeriodEnd": false, "canceledAt": null, "createdAt": "2023-06-01T00:00:00Z", "updatedAt": "2023-06-15T00:00:00Z", "promotion": null }
Error Responses:
{ "message": "Payment intent ID is required" } { "message": "Subscription not found or could not be updated" }
/api/subscriptions/verify-setup
Verify setup intent status for a subscription (requires authentication)
Headers:
Authorization: Bearer ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr...
Query Parameters:
setupIntentId
- The Stripe setup intent ID to verifyResponse (200 OK):
{ "id": 1, "userId": 1, "email": "user@example.com", "username": "user123", "plan": { "id": 1, "stripePriceId": "price_...", "name": "Pro Plan", "interval": "month", "amount": 999, "currency": "usd", "trialPeriodDays": 14, "isActive": true, "createdAt": "2023-01-15T08:30:00Z", "updatedAt": null }, "status": "active", "currentPeriodStart": "2023-06-01T00:00:00Z", "currentPeriodEnd": "2023-07-01T00:00:00Z", "trialStart": null, "trialEnd": null, "cancelAtPeriodEnd": false, "canceledAt": null, "createdAt": "2023-06-01T00:00:00Z", "updatedAt": "2023-06-15T00:00:00Z", "promotion": null }
Error Responses:
{ "message": "Setup intent ID is required" } { "message": "Subscription not found or could not be updated" }
/api/subscriptions/change-plan
Change the user's subscription to a different plan (requires authentication)
Headers:
Authorization: Bearer ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr...
Request Body:
{ "planId": 2, "prorationBehavior": "create_prorations" // Optional: "create_prorations", "none", or "always_invoice" }
Response (200 OK):
{ "message": "Subscription plan changed successfully", "subscription": { "id": 1, "userId": 1, "email": "user@example.com", "username": "user123", "plan": { "id": 2, "stripePriceId": "price_...", "name": "Premium Plan", "interval": "month", "amount": 1999, "currency": "usd", "trialPeriodDays": 0, "isActive": true, "createdAt": "2023-01-15T08:30:00Z", "updatedAt": null }, "status": "active", "currentPeriodStart": "2023-06-01T00:00:00Z", "currentPeriodEnd": "2023-07-01T00:00:00Z", "trialStart": null, "trialEnd": null, "cancelAtPeriodEnd": false, "canceledAt": null, "createdAt": "2023-06-01T00:00:00Z", "updatedAt": "2023-06-15T00:00:00Z", "promotion": null } }
Error Responses:
{ "message": "Plan ID is required" } { "message": "You don't have an active subscription" } { "message": "You are already subscribed to this plan" } { "message": "The selected plan is not available" }
/api/subscriptions/change-plan-with-payment-method
Change the user's subscription to a different plan while updating payment method (requires authentication)
Headers:
Authorization: Bearer ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr...
Request Body:
{ "planId": 2, "paymentMethodId": "pm_1234567890", "prorationBehavior": "create_prorations" // Optional: "create_prorations", "none", or "always_invoice" }
Response (200 OK):
{ "requiresAction": true, "setupIntentClientSecret": "seti_1RJYc0PFpKHu6YD8quMd7VH8_secret_...", "setupIntentId": "seti_1RJYc0PFpKHu6YD8quMd7VH8", "planId": 2, "prorationBehavior": "create_prorations" }
Error Responses:
{ "message": "Plan ID is required" } { "message": "Payment method ID is required" } { "message": "You don't have an active subscription" } { "message": "There was a problem setting up the payment method" }
/api/subscriptions/confirm-change-plan
Confirm plan change after setup intent is completed (requires authentication)
Headers:
Authorization: Bearer ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr...
Request Body:
{ "setupIntentId": "seti_1RJYc0PFpKHu6YD8quMd7VH8", "planId": 2, "prorationBehavior": "create_prorations" // Optional: "create_prorations", "none", or "always_invoice" }
Response (200 OK):
{ "message": "Subscription plan and payment method updated successfully", "subscription": { "id": 1, "userId": 1, "email": "user@example.com", "username": "user123", "plan": { "id": 2, "stripePriceId": "price_...", "name": "Premium Plan", "interval": "month", "amount": 1999, "currency": "usd", "trialPeriodDays": 0, "isActive": true, "createdAt": "2023-01-15T08:30:00Z", "updatedAt": null }, "status": "active", "currentPeriodStart": "2023-06-01T00:00:00Z", "currentPeriodEnd": "2023-07-01T00:00:00Z", "trialStart": null, "trialEnd": null, "cancelAtPeriodEnd": false, "canceledAt": null, "createdAt": "2023-06-01T00:00:00Z", "updatedAt": "2023-06-15T00:00:00Z", "promotion": null } }
Error Responses:
{ "message": "Setup intent ID is required" } { "message": "Plan ID is required" } { "message": "Setup intent is not complete. Current status: requires_payment_method" } { "message": "Failed to attach payment method" }
/api/subscriptions/create-free-trial
Create a free trial subscription without requiring payment method (requires authentication)
Headers:
Authorization: Bearer ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr...
Request Body:
{ "priceId": "price_H5ggYwtDq4fbrJ", "trialPeriodDays": 14 // Optional: Defaults to 14 days if not specified }
Response (200 OK):
{ "message": "Free trial subscription created successfully", "subscription": { "id": 1, "userId": 1, "email": "user@example.com", "username": "user123", "plan": { "id": 1, "stripePriceId": "price_H5ggYwtDq4fbrJ", "name": "Pro Plan", "interval": "month", "amount": 999, "currency": "usd", "trialPeriodDays": 14, "isActive": true, "createdAt": "2023-01-15T08:30:00Z", "updatedAt": null }, "status": "trialing", "currentPeriodStart": "2023-06-01T00:00:00Z", "currentPeriodEnd": "2023-07-01T00:00:00Z", "trialStart": "2023-06-01T00:00:00Z", "trialEnd": "2023-06-15T00:00:00Z", "cancelAtPeriodEnd": false, "canceledAt": null, "createdAt": "2023-06-01T00:00:00Z", "updatedAt": null, "promotion": null }, "trialEnd": "2023-06-15T00:00:00Z" }
Error Responses:
{ "message": "User already has an active subscription" } { "message": "Price ID is required" } { "message": "User not found" } { "message": "Subscription plan not found" }
/api/subscriptions/create-with-payment-method
Create a subscription with payment method ID (deferred payment flow) (requires authentication)
Headers:
Authorization: Bearer ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr...
Request Body:
{ "priceId": "price_H5ggYwtDq4fbrJ", "paymentMethodId": "pm_1234567890", "trialPeriodDays": 14 // Optional: Number of trial days }
Response (200 OK):
{ "subscriptionId": "sub_1RJYc0PFpKHu6YD8quMd7VH8", "type": "payment", "clientSecret": "cs_test_..." }
Alternative Response (Setup Flow):
{ "subscriptionId": "sub_1RJYc0PFpKHu6YD8quMd7VH8", "type": "setup", "clientSecret": "seti_1RJYc0PFpKHu6YD8quMd7VH8_secret_..." }
Error Responses:
{ "message": "Price ID is required" } { "message": "Payment method ID is required" } { "message": "User already has an active subscription" } { "message": "Subscription plan not found" }
Notes:
/api/subscriptions/resume
Resume a subscription that was previously scheduled for cancellation (requires authentication)
Headers:
Authorization: Bearer ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr...
Response (200 OK):
{ "id": 1, "userId": 1, "email": "user@example.com", "username": "user123", "plan": { "id": 1, "stripePriceId": "price_...", "name": "Pro Plan", "interval": "month", "amount": 999, "currency": "usd", "trialPeriodDays": 14, "isActive": true, "createdAt": "2023-01-15T08:30:00Z", "updatedAt": null }, "status": "active", "currentPeriodStart": "2023-06-01T00:00:00Z", "currentPeriodEnd": "2023-07-01T00:00:00Z", "trialStart": null, "trialEnd": null, "cancelAtPeriodEnd": false, "canceledAt": null, "createdAt": "2023-06-01T00:00:00Z", "updatedAt": "2023-06-15T00:00:00Z", "promotion": null }
Error Responses:
{ "message": "Subscription not found or could not be resumed" } { "message": "Failed to resume subscription", "error": "Cannot resume subscription because it is already fully canceled" }
/api/subscriptions/sync-plans
Sync subscription plans with Stripe (requires authentication and admin privileges)
Headers:
Authorization: Bearer ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr...
Response (200 OK):
{ "message": "Successfully synchronized 8 subscription plans with Stripe", "syncedPlans": 8 }
Error Responses:
{ "message": "Access denied. Admin privileges required." }
/api/subscriptions/update-payment-method
Update the payment method for a user's subscription (requires authentication)
Headers:
Authorization: Bearer ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr...
Request Body:
{ "paymentMethodId": "pm_1234567890" }
Response (200 OK):
{ "success": true, "message": "Payment method updated successfully", "subscription": { "id": 1, "userId": 1, "email": "user@example.com", "username": "user123", "plan": { "id": 1, "stripePriceId": "price_...", "name": "Pro Plan", "interval": "month", "amount": 999, "currency": "usd", "trialPeriodDays": 14, "isActive": true, "createdAt": "2023-01-15T08:30:00Z", "updatedAt": null }, "status": "active", "currentPeriodStart": "2023-06-01T00:00:00Z", "currentPeriodEnd": "2023-07-01T00:00:00Z", "trialStart": null, "trialEnd": null, "cancelAtPeriodEnd": false, "canceledAt": null, "createdAt": "2023-06-01T00:00:00Z", "updatedAt": "2023-06-15T00:00:00Z", "promotion": null } }
Error Responses:
{ "success": false, "message": "Payment method ID is required" } { "success": false, "message": "Failed to update payment method", "error": { "type": "card_error", "message": "Your card was declined.", "code": "card_declined", "decline_code": "generic_decline" } }
Notes:
/api/subscriptions/me
Update the current user's subscription (requires authentication)
Headers:
Authorization: Bearer ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr... x-csrf-token: a8d7f9c6e5b4a3c2d1e0f9a8d7f6c5b4a3
Request Body:
{ "planId": 2, "paymentMethodId": "pm_1234567890" // Optional: New payment method }
Response (200 OK):
{ "id": 1, "userId": 1, "email": "user@example.com", "username": "user123", "plan": { "id": 2, "stripePriceId": "price_...", "name": "Premium Plan", "interval": "month", "amount": 1999, "currency": "usd", "trialPeriodDays": 0, "isActive": true, "createdAt": "2023-01-15T08:30:00Z", "updatedAt": null }, "status": "active", "currentPeriodStart": "2023-06-01T00:00:00Z", "currentPeriodEnd": "2023-07-01T00:00:00Z", "trialStart": null, "trialEnd": null, "cancelAtPeriodEnd": false, "canceledAt": null, "createdAt": "2023-06-01T00:00:00Z", "updatedAt": "2023-06-15T00:00:00Z", "promotion": null }
/api/subscriptions/me
Cancel the current user's subscription (requires authentication)
Headers:
Authorization: Bearer ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr...
Query Parameters:
cancelAtPeriodEnd
- Whether to cancel at period end (default: true). Set to false for immediate cancellation.Response (200 OK):
{ "id": 1, "userId": 1, "email": "user@example.com", "username": "user123", "plan": { "id": 1, "stripePriceId": "price_...", "name": "Pro Plan", "interval": "month", "amount": 999, "currency": "usd", "trialPeriodDays": 14, "isActive": true, "createdAt": "2023-01-15T08:30:00Z", "updatedAt": null }, "status": "active", "currentPeriodStart": "2023-06-01T00:00:00Z", "currentPeriodEnd": "2023-07-01T00:00:00Z", "trialStart": null, "trialEnd": null, "cancelAtPeriodEnd": true, "canceledAt": "2023-06-15T00:00:00Z", "createdAt": "2023-06-01T00:00:00Z", "updatedAt": "2023-06-15T00:00:00Z", "promotion": null }