Billing
Read the billing account, set a monthly budget, opt into overage, start Stripe Checkout, open the customer portal, and the Stripe webhook contract.
Stripe is the source of truth for money; Zumik keeps the projection it needs to enforce caps inline with inference. The console reads the account, sets budgets, opts into overage, and starts Checkout; Stripe webhooks credit prepaid balances and refresh subscription state. Money is tracked in integer micro-USD (1e-6 USD). See the billing and budgets guide.
All endpoints except the webhook require a bearer API key. See authentication.
Read the account
GET /v2/billing/account
curl https://api.zumik.ai/v2/billing/account \
-H "Authorization: Bearer $ZUMIK_API_KEY"{
"id": "prj_01jy7n0a4c8m2t6v9q3wrxk7bd",
"object": "billing_account",
"project_id": "prj_01jy7n0a4c8m2t6v9q3wrxk7bd",
"plan": "base",
"subscription_status": "active",
"credit_balance_micros": 4250000,
"cycle_spend_micros": 750000,
"monthly_budget_micros": 20000000,
"overage_mode": "pause",
"created_at": "2026-06-01T00:00:00Z",
"updated_at": "2026-06-15T16:40:11Z"
}objectstringAlways billing_account.
project_idstringThe owning project.
planstringThe plan tier: free, base, or pilot.
stripe_customer_idstringThe Stripe customer id, omitted until a payment method is linked. Never a card number.
subscription_statusstringnone, active, past_due, or canceled. Inference is allowed only when active.
credit_balance_microsintegerRemaining prepaid plus allowance credits this cycle, in micro-USD.
cycle_spend_microsintegerSpend accumulated this cycle, in micro-USD.
monthly_budget_microsintegerThe hard monthly cap, omitted when none is set.
overage_modestringpause (default) or allow.
created_atstringupdated_atstringSet a monthly budget
POST /v2/billing/budget
Sets the hard monthly cap and re-arms the 50/80/100% alert ladder for the cycle.
monthly_budget_usdnumberThe cap in whole USD. Must be non-negative. null removes the cap.
curl https://api.zumik.ai/v2/billing/budget \
-H "Authorization: Bearer $ZUMIK_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "monthly_budget_usd": 20 }'Returns the updated billing account.
Opt into overage
POST /v2/billing/overage
When overage is off (the default), inference pauses at the cap with quota_exceeded. Enabling it bills past the cap at pay-as-you-go rates and requires explicit confirmation.
allow_overagebooleanrequiredtrue to bill past the cap, false to pause at it.
confirmbooleanMust be true when allow_overage is true.
curl https://api.zumik.ai/v2/billing/overage \
-H "Authorization: Bearer $ZUMIK_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "allow_overage": true, "confirm": true }'Returns the updated billing account with overage_mode set.
Add credits (PaymentIntent)
POST /v2/billing/payment-intent
Creates a Stripe PaymentIntent for a amount_usd credit top-up and returns its client secret plus the publishable key. The console mounts the Stripe Payment Element with these, so the card is entered inline on Zumik — the customer never leaves the app, and card data goes from the browser straight to Stripe (it never touches Zumik's servers). The card is saved for off-session auto-recharge. The webhook credits the balance on payment_intent.succeeded.
amount_usdnumberrequiredCredits to add, in whole USD. Must be between $5 and $10,000.
curl -X POST https://api.zumik.ai/v2/billing/payment-intent \
-H "Authorization: Bearer $ZUMIK_API_KEY" \
-H "content-type: application/json" \
-d '{"amount_usd": 25}'{
"client_secret": "pi_..._secret_...",
"publishable_key": "pk_live_...",
"amount_usd": 25
}client_secretstringThe PaymentIntent client secret. Pass it to Stripe.js to confirm the payment client-side.
publishable_keystringThe Stripe publishable key for mounting the Payment Element.
Auto-recharge
POST /v2/billing/auto-recharge
Configure balance-triggered auto top-up. When on and the credit balance falls to or below threshold_usd, Zumik charges the saved card for amount_usd off-session. Enabling requires a saved card (made by a prior top-up). Returns the updated billing account.
enabledbooleanrequiredTurn auto-recharge on or off.
threshold_usdnumberRecharge when the balance falls to or below this (USD). Default $5.
amount_usdnumberHow much to add per recharge (USD), $5-$10,000. Default $25.
curl -X POST https://api.zumik.ai/v2/billing/auto-recharge \
-H "Authorization: Bearer $ZUMIK_API_KEY" \
-H "content-type: application/json" \
-d '{"enabled": true, "threshold_usd": 5, "amount_usd": 25}'Open the customer portal
POST /v2/billing/portal
Opens the Stripe customer portal so the user can update their card or view invoices. Requires an existing Stripe customer (i.e. they have made a top-up).
curl -X POST https://api.zumik.ai/v2/billing/portal \
-H "Authorization: Bearer $ZUMIK_API_KEY"{ "url": "https://billing.stripe.com/p/session/..." }urlstringThe hosted Stripe billing-portal URL.
Stripe webhook
POST /v2/billing/stripe-webhook
The endpoint Stripe posts events to. It is unauthenticated at the bearer-token layer and authenticates by verifying the Stripe-Signature header against the configured webhook secret before any state change. It is not called by your application.
It acts on checkout.session.completed, invoice.payment_succeeded, invoice.payment_failed, and customer.subscription.deleted for subscriptions, and invoice.payment_succeeded/invoice.paid, invoice.voided, and invoice.finalized for enterprise contracts (routed by the invoice's contract_id metadata). Unknown event types are acknowledged and ignored.
{ "received": true }receivedbooleanAlways true once a verified event is accepted.
Enterprise contracts
Negotiated annual deals are billed with Stripe Invoicing, not the self-serve credit top-up. These endpoints require an API key with the admin scope.
A contract moves open (invoice issued) → paid (the contract invoice is paid, which sets the account to the enterprise plan, marks it active, and grants the contract's credit allowance for the term) or void. The term is term_months from the paid date. Renewal issues a fresh invoice on the same terms.
Create a contract
POST /v2/billing/enterprise/contracts
Creates (or reuses) the project's Stripe customer, adds an invoice item for the annual value, then finalizes and sends a collection invoice carrying the project and contract metadata.
annual_price_usdnumberrequiredThe negotiated annual contract value billed on the invoice.
credit_allowance_usdnumberrequiredInference credit granted to the account when the invoice is paid.
term_monthsintegerdefault: 12Contract term, 1–60 months.
customer_emailstringBilling email. Required when the project has no Stripe customer yet.
descriptionstringLine-item description shown on the invoice.
{
"id": "ent_01jy...",
"object": "enterprise_contract",
"project_id": "prj_01jy...",
"status": "open",
"annual_price_micros": 120000000000,
"credit_allowance_micros": 50000000000,
"term_months": 12,
"stripe_customer_id": "cus_...",
"stripe_invoice_id": "in_...",
"hosted_invoice_url": "https://invoice.stripe.com/i/...",
"created_at": "2026-06-15T16:00:00Z",
"updated_at": "2026-06-15T16:00:00Z"
}List / retrieve
GET /v2/billing/enterprise/contracts returns { "object": "list", "data": [...] }, newest first. GET /v2/billing/enterprise/contracts/{id} returns one contract.
Void
POST /v2/billing/enterprise/contracts/{id}/void voids the contract's open Stripe invoice and marks the contract void. A paid contract can't be voided (issue a credit note in Stripe instead).
Renew
POST /v2/billing/enterprise/contracts/{id}/renew issues the next term's invoice on the same price, allowance, and term, returning the new contract. The account is re-credited when that invoice is paid.
Errors
| Status | Code | When |
|---|---|---|
| 400 | invalid_request_error | Negative budget, overage without confirm: true, billing not configured, a non-positive annual_price_usd, voiding a paid contract, or Stripe rejected the request. |
| 401 | invalid_api_key | Missing or invalid API key, or an invalid Stripe signature on the webhook. |
| 403 | insufficient_scope | An enterprise endpoint called without an admin-scoped key. |
| 404 | invalid_request_error | The contract does not exist in this project. |
See the full table on errors.
Retention profile
Set and read how much of a request Zumik retains. The default is metadata-only; opt into tokenized or encrypted full-fidelity traces when you need them.
SAML SSO
Configure an enterprise SAML connection and let your team sign in to the Zumik console through your identity provider, with signed-assertion verification, replay protection, and JIT provisioning.