Skip to content

Subscriptions

Subscriptions connect customers to plans and drive the billing lifecycle. BoxBilling supports trials, pay-in-advance/arrear billing, calendar and anniversary billing, plan upgrades/downgrades, pause/resume, bulk operations, and flexible termination options.

┌──────────┐
│ PENDING │
└────┬──────┘
│ activate
┌────▼──────┐
┌────│ ACTIVE │◄───┐
│ └──┬────────┘ │
│ │ │ resume
cancel│ │ pause │
│ ┌──▼─────┐ │
│ │ PAUSED │──────┘
│ └─────────┘
┌─────▼────┐ ┌────────────┐
│ CANCELED │ │ TERMINATED │
└───────────┘ └────────────┘

Any state except terminated can transition to terminated via the terminate (DELETE) endpoint.

StatusDescription
pendingCreated but not yet activated
activeCurrently billing
pausedBilling suspended; can be resumed
canceledSoft-canceled, will terminate at period end
terminatedFully ended
Terminal window
curl -X POST /v1/subscriptions/ \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{
"external_id": "sub_001",
"customer_id": "cust-uuid",
"plan_id": "plan-uuid",
"billing_time": "calendar",
"pay_in_advance": true,
"trial_period_days": 14,
"on_termination_action": "generate_invoice"
}'
ModeDescription
calendarBilling periods align to calendar boundaries (1st of month, start of week, etc.)
anniversaryBilling periods align to the subscription start date
ModeWhen invoicedUse case
Pay-in-advance (pay_in_advance: true)At the start of each billing periodSaaS subscriptions
Pay-in-arrear (pay_in_advance: false)At the end of each billing periodUsage-heavy products

Pending subscriptions must be explicitly activated:

Terminal window
POST /v1/subscriptions/{subscription_id}/activate

Once activated, the subscription moves to active status and started_at is recorded.

When trial_period_days > 0, the subscription enters a trial period. During the trial:

  • No invoices are generated
  • The subscription is marked as active
  • When the trial ends, the system processes the transition via the process_trial_expirations background task (runs hourly)

If pay_in_advance is enabled, the first invoice is generated when the trial ends.

Before executing a plan change, preview the financial impact:

Terminal window
POST /v1/subscriptions/{subscription_id}/change_plan_preview
{
"plan_id": "new-plan-uuid"
}

Returns a price comparison and proration details so the customer can review before confirming.

Terminal window
PUT /v1/subscriptions/{subscription_id}
{
"plan_id": "new-plan-uuid"
}

When upgrading with pay_in_advance:

  1. A credit note is generated for the remaining period on the old plan
  2. A prorated invoice is generated for the new plan

Downgrades are scheduled to take effect at the next billing period boundary:

  1. The previous_plan_id is set to the new plan
  2. downgraded_at timestamp is recorded
  3. The process_pending_downgrades task (runs daily) executes the switch
Terminal window
POST /v1/subscriptions/{subscription_id}/pause

Pausing a subscription suspends billing. The subscription moves to paused status and paused_at is recorded. No invoices are generated while paused.

Terminal window
POST /v1/subscriptions/{subscription_id}/resume

Resuming moves the subscription back to active and records resumed_at.

Terminal window
POST /v1/subscriptions/{subscription_id}/cancel

Soft cancellation — the subscription remains active until the end of the current billing period, then transitions to canceled status.

Terminal window
DELETE /v1/subscriptions/{subscription_id}?on_termination_action=generate_invoice

Immediate termination. The subscription is ended right away.

The on_termination_action parameter controls what happens financially when a subscription ends:

ActionDescription
generate_invoiceGenerate a final invoice for the period
generate_credit_noteIssue a credit note for the remaining period
skipNo financial action taken

This can be set at creation time (as a default) or passed at cancellation/termination.

Perform operations on multiple subscriptions at once:

EndpointDescription
POST /v1/subscriptions/bulk_pausePause multiple subscriptions
POST /v1/subscriptions/bulk_resumeResume multiple subscriptions
POST /v1/subscriptions/bulk_terminateTerminate multiple subscriptions

Each returns a BulkSubscriptionResponse with per-subscription results.

Terminal window
GET /v1/subscriptions/{subscription_id}/current_usage

Returns the current billing-period usage for all metered charges on the subscription.

Terminal window
GET /v1/subscriptions/{subscription_id}/usage_trend

Returns daily usage trend data for the subscription.

Terminal window
# Create a threshold
POST /v1/subscriptions/{subscription_id}/usage_thresholds
# List thresholds
GET /v1/subscriptions/{subscription_id}/usage_thresholds

Usage thresholds trigger alerts or actions (e.g., progressive billing) when usage reaches defined amounts.

Terminal window
GET /v1/subscriptions/{external_id}/entitlements

Returns the feature entitlements granted by the subscription’s plan.

Terminal window
GET /v1/subscriptions/{subscription_id}/next_billing_date

Returns the next billing date for the subscription, useful for displaying to customers.

Terminal window
GET /v1/subscriptions/{subscription_id}/lifecycle

Returns the full lifecycle timeline — a chronological list of events (creation, activation, pauses, plan changes, cancellation, etc.) for audit and debugging.

Each charge on a plan uses one of the following charge models:

ModelDescription
standardFixed price per unit
graduatedTiered pricing — different rates for different quantity ranges
volumeVolume pricing — the tier reached applies to all units
packagePrice per package of units
percentagePercentage of a base amount
graduated_percentageTiered percentage rates
dynamicDynamically calculated pricing
customCustom pricing logic

The following webhook events are sent during the subscription lifecycle:

EventTrigger
subscription.createdNew subscription created
subscription.startedSubscription activated
subscription.plan_changedPlan upgrade or downgrade executed
subscription.trial_endedTrial period expired
subscription.canceledSubscription canceled
subscription.terminatedSubscription terminated
MethodPathDescription
GET/v1/subscriptions/List subscriptions
POST/v1/subscriptions/Create a subscription
GET/v1/subscriptions/{subscription_id}Get subscription details
PUT/v1/subscriptions/{subscription_id}Update a subscription
DELETE/v1/subscriptions/{subscription_id}Terminate a subscription
POST/v1/subscriptions/{subscription_id}/activateActivate a pending subscription
POST/v1/subscriptions/{subscription_id}/pausePause a subscription
POST/v1/subscriptions/{subscription_id}/resumeResume a paused subscription
POST/v1/subscriptions/{subscription_id}/cancelCancel a subscription
GET/v1/subscriptions/{subscription_id}/lifecycleGet lifecycle timeline
GET/v1/subscriptions/{subscription_id}/next_billing_dateGet next billing date
POST/v1/subscriptions/{subscription_id}/change_plan_previewPreview plan change
GET/v1/subscriptions/{subscription_id}/current_usageGet current usage
GET/v1/subscriptions/{subscription_id}/usage_trendGet usage trend
POST/v1/subscriptions/{subscription_id}/usage_thresholdsCreate usage threshold
GET/v1/subscriptions/{subscription_id}/usage_thresholdsList usage thresholds
GET/v1/subscriptions/{external_id}/entitlementsGet entitlements
POST/v1/subscriptions/bulk_pauseBulk pause subscriptions
POST/v1/subscriptions/bulk_resumeBulk resume subscriptions
POST/v1/subscriptions/bulk_terminateBulk terminate subscriptions