Skip to main content

Overview

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, and flexible termination options.

Subscription states

              ┌──────────┐
              │ PENDING   │
              └────┬──────┘
                   │ activate
              ┌────▼──────┐
         ┌────│  ACTIVE   │────┐
         │    └───────────┘    │
    cancel│                    │terminate
         │                    │
   ┌─────▼────┐       ┌──────▼─────┐
   │ CANCELED  │       │ TERMINATED │
   └───────────┘       └────────────┘
  • Pending — Created but not yet activated
  • Active — Currently billing
  • Canceled — Soft-canceled, will terminate at period end
  • Terminated — Fully ended

Create a subscription

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
  }'

Billing time modes

ModeDescription
CalendarBilling periods align to calendar boundaries (1st of month, start of week, etc.)
AnniversaryBilling periods align to the subscription start date

Pay-in-advance vs pay-in-arrear

ModeWhen invoicedUse case
Pay-in-advanceAt the start of each billing periodSaaS subscriptions
Pay-in-arrearAt the end of each billing periodUsage-heavy products

Trials

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.

Plan changes

Upgrades (immediate)

# Handled via SubscriptionLifecycleService
PUT /v1/subscriptions/{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 (end of period)

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

Cancellation vs termination

Cancel

POST /v1/subscriptions/{id}/cancel?on_termination_action=generate_invoice
Soft cancellation — the subscription remains active until the end of the current billing period, then transitions to canceled status.

Terminate

DELETE /v1/subscriptions/{id}?on_termination_action=generate_invoice
Immediate termination. The subscription is ended right away.

Termination actions

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

Webhooks

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

API endpoints

MethodPathDescription
GET/v1/subscriptionsList subscriptions
GET/v1/subscriptions/{id}Get subscription details
POST/v1/subscriptionsCreate a subscription
PUT/v1/subscriptions/{id}Update a subscription
POST/v1/subscriptions/{id}/cancelCancel a subscription
DELETE/v1/subscriptions/{id}Terminate a subscription