Billing Service API
Base URL: https://billing.stashly.io
Team members cannot access billing
All billing endpoints require JWT authentication and the caller must not be a member role. Only admin and solo users can manage billing.
Plans#
/plansList all publicly available plans.
{
"success": true,
"data": [
{
"id": "plan_free",
"name": "Free",
"price": 0,
"storageGb": 5,
"features": ["5 GB storage", "API access", "1 bucket"]
},
{
"id": "plan_pro",
"name": "Pro",
"price": 2900,
"storageGb": 100,
"features": ["100 GB storage", "Unlimited buckets", "Webhooks"]
}
]
}
/plans/:idGet details for a specific plan.
Subscriptions#
/billing/checkoutJWT RequiredCreate a Stripe Checkout session for plan selection. Returns a redirect URL.
Request Body
| Name | Type | Description |
|---|---|---|
planId* | string | The plan ID to subscribe to |
successUrl* | string | URL to redirect after successful payment |
cancelUrl* | string | URL to redirect if user cancels checkout |
{
"success": true,
"data": { "url": "https://checkout.stripe.com/pay/cs_test_..." }
}
/billing/subscribeJWT RequiredSubscribe directly to a plan (for plans with a saved payment method).
Request Body
| Name | Type | Description |
|---|---|---|
planId* | string | The plan ID to subscribe to |
/billing/portalJWT RequiredCreate a Stripe Customer Portal session for managing payment methods, invoices, and subscriptions.
Request Body
| Name | Type | Description |
|---|---|---|
returnUrl* | string | URL to return to after leaving the portal |
{
"success": true,
"data": { "url": "https://billing.stripe.com/p/session/..." }
}
/billing/subscriptionJWT RequiredGet the user's subscription details.
{
"success": true,
"data": {
"id": "sub_01j9",
"plan": "pro",
"status": "active",
"currentPeriodEnd": "2025-06-29T00:00:00Z",
"cancelAtPeriodEnd": false
}
}
/billing/currentJWT RequiredGet the user's current active subscription (shorthand, returns just the active subscription).
/billing/cancelJWT RequiredCancel the current subscription. It remains active until the end of the billing period.
{
"success": true,
"data": { "cancelAtPeriodEnd": true, "currentPeriodEnd": "2025-06-29T00:00:00Z" }
}
/billing/update-planJWT RequiredUpgrade or downgrade the subscription plan. Takes effect immediately (prorated).
Request Body
| Name | Type | Description |
|---|---|---|
planId* | string | The new plan ID |
/billing/apply-couponJWT RequiredApply a discount coupon to the current subscription.
Request Body
| Name | Type | Description |
|---|---|---|
code* | string | Coupon code to apply |
{
"success": true,
"data": { "discount": 20, "type": "percent", "validUntil": "2025-12-31T00:00:00Z" }
}
{ "success": false, "message": "Coupon code is invalid or expired" }
Webhooks#
/webhooks/stripeStripe webhook receiver. Requires Stripe-Signature header verification. Must receive raw body.
See the Webhooks guide for full details on signature verification and event handling.