> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.fluveo.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.fluveo.com/_mcp/server.

# Subscriptions

> **Status: `contracted_test`.** In the machine-checked test-mode contract
> (`openapi.subset.json`) and the [API Reference](/api-reference): create,
> retrieve, list. Served by the `fluveo-billing` sidecar (ADR 0019); promoted
> 2026-07-13. Update/cancel are not in the contract yet. The `Stripe-Version`
> header is optional; send an `Idempotency-Key` on POST writes. See
> [API coverage](/api-coverage).

A Subscription bills a [customer](/resources/customers) on a recurring
[price](/billing/prices), generating an [invoice](/billing/invoices) each cycle. It
tracks the billing period, status (`incomplete`, `active`, `past_due`, `canceled`, …),
and its items — each subscription item expands its price inline on reads. A new
subscription starts `incomplete` and activates through its first hosted invoice
payment.

Served operations: **create**, **retrieve**, and **list**. Create items are
form-encoded with indexed brackets (`items[0][price]`, `items[0][quantity]`) — the
service reads those literally. A create that brings its own saved card and mandate, and the
legacy renew call, answer `400 subscription_automatic_collection_unavailable`. Billing renews an
enrolled subscription on its own at period end (see below).
Dashboard-created subscriptions use the same API and persist in merchant-scoped
durable Billing storage.

> **Warning**
>
> **Only a first invoice paid on its hosted page enrolls renewal.** A
> `charge_automatically` subscription renews only once its first invoice has been paid on the
> invoice's `hosted_invoice_url`. That page shows the renewal consent text above Pay, and the card is
> saved with the customer's acceptance. A first invoice paid with `POST /v1/invoices/{id}/pay`, or
> any other way, leaves the subscription `active` with **no renewal invoice and no charge** at period
> end; Stripe would renew it. No public field shows which case a subscription is in, and
> `default_payment_method` does not decide it. Send customers the first invoice's
> `hosted_invoice_url`.

## Hidden from the public API

Each item below is hidden because it does not follow the Stripe parity ADR (ADR 0004 as amended). The [hidden public `/v1` registry](https://github.com/fluveohq/fluveo/blob/main/tests/api-contract/stripe/hidden-public-v1.json) lists every
hidden item. Public `/v1` answers a hidden operation as an unknown URL, refuses a hidden request
parameter or value with Stripe's `invalid_request_error`, and omits a hidden response key.

* the request parameter `mandate` of `POST /v1/subscriptions` (HIDE0-035)
* the request parameter `start_date` of `POST /v1/subscriptions` (HIDE0-036)
* the response key `current_period_end` of `POST /v1/subscriptions` (HIDE0-037)
* the response key `current_period_start` of `POST /v1/subscriptions` (HIDE0-038)
* the response key `current_period_end` of `GET /v1/subscriptions` (HIDE0-059)
* the response key `current_period_start` of `GET /v1/subscriptions` (HIDE0-060)
* the response key `current_period_end` of `GET /v1/subscriptions/{subscription}` (HIDE0-069)
* the response key `current_period_start` of `GET /v1/subscriptions/{subscription}` (HIDE0-070)

## In the dashboard

A subscription's page in the dashboard (test mode) warns **Renewal not enrolled**, with the reason, when Billing will not renew it at the end of its period.