Skip to main content
POST
cURL
Starts an upgrade for a customer with an active Stripe-backed monthly subscription. Send customerId and the target planId, plus a client-generated Idempotency-Key header. The target must be an active paid plan with a synced Stripe Price and a higher monthly price than the customer’s current plan. The Stripe connection must have a stored signed webhook endpoint. Ledger returns 502 stripe_not_configured before starting an upgrade when that setup is incomplete. The response reports an upgradeId, a status (applied, pending_payment, processing, or closed), and a nullable paymentUrl. If paymentUrl is present, send the customer to Stripe’s hosted invoice page. Ledger applies the new plan and its credits after Stripe confirms payment; processing means the result is still being reconciled. A verified upgrade starts a new full-price monthly billing cycle. Ledger expires the previous plan’s unspent allowance and grants the new plan’s allowance; separately purchased credit-pack credits remain available. If payment fails or expires, the existing plan and allowance remain in place. Reuse the same idempotency key when retrying this intended upgrade. Reusing it for a different target returns 409 idempotency_key_mismatch; starting another upgrade while one is pending returns 409 upgrade_pending. An ineligible subscription, unsynced or non-higher target, or incompatible Stripe billing state returns 400. If Stripe reconciliation needs another attempt (503) or a Stripe request fails (502), retry with the same key rather than starting a second upgrade. See Billing and Checkout for payment timing and Customers for plan attachment. The API key selects the environment; live upgrades require live activation and Ledger’s live-charge gate.

Authorizations

Authorization
string
header
required

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

Headers

idempotency-key
string
required
Required string length: 1 - 255

Body

application/json
customerId
string
required
Required string length: 1 - 255
planId
string
required
Required string length: 1 - 255

Response

Current upgrade outcome

upgradeId
integer
required
status
enum<string>
required
Available options:
applied,
pending_payment,
processing,
closed
paymentUrl
string<uri> | null
required