Subscription
Manage your workspace’s billing plan, AI add-on, and subscription lifecycle — including plan previews, downgrade readiness checks, and pending-change management.
Base URL
https://api.voxburst.io/v1/subscriptionAll subscription endpoints require a valid bearer token. The workspace is resolved from the token. Endpoints that write to Stripe (change-plan, preview-change, ai-addon, update, cancel-pending) return 503 Service Unavailable if the Stripe integration is not configured in the current environment.
Preview Plan Change
POST /v1/subscription/preview-change
Preview the proration cost for a plan change without executing it. Use this before calling change-plan to show the user exactly what they will be charged (upgrade) or credited (downgrade).
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
plan | string | Yes | Target plan: starter, pro, or agency |
billingPeriod | string | No | monthly (default) or yearly |
curl -X POST https://api.voxburst.io/v1/subscription/preview-change \
-H "Authorization: Bearer vb_live_xxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"plan": "pro",
"billingPeriod": "monthly"
}'Response
{
"currentPlan": "starter",
"newPlan": "pro",
"billingPeriod": "monthly",
"isUpgrade": true,
"prorationAmount": 18.39,
"effectiveDate": "2026-05-06T00:00:00.000Z",
"message": "You will be charged $18.39 immediately for the prorated difference."
}| Field | Type | Description |
|---|---|---|
currentPlan | string | Workspace’s current plan |
newPlan | string | Target plan |
billingPeriod | string | Billing cadence for the new plan |
isUpgrade | boolean | true if moving to a higher-priced plan |
prorationAmount | number | Amount charged (upgrade) or credited (downgrade) in USD |
effectiveDate | string | ISO 8601 timestamp when the change takes effect |
message | string | Human-readable summary of the charge or credit |
Change Plan
POST /v1/subscription/change-plan
Execute a plan change. For upgrades, the prorated amount is charged immediately. For downgrades, a credit is applied to the next invoice. Preview the cost first with POST /preview-change.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
plan | string | Yes | Target plan: free, starter, pro, or agency |
billingPeriod | string | No | monthly (default) or yearly |
curl -X POST https://api.voxburst.io/v1/subscription/change-plan \
-H "Authorization: Bearer vb_live_xxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"plan": "pro",
"billingPeriod": "monthly"
}'Response
{
"success": true,
"message": "Plan updated to Pro successfully.",
"plan": "pro",
"billingPeriod": "monthly"
}Error Codes
| Status | Description |
|---|---|
400 | Invalid plan transition or Stripe error (e.g. no payment method on file) |
503 | Stripe not configured in this environment |
Add or Update AI Add-On
POST /v1/subscription/ai-addon
Add, change, or remove the AI add-on for the authenticated user. Pass tier: null to remove the add-on.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
tier | string | null | Yes | AI add-on tier: starter, pro, or null to cancel |
# Add the Pro AI add-on
curl -X POST https://api.voxburst.io/v1/subscription/ai-addon \
-H "Authorization: Bearer vb_live_xxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{ "tier": "pro" }'
# Remove the AI add-on
curl -X POST https://api.voxburst.io/v1/subscription/ai-addon \
-H "Authorization: Bearer vb_live_xxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{ "tier": null }'Response
{
"success": true,
"message": "AI add-on updated to Pro.",
"tier": "pro"
}Error Codes
| Status | Description |
|---|---|
400 | Invalid tier or subscription state |
401 | User not authenticated |
422 | Payment processing error — card declined, no payment method, etc. The message field contains the Stripe error text |
503 | Stripe not configured |
Stripe payment errors are returned as 422 Unprocessable Entity rather than 500. Check the message field in the response body for the human-readable Stripe error (e.g. “Your card was declined.”).
Update Subscription (Combined)
POST /v1/subscription/update
Change the plan and/or AI add-on tier in a single atomic operation. Useful when the user wants to upgrade their plan and add an AI tier at the same time.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
plan | string | No | Target plan: free, starter, pro, or agency |
billingPeriod | string | No | monthly (default) or yearly |
aiTier | string | null | No | AI add-on tier (starter, pro) or null to remove |
curl -X POST https://api.voxburst.io/v1/subscription/update \
-H "Authorization: Bearer vb_live_xxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"plan": "pro",
"billingPeriod": "yearly",
"aiTier": "starter"
}'Response
{
"success": true,
"message": "Subscription updated successfully.",
"plan": "pro",
"billingPeriod": "yearly",
"aiTier": "starter"
}Get AI Add-On Usage
GET /v1/subscription/ai-usage
Return the authenticated user’s current AI add-on status, credit usage, and billing period. If the user is on a legacy AI tier that has a recommended migration path, a migration object is included.
curl https://api.voxburst.io/v1/subscription/ai-usage \
-H "Authorization: Bearer vb_live_xxxxxxxxxxxxx"Response (subscribed)
{
"subscribed": true,
"tier": "pro",
"credits_used": 1240,
"credits_limit": 5000,
"credits_remaining": 3760,
"billing_period_start": "2026-05-01T00:00:00.000Z",
"billing_period_end": "2026-06-01T00:00:00.000Z",
"migration": null
}Response (not subscribed)
{
"subscribed": false,
"tier": null,
"credits_used": 0,
"credits_limit": null,
"credits_remaining": null,
"billing_period_start": null,
"billing_period_end": null,
"migration": null
}Response Fields
| Field | Type | Description |
|---|---|---|
subscribed | boolean | Whether the user has an active AI add-on |
tier | string | null | Current tier: starter, pro, or null |
credits_used | number | Credits consumed this billing period |
credits_limit | number | null | Credits allotted per period (null = unlimited) |
credits_remaining | number | null | Remaining credits (null = unlimited) |
billing_period_start | string | null | ISO 8601 start of current billing period |
billing_period_end | string | null | ISO 8601 end of current billing period |
migration | object | null | Migration banner info if on a legacy tier (see below) |
Migration Object
Present only when the user is on a legacy AI tier that has a recommended upgrade path:
| Field | Type | Description |
|---|---|---|
banner | string | Human-readable migration notice for display in the UI |
recommendedTier | string | The recommended new tier (starter or pro) |
monthlySavings | number | Monthly savings in USD if the user switches |
isClearUpgrade | boolean | true if the new tier offers strictly more for less cost |
Get Pending Changes
GET /v1/subscription/pending-changes
Returns any scheduled subscription changes — a pending downgrade to a lower plan, or a pending cancellation (reverts to free at period end). Returns { "pendingChanges": null } if no changes are scheduled.
curl https://api.voxburst.io/v1/subscription/pending-changes \
-H "Authorization: Bearer vb_live_xxxxxxxxxxxxx"Response (pending downgrade)
{
"pendingChanges": {
"type": "downgrade",
"effectiveDate": "2026-06-01T00:00:00.000Z",
"newPlan": "starter"
}
}Response (pending cancellation)
{
"pendingChanges": {
"type": "cancellation",
"effectiveDate": "2026-06-01T00:00:00.000Z",
"newPlan": "free"
}
}Response (no pending changes)
{
"pendingChanges": null
}| Field | Type | Description |
|---|---|---|
type | string | downgrade or cancellation |
effectiveDate | string | null | ISO 8601 date when the change takes effect |
newPlan | string | The plan the workspace will move to |
Cancel Pending Changes
POST /v1/subscription/cancel-pending
Cancel a scheduled downgrade or cancellation, keeping the current plan active. This calls Stripe to reverse the cancel_at_period_end flag if set, and clears any pending-downgrade metadata from the subscription record.
curl -X POST https://api.voxburst.io/v1/subscription/cancel-pending \
-H "Authorization: Bearer vb_live_xxxxxxxxxxxxx"Response
{
"success": true,
"message": "Pending changes cancelled. Your subscription will continue as normal."
}Error Codes
| Status | Description |
|---|---|
404 | No subscription found for the workspace owner |
503 | Stripe not configured |
Downgrade Readiness Check
GET /v1/subscription/downgrade-readiness?targetPlan=<plan>
Advisory pre-flight check that compares the workspace’s current usage against the limits of the target plan. Returns a list of readiness items — one per resource category — each flagged as ok, heads_up, or action_needed. No changes are made; this endpoint is purely informational.
Categories checked: social_accounts, workspaces, ai_credits, monthly_posts.
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
targetPlan | string | Yes | Target plan: free, starter, pro, or agency |
curl "https://api.voxburst.io/v1/subscription/downgrade-readiness?targetPlan=starter" \
-H "Authorization: Bearer vb_live_xxxxxxxxxxxxx"Response
{
"targetPlan": "starter",
"effectiveDate": "2026-06-01T00:00:00.000Z",
"graceExpiresDate": "2026-06-06T00:00:00.000Z",
"graceDays": 5,
"items": [
{
"category": "social_accounts",
"current": 12,
"allowed": 5,
"excess": 7,
"severity": "action_needed",
"message": "You have 12 connected accounts. Starter allows 5. Designate 5 to keep before June 6 — posts to undesignated accounts will stop publishing.",
"actionUrl": "/accounts?mode=downgrade-select&targetPlan=starter",
"requiresDesignation": true
},
{
"category": "workspaces",
"current": 1,
"allowed": 1,
"excess": 0,
"severity": "ok",
"message": "Your 1 workspace fits within Starter."
},
{
"category": "ai_credits",
"current": 500,
"allowed": 0,
"excess": 500,
"severity": "heads_up",
"message": "Starter has no bundled AI credits. AI-assisted post generation stops on June 1.",
"actionUrl": "/ai"
}
]
}Response Fields
| Field | Type | Description |
|---|---|---|
targetPlan | string | The plan being evaluated |
effectiveDate | string | null | ISO 8601 date the downgrade takes effect |
graceExpiresDate | string | null | ISO 8601 date the 5-day grace period expires after the downgrade |
graceDays | number | Number of grace days (currently 5) |
items | object[] | Array of readiness items (one per category checked) |
Readiness Item Fields
| Field | Type | Description |
|---|---|---|
category | string | Resource category: social_accounts, workspaces, ai_credits, or monthly_posts |
current | number | Current usage count (-1 = unlimited) |
allowed | number | Limit under the target plan |
excess | number | Amount over the limit (0 if within limits) |
severity | string | ok, heads_up, or action_needed |
message | string | Human-readable explanation, suitable for display in a checklist UI |
actionUrl | string | Optional URL to the settings page where the user can resolve the issue |
requiresDesignation | boolean | true if the user must designate which accounts to keep (see Downgrade Designations) |
severity: "action_needed" items with requiresDesignation: true require the user to explicitly choose which accounts to keep before the downgrade takes effect. Save their selection with PUT /v1/subscription/downgrade-designations.
Save Downgrade Designations
PUT /v1/subscription/downgrade-designations
Save (or update) the list of social accounts the workspace wants to keep when downgrading. If the workspace has more connected accounts than the target plan allows, the user must designate which ones to retain — posts to undesignated accounts will stop publishing after the grace period expires.
Calling this endpoint again with the same effectiveAt replaces the previous designation list (upsert by workspaceId + effectiveAt).
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
effectiveAt | string | Yes | ISO 8601 datetime matching the downgrade effective date |
targetPlan | string | Yes | Target plan: free, starter, pro, or agency |
accountIds | string[] | Yes | Array of social account IDs to keep. Length must not exceed the target plan’s account limit. |
curl -X PUT https://api.voxburst.io/v1/subscription/downgrade-designations \
-H "Authorization: Bearer vb_live_xxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"effectiveAt": "2026-06-01T00:00:00.000Z",
"targetPlan": "starter",
"accountIds": ["acc_111", "acc_222", "acc_333", "acc_444", "acc_555"]
}'Response
{
"saved": true,
"count": 5
}Error Codes
| Status | Description |
|---|---|
400 | accountIds length exceeds the target plan’s account limit, or effectiveAt is not a valid ISO 8601 datetime |
Billing Information Endpoints
The following endpoints live under /v1/billing/ and provide current subscription state, plan listings, and Stripe portal access.
Get Current Billing Status
GET /v1/billing/current
Returns the workspace’s current plan, billing interval, subscription status, trial information, and AI add-on status. This is the primary endpoint for checking what plan a workspace is on.
curl https://api.voxburst.io/v1/billing/current \
-H "Authorization: Bearer vb_live_xxxxxxxxxxxxx"Response fields:
| Field | Type | Description |
|---|---|---|
plan | string | Current plan: free, starter, pro, or agency |
billingInterval | string | monthly or annual (note: "annual" not "yearly") |
status | string | Stripe subscription status: active, canceled, past_due, trialing, etc. |
currentPeriodStart | string | null | ISO 8601 start of current billing period |
currentPeriodEnd | string | null | ISO 8601 end of current billing period |
cancelAtPeriodEnd | boolean | true if the subscription will cancel at period end |
trialEnd | string | null | ISO 8601 trial end date (if on trial) |
trialTotalDays | number | null | Total trial length in days |
recentlyExpiredTrial | boolean | true if the trial has expired and the user has not yet chosen a paid plan |
currentAmountCents | number | null | Current subscription amount in cents |
isFoundingPrice | boolean | true if the workspace is on a grandfathered founding member price |
pendingDowngrade | string | null | Plan slug if a downgrade is scheduled, else null |
pendingDowngradeEffective | string | null | ISO 8601 date the pending downgrade takes effect |
subscriptionId | string | null | Stripe subscription ID |
aiAddon | object | null | Current AI add-on status. See AI Add-On Object below. |
AI Add-On Object
The aiAddon field is an object (or null if no AI add-on data is available). It has the following shape:
| Field | Type | Description |
|---|---|---|
subscribed | boolean | true if the workspace has an active AI add-on subscription or complimentary AI access. |
tier | string | null | Current tier: starter, pro, or null. null is valid even when subscribed is true — this indicates complimentary or admin-granted AI access that is not tied to a specific Stripe-billed tier. |
creditsUsed | number | Credits consumed in the current billing period. |
creditsLimit | number | null | Credits allotted per period. null means unlimited — this occurs for complimentary subscriptions and admin-granted accounts. Do not treat null as missing data; treat it as no credit cap. |
creditsRemaining | number | null | Remaining credits. null means unlimited (same condition as creditsLimit: null). |
billingPeriodEnd | string | null | ISO 8601 end of the current AI billing period. null for non-Stripe-billed (complimentary) subscriptions. |
Known valid state combinations:
subscribed | tier | creditsLimit | Meaning |
|---|---|---|---|
true | "starter" or "pro" | number | Standard paid AI add-on |
true | null | null | Complimentary or admin-granted AI access (unlimited, not Stripe-billed) |
false | null | null | No AI access |
When creditsLimit is null, do not show a credit usage bar or a “credits remaining” counter — instead show an “Unlimited” badge or omit the field entirely. Rendering null as 0 will incorrectly suggest the workspace has no credits.
List Plans
GET /v1/billing/plans
Returns all available plans with pricing and limits. No authentication required.
curl https://api.voxburst.io/v1/billing/plansResponse:
{
"plans": [
{
"id": "free",
"name": "Free",
"description": "Get started for free",
"priceMonthly": 0,
"priceYearly": 0,
"limits": { "socialAccounts": 3, "monthlyPosts": 30 },
"popular": false
}
]
}Create Checkout Session
POST /v1/billing/checkout
Creates a Stripe Checkout session for upgrading to a paid plan. Redirect the user to the returned url to complete payment.
Request body:
| Field | Type | Required | Description |
|---|---|---|---|
planId | string | Yes | Target plan: starter, pro, or agency |
billingPeriod | string | No | monthly (default), yearly, or annual |
successUrl | string | Yes | URL to redirect to after successful payment |
cancelUrl | string | Yes | URL to redirect to if the user cancels checkout |
Response:
{
"sessionId": "cs_live_xxxxxxxxxxxxx",
"url": "https://checkout.stripe.com/..."
}Get Stripe Portal URL
GET /v1/billing/portal or POST /v1/billing/portal
Returns a Stripe Customer Portal URL for managing payment methods, invoices, and subscription settings.
# GET with query parameter
curl "https://api.voxburst.io/v1/billing/portal?returnUrl=https://app.voxburst.io/settings/billing" \
-H "Authorization: Bearer vb_live_xxxxxxxxxxxxx"
# POST with JSON body
curl -X POST https://api.voxburst.io/v1/billing/portal \
-H "Authorization: Bearer vb_live_xxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{ "returnUrl": "https://app.voxburst.io/settings/billing" }'Response:
{ "url": "https://billing.stripe.com/session/..." }Cancel Subscription
POST /v1/billing/cancel
Schedules the subscription for cancellation at the end of the current billing period. The workspace continues on its current plan until currentPeriodEnd, then reverts to Free.
curl -X POST https://api.voxburst.io/v1/billing/cancel \
-H "Authorization: Bearer vb_live_xxxxxxxxxxxxx"Resume Subscription
POST /v1/billing/resume
Reverses a pending cancellation. Only valid when cancelAtPeriodEnd is true. The subscription continues normally at the next renewal.
curl -X POST https://api.voxburst.io/v1/billing/resume \
-H "Authorization: Bearer vb_live_xxxxxxxxxxxxx"Create Trial Checkout Session
POST /v1/billing/checkout/trial
Creates a Stripe Checkout session for starting a free trial. Redirect the user to the returned url.
Request body:
| Field | Type | Required | Description |
|---|---|---|---|
plan | string | Yes | Plan to trial: starter, pro, or agency |
billing | string | No | monthly (default) or annual |
successUrl | string | Yes | URL to redirect to after checkout completes |
cancelUrl | string | Yes | URL to redirect to if the user cancels |
Response:
{
"sessionId": "cs_live_xxxxxxxxxxxxx",
"url": "https://checkout.stripe.com/..."
}Create AI Add-On Checkout Session
POST /v1/billing/checkout/ai-addon
Creates a Stripe Checkout session to subscribe to an AI add-on tier.
Request body:
| Field | Type | Required | Description |
|---|---|---|---|
tier | string | Yes | AI add-on tier: starter or pro |
successUrl | string | Yes | URL to redirect to after checkout completes |
cancelUrl | string | Yes | URL to redirect to if the user cancels |
Response:
{
"sessionId": "cs_live_xxxxxxxxxxxxx",
"url": "https://checkout.stripe.com/..."
}Get Subscription Details
GET /v1/billing/subscription
Returns the current Stripe subscription record for the workspace, including plan limits.
curl https://api.voxburst.io/v1/billing/subscription \
-H "Authorization: Bearer vb_live_xxxxxxxxxxxxx"Response:
{
"plan": "pro",
"status": "active",
"currentPeriodStart": "2026-05-01T00:00:00.000Z",
"currentPeriodEnd": "2026-06-01T00:00:00.000Z",
"cancelAtPeriodEnd": false,
"limits": {
"maxWorkspaces": 3,
"maxAccountsPerOrg": 35,
"maxPostsPerMonth": 1000,
"aiEnabled": true
}
}Get Usage Summary
GET /v1/billing/usage
Returns current usage versus plan limits.
curl https://api.voxburst.io/v1/billing/usage \
-H "Authorization: Bearer vb_live_xxxxxxxxxxxxx"Response:
{
"plan": "pro",
"usage": {
"workspaces": { "used": 1, "limit": 3 },
"accounts": { "used": 8, "limit": 35 },
"posts": { "used": 124, "limit": 1000 }
},
"features": {
"aiEnabled": true
},
"billing": {
"currentPeriodStart": "2026-05-01T00:00:00.000Z",
"currentPeriodEnd": "2026-06-01T00:00:00.000Z",
"cancelAtPeriodEnd": false
}
}Acknowledge Trial End
POST /v1/billing/acknowledge-trial-end
Acknowledge that the user has seen the trial-ended notification. Clears the recentlyExpiredTrial flag on the workspace.
curl -X POST https://api.voxburst.io/v1/billing/acknowledge-trial-end \
-H "Authorization: Bearer vb_live_xxxxxxxxxxxxx"Response:
{ "success": true }