/api/subscriptions
List all subscriptions with filtering and pagination (requires authentication)
Headers:
Authorization: Bearer ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr...
Query Parameters:
sort - JSON array with field name and direction
["fieldName","ASC|DESC"]
id, userId, username, email, subscriptionPlanId, status, currentPeriodStart, currentPeriodEnd, trialStart, trialEnd, cancelAtPeriodEnd, canceledAt, createdAt, updatedAt, planName, interval, amount, currency, trialPeriodDays, isActive
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 field name/value pairs for filtering
{"fieldName1":"value1","fieldName2":value2}
filter={"status":"active","planName":"Pro"} - Filter active subscriptions with plan name containing "Pro"
q - Global search across username, email, subscription status, plan name, plan interval, and currencyusername - Filter by username (partial match, case-insensitive)email - Filter by email address (partial match, case-insensitive)status - Filter by subscription status (active, trialing, past_due, canceled, incomplete, etc.)planName - Filter by subscription plan name (partial match, case-insensitive)interval - Filter by billing interval (month, year)amount - Filter by plan amount in cents (exact match)currency - Filter by currency code (usd, eur, etc.)trialPeriodDays - Filter by trial period days (exact match)isActive - Filter by plan active status (true/false)createdAt - Filter by subscription creation date (exact date or date range)updatedAt - Filter by last update date (exact date or date range)currentPeriodStart - Filter by current period start date (exact date or date range)currentPeriodEnd - Filter by current period end date (exact date or date range)trialStart - Filter by trial start date (exact date or date range)trialEnd - Filter by trial end date (exact date or date range)canceledAt - Filter by cancellation date (exact date or date range)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)
Example Requests:
GET /api/subscriptions?page=1&perPage=10&sort=["createdAt","DESC"]&filter={"status":"active"}
GET /api/subscriptions?page=2&perPage=20&filter={"q":"pro","status":"active"}
GET /api/subscriptions?filter={"planName":"Premium","interval":"month"}
GET /api/subscriptions?filter={"currency":"usd","amount":999}
GET /api/subscriptions?filter={"email":"gmail.com","isActive":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 field name and direction
["fieldName","ASC|DESC"]
id, stripePriceId, name, interval, amount, currency, trialPeriodDays, isActive, createdAt, updatedAt
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 field name/value pairs for filtering
{"fieldName1":"value1","fieldName2":value2}
filter={"isActive":true} - Show only active subscription plans
filter={"interval":"month"} - Filter by billing interval
filter={"currency":"usd"} - Filter by currency
q - Global search across plan name, interval, and currencyname - Filter by plan name (partial match, case-insensitive)interval - Filter by billing interval (month, year, etc.)amount - Filter by plan amount in cents (exact match)currency - Filter by currency code (usd, eur, etc.)trialPeriodDays - Filter by trial period days (exact match)isActive - Filter by plan active status (true/false)q in the filter will search across all text columns:
filter={"q":"pro"} - Find plans with "pro" in their name
syncWithStripe - Whether to sync with Stripe before fetching data (default: true)
Example Requests:
GET /api/subscriptions/plans?page=1&perPage=10&sort=["amount","ASC"]&filter={"isActive":true}&syncWithStripe=true
GET /api/subscriptions/plans?page=2&perPage=20&filter={"q":"pro","interval":"month"}
GET /api/subscriptions/plans?filter={"currency":"usd","amount":999}
GET /api/subscriptions/plans?filter={"trialPeriodDays":14,"isActive":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
}