Credits & billing
Credits are your organization's prepaid balance with Ingram Cloud — the money you pay us for platform usage. This is the opposite direction from Customers & metering, which is the money you bill your own customers; the two never share a page on purpose.
Credits are held at the organization level (one wallet pooled across all of your projects), not per project or per customer. Ingram Cloud is the merchant of record for these charges; your card is charged through Stripe.
Your wallet is held in your organization's billing currency — EUR by default,
set from Stripe when you add a card. Every amount below (balance_cents, ledger
entries, top-ups) is in that currency; format *_cents as minor units of it.
Start free: unlock €10
Running agents needs a verified card — the free trial is card-gated to keep
fraud out, but adding a card costs nothing. Add one (Settings → Billing → Add a
card) and €10 in credits unlocks immediately, no charge. Until a card is
added, runs are refused with 402 card_required.
# Authorization: organization key (server-side only)
curl https://api.cloud.ingram.tech/v1/organization/billing/setup \
-H "Authorization: Bearer $IC_ORG_TOKEN" \
-H "IC-Api-Version: 2026-05-01" \
-H "Content-Type: application/json" \
-d '{ "return_url": "https://your.app/billing?setup={CHECKOUT_SESSION_ID}" }'
# → 201 { "url": "https://checkout.stripe.com/c/pay/cs_…" }
This is a no-charge Stripe setup session: the card is saved (and reused for top-ups and auto-reload), and the €10 welcome credit is granted once per organization, when the card verifies.
Buying credits
The console is the way in: Settings → Billing → Buy credits. Pick a preset (€20 / €100 / €500) or enter another amount, then pay by card inline — Stripe collects the card and billing address and computes any tax. Your balance updates the moment Stripe confirms the charge.
A Stripe customer record for your organization is created only on the first successful payment, and reused (with any saved card) on later top-ups.
Checking your balance
The balance lives on the organization surface, so it takes an organization key:
# Authorization: organization key (server-side only)
curl https://api.cloud.ingram.tech/v1/organization/billing/balance \
-H "Authorization: Bearer $IC_ORG_TOKEN" \
-H "IC-Api-Version: 2026-05-01"
# → 200 { "currency": "eur", "balance_cents": 10000,
# "stripe_customer": true }
GET /v1/organization/billing/ledger returns the append-only ledger, newest
first — each entry carries a signed amount_cents and a kind. Top-ups are
positive kind:"topup"; usage debits are negative kind:"debit". Pass
?direction=credit to return only money-in rows (top-ups and grants) or
?direction=debit for only usage. The list is keyset-paginated like every other
(?limit= up to 100, default 25; pass the returned next_cursor back as
?cursor= until has_more is false).
How usage draws down credits
Every run your agents make is metered and debited from the org wallet when it finishes. On an Ingram-hosted key the charge is the run's provider cost (priced from the model price book and converted into your billing currency) times your organization's margin (the platform markup; 20% by default, set per organization). On a key of your own it is the platform fee alone — see Your own keys. The wallet is one pool across all your projects; which project drew how much is on each debit and summarized by the per-project endpoint below. Usage you've already started always finishes — the balance can dip slightly negative on an in-flight run; the gate below catches the next one.
Your own keys
The wallet recovers the provider cost only when we paid it. When a turn runs on
a key of yours — your organization's BYOK key
or a smith's own end-user key — the provider billed
that account directly, so the wallet is charged the platform fee only
(cost × (margin − 1), i.e. 20% of list cost at the default margin, not 120%).
This is what "no model markup" means: bring your own key and you never pay us for
the tokens, only for the platform.
Ingram-hosted keys are our spend, so those turns draw the full cost × margin.
The run's metered usage always records the full token count and list cost for
attribution; only the wallet draw changes. Each debit's metadata carries
key_source (smith / byok / hosted) so a fee-only draw is auditable.
Per-project spend
One wallet funds every project, so the org view is "which project is spending it":
# Authorization: organization key (server-side only)
curl "https://api.cloud.ingram.tech/v1/organization/billing/usage?period=2026-06" \
-H "Authorization: Bearer $IC_ORG_TOKEN" \
-H "IC-Api-Version: 2026-05-01"
# → 200 { "period": "2026-06", "currency": "eur", "total_drawn_cents": 4210,
# "total_tokens": 512000, "projects": [ { "project_id": "proj_…",
# "name": "Acme", "drawn_cents": 4210, "tokens": 512000,
# "budget_limit": 100, "budget_action": "block" } ] }
drawn_cents is the wallet draw (the platform margin is already in it — this is
your cost, not the raw provider cost); tokens is what the project's runs
consumed that period. period defaults to the current calendar month (UTC).
budget_limit is the
project's funding cap — a tenant-scope cost budget set
on that project — or null when the project draws freely from the org wallet.
Without a budget a project is bounded only by the org's overall balance; with a
block budget it stops at its own limit even while the wallet still has funds.
For the trend rather than the total — to catch a recent spike or drop in one project — ask for the daily draw over a rolling window:
# Authorization: organization key (server-side only)
curl "https://api.cloud.ingram.tech/v1/organization/billing/usage/series?days=30" \
-H "Authorization: Bearer $IC_ORG_TOKEN" \
-H "IC-Api-Version: 2026-05-01"
# → 200 { "currency": "eur", "from": "2026-06-13", "to": "2026-07-12",
# "projects": [ { "project_id": "proj_…", "name": "Acme" } ],
# "points": [ { "day": "2026-07-11", "project_id": "proj_…",
# "drawn_cents": 320 } ] }
days is the rolling window ending today (UTC), 1–365, default 30. points are
sparse — a day/project with no draw is simply absent, so treat a missing cell as
zero. projects lists those with any draw in the window, ranked by total.
When runs are refused
Two prepaid gates, both at run creation:
402 card_required— no verified card yet. Add one to unlock €10 free (above).402 insufficient_credits— the wallet is empty; acredit.exhaustedevent fires. If auto-reload (below) is on, it charges your saved card first and the run proceeds when the top-up clears.
A run already in flight is never interrupted. When the wallet runs out, the organization's owners and admins get one email — the next one only after the balance is topped up and depleted again.
Starting a top-up programmatically
The console uses a Stripe-hosted Checkout Session under the hood. If you build your own top-up UI, mint the session and redirect the buyer to its URL:
# Authorization: organization key (server-side only)
curl https://api.cloud.ingram.tech/v1/organization/billing/checkout \
-H "Authorization: Bearer $IC_ORG_TOKEN" \
-H "IC-Api-Version: 2026-05-01" \
-H "Content-Type: application/json" \
-d '{ "amount_cents": 10000,
"return_url": "https://your.app/billing?topup={CHECKOUT_SESSION_ID}" }'
# → 201 { "url": "https://checkout.stripe.com/c/pay/cs_…" }
Send the browser to url (Stripe's hosted checkout). Credits are applied when
Stripe confirms the payment (via our webhook), not when the session is created —
so a balance reflects a top-up a moment after the customer finishes paying.
Redeeming a credit code
If you've been given a credit code, redeem it from the Redemption code box on
the billing page, or call the API. Codes are one-time-use and matched
case-insensitively; the credit lands in your wallet immediately as a
kind:"redemption" ledger entry.
# Authorization: organization key (server-side only)
curl https://api.cloud.ingram.tech/v1/organization/billing/redeem \
-H "Authorization: Bearer $IC_ORG_TOKEN" \
-H "IC-Api-Version: 2026-05-01" \
-H "Content-Type: application/json" \
-d '{ "code": "WELCOME10" }'
# → 200 { "amount_cents": 1000, "currency": "eur" }
amount_cents is the amount credited in your wallet's currency (a code in another
currency is converted on the way in). An unknown or malformed code returns
422 invalid_code; one already used returns 409 code_already_redeemed.
Auto-reload
Auto-reload keeps your balance from running dry without you watching it: when the balance falls below a threshold, your saved card is charged for a fixed reload amount. It's off by default; the threshold defaults to €10 (the console's low-balance line, so it fires before the wallet empties) and the amount is yours to set. The first top-up saves your card, so auto-reload only works once you've bought credits at least once.
# Authorization: organization key (server-side only)
curl -X PUT https://api.cloud.ingram.tech/v1/organization/billing/autoreload \
-H "Authorization: Bearer $IC_ORG_TOKEN" \
-H "IC-Api-Version: 2026-05-01" \
-H "Content-Type: application/json" \
-d '{ "enabled": true, "threshold_cents": 1000, "amount_cents": 10000 }'
# → 200 { "enabled": true, "threshold_cents": 1000, "amount_cents": 10000 }
GET /v1/organization/billing/autoreload reads the current settings back. Once
usage debits draw your balance down past the threshold, auto-reload tops it back
up off-session. You can also top up from the saved card on demand — POST /v1/organization/billing/reload charges it now (amount_cents optional, defaults
to your configured reload amount):
# Authorization: organization key (server-side only)
curl -X POST https://api.cloud.ingram.tech/v1/organization/billing/reload \
-H "Authorization: Bearer $IC_ORG_TOKEN" \
-H "IC-Api-Version: 2026-05-01" \
-H "Content-Type: application/json" \
-d '{ "amount_cents": 5000 }'
# → 200 { "credited": true, "payment_status": "succeeded" }
A reload returns 409 no_saved_card if no card has been saved yet.
Managing billing & invoices
GET /v1/organization/billing/portal mints a Stripe billing portal
session — manage your billing address and VAT id, update the saved card, and
download invoice history. Pass a return_url Stripe sends the user back to:
# Authorization: organization key (server-side only)
curl "https://api.cloud.ingram.tech/v1/organization/billing/portal?return_url=https://your.app/billing" \
-H "Authorization: Bearer $IC_ORG_TOKEN" \
-H "IC-Api-Version: 2026-05-01"
# → 200 { "url": "https://billing.stripe.com/p/session/…" }
The portal needs an existing Stripe customer, so it returns 404 no_customer
until your first top-up has created one.
In the console
Organization overview (from the organization menu in the workspace switcher)
is the at-a-glance, cross-project view: this month's combined spend, tokens, and
credits remaining, plus a spend-by-project breakdown that ranks each
project's draw against its funding cap (toggle it to rank by tokens instead) and
a spend-over-time chart — daily draw per project over a 7/30/90-day window,
for spotting a recent spike or drop. It reads the
GET /v1/organization/billing/usage and …/usage/series endpoints above.
Settings → Billing shows your current balance with Add a card (unlock €10 free, shown until a card is on file), Buy credits, Auto-reload (with a Reload now button), Manage billing & invoices (the Stripe portal), and the same per-project breakdown. Both sit apart from Observe → Usage & cost (the single-project provider-cost view and per-project budgets) and Build → End users (what you bill others).