Billing & Subscriptions

Manage subscriptions, view invoices, and update payment methods. Billing is powered by Stripe and operates at the organization level.

Subscription Status

GET /v1/billing/subscription-status

Get the current subscription status for the authenticated user’s organization. The organization is resolved from the authenticated session; no query parameters are required.

Response

{
  "data": {
    "status": "active",
    "has_paid_subscription": true,
    "plan_name": "Backbuild Pro",
    "trial_end": null,
    "credits_monthly": 0,
    "current_period_start": "2026-04-01T00:00:00Z",
    "current_period_end": "2026-05-01T00:00:00Z"
  }
}

List Subscriptions

GET /v1/billing/subscriptions

The organization is resolved from the authenticated session.

Query Parameters

ParameterTypeDescription
statusstringFilter: active, trialing, past_due, canceled, incomplete, paused
limitintegerMax results (default: 25, max: 100)
offsetintegerPagination offset

Create Subscription

POST /v1/billing/subscriptions

Record a subscription to a plan in your own organization’s catalogue (a plan your organization publishes). The organization is resolved from the session, and this endpoint does not charge a card. To buy a Backbuild plan, use hosted Stripe Checkout at POST /v1/billing/create-checkout-session; the subscription is then created for you once payment is confirmed. A Backbuild platform plan is not created here: the response reports it as refused, so purchase it through Checkout.

Request Body

{
  "plan_id": "...",
  "interval": "month",
  "payment_method_id": "pm_...",
  "billing_details": {
    "name": "Acme Inc.",
    "email": "billing@example.com"
  },
  "seats": 5
}

Do not send id, org_id, status, created_at, or updated_at; these are assigned by the server, and the organization is resolved from the authenticated session.

Response

On success the complete created subscription record is returned.

{
  "success": true,
  "data": {
    "id": "...",
    "stripe_subscription_id": "sub_...",
    "plan_key": "...",
    "status": "active",
    "current_period_start": "2026-04-01T00:00:00Z",
    "current_period_end": "2026-05-01T00:00:00Z",
    "cancel_at": null,
    "trial_end": null,
    "quantity": 5,
    "metadata": {},
    "prerequisite_subscription_id": null,
    "created_at": "2026-04-01T00:00:00Z",
    "updated_at": "2026-04-01T00:00:00Z"
  }
}

Response Codes

StatusMeaning
201 CreatedRequest accepted. On success the full record is returned; a platform plan or a plan not in your catalogue is reported as refused in the response body (buy it through hosted Checkout instead)
400 Bad RequestRequest body validation failure (e.g. missing or malformed fields)
401 UnauthorizedMissing or invalid access token
500 Internal Server ErrorUnexpected server error

Hosted Checkout (redirect flow)

POST /v1/billing/create-checkout-session

Creates a Stripe Checkout session and returns its URL for redirect-based payment collection. Request body: price_id, package_id, and optional success_url, cancel_url, and trial_period_days. The success_url and cancel_url values are validated against an allowlist of permitted application domains, preventing open redirect attacks through Stripe Checkout.

Update Subscription

PUT /v1/billing/subscriptions/:id

Update the metadata on an existing subscription. Changing your plan or seat count, and buying or cancelling a Backbuild plan, are done through hosted Stripe Checkout and your billing settings, not here. A subscription to a Backbuild platform plan is managed by the billing system: its billing period, trial, seats, metadata and cancellation dates cannot be changed through this endpoint.

Request Body

{
  "metadata": { "note": "..." }
}

List Invoices

GET /v1/billing/invoices

The organization is resolved from the authenticated session.

Query Parameters

ParameterTypeDescription
statusstringFilter: draft, open, paid, uncollectible, void
limitintegerMax results (default: 25, max: 100)
offsetintegerPagination offset

Response

{
  "success": true,
  "data": {
    "items": [
      {
        "id": "...",
        "invoice_number": "...",
        "status": "paid",
        "amount_due": 9900,
        "amount_paid": 9900,
        "currency": "usd",
        "due_date": "2026-03-01T00:00:00Z",
        "paid_at": "2026-03-01T00:05:00Z",
        "hosted_invoice_url": "https://invoice.stripe.com/...",
        "pdf_url": "https://pay.stripe.com/..."
      }
    ],
    "total": 12,
    "page": 1,
    "page_size": 25
  }
}

Update Payment Method

PUT /v1/billing/payment-methods

Attach (or update the default) Stripe payment method for the authenticated user’s organization. The payment method is verified to belong to the organization’s Stripe customer before it is recorded. The organization is resolved from the session.

Request Body

{
  "payment_method_id": "pm_...",
  "set_as_default": true,
  "billing_details": {
    "name": "Acme Inc.",
    "email": "billing@example.com"
  }
}