Ingram Cloud

Documentation

Credits & billing

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.

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.

Free €10 when you add a card

Running agents needs a verified card; the trial is card-gated against fraud. Add one (Settings → Billing → Add a card) and €10 in credits is granted immediately. 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

Buy credits in the console: 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%).

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.

Stored data

Inference is charged as it happens; stored bytes are charged once a day, for what you were holding when the sweep ran. Two classes, priced separately:

ClassRateWhat it counts
storage.blob€0.03 / GiB-monthFiles you uploaded and files captured from conversations
storage.vector€0.12 / GiB-monthVector-store chunks, counting each chunk's text and the 6,144-byte embedding it carries

Vector data is dearer because it lives in Postgres behind an index, where files sit in object storage. Unlike model tokens, these are flat rates of ours rather than a provider's price with a margin on it, so there is no markup on them.

The first 1 GiB per organization is free, and the allowance is spent on the dearer class first, so a mixed org's allowance covers more spend. The allowance pools across your projects, exactly as the wallet does.

Each day's charge lands as one Storage — <date> debit whose metadata carries the gross and billable bytes, and it shows in usage under the storage.blob and storage.vector models:

# Authorization: tenant-admin token (server-side only)
curl "https://api.cloud.ingram.tech/v1/usage?group_by=model&period=2026-08" \
  -H "Authorization: Bearer $IC_ADMIN_TOKEN" \
  -H "IC-Api-Version: 2026-05-01"
# → 200 { "data": [ { "model": "storage.vector", "tokens": 0, "cost": 0.42 },
#                   { "model": "openai.gpt-5.6-sol", "tokens": 512000, "cost": 3.10 } ] }

Two consequences follow. Because it samples rather than integrates, data created and deleted inside the same day is never charged. And because the bytes are already written, a storage charge is not refused when the balance is empty: runs stop at a 402, storage keeps accruing and can take the wallet negative.

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; a credit.exhausted event fires. If auto-reload (below) is on, it charges your saved card first and the run proceeds when the top-up clears.

A third-party app the organization linked gets the same 402s. It should send the person to https://cloud.ingram.tech/console/settings/billing?client_id=<its client_id>&return_url=<where to return>: the billing page names the app, and once a card is added or credits bought it sends them back to return_url. The return is honoured only for a linked app and only to the origin that serves its client metadata document.

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 charges your saved card for a fixed reload amount when the balance falls below a threshold. It's off by default; the threshold defaults to €10 (the console's low-balance line, so it fires before the wallet empties) and you set the amount. 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. 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).