Skip to main content
POST
cURL
Create one plan without replacing other catalog items. A plan grants a monthly credit allowance to each customer who buys it. The request uses integer cents for the monthly price and an integer credit count for the allowance.

Choose a free or paid plan

  • Set monthlyPriceCents to 0 for a free plan. Attach it with POST /v1/billing/attach; Ledger activates it and grants its first monthly allowance immediately, without Stripe or a Checkout URL.
  • Set monthlyPriceCents above 0 for a recurring plan. Ledger syncs a monthly Stripe Price to the Stripe account connected in the key’s environment. For example, 1900 means $19.00 per month in a USD catalog.
  • monthlyCredits must be positive. Paid plans grant the allowance after Ledger receives Stripe’s paid invoice event. Free plans grant it on assignment; each new monthly period creates an allowance when the customer’s balance is next read or usage is recorded.
The plan ID is your stable API identifier. Use letters, numbers, underscores, or hyphens (up to 100 characters). The display name can be changed later; the ID cannot. A second active plan with the same ID returns 409 already_exists.

After creating a paid plan

The response contains the created item, changed: true, and a stripeSync state. awaiting_connection means Stripe has not been connected yet; connect it under Developer → Stripe in the dashboard, then confirm the plan reports synced. If the state is pending or failed, check the sync result before sending customers to Checkout. Ledger can retry synchronization when an attach request arrives. The dashboard shows the state in Catalog → Plans. Create a customer with Create or get a customer, then use Attach a plan or add-on to get a hosted Checkout URL. A successful browser redirect is not proof of payment. Ledger activates the subscription and grants credits after the signed Stripe invoice webhook arrives. For a free plan, the attach response contains subscriptionId and status: "active" rather than checkoutUrl. No Stripe connection or payment redirect is needed.

Changing a plan later

Update a plan requires its full editable body. A changed plan creates a new version for future Checkouts; existing subscriptions retain their referenced version. Archive a plan removes it from active lists and new purchases while retaining historical subscriptions. See Catalog for the full lifecycle.

Authorizations

Authorization
string
header
required

Bearer authentication header of the form Bearer <token>, where <token> is your auth token.

Body

application/json
id
string
required
Required string length: 1 - 100
Pattern: ^[a-zA-Z0-9_-]+$
name
string
required
Required string length: 1 - 120
monthlyCredits
integer
required
Required range: x <= 2147483647
monthlyPriceCents
integer
required
Required range: 0 <= x <= 2147483647

Response

Plan created

item
object
required
changed
boolean
required
stripeSync
enum<string>
Available options:
synced,
pending,
failed,
awaiting_connection