Skip to main content
Six methods. Every monetary value is integer micro-USD — the client never exposes a float and never converts to dollars; formatting is your presentation decision. API detail: Credits.

show

GET /v1/credits/balance:
79416537 micro-USD is $79.416537.

topup

POST /v1/credits/topups, body { amount_micro_usd }. Opens a hosted checkout and credits nothing — only the verified provider callback moves the balance. Send the person to the returned URL.

ledger

GET /v1/credits/ledger. LedgerFilter extends the page query with type ("debit" | "credit"), session_id, agent_id, deployment_id, from, and to — every movement, attributable to what spent it.

subscription

GET /v1/credits/subscription — the plan, which is the right to use the organization at all:
status is none | active | past_due | canceled. Every route outside billing answers 402 subscription_required until it reads active. While past_due, grace_until is the moment the organization stops working. action_url is null on a read. plan is "standard" | "pro" | null (null before the first subscription), with its monthly price_micro_usd and included_credit_micro_usd. A free trial reads status: "active" — there is no trial status — with trial_end set while it runs. pending_plan is a downgrade scheduled for current_period_end. trial_eligible says whether subscribe({ plan: "standard" }) would start the 7-day free trial. trial_days and trial_credit_micro_usd are the trial’s length and starting credit on this deployment (0 when trials are off). The plan fields are optional in the schema, so the client still parses an older server that omits them.

subscribe

POST /v1/credits/subscription. Opens the hosted checkout for the plan — Standard by default, with the 7-day free trial when trial_eligible — and answers action_url. Send the person there; nothing changes until the signed callback lands. An organization whose plan is already active throws ApiError state_conflict: use changePlan.

changePlan

PATCH /v1/credits/subscription. Changes an active plan. "pro" is immediate: the difference for the rest of the month is charged now on the card on file, and a running trial ends with $200 charged. "standard" from Pro takes effect at current_period_end — nothing refunded, the Pro credit kept — and reads back as pending_plan: "standard"; changePlan("pro") before then takes it back. The plan already held with nothing pending is a no-op. No active plan throws state_conflict.

cancelSubscription

DELETE /v1/credits/subscription. Stops the plan at the end of the period already paid for — never immediately. The state follows the provider’s callback, so the answer reports the request, not a completed change (cancel_at_period_end: true).

billingPortal

POST /v1/credits/billing_portal. Returns a link to the payment provider’s own hosted account page — change the card, download invoices, cancel. Send the person to action_url; it is single-use and expires, so mint one per visit rather than caching it.
An organization that has never held a plan has no account to manage: the call throws ApiError with code not_found. Catch it and offer subscribe() instead.