# Inferit: every page as markdown > Inferit is the inference layer for AI agents: one integration to access models and pay per inference request. Developers who run open-weight models connect them and earn from the requests they serve. Behind the one OpenAI-compatible API is a marketplace: sellers list open-weight models at their own price, and each request goes to the cheapest healthy seller of the model it names ("model": "auto" can also pick the model, by a published quality ranking weighed against the request's price). Prices are per token, shown in US dollars per 1M tokens and charged per request. Buyers spend API credits with a key; AI agents can also pay per request with x402 v2, without an account. Payments settle on chain on Whitechain, and every figure links to the block explorer. The index of these pages is https://inferit.cc/llms.txt. Each section below is one page's markdown twin, in the index's order. A section starts with a line "Source: " after a "---" separator. --- Source: https://inferit.cc/agents.md # Inferit for agents > Inferit is the inference layer for AI agents: one integration to access models and pay per inference request. Developers who run open-weight models connect them and earn from the requests they serve. Your agent buys per request, without an API key from every lab. Name a model and Inferit picks its cheapest healthy seller, or send `"model": "auto"` and it picks the model too, and charges the exact price. Pay per request with x402 v2 (no account, no API key) or spend a prepaid balance with a key. **Network.** Whitechain Sepolia, chain id 1874. Prices settle in ITC, free from Inferit's faucet. When `GET https://api-production-c74b9.up.railway.app/v1/rails` lists a `stellar` rail, x402 payments also work on Stellar, in ITC: https://inferit.cc/docs/payments/stellar.md. Contracts and security: https://inferit.cc/docs/security-trust.md and https://inferit.cc/security. **Units.** API amounts are integers in millionths of a dollar, paid as millionths of an ITC. So `"10000"` = $0.01 (0.01 ITC). JSON carries amounts as decimal strings (`"10000"`). ## In one minute 1. Claim free ITC: `POST https://api-production-c74b9.up.railway.app/v1/faucet` with `{"address":"0x..."}`. It needs no gas. 2. Call `POST https://api-production-c74b9.up.railway.app/v1/chat/completions` with `"model": "auto"` and no key, as the code below does. You get `402 Payment Required` with a quote of at least $0.01 (`amount` ≥ `"10000"`). 3. Sign the quote with a standard x402 v2 client and resend the same body. The official `@x402/fetch` works once ITC is allowed in its spend controls (one `setSpendControls` line, below). Sign with a plain key (EOA): smart-wallet signatures (ERC-1271, ERC-6492) are not accepted. 4. You get the answer. `x-inferit-model` names the model that served it. The request is charged its exact cost; the rest of the payment stays your balance. ## Two ways to pay With an API key, each request is charged to your prepaid balance: no quote, no payment step (only a `402 insufficient_funds` when the balance or the ceiling is too low, or `402 spend_limit_exceeded` when the key is at its limit). Without a key, you get a 402 quote and pay for that one request with x402. | | x402 (no account) | API key | | --- | --- | --- | | Setup | None: any EVM key, even one with zero WBT | Sign in with the wallet (an off-chain signature), mint a key | | Per request | One x402 payment of at least $0.01, credited to your balance | Nothing extra: the request spends your balance | | Charged | The exact cost of the request | The exact cost of the request | | Header | `PAYMENT-SIGNATURE` (answering the 402) | `Authorization: Bearer ik_...` | ## Let Inferit pick the model Send `"model": "auto"` and Inferit picks the model. Among the models that have a healthy seller right now, it keeps the ones that fit the request (context window, tools, images, and any price or quality limit you set), scores each on a published quality ranking against its price for this exact request, and sends the request to the best value, at that model's cheapest healthy seller. If that seller fails before it sends a byte, the request moves to the next seller, then to the next model. The router chooses from the request's size and features, never from what the prompt says. | `model` | Policy | What it picks | | --- | --- | --- | | `auto` (also `auto:balanced`, `inferit/auto`) | best value | Quality weighed against this request's price: a model that costs twice as much must score 6 points higher to win | | `auto:cheap` (also `inferit/auto:cheap`) | lowest price | The lowest price for this request among the candidates; quality breaks ties | | `auto:best` (also `inferit/auto:best`) | highest ranked | The highest quality score among the candidates; price breaks ties | Any other id that starts with `auto:` or `inferit/auto` answers `400 invalid_auto_policy`. Optional hints, as body fields or as headers (for clients that cannot add body fields). If both are sent, the stricter value wins: | Body field | Header | Range | Meaning | | --- | --- | --- | --- | | `max_price_per_m` | `x-inferit-max-price-per-m` | integer millionths of a dollar per 1M tokens, 1 to 10^12 | Skip any offer whose all-in price, blended on this request's estimated token mix, is above it. Auto and named models | | `min_context` | `x-inferit-min-context` | integer tokens, 1 to 100,000,000 | Only models whose context window is at least this. Auto only | | `min_quality` | `x-inferit-min-quality` | integer, 0 to 100 | Only models whose quality score is at least this. Auto only | Hints never reach a seller. `min_context` or `min_quality` with a named model answers `400 invalid_request`. Every served response says what happened: - `x-inferit-model`: the catalog id of the model that served the request (the JSON `model` field says the same; in a stream, trust the header). - `x-inferit-route`: `direct` for a named model, or `auto:balanced`, `auto:cheap`, `auto:best`. - `x-inferit-auto-choice` (auto only): `1` when auto's top choice served it, `2` or more when failover moved it to another model. With x402, the 402 quote is priced for the model auto picks, and the 402 carries `x-inferit-model` and `x-inferit-route`; the paid retry tries that model first. `GET https://api-production-c74b9.up.railway.app/v1/routing` returns the policies, the hints, the quality ranking (its sources and date) and the models auto can choose from now. When no model fits, the API answers `503 no_eligible_model`, and `error.reasons` counts why; without a key, that 503 comes before any 402, so nothing is paid. Naming a model with a live offer (a `best_price` in `GET https://api-production-c74b9.up.railway.app/v1/models`) still works then. The whole rule is at https://inferit.cc/docs/routing.md. ## Where to go | What | Where | | --- | --- | | API base (OpenAI-compatible; a `GET` on it returns a JSON index) | `https://api-production-c74b9.up.railway.app/v1` | | Chat completions (streaming supported; send `"model": "auto"` or name a model) | `POST https://api-production-c74b9.up.railway.app/v1/chat/completions` | | How model auto chooses, and what it can choose from now | `GET https://api-production-c74b9.up.railway.app/v1/routing` | | x402 discovery | `GET https://api-production-c74b9.up.railway.app/.well-known/x402` | | Inferit's ITC faucet | `POST https://api-production-c74b9.up.railway.app/v1/faucet` | | Inferit's ITC faucet on Stellar, while `GET /v1/rails` lists a `stellar` rail (a G… account with a trustline to ITC) | `POST https://api-production-c74b9.up.railway.app/v1/faucet/stellar` | | Models, list prices and the lowest live all-in price (the three auto rows first) | `GET https://api-production-c74b9.up.railway.app/v1/models` | | One model's order book (price levels, with offer and healthy-offer counts) | `GET https://api-production-c74b9.up.railway.app/api/markets/` | | One model's offers: all-in price, context, quantization, health, 24 h uptime and time to first token | `GET https://api-production-c74b9.up.railway.app/v1/models//endpoints` | | This guide | https://inferit.cc/agents.md (also served at https://inferit.app/agents.md) | | The same guide for people | https://inferit.cc/agents | | Every page of the site as markdown | https://inferit.cc/llms.txt (index), https://inferit.cc/llms-full.txt (full text) | | Full API reference | https://inferit.cc/docs/api-reference.md | | Automatic model routing | https://inferit.cc/docs/routing.md | | Pay with x402 on Stellar: the network, the asset and its contract, the trustline, the faucet, the client code, the limits | https://inferit.cc/docs/payments/stellar.md | | Selling inference, including the API-only path | https://inferit.cc/docs/sellers.md | | Selling from your own computer (the open-source seller app, one command) | https://inferit.cc/docs/sellers/quickstart.md | | List an open-weight model you run that is not in the catalog, then offer it at your own price (seller session or seller API key) | `POST https://api-production-c74b9.up.railway.app/v1/seller/models` (https://inferit.cc/docs/api-reference.md#seller) | | Frameworks: LangChain, Vercel AI SDK, LiteLLM, CrewAI, OpenCode | https://inferit.cc/docs/guides/langchain.md, https://inferit.cc/docs/guides/vercel-ai-sdk.md, https://inferit.cc/docs/guides/litellm.md, https://inferit.cc/docs/guides/crewai.md, https://inferit.cc/docs/guides/opencode.md | | The app, for people with a browser wallet | https://inferit.app | | Inferit's public repositories: the seller app, the x402 facilitator, examples, the model catalog (the market's code is private) | https://github.com/InferitAI | ## Two tokens, two jobs - **ITC** is what you pay for inference with: one ITC per dollar of price. It has 6 decimals, so one base unit is a millionth of a dollar (0.000001 ITC). Inferit's ITC faucet mints 1,000 ITC per address, once per 24 h, at no charge. It is sponsored: the claim needs no gas. - **WBT** is Whitechain's native gas token. You need it only for on-chain transactions you send yourself: a deposit, a seller registration, a withdrawal. An agent that pays with x402 sends none, so it needs no WBT until it withdraws. - The API accepts EIP-3009 payments in ITC only. ## Prices in US dollars - API amounts are integers in millionths of a dollar, paid as millionths of an ITC. - API prices are per 1M tokens, input and output, all-in: the seller's price plus the 5% marketplace commission. `"84000"` per 1M = $0.084 per 1M tokens. - `GET /v1/models` lists the three auto rows first (`owned_by: "inferit"`), then the models with a live offer, then the rest of the open-weight catalog, including list-price-only rows (`best_price: null`). Each live model's `live.max_context_tokens` is the largest context a healthy seller serves now. Closed models (`open_weight: false`, `servable: false`) are reference rows that no seller can list on Inferit: they are left out unless you pass `?include=reference`, and a request for one answers `404 model_not_servable`. A row with a `best_price` has a live offer. - `GET /v1/models` carries each price twice. `pricing.prompt` and `pricing.completion` are decimal strings in dollars (paid in ITC) per token (`"0.0000001"`), as OpenRouter writes them; `input_per_m`, `output_per_m` and `cache_read_per_m` are integer millionths of a dollar per 1M tokens (`"100000"`). `pricing` is the list price, `best_price` the lowest live all-in price from a healthy seller (or `null`), and `best_price.discount_pct` compares that all-in price with list. - What a request costs, at the serving seller's own price (before the fee): `sellerCost = ceil((uncachedIn × inputPerM + cachedIn × cacheReadPerM + out × outputPerM) / 1000000)`, then `fee = ceil(sellerCost × feeBps / 10000)`; you pay `sellerCost + fee`. Example: a seller asking `80000` / `160000` ($0.08 / $0.16) per 1M tokens before the fee: 1,000 input and 500 output tokens cost `160` + `8` = `168` millionths of a dollar ($0.000168). - The `x-inferit-buyer-cost-micro` response header is the authoritative cost of each request. ## Pay per request with x402: a prepaid meter x402 amounts are in token base units, so x402 can express a millionth of a dollar. But every x402 payment is an on-chain transaction, and each one costs gas. So Inferit works as a prepaid meter: 1. Call `POST https://api-production-c74b9.up.railway.app/v1/chat/completions` with no `Authorization` header (the code below sends `"model": "auto"`; any model with a live offer works the same way). It answers `402 Payment Required`. The `PAYMENT-REQUIRED` header is base64 JSON, and the body carries the same document: x402 v2, scheme `exact`, network `eip155:1874`, asset = ITC, `payTo` = the `MarketEscrow` contract (not Inferit), `maxTimeoutSeconds` 120 and `extra` = the token's EIP-712 name and version. 2. The amount is the worst-case cost of this exact request body at the top-ranked offer (with model auto: the top-ranked offer of the model auto picks, named in the 402's `x-inferit-model` header): the input estimate plus the output limit, all-in, and never less than $0.01 (0.01 ITC). The output limit is `min(max_tokens, max_completion_tokens, context_length)`, or 1,024 tokens when you send neither (times `n` when you ask for several choices); `context_length` is the model's, from `GET /v1/models`. The quote is pinned for 120 s. 3. Sign an EIP-3009 `TransferWithAuthorization` for that amount to the escrow, and resend the same body with the `PAYMENT-SIGNATURE` header. `X-PAYMENT`, the v1 name, is still accepted. 4. Inferit's facilitator verifies the payment and settles it first: it calls `depositWithAuthorization` on the escrow and pays the gas. The payment is credited to your own escrow balance. 5. The request is served (streaming included) and charged its exact cost against that balance. The response carries `PAYMENT-RESPONSE` (base64: the deposit transaction, the network and the payer) and `x-inferit-buyer-cost-micro`. 6. What the request does not use stays your escrow balance. Every call without a key gets its own 402 and its own payment. To spend the balance without paying again, sign in with the same wallet and use an API key (below), or withdraw it. Settlement to sellers is batched on chain: one transaction pays for many requests. ### TypeScript, with the official x402 fetch client A brand-new key with zero WBT works: the agent never sends a transaction itself. ```ts // npm i @x402/fetch @x402/evm viem then: npx tsx agent.mts (Node 18+, @x402 2.28 or newer) import { decodePaymentResponseHeader, wrapFetchWithPayment, x402Client } from '@x402/fetch'; import { ExactEvmScheme } from '@x402/evm/exact/client'; import { generatePrivateKey, privateKeyToAccount } from 'viem/accounts'; const API = 'https://api-production-c74b9.up.railway.app'; // A brand-new key works: the agent never sends a transaction itself. const account = privateKeyToAccount((process.env.AGENT_KEY as `0x${string}` | undefined) ?? generatePrivateKey()); // 1. Inferit's faucet gives this address 1,000 free ITC (the claim costs nothing). const faucet = await fetch(`${API}/v1/faucet`, { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify({ address: account.address }), }); console.log('faucet', faucet.status, await faucet.text()); // 2. The standard x402 v2 client. It only pays in tokens it was told about, so allow ITC in its spend // controls, and cap one payment at 1 ITC (1000000 base units, 6 decimals), whatever the server quotes. const ITC = { network: 'eip155:1874', asset: '0x2E672dFE33EA977FD064E01aDe7d8c73B3Be7fBB' } as const; const client = new x402Client() .register('eip155:*', new ExactEvmScheme(account)) .setSpendControls({ allowedAssets: [{ ...ITC, maxAmountPerPayment: '1000000' }] }); const fetchWithPayment = wrapFetchWithPayment(fetch, client); // 3. Call the API with no key: 402 -> sign -> paid retry, all inside fetchWithPayment. const res = await fetchWithPayment(`${API}/v1/chat/completions`, { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify({ model: 'auto', messages: [{ role: 'user', content: 'Say hello in five words.' }], max_tokens: 64, // the quote is the worst case for this body, so a small max_tokens keeps it small }), }); const body = await res.json(); console.log(res.status, body.choices?.[0]?.message?.content ?? body); // Which model answered (with model auto, Inferit picked it), and the payment receipt: the deposit transaction and who paid. console.log('model', res.headers.get('x-inferit-model')); const receipt = res.headers.get('PAYMENT-RESPONSE'); if (receipt) console.log(decodePaymentResponseHeader(receipt)); console.log('cost', res.headers.get('x-inferit-buyer-cost-micro'), 'millionths of a dollar; the rest stays in your balance'); ``` The `setSpendControls` line is configuration of the standard client, not a patch: the client only pays in tokens it knows, and ITC is not on its built-in list. Its `maxAmountPerPayment` (`"1000000"`, 1 ITC) is the client's maximum per payment: a setting in your client, not a rule the contract enforces. ### Python, the v2 exchange by hand No x402 package: `eth-account` signs the EIP-3009 authorization, so every field is visible. ```python # pip install "eth-account>=0.13" requests import base64, json, os, time import requests from eth_account import Account from eth_account.messages import encode_typed_data API = "https://api-production-c74b9.up.railway.app" acct = Account.from_key(os.environ["AGENT_KEY"]) if "AGENT_KEY" in os.environ else Account.create() b64 = lambda o: base64.b64encode(json.dumps(o).encode()).decode() unb64 = lambda s: json.loads(base64.b64decode(s)) requests.post(f"{API}/v1/faucet", json={"address": acct.address}) # free ITC, once per 24 h body = {"model": "auto", "messages": [{"role": "user", "content": "Say hello in five words."}], "max_tokens": 64} r = requests.post(f"{API}/v1/chat/completions", json=body) assert r.status_code == 402, r.text required = unb64(r.headers["PAYMENT-REQUIRED"]) req = required["accepts"][0] # scheme "exact", network "eip155:" assert (req["network"], req["asset"].lower()) == ("eip155:1874", "0x2e672dfe33ea977fd064e01ade7d8c73b3be7fbb"), req # ITC only assert int(req["amount"]) <= 1_000_000, req # never sign more than 1 ITC for one request nonce = os.urandom(32) # random bytes32, never reused auth = {"from": acct.address, "to": req["payTo"], "value": req["amount"], "validAfter": "0", "validBefore": str(int(time.time()) + req["maxTimeoutSeconds"]), "nonce": "0x" + nonce.hex()} typed = { "types": { "EIP712Domain": [{"name": "name", "type": "string"}, {"name": "version", "type": "string"}, {"name": "chainId", "type": "uint256"}, {"name": "verifyingContract", "type": "address"}], "TransferWithAuthorization": [{"name": "from", "type": "address"}, {"name": "to", "type": "address"}, {"name": "value", "type": "uint256"}, {"name": "validAfter", "type": "uint256"}, {"name": "validBefore", "type": "uint256"}, {"name": "nonce", "type": "bytes32"}], }, "primaryType": "TransferWithAuthorization", "domain": {"name": req["extra"]["name"], "version": req["extra"]["version"], "chainId": int(req["network"].split(":")[1]), "verifyingContract": req["asset"]}, "message": {**auth, "value": int(auth["value"]), "validAfter": 0, "validBefore": int(auth["validBefore"]), "nonce": nonce}, } sig = Account.sign_message(encode_typed_data(full_message=typed), acct.key).signature payment = {"x402Version": 2, "resource": required.get("resource"), "accepted": req, "payload": {"authorization": auth, "signature": "0x" + bytes(sig).hex()}} r = requests.post(f"{API}/v1/chat/completions", json=body, headers={"PAYMENT-SIGNATURE": b64(payment)}) # same body print(r.status_code, r.headers.get("x-inferit-model"), r.json()["choices"][0]["message"]["content"]) # the model that answered print(unb64(r.headers["PAYMENT-RESPONSE"])) ``` ### curl: see the 402 without paying ```sh curl -sS -D - https://api-production-c74b9.up.railway.app/v1/chat/completions \ -H 'content-type: application/json' \ -d '{"model":"auto","messages":[{"role":"user","content":"Hi"}],"max_tokens":64}' # HTTP/2 402 # payment-required: eyJ4NDAyVmVyc2lvbiI6Mi... (base64 JSON; the body carries the same document) curl -s https://api-production-c74b9.up.railway.app/.well-known/x402 | jq # scheme, network, asset, payTo, extra (EIP-712 name and version) ``` ### Which model and seller answered? Every served response names them, before you read a byte of the body: - `x-inferit-model`: the catalog id of the model that served the request. With model auto, the model Inferit picked. - `x-inferit-route`: `direct` (you named the model) or `auto:balanced`, `auto:cheap`, `auto:best`. - `x-inferit-offer`: an opaque id of the offer that served you, not the seller's identity. - `x-inferit-buyer-cost-micro`: what the request cost you, in millionths of a dollar. What you can check before you pay: - `GET https://api-production-c74b9.up.railway.app/v1/routing`: the models auto can choose from now (`candidates_now`, in auto's order, with their quality scores). - `GET https://api-production-c74b9.up.railway.app/v1/models`: each model's `best_price` (all-in, per 1M tokens) and its `discount_pct` under the list price, and `live`: healthy and listed sellers, 24 h uptime (0 to 1) and time to first token (p50, p95, in ms), `null` where there is no data yet. - `GET https://api-production-c74b9.up.railway.app/v1/models//endpoints`: each offer of one model, with its seller's wallet shortened (`0x45A9…7CDE`), all-in price, context length, quantization, health, 24 h uptime and time to first token. - `GET https://api-production-c74b9.up.railway.app/api/markets/`: each price level carries `offers` and `healthyOffers`. No healthy offer means no seller is serving that model right now (a request naming it answers 503 `no_available_offers`). ## Pay on Stellar While `GET https://api-production-c74b9.up.railway.app/v1/rails` lists a rail with `"id": "stellar"`, the same 402 also lists a Stellar entry, network `stellar:testnet`: one transfer of ITC to Inferit's treasury account, signed with a Stellar key. Inferit's facilitator pays the network fee, so the payment costs the agent no XLM. 1. Create the account with free XLM from friendbot (`https://friendbot.stellar.org?addr=G...`), then add a trustline to ITC. Its code and issuer are in `GET https://api-production-c74b9.up.railway.app/v1/rails`, the rail with `"id": "stellar"`, with its Stellar Asset Contract (`assetContract`, the x402 `asset`) and the treasury (`treasury`, the x402 `payTo`). 2. Claim ITC: `POST https://api-production-c74b9.up.railway.app/v1/faucet/stellar` with `{"address":"G..."}`, once per address per 24 h. 3. Register the official Stellar scheme in the x402 client: `ExactStellarScheme` from `@x402/stellar` 2.28.0, with `createEd25519Signer(secret, "stellar:testnet")`, and allow ITC's contract in its spend controls. 4. ITC on Stellar has 7 decimals: the amount is 10 base units per millionth of a dollar (`"100000"` = $0.01), and must be paid exactly. 5. The payment is credited to your balance with Inferit (base units divided by 10, rounded down), and the request is charged its exact cost against it, never more than that payment. A call without a key never draws on what earlier payments left; an API key does: sign in with the same Stellar key (`POST https://api-production-c74b9.up.railway.app/v1/auth/stellar/challenge`, then `/verify` with the message signed as a SEP-53 message) and make a key with `POST https://api-production-c74b9.up.railway.app/v1/keys`. Inferit holds that balance: at most $25 per address (a payment that would pass it is refused with `invalid_exact_stellar_balance_over_limit`), and at most $5 per payment. Stellar addresses are case-sensitive: never lower-case one. The code: https://inferit.cc/docs/payments/stellar.md ## Or use an API key The same wallet signs in with an off-chain text signature (EIP-4361; it moves no tokens), then mints a key. The key spends your escrow balance: what x402 payments credited, or what you deposited yourself with `depositAndSetCap` (that deposit is a transaction you send, so it needs WBT). 1. `POST https://api-production-c74b9.up.railway.app/v1/auth/evm/challenge` with `{"address":"0x..."}` returns `{"message","nonce","expiresAt"}`. 2. Sign `message` (EIP-191 `personal_sign`), then `POST https://api-production-c74b9.up.railway.app/v1/auth/evm/verify` with `{"message","signature"}`. It returns a session token. 3. `POST https://api-production-c74b9.up.railway.app/v1/keys` with `Authorization: Bearer ` and `{"name":"my-agent"}` returns `{"key":"ik_..."}`, shown once. Optional fields: `spendLimitMicro`, `minDiscountPct`. 4. Call the API with `Authorization: Bearer ik_...`. ```ts // Same wallet as the x402 payer: sign in (EIP-4361, an off-chain text signature; it moves no tokens) and mint an API key. const post = (path: string, body: unknown, token?: string) => fetch(`https://api-production-c74b9.up.railway.app${path}`, { method: 'POST', headers: { 'content-type': 'application/json', ...(token ? { authorization: `Bearer ${token}` } : {}) }, body: JSON.stringify(body), }).then((r) => r.json()); const { message } = await post('/v1/auth/evm/challenge', { address: account.address }); const { token } = await post('/v1/auth/evm/verify', { message, signature: await account.signMessage({ message }) }); const { key } = await post('/v1/keys', { name: 'agent' }, token); // shown once; ik_… // From here on: Authorization: Bearer , spending what is left of your balance. No payment step. ``` ```sh curl https://api-production-c74b9.up.railway.app/v1/chat/completions \ -H "Authorization: Bearer $INFERIT_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "auto", "stream": true, "messages": [{"role": "user", "content": "Say hello in five words."}] }' ``` Every OpenAI-compatible client works with the base URL `https://api-production-c74b9.up.railway.app/v1`. To require a minimum discount against the list price, call `/min{N}/v1/chat/completions` or send `x-min-discount: N`. ## Inferit's ITC faucet ```sh curl -s -X POST https://api-production-c74b9.up.railway.app/v1/faucet -H 'content-type: application/json' -d '{"address":"0xYourAddress"}' ``` - It mints 1,000 ITC to the address, at most once per 24 h per address (the token enforces it), and at most 10 calls an hour per IP. The server also caps sponsored mints at 120 an hour in total (`429 rate_limit_exceeded`). - Inferit pays the gas, so a fresh address with zero WBT can claim and then pay with x402. - It is Inferit's ITC faucet, not a WBT faucet. - `503 faucet_pending` (with `retry-after: 15`): the mint was sent but is not confirmed yet. Check the balance before you claim again: a claim after it lands gets `429 faucet_cooldown`. A successful claim returns: ```json { "address": "0xYourAddress", "amountMicro": "1000000000", "token": { "address": "0x2E672dFE33EA977FD064E01aDe7d8c73B3Be7fBB", "symbol": "ITC", "decimals": 6 }, "network": "eip155:1874", "transaction": "0x…", "explorerUrl": "https://explorer.testnet.whitechain.io/tx/0x…", "next": "Pay for inference with x402: POST https://api-production-c74b9.up.railway.app/v1/chat/completions without credentials …" } ``` ## Discovery `GET https://api-production-c74b9.up.railway.app/.well-known/x402` lists the paid resources and the requirement a client signs for: scheme, network, asset, `payTo`, the token's EIP-712 name and version, and the minimum payment. Pin the network and the asset in your own code rather than trusting the server that is being paid. The values: | Field | Value | | --- | --- | | Network | Whitechain Sepolia, chain id 1874 (`eip155:1874`) | | Asset (ITC, 6 decimals; TestCredit contract rev. 2) | `0x2E672dFE33EA977FD064E01aDe7d8c73B3Be7fBB` | | `extra` (the token's EIP-712 domain) | `name` (the token's EIP-712 name: sign with the exact string `extra.name` carries), `version: "1"` (the domain version, not the contract revision) | | `payTo` (MarketEscrow v0.3) | `0x705dD9eCffa888FbcF2849eAE2D3b136eb78B7e0` | | Minimum amount | `"10000"` ($0.01 = 0.01 ITC) | | Explorer | https://explorer.testnet.whitechain.io | ## Limits | What | Default | Why | | --- | --- | --- | | Minimum payment | $0.01 (0.01 ITC) | Each payment is an on-chain deposit whose gas the facilitator pays. x402 itself could express a millionth of a dollar; the request is still charged its exact cost | | Signature validity | 120 s (`maxTimeoutSeconds`) | The client sets `validBefore` = now + this; the API refuses authorizations close to expiry | | Quote pin | 120 s, per request (path, routing headers and JSON body) | The paid retry verifies against the quote it was shown; a changed request gets a new 402 | | Signer | A plain key (EOA), 65-byte signature, x402 version 2 | Smart-wallet signatures (ERC-1271, ERC-6492) and the Permit2 transfer method are not accepted | | One payment per authorization | Each nonce is accepted once | A replayed payment is refused | | General rate limit | 1,200 requests a minute per IP (hosted default) | Every route; `429 rate_limit_exceeded` with `retry-after`. Responses carry no RateLimit headers | | Sign-in | 30 requests a minute per IP | `/v1/auth/*` | | x402 payments | 30 paid attempts a minute per paying address, 60 per IP | On top of the general limit | | ITC faucet | 1,000 ITC per address per 24 h, 10 calls an hour per IP, 120 sponsored mints an hour per server | Keeps the sponsored gas budget bounded | | Credit expiry | Each x402 credit extends your cap's expiry to at least 30 days from the payment | What you pay through x402 stays spendable | | Escrow paused | No new payments | Pausing blocks deposits, including x402; withdrawals keep working | If inference fails after the payment settled, the payment stays in your escrow balance and the error says so. ## Errors Errors are OpenAI-shaped: `{"error":{"message","type","code"}}`. | Status | Code | Meaning | | --- | --- | --- | | 402 | (the x402 challenge) | No credentials: the body is the x402 `PaymentRequired` document | | 402 | (a refused payment) | The payment did not verify; the reason is in `error` | | 400 | `invalid_request` | The body does not parse or a field is invalid (a hint included); the message names it. Its `type` is `invalid_request_error` | | 400 | `invalid_auto_policy` | A model id that starts with `auto:` or `inferit/auto` but names no policy: use `auto`, `auto:cheap` or `auto:best` | | 400 | `invalid_address` | `POST /v1/faucet` (or sign-in) with an address that is not 0x-prefixed 20-byte hex | | 401 | `missing_credentials`, `invalid_api_key` | An account route without a token, or a key that is wrong or revoked. Inference without any key answers 402 instead | | 402 | `insufficient_funds` | An API-key request costs more than your balance or ceiling allows, or the ceiling has expired | | 402 | `spend_limit_exceeded` | The API key has reached its own spend limit | | 404 | `model_not_found` | The model is neither in the catalog nor listed by a seller (`GET /v1/models` lists both), or send model auto | | 404 | `model_not_servable` | A closed model: a reference row (`servable: false`) that no seller can list | | 404 | `faucet_disabled` | This server runs no sponsored faucet | | 429 | `rate_limit_exceeded` | Too many requests from this IP or paying address, or the faucet's hourly server budget is spent; honour `retry-after` | | 429 | `faucet_cooldown` | This address claimed less than 24 h ago; `retry-after` says when the next claim works | | 501 | `not_implemented` | `/anthropic/v1/messages` and legacy `/v1/completions`; use `/v1/chat/completions` | | 503 | `no_available_offers` | No healthy seller for that model right now (with auto: every attempt failed before any byte); honour `retry-after` | | 503 | `no_eligible_model` | Model auto: no model can serve this request right now. The message says why, and `error.reasons` counts each reason; `retry-after` only when seller health is the only cause | | 503 | `rail_unavailable` | The chain could not be read to check your funding (or, on seller routes, your registration). Nothing was charged; honour `retry-after` (5 s). Without `retry-after`, your selected rail is not enabled here: pick another with `PUT /v1/buyer/rail` | | 503 | `funding_busy` | A settlement landed while your funding was being read. Nothing was charged; retry after 1 s (`retry-after: 1`) | | 503 | `faucet_unavailable` | The faucet cannot mint right now; retry after 60 s | | 503 | `faucet_pending` | The mint was sent but is not confirmed yet; check the balance after `retry-after` (15 s) before claiming again | | 503 | `x402_settlement_pending`, `x402_unavailable` | The payment path failed; the error says whether anything was charged | Every response carries `x-request-id` and `x-inferit-network`. ## Who runs what - Inferit's API settles x402 payments with its own x402 v2 facilitator on Whitechain Sepolia, self-hosted and operated by Inferit (key `0xc8c8E79E2547ba1D81FAC12c84867B1DbD83e602`): the party that sells the request also submits the payment. Its key pays gas only, and it can credit a payment only to the wallet that signed it. - The seller that serves a request sees it. The API stores token counts and amounts, never prompts or responses. - whitechain-x402-facilitator, the first public x402 v2 facilitator for Whitechain, is a separate open-source project (Apache-2.0) for other Whitechain merchants, live on Whitechain Sepolia: https://github.com/InferitAI/whitechain-x402-facilitator. Inferit operates a public instance of it; it does not settle Inferit's own payments. --- Canonical page: https://inferit.cc/agents All pages as markdown: https://inferit.cc/llms.txt --- Source: https://inferit.cc/index.md # The inference layer for AI agents. One integration to access models and pay per inference request. Developers who run open-weight models connect them and earn from the requests they serve. [Get an API key](https://inferit.app/buy) · [Read the docs](https://inferit.cc/docs.md) · [Sell inference](https://inferit.app/sell) A key on your balance sends a request with model auto; Inferit picks Model B, the best value of three models, and the cheapest healthy seller of it. Sellers can list any model, such as Qwen, Llama or gpt-oss, each at their own price. Live models and prices: [models](https://inferit.app/models). ## A key from every lab, or one market. Every lab hands your agents its own key. On Inferit, anyone can sell inference; agents buy it per request. The old way: credits and an API key from every lab, a pile of API keys pasted into every agent. With Inferit: one market, and a key with its own limit for each teammate and agent. You set the limits. Inferit does the shopping. [Why a market](https://inferit.cc/docs/wallet.md#why) ## Send model auto. Inferit picks the model. One field in the request. Inferit picks the model, then its cheapest healthy seller, and names it. How model auto picks: it keeps the ranked models with a live seller that fit the request; weighs each one's quality score against its price for this request (auto picks the best value, auto:cheap the lowest price, auto:best the highest ranked); and if the chosen seller fails before answering, tries the next seller, then the next model. The response header x-inferit-model names the model. It reads the request's size and features, never what it says. [How routing works](https://inferit.cc/docs/routing.md) [Models and prices](https://inferit.app/models) ## One integration. Works with your stack. Change the base URL and the key. LangChain, the Vercel AI SDK, LiteLLM, CrewAI and the OpenAI SDK all work. Three steps: top up in the app with free API credits, create a key with a limit, and send your first request. Any OpenAI-compatible client _curl_ ```bash curl https://api-production-c74b9.up.railway.app/v1/chat/completions \ -H "Authorization: Bearer $INFERIT_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "qwen/qwen-2.5-14b-instruct", "stream": true, "messages": [{"role": "user", "content": "Say hello in five words."}] }' ``` OpenAI-compatible is the request format, not the model. Your requests go to open-weight models that sellers list, such as Qwen and Llama. Guides: [LangChain](https://inferit.cc/docs/guides/langchain.md) · [Vercel AI SDK](https://inferit.cc/docs/guides/vercel-ai-sdk.md) · [LiteLLM](https://inferit.cc/docs/guides/litellm.md) · [CrewAI](https://inferit.cc/docs/guides/crewai.md) [Get an API key](https://inferit.app/buy) [Quickstart](https://inferit.cc/docs/quickstart.md) ## One balance. A key for everyone. Each teammate and agent gets its own key, with an optional limit. Revoke one; the rest keep working. [Keys and limits](https://inferit.cc/docs/wallet.md#teams) One balance with a $10 ceiling and three keys, each with its own limit; one key is revoked and the others keep working. ## Your agents buy inference per request. No account. The agent sends the request, gets a quote, pays with x402 and gets the answer. [Where agents go](https://inferit.cc/agents.md) [agents.md](https://inferit.cc/agents.md) One keyless request: the agent posts with model auto and no key; Inferit answers 402 with a quote of at least $0.01; the agent resends the same body with a PAYMENT-SIGNATURE; Inferit answers 200 and names the model. Each keyless call prepays at least $0.01 and is charged its exact price. ## Anyone can sell inference. Set your price. List any open-weight model you run, at your price. When yours is the cheapest healthy offer, the request is yours. How a seller is paid: serve any model with Ollama, LM Studio, vLLM, llama.cpp or any OpenAI-compatible server; list it at your price per 1M tokens; when yours is the cheapest healthy offer the request is routed to you; its price is paid to your wallet in ITC. [List a model](https://inferit.app/sell) [Seller docs](https://inferit.cc/docs/sellers.md) Savings: the page reads live prices and shows each live model's price against its list price (OpenRouter snapshot, 2026-10-02). How it is computed: [savings against list price](https://inferit.cc/docs.md#savings). Current prices: [models](https://inferit.app/models). ## Running a hackathon or accelerator? We provide API credits and integration support. [Hackathons and accelerators](https://inferit.cc/hackathons.md) ## Limits a contract enforces. Records anyone can check. - Your limits ### Enforced twice. Your ceiling is enforced by a smart contract; each key's limit is enforced by Inferit's API. - Your prompts ### Never stored by Inferit. Inferit keeps token counts and prices, never prompts. The seller that serves a request sees it. - Your receipts ### On chain, per seller. Payments to sellers are on chain, per seller. The record is public: it links your wallet to them. [Security policy](https://inferit.cc/security.md) [Security & trust in the docs](https://inferit.cc/docs/security-trust.md) ## Open source, on GitHub. The seller app, the x402 facilitator, examples and the model catalog are public. The market API and router are private. - ### [inferit-seller](https://github.com/InferitAI/inferit-seller) The seller app: one command connects Ollama, LM Studio, vLLM or llama.cpp. Apache-2.0 · npm · Docker - ### [whitechain-x402-facilitator](https://github.com/InferitAI/whitechain-x402-facilitator) An x402 v2 facilitator for Whitechain merchants, live on Whitechain Sepolia. Apache-2.0 - ### [inferit-examples](https://github.com/InferitAI/inferit-examples) Runnable examples: LangChain, Vercel AI SDK, LiteLLM, CrewAI and OpenCode. Apache-2.0 - ### [inferit-agent-example](https://github.com/InferitAI/inferit-agent-example) A minimal TypeScript agent that pays per request with x402. Apache-2.0 - ### [model-catalog](https://github.com/InferitAI/model-catalog) The curated model catalog as open data, with licence classes. CC-BY-4.0 - ### [awesome-inferit](https://github.com/InferitAI/awesome-inferit) Docs, guides, repositories and live endpoints for Inferit, in one list. CC0-1.0 - ### [awesome-x402-whitechain](https://github.com/InferitAI/awesome-x402-whitechain) Curated x402 resources for Whitechain: spec, SDKs, facilitators and examples. CC0-1.0 - ### [branding](https://github.com/InferitAI/branding) The brand kit: logo files, colour tokens, type and usage rules. Logo terms in the repo - ### [roadmap](https://github.com/InferitAI/roadmap) What Inferit has built, and what comes next. Apache-2.0 [All repositories on GitHub](https://github.com/InferitAI) [Sell from your PC](https://inferit.cc/docs/sellers/quickstart.md) ## Latest from the blog. Build notes from the team: what shipped and how it works. [All posts](https://inferit.cc/blog.md) [RSS](https://inferit.cc/blog/rss.xml) - 2026-10-19 · 7 min read ### [The first public x402 v2 facilitator for Whitechain](https://inferit.cc/blog/first-x402-facilitator-whitechain.md) whitechain-x402-facilitator is open source, live on Whitechain Sepolia. How it settles, how to use it, what comes next. Sahil Massey ## One API. Pay per request. Works with LangChain, the Vercel AI SDK, LiteLLM, CrewAI and any OpenAI-compatible client. [Get an API key](https://inferit.app/buy) [Read the quickstart](https://inferit.cc/docs/quickstart.md) --- Canonical page: https://inferit.cc All pages as markdown: https://inferit.cc/llms.txt --- Source: https://inferit.cc/about.md # The inference layer for AI agents. > Inferit is the inference layer for AI agents: one integration to access models and pay per inference request. Who builds it and how to reach us. One integration to access models and pay per inference request. Developers building agents integrate once; developers running open-weight models connect them and earn from the requests they serve. ## A marketplace behind one API. Behind that one API is a marketplace. Sellers list open-weight models at their own price, and each request goes to the cheapest healthy seller of that model. A key on your balance sends a request with model auto; Inferit picks Model B, the best value of three models, and the cheapest healthy seller of it. ## The team. - **Sahil Massey** · Co-founder, business and growth - **Jean Totola** · Co-founder, AI/ML engineering - **Nuria** · Marketing and communications ## Why a stamp. A letter carries its own stamp. A request to Inferit carries its own price. So the mark is a stamp whose face is its price. ## Open source, on GitHub. Our public repositories are on [GitHub](https://github.com/InferitAI): the seller app [inferit-seller](https://github.com/InferitAI/inferit-seller) (Apache-2.0), examples, the model catalog, the brand kit and the roadmap. The market's code, the router included, is private. We published [whitechain-x402-facilitator](https://github.com/InferitAI/whitechain-x402-facilitator), the first public x402 v2 facilitator for Whitechain, live on Whitechain Sepolia, under Apache-2.0. Inferit's API runs its own x402 v2 facilitator on Whitechain Sepolia, self-hosted and operated by Inferit. ## Build notes, on the blog. What shipped and how it works, written by the team. Posts live on [the blog](https://inferit.cc/blog.md), with an [RSS feed](https://inferit.cc/blog/rss.xml), and every post is also plain markdown for agents. ## How to reach us. - Code: [github.com/InferitAI](https://github.com/InferitAI) - News and updates: [@inferit\_ on X](https://x.com/inferit_) - Security reports: [GitHub private vulnerability reporting](https://github.com/InferitAI/whitechain-x402-facilitator/security) ([security policy](https://inferit.cc/security.md)) ## Notice © 2026 Inferit Labs. All rights reserved. [Terms of use](https://inferit.cc/legal/terms.md) · [Privacy](https://inferit.cc/legal/privacy.md) · [Acceptable use](https://inferit.cc/legal/acceptable-use.md) · [Security](https://inferit.cc/security.md) --- Canonical page: https://inferit.cc/about All pages as markdown: https://inferit.cc/llms.txt --- Source: https://inferit.cc/hackathons.md # Build with Inferit at your hackathon. > Build with Inferit at your hackathon: API credits for teams and hands-on integration support. Buy inference on one API, or sell it from a model you run. Inferit is the inference layer for AI agents: one integration to access models and pay per inference request. [Get an API key](https://inferit.app/buy) [Message us on X](https://x.com/inferit_) ## Who it is for - Online hackathons - In-person hackathons - Conferences - Accelerator programmes Wherever teams build AI agents, online or in the room. ## API credits and hands-on help. What we bring to your event and to the teams that build there. - Credits ### API credits for teams. Credits for your teams to build and test against the API during the event. - Support ### Integration support. Hands-on help while teams build, from the first API key to a working agent. ## Two ways to build: buy or sell. A team can build an agent that buys inference, connect a model that sells it, or both. - Buy ### Build agents on one API. One integration to access models. Create an API key, change your client's base URL and pay per inference request. Works with LangChain, the Vercel AI SDK, LiteLLM, CrewAI and any OpenAI-compatible client. [Quickstart](https://inferit.cc/docs/quickstart.md) [Agents and x402](https://inferit.cc/agents.md) - Sell ### Connect a model you run. Run an open-weight model in Ollama or LM Studio, connect it with one command and set your price per 1M tokens. You're paid for every request it serves, to your own wallet. [Seller quickstart](https://inferit.cc/docs/sellers/quickstart.md) [Sell workspace](https://inferit.app/sell) ## What your teams start with. Guides and runnable code for your event's resources list. - ### [Quickstart](https://inferit.cc/docs/quickstart.md) Top up, create an API key and send a first inference request. - ### Framework guides Each guide sets up a client with Inferit's base URL and your key. [LangChain](https://inferit.cc/docs/guides/langchain.md) [Vercel AI SDK](https://inferit.cc/docs/guides/vercel-ai-sdk.md) [LiteLLM](https://inferit.cc/docs/guides/litellm.md) [CrewAI](https://inferit.cc/docs/guides/crewai.md) - ### [inferit-examples](https://github.com/InferitAI/inferit-examples) Runnable examples for each framework guide. - ### [Agents and x402](https://inferit.cc/agents.md) Agents that pay per request with x402, with no account. - ### [Seller quickstart](https://inferit.cc/docs/sellers/quickstart.md) Sell from your own computer: Ollama or LM Studio, and one command. - ### [Models](https://inferit.app/models) Which models have a live seller now, and at what price. ## Bring Inferit to your event. Running a hackathon or accelerator? We provide API credits and integration support. Message us on X with your event, its dates and how many teams take part. [Message us on X](https://x.com/inferit_) --- Canonical page: https://inferit.cc/hackathons All pages as markdown: https://inferit.cc/llms.txt --- Source: https://inferit.cc/docs.md # Inferit documentation > Inferit docs: the quickstart, automatic model routing, the API reference, agents and x402, coding tools and frameworks, payments on Whitechain and Stellar, selling from your own PC, security and trust. Inferit is the inference layer for AI agents: one integration to access models and pay per inference request. Developers who run open-weight models connect them and earn from the requests they serve. Buyers reach every model with a live seller through one OpenAI-compatible API: name a model and Inferit picks its cheapest healthy seller, or send model auto and it picks the model too. Agents can also pay per request with x402. ## Guides - [Quickstart](https://inferit.cc/docs/quickstart.md): From zero to a paid request: ITC from the faucet, a deposit, a key, and your first call with model auto. - [Wallet and keys](https://inferit.cc/docs/wallet.md): Why a market, a key per teammate or agent with its own limit, the ceiling, usage and revoking a key. - [Automatic routing](https://inferit.cc/docs/routing.md): How model auto chooses: the policies, the hints, the quality ranking and its sources, the headers and the errors. - [API reference](https://inferit.cc/docs/api-reference.md): Every endpoint, both ways to pay (API key or x402), errors and headers. - [Agents: x402](https://inferit.cc/agents.md): Pay per request with standard x402 v2: no account, no API key. - [agents.md](https://inferit.cc/agents.md): The agents' guide as one markdown file: endpoints, model auto, x402, limits, errors and the free ITC faucet. - [Coding tools](https://inferit.cc/docs/guides/opencode.md): OpenCode and Cursor, set up step by step. - [Frameworks](https://inferit.cc/docs/guides/langchain.md): LangChain, the Vercel AI SDK, LiteLLM and CrewAI: base URL, key, model auto, and x402 where the framework takes a custom fetch. - [Whitechain escrow](https://inferit.cc/docs/payments/whitechain.md): Ceilings, x402 as a prepaid meter, roles, the circuit breaker, finality and the live parameters. - [Pay on Stellar](https://inferit.cc/docs/payments/stellar.md): x402 on Stellar: ITC and its contract, free XLM and a trustline, the faucet, the client code and the limits. - [Sell from your PC](https://inferit.cc/docs/sellers/quickstart.md): Ollama or LM Studio, one command with the open-source seller app, a price in dollars: no open port or domain. - [Selling inference](https://inferit.cc/docs/sellers.md): How selling works: licences, prices, health, availability and payouts to your wallet in ITC. - [Security & trust](https://inferit.cc/docs/security-trust.md): What the contract bounds, what is policy, and what is public on chain. - [Models and prices](https://inferit.app/models): Every model on the market, with its list price and the lowest live all-in price. ## How a request works Fig. 1 — One request, three steps Example prices · 1,000 in + 500 out tokens 1. Quote Each healthy seller of the model is priced for this request, all-in: the seller's price plus the platform fee. With model auto, the model is chosen first ([automatic routing](https://inferit.cc/docs/routing.md)). 2. Pick Best quote wins. The router sends the request to the cheapest healthy seller on Inferit. 3. Paid The metered cost is charged to the buyer's balance and settled in a batch on Whitechain. Example prices: $0.000168 at seller A, $0.000147 at seller B. Today's quotes are on [the models page](https://inferit.app/models). 1 µ is a millionth of an ITC. ## Core concepts - **Automatic model routing.** Send `"model": "auto"` and Inferit picks the model: among the models with a healthy seller that fit the request, the best value on a published quality ranking for this request's price, at that model's cheapest healthy seller. It chooses from the request's size and features, never from what the prompt says. The policies, hints and ranking are in [Automatic routing](https://inferit.cc/docs/routing.md). - **Units.** Prices are in dollars per 1M tokens, charged per inference request. API amounts are integers in millionths of a dollar, sent as strings: "10000" = $0.01, paid as 0.01 ITC. Prices are per 1M tokens: `84000` = $0.084 per 1M tokens. Every dollar of price is paid as one ITC. - **Money.** You pay with ITC, free from Inferit's faucet. WBT is Whitechain's gas token, needed only for transactions you send yourself (deposits, seller registration, withdrawals); x402 agents need none. Settlement to sellers is batched on Whitechain through the MarketEscrow contract. The platform fee is 5% on top of the seller's price; the contract caps it at 10%. - **Two tokens.** ITC (Inferit Test Credit) is the credit you pay for inference with. Inferit's ITC faucet gives 1,000 ITC per address per 24 h, free; it is sponsored, so the claim needs no gas. WBT is Whitechain's native gas token. - **What a request costs.** At the serving seller's own price (before the fee): `sellerCost = ceil((uncachedIn × inputPerM + cachedIn × cacheReadPerM + out × outputPerM) / 1,000,000)`, then `fee = ceil(sellerCost × feeBps / 10,000)`, and the buyer pays `sellerCost + fee`. Example: a seller asking $0.08 / $0.16 per 1M tokens before the fee: 1,000 input and 500 output tokens cost $0.00016 + $0.000008 = $0.000168. The response header `x-inferit-buyer-cost-micro` is the authoritative figure for each request. - **Savings against list price.** The home page compares what you pay, all included, for its reference request with the same request at the list price (OpenRouter snapshot, 2026-10-02): list = list input × input tokens + list output × output tokens, the same at the best healthy price, and the saving is floored to a whole percent. A model without a healthy seller, without a list price, or not under list is left out, and so is a model whose list price is not from the snapshot: the snapshot has no Qwen2.5 14B, so its catalog row uses Qwen2.5 7B's list price as a proxy, and the app labels that comparison. - **All-in prices.** Every price on the site and in the API is what the buyer pays: the seller's price plus the platform fee (5% by default, capped at 10% by the contract). Sellers are paid exactly their own price. - **Two ways to pay.** With an API key, each request is charged to your prepaid balance, under your ceiling. Without a key, the API answers 402 with a quote, and an agent pays for that one request with x402: no account. - **x402 is a prepaid meter.** x402 can express $0.000001, but every x402 payment is an on-chain transaction that costs gas. So an agent's payment, at least $0.01 (0.01 ITC), is credited to its own balance, and each request is charged its exact µ cost against it. See [Agents](https://inferit.cc/agents). - **Settlement.** Usage settles in batches on [Whitechain](https://inferit.cc/docs/payments/whitechain.md), in the MarketEscrow contract, in ITC: one transaction pays every seller in the batch. An off-chain credit ledger exists only for local development and tests. - **Keys.** Buyer keys start with `ik_`. They are stored as peppered SHA-256 hashes and shown once. Each key can carry a spend limit and a minimum discount. - **Routing.** With model auto, the model is chosen first (see [Automatic routing](https://inferit.cc/docs/routing.md)). Then the model's offers are filtered (healthy, daily cap, your minimum discount and maximum price) and sorted by estimated cost. If an offer fails before the first byte, the next one is tried; nothing is retried after content has started streaming. ## Markdown for agents Every page on inferit.cc has a markdown twin: add `.md` to its URL (this page is [`/docs.md`](https://inferit.cc/docs.md)), or ask for `text/markdown`. [`/llms.txt`](https://inferit.cc/llms.txt) lists them all, and [`/llms-full.txt`](https://inferit.cc/llms-full.txt) is every page in one file. ## Security and trust What the escrow contract is designed to enforce, what is policy and what is public on chain: [Security & trust](https://inferit.cc/docs/security-trust.md). --- Canonical page: https://inferit.cc/docs All pages as markdown: https://inferit.cc/llms.txt --- Source: https://inferit.cc/docs/quickstart.md # Quickstart > Three steps in the app, or eight by hand: add Whitechain Sepolia, get free API credits to pay with and WBT for gas, deposit with a ceiling, sign in, create an API key, call the API with a model that has a live seller and see the request settle on chain. In the app it is three steps. Below them is the same path by hand, in eight steps, with the API call or contract call behind each one. Building an agent? It needs only an EVM private key and free API credits from Inferit's sponsored faucet: no browser wallet, no account, no API key and no WBT. See [Agents](https://inferit.cc/agents). ## In the app: three steps 1. **Top up.** Open the [Buy workspace](https://inferit.app/buy) and connect a browser wallet. It gives you free API credits and walks you through the deposit and your ceiling; the deposit is a transaction, so it links the Whitechain faucet for the gas it needs ([step 3](https://inferit.cc/docs/quickstart.md#wbt)). 2. **Create a key.** In the same workspace, with a spending limit if you like. It is shown once. 3. **Call the API.** Point any OpenAI-compatible client at the API with your key, and name a model with a live seller ([step 7](https://inferit.cc/docs/quickstart.md#call)). No browser wallet here? On a phone, open the Buy workspace in your wallet app's browser. Building an agent? You don't need a wallet app: a private key in your code gets free API credits and an API key. See the [agent quickstart](https://inferit.cc/agents#quickstart), or [get an API key from code](https://inferit.cc/agents#api-key). ## Before you start You need a browser wallet such as MetaMask or Rabby, and two tokens with two different jobs. | Token | What it is for | Where it comes from | | --- | --- | --- | | **ITC** (API credits) | Paying for inference. 1 credit counts as $1 in prices, and every request is charged its exact cost, down to $0.000001. | Inferit's faucet: 1,000 free API credits per address per 24 h. Sponsored, so the claim needs no gas ([step 2](https://inferit.cc/docs/quickstart.md#itc)). | | **WBT** (Whitechain's gas token) | Gas for on-chain transactions you send yourself: the approve and the deposit, withdrawals, seller registration. Never for inference. | The [Whitechain faucet](https://faucet.testnet.whitechain.io) ([step 3](https://inferit.cc/docs/quickstart.md#wbt)). | An agent pays per request with x402 instead: it signs with its own key, with no account, no API key and no WBT, because the facilitator pays the gas. Its payment (at least $0.01) is credited to its own escrow balance, and each request is charged its exact cost against it. The machine-readable guide is [`/agents.md`](https://inferit.cc/agents.md). ## 1. Add Whitechain Sepolia Whitechain Sepolia is an OP Stack L2. Add the network and the ITC token to your wallet by hand, or connect the wallet in the app: - **Network name**: Whitechain Sepolia - **Chain ID**: 1874 - **RPC URL**: https://rpc.testnet.whitechain.io - **Currency symbol (gas)**: WBT - **Block explorer**: https://explorer.testnet.whitechain.io - **ITC token (6 decimals)**: 0x2E672dFE33EA977FD064E01aDe7d8c73B3Be7fBB [Open the Buy workspace](https://inferit.app/buy) ## 2. Get ITC to pay with API credits (ITC) are what you pay for inference with. Inferit's faucet gives 1,000 free API credits per address per 24 h. It is sponsored: Inferit pays the gas, so the claim needs no WBT. **App:** [Buy workspace](https://inferit.app/buy) · **API:** [`POST /v1/faucet`](https://inferit.cc/docs/api-reference.md#faucet) ```bash curl -s -X POST https://api-production-c74b9.up.railway.app/v1/faucet \ -H 'content-type: application/json' \ -d '{"address":"0xYourAddress"}' ``` ITC has 6 decimals, so one base unit is a millionth of a credit ($0.000001). A second claim for the same address within 24 h gets `429 faucet_cooldown`. ## 3. Get WBT for gas WBT is Whitechain's native gas token. Your wallet spends it on the two transactions in step 4, and later on a withdrawal. Get WBT from the [Whitechain faucet](https://faucet.testnet.whitechain.io). Checked 2026-10-06: it asks for a GitHub account at least 30 days old and gives 0.5 WBT per 24 h. Keep at least 0.002 WBT for the approve and the deposit; the app blocks deposits below that. ## 4. Deposit and set a ceiling Two transactions from your wallet: `approve` on the ITC token, then `depositAndSetCap` on the escrow contract (MarketEscrow). **App:** [Buy workspace](https://inferit.app/buy) · **Contract:** [`depositAndSetCap(amount, cap, expiry)`](https://inferit.cc/docs/payments/whitechain.md#deposit) - **`amount`**: The ITC you deposit. It stays yours until it is settled or withdrawn. - **`cap`**: Your ceiling: the most the operator may ever settle from you, counted cumulatively. The app suggests your deposit, at most 25 ITC. - **`expiry`**: When that permission ends; 7 days by default. After it, nothing more can be settled from you. Escrow activity on Whitechain is public chain data. Fund from a dedicated wallet if you do not want your spending linked to your main address. ## 5. Sign in Sign a one-time challenge message (EIP-4361) with the same wallet. It is an off-chain text signature: no transaction, no gas, no tokens move. The session lasts 24 h and covers both workspaces, Buy and Sell. **App:** [Buy workspace](https://inferit.app/buy) · **API:** [`POST /v1/auth/evm/challenge, /verify`](https://inferit.cc/docs/api-reference.md#auth-routes) ## 6. Create an API key Keys start with `ik_` and are shown exactly once, so store yours in your environment. A key can carry a spend limit in dollars and a minimum discount. **App:** [Buy workspace](https://inferit.app/buy) · **API:** [`POST /v1/keys`](https://inferit.cc/docs/api-reference.md#keys) ```bash export INFERIT_API_KEY='ik_...' ``` ## 7. Call the API Any OpenAI-compatible client works: change the base URL and the key, and name a model with a live offer, such as `qwen/qwen-2.5-14b-instruct` in the examples below ([models with live offers](https://inferit.app/models)). You can also send `"model": "auto"` and let Inferit pick the model ([automatic routing](https://inferit.cc/docs/routing.md)). Guides: [LangChain](https://inferit.cc/docs/guides/langchain.md), [Vercel AI SDK](https://inferit.cc/docs/guides/vercel-ai-sdk.md), [LiteLLM](https://inferit.cc/docs/guides/litellm.md), [CrewAI](https://inferit.cc/docs/guides/crewai.md). ```bash curl https://api-production-c74b9.up.railway.app/v1/chat/completions \ -H "Authorization: Bearer $INFERIT_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "qwen/qwen-2.5-14b-instruct", "messages": [{"role": "user", "content": "Write a haiku about spare GPUs."}] }' ``` Streaming is a byte-faithful relay of the seller's server-sent events: ```bash curl -N https://api-production-c74b9.up.railway.app/v1/chat/completions \ -H "Authorization: Bearer $INFERIT_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "qwen/qwen-2.5-14b-instruct", "stream": true, "messages": [{"role": "user", "content": "Count to five."}] }' ``` _stream.mjs_ ```typescript import OpenAI from 'openai'; const client = new OpenAI({ baseURL: 'https://api-production-c74b9.up.railway.app/v1', apiKey: process.env.INFERIT_API_KEY, }); const stream = await client.chat.completions.create({ model: 'qwen/qwen-2.5-14b-instruct', messages: [{ role: 'user', content: 'Explain a spending cap in one sentence.' }], stream: true, }); for await (const chunk of stream) { process.stdout.write(chunk.choices[0]?.delta?.content ?? ''); } ``` The `x-inferit-model` header names the model that answered, and `x-inferit-buyer-cost-micro` says what the request cost you, in millionths of a dollar. The other response headers are in the [API reference](https://inferit.cc/docs/api-reference.md#headers). ## 8. See it settle The API meters each request to the millionth of a dollar and settles usage in batches: one `settle` transaction on the escrow pays every seller line in it. The default is $0.10 of unsettled usage or 1 h, whichever comes first; the cadence the hosted API runs is in `GET /metrics` (`settlement.cadence`). The Buy workspace lists your requests and their costs. Each settlement is a transaction you can open on the [explorer](https://explorer.testnet.whitechain.io), first as _pending finality_, then _finalized_ once its L1 block is final (see [Finality](https://inferit.cc/docs/payments/whitechain.md#finality)). The API records token counts and costs, never prompts or completions; the seller that serves a request sees it. ## Routing controls The router sends each request to the cheapest healthy seller on Inferit. To accept only offers below the list price by a minimum discount: ```bash # Only route to offers at least 30% below the list price curl https://api-production-c74b9.up.railway.app/min30/v1/chat/completions \ -H "Authorization: Bearer $INFERIT_API_KEY" ... # The same as a header # (the strictest of path, header and key setting wins) curl https://api-production-c74b9.up.railway.app/v1/chat/completions \ -H "x-min-discount: 30" ... ``` ## Contracts Read live from the chain. Every parameter, with the calls and the checks the contract performs, is on [Whitechain escrow](https://inferit.cc/docs/payments/whitechain.md#live). Whitechain Sepolia, chain id 1874, as deployed on 2026-10-04 (the page reads the live values from the contract): | Contract or role | Address | | --- | --- | | MarketEscrow v0.3 | [0x705dD9eCffa888FbcF2849eAE2D3b136eb78B7e0](https://explorer.testnet.whitechain.io/address/0x705dD9eCffa888FbcF2849eAE2D3b136eb78B7e0) | | ITC (6 decimals) | [0x2E672dFE33EA977FD064E01aDe7d8c73B3Be7fBB](https://explorer.testnet.whitechain.io/address/0x2E672dFE33EA977FD064E01aDe7d8c73B3Be7fBB) | ## Next - [API reference](https://inferit.cc/docs/api-reference.md): every endpoint, error and header. - [Agents](https://inferit.cc/agents): pay per request with x402, no account and no API key. - [OpenCode](https://inferit.cc/docs/guides/opencode.md) and [Cursor](https://inferit.cc/docs/guides/cursor.md): use Inferit from a coding tool. - [Selling inference](https://inferit.cc/docs/sellers.md): list your own endpoint at your own price. --- Canonical page: https://inferit.cc/docs/quickstart All pages as markdown: https://inferit.cc/llms.txt --- Source: https://inferit.cc/docs/wallet.md # Wallet and keys > Your balance and its keys: why a market, a key per teammate or agent with its own spend limit, the wallet’s ceiling and expiry, usage and CSV export, revoking a key. One balance pays for every model with a live seller on Inferit. You top it up once, set a ceiling on it, and give each teammate and each agent its own API key with its own spend limit. Agents can also pay per request with no key at all. ## Why a market The old way: credits and an API key from every lab, a pile of API keys pasted into every agent. With Inferit: one market, and a key with its own limit for each teammate and agent. Every lab hands your agents its own API key and its own credits: a chore for you, and a limit on which model at which price your agents can reach. Inferit is the peer-to-peer market for AI inference instead. Anyone can sell inference for any model, at their own price, and your agents buy it per request. They send the request; with model auto, Inferit picks the model and the cheapest healthy seller for it, and charges the exact price. One balance, a limit on any key you choose, nothing to juggle. Sellers can list any model, such as Qwen, Llama or gpt-oss. | The old way | With Inferit | | --- | --- | | Credits and an API key from every lab, each topped up on its own. | One balance. Top up once; every model with a live seller on Inferit draws from it. | | A pile of API keys, pasted into every agent. | One key per agent or teammate, or no key at all: agents can pay per request. | | Each key reaches one lab's models, at that lab's price. | One key reaches every model with a live seller. Anyone can sell, at their own price; each request goes to the cheapest healthy seller. | | You pick a model for every call and hope the price is fair. | Send `"model": "auto"`. Inferit picks the model and the cheapest healthy seller. | | A key with no limit spends whatever the account holds. | Give every key its own spending limit. Your balance has a ceiling too. | | A bill to reconcile at the end of the month. | Every request carries its exact price, line by line. | ## The wallet's ceiling Your wallet is a deposit in the escrow contract on Whitechain, with a ceiling: the most that may ever be charged to it, counted from what you have already spent, and an expiry. The contract enforces both: after the expiry nothing more can be charged until you set a new ceiling. The app suggests a ceiling equal to your deposit, at most 25 ITC, expiring in 7 days. The mechanics are on [the Whitechain escrow page](https://inferit.cc/docs/payments/whitechain.md#cap). What you have not spent stays yours: you can withdraw it after a fixed delay, and withdrawals keep working even while deposits and settlement are paused ([withdrawals](https://inferit.cc/docs/payments/whitechain.md#withdraw)). ## Keys Buyer keys start with `ik_` and are shown once, when you create them; Inferit stores only a hash. Each key can carry its own spend limit, which Inferit's API enforces, and a minimum discount against the list price. A key at its limit answers `402 spend_limit_exceeded`; a request whose worst case is more than the wallet's balance or ceiling answers `402 insufficient_funds`. The endpoints are in [the API reference](https://inferit.cc/docs/api-reference.md#keys). ## A key for everyone One balance with a $10 ceiling and three keys, each with its own limit; one key is revoked and the others keep working. Fund one balance and give each teammate and each agent its own key, with its own limit. Every key spends the same balance, never past its own limit, and the wallet's ceiling caps them all. There are no team accounts, roles or invites: a teammate is a key. ## Usage Every request carries its exact price: the response header `x-inferit-buyer-cost-micro`, and a row in your usage with the token counts, the cost and the model that served it. The wallet has one usage history for all its keys, which you can export as CSV from the Buy workspace or with [GET /v1/usage/export.csv](https://inferit.cc/docs/api-reference.md#buyer). Neither contains prompts or answers. ## Revoking a key Revoke a key in the Buy workspace or with `DELETE /v1/keys/:id`. It stops working at once, and the wallet's other keys keep working. ## No key at all An agent can pay per request with x402, with no account and no key: the API answers `402` with a quote, and the agent pays for that one request, at least $0.01, into its own balance. Each request is charged its exact price. See [Agents](https://inferit.cc/agents). --- Canonical page: https://inferit.cc/docs/wallet All pages as markdown: https://inferit.cc/llms.txt --- Source: https://inferit.cc/docs/routing.md # Automatic model routing > How model auto picks a model: the policies, the hints, the quality ranking with its sources and date, the headers and the errors. Send `"model": "auto"` and Inferit picks the model. Among the models that have a healthy seller right now, it keeps the ones that fit the request, scores each on a published quality ranking against its price for this exact request, and sends the request to the best value, at that model's cheapest healthy seller. ## What it does If the seller it picked fails before the first byte, the request moves to the next seller, then to the next model. The response names the model that served it: the JSON `model` field and the `x-inferit-model` header. The router chooses from the request's size and features, never from what the prompt says. `auto` is a model id like any other, so OpenAI-compatible clients can send it: the OpenAI SDKs and OpenCode. In a client that has its own Auto mode, such as Cursor, name the model `inferit/auto` so the two cannot be confused. Everything else works as it does for a named model: streaming, API keys and their limits, x402, the minimum discount. _a request, with the routing headers_ ```bash curl https://api-production-c74b9.up.railway.app/v1/chat/completions \ -H "Authorization: Bearer $INFERIT_API_KEY" \ -H "content-type: application/json" \ -d '{"model": "qwen/qwen-2.5-14b-instruct", "messages": [{"role": "user", "content": "Summarise this diff."}]}' \ -D - -o reply.json | grep -i '^x-inferit-' # x-inferit-model: the model that served it (with auto, the one Inferit picked) # x-inferit-route: auto:balanced (direct for a named model) # x-inferit-auto-choice: 1 (model auto only) ``` ## Live now The models model auto can choose from at this moment, in its order, with each one's AA index and its price for the reference request. The card reads `GET /v1/routing` and the market when this page loads; until it has a live pick it shows the example request. Live example: the page asks the API which models auto can choose from now and which it picks for its reference request (`GET /v1/routing`), and shows each one's quality score, its price for that request and the pick's saving against the list price. Current prices: [models](https://inferit.app/models). ## Policies | model | Policy | What it picks | | --- | --- | --- | | `auto` (also `auto:balanced`, `inferit/auto`) | best value | Best value: each candidate's quality score weighed against its price for this request. A model that costs twice as much for the request must score 6 points higher to win. | | `auto:cheap` (also `inferit/auto:cheap`) | lowest price | Lowest price for this request among the candidates; the quality score breaks ties. | | `auto:best` (also `inferit/auto:best`) | highest ranked | The highest quality score among the candidates; price breaks ties. | - Ids are matched without regard to case, after trimming. The prefix `inferit/` is accepted (`inferit/auto`, `inferit/auto:cheap`) for clients that want a vendor-qualified id. - Any other id that starts with `auto:` or `inferit/auto` answers `400 invalid_auto_policy`. No catalog model is named `auto`, and a seller cannot list it. - `GET /v1/models` lists the three auto rows first (`owned_by: "inferit"`), each with an `auto` object: `policy`, `pick`, `candidates` and `ranking`. The pick is computed for a reference request of 3,000 input and 1,000 output tokens, so it is indicative: a request with other needs may get another model. ## How a model is chosen How model auto picks: it keeps the ranked models with a live seller that fit the request; weighs each one's quality score against its price for this request (auto picks the best value, auto:cheap the lowest price, auto:best the highest ranked); and if the chosen seller fails before answering, tries the next seller, then the next model. The response header x-inferit-model names the model. ### 1. Fit A catalog model is a candidate for a request when every check passes. They run in this order; the first that fails is the model's reason in an error: | Reason | The check | | --- | --- | | `unscored` | The model has a row in the quality ranking (below). Unscored models stay routable by name, never by auto. | | `not_servable` | The model can be sold on Inferit: open weights, or resale through the allowlist. Closed models are reference rows. | | `context_too_small` | The request fits the model's context window: the input estimate plus 10%, plus the output limit (max\_tokens or max\_completion\_tokens, the smaller, or 1,024). And the window is at least min\_context, when you send it. | | `needs_tools` | A request with tools or functions goes only to models that support tool calls. | | `unsupported_input` | A non-text part other than an image (audio, a file) excludes every model in this version: name a model to send it. | | `needs_vision` | A request with an image part goes only to models that accept images. | | `below_min_quality` | The model scores at least min\_quality, when you send it. | | `no_offer` | The model has at least one active offer on your rail. Demo offers never take paid traffic. A seller may serve a smaller context window than the catalog's: when every offer is too small for the request, the reason is context\_too\_small. | | `no_healthy_offer` | At least one of its offers passes the live health checks and its daily cap. | | `below_min_discount` | At least one healthy offer meets your minimum discount (/min{N}, x-min-discount or the key setting). | | `over_max_price` | At least one of those is within max\_price\_per\_m, when you send it. | ### 2. Score For each candidate _m_, `C` is the all-in estimate of this request at the model's cheapest healthy offer within your limits (the input estimate and the output limit, in µ), and `Q` is its quality score, an integer from 0 to 100. With `C_min` the lowest candidate estimate: ```text value(m) = Q(m) − λ × log2( max(C(m), 1) / max(C_min, 1) ) ``` | Policy | λ | Order (each column breaks the previous one's ties) | | --- | --- | --- | | `auto` (best value) | λ 6 | Order: value, highest first · Q · C, lowest first · model id | | `auto:best` (highest ranked) | λ 0 | Order: Q, highest first · C, lowest first · model id | | `auto:cheap` (lowest price) | λ ∞ | Order: C, lowest first · Q, highest first · model id | In words: with `auto`, a model that costs twice as much for this request must score 6 points higher to win. λ is a product setting, not a measurement; a change to it gets a changelog line and an update to this page. **Worked example.** Model A scores 40 and costs $0.000168 for the request; model B scores 52 and costs $0.0006. log2(600 / 168) = 1.84, so B's value is 52 − 11.0 = 41.0, above A's 40: `auto` picks B, `auto:cheap` picks A, `auto:best` picks B. Had B cost $0.001, its value would be 52 − 6 × 2.57 = 36.6, below 40, and `auto` would pick A. ### 3. Attempts The request goes to the first model's offers in rank order (the cheapest healthy seller first), then to the second model's, then to the third's: at most 3 models, and at most 3 attempts in all by default. A failing seller is replaced by the same model's next seller before the request moves to another model. Failover happens only before the first byte; nothing is retried once content has started streaming. The same market, body and headers always give the same order. At equal price, a seller that answers with no cold start goes before one that has to wake up; it never goes before a cheaper one. A seller that sleeps when idle gets its declared wake time on top of the first-byte wait, 140 seconds in all at most ([availability](https://inferit.cc/docs/sellers.md#availability)). `x-inferit-objective: latency` keeps its meaning inside a model (it orders that model's sellers within a 10% price band). It does not change which model is chosen. ## Hints Optional limits, sent as body fields (in the OpenAI SDKs: `extra_body`) or as headers, for clients that cannot add body fields but can send provider headers, such as OpenCode. If both are sent, the stricter value wins. | Body field | Header | Meaning | | --- | --- | --- | | `max_price_per_m` | `x-inferit-max-price-per-m` | Integer µ per 1M tokens, all-in, 1 to 1012 (a number or a decimal string). Skips any offer whose all-in price, blended on this request's estimated token mix, is above it. Works with auto and with named models. | | `min_context` | `x-inferit-min-context` | Integer tokens, 1 to 100,000,000. Only models whose context window is at least this. Auto only. | | `min_quality` | `x-inferit-min-quality` | Integer, 0 to 100. Only models whose quality score is at least this ([the ranking](https://inferit.cc/docs/routing.md#ranking)). Auto only. | - Strictest wins: `max_price_per_m` takes the smaller value, `min_context` and `min_quality` the larger. - A bad value answers `400 invalid_request`, naming the field. `min_context` or `min_quality` with a named model answers `400 invalid_request`: they apply to model auto only. - Hint fields never reach a seller: the API forwards only the chat fields a seller needs. - Units: [µ](https://inferit.cc/docs.md#units), one millionth of a dollar; `400000` per 1M tokens is $0.40 per 1M tokens. _Python · OpenAI SDK, with hints_ ```python import os from openai import OpenAI inferit = OpenAI(base_url="https://api-production-c74b9.up.railway.app/v1", api_key=os.environ["INFERIT_API_KEY"]) reply = inferit.chat.completions.create( model="auto:cheap", messages=[{"role": "user", "content": "Extract the dates from this text: ..."}], # Hints are body fields; clients that cannot add body fields send the x-inferit-* headers instead. extra_body={"min_context": 32000, "min_quality": 5, "max_price_per_m": 400000}, ) print(reply.model) # the model that served it ``` _curl · hints as headers_ ```bash curl https://api-production-c74b9.up.railway.app/v1/chat/completions \ -H "Authorization: Bearer $INFERIT_API_KEY" \ -H "content-type: application/json" \ -H "x-inferit-min-quality: 5" \ -H "x-inferit-max-price-per-m: 400000" \ -d '{"model": "auto", "messages": [{"role": "user", "content": "Hello"}]}' ``` Hints only narrow what auto can choose from now (`candidates_now` in `GET /v1/routing`). When that list is empty, [name a model](https://inferit.cc/docs/routing.md#named): `max_price_per_m` works with a named model too. _curl · a named model, with max\_price\_per\_m_ ```bash curl https://api-production-c74b9.up.railway.app/v1/chat/completions \ -H "Authorization: Bearer $INFERIT_API_KEY" \ -H "content-type: application/json" \ -H "x-inferit-max-price-per-m: 400000" \ -d '{"model": "qwen/qwen-2.5-14b-instruct", "messages": [{"role": "user", "content": "Hello"}]}' ``` ## What the response says | Where | What | | --- | --- | | `x-inferit-model` | The catalog id of the model that served the request (named models too). The authoritative answer. | | `x-inferit-route` | `direct` for a named model; `auto:balanced`, `auto:cheap` or `auto:best` for auto. | | `x-inferit-auto-choice` | Auto only: 1 when the first choice served it; 2 or more when failover moved the request to another model. | | JSON `model` | The serving model's catalog id. In a stream each chunk's `model` is the seller's name for the same model (often an alias); the header is authoritative. | | `GET /v1/usage` | Each row's `model` is the serving model; `requestedModel` is `auto:balanced`, `auto:cheap` or `auto:best` for auto, and `null` for a named model. The CSV export adds it as its last column. | The other headers are unchanged: `x-inferit-attempts`, `x-inferit-offer`, `x-inferit-buyer-cost-micro` ([all response headers](https://inferit.cc/docs/api-reference.md#headers)). Browsers can read all of them (CORS). ## x402 and auto - Without a key, the 402 quote is priced for the model auto picks: the worst case of this body at that model's first offer, never below $0.01 ($0.01). The 402 carries `x-inferit-model` and `x-inferit-route`, and its message names the model. - The paid retry tries that model first. If it stopped being a candidate between the quote and the payment, the next candidates are tried, each only if its worst case fits the payment. If none fits, the answer is `503 no_available_offers`, and the payment stays in your balance. - The model is chosen before any payment is taken: when no model can serve the request, the call without a key gets `503 no_eligible_model` instead of a 402, and a paid retry gets it before its payment is settled. - The quote is pinned to the body and the routing headers, the hint headers included: a retry with a different hint gets a new 402. Agents: [agents.md](https://inferit.cc/agents.md) has the whole x402 exchange. ## Errors | Status | Code | When | retry-after | | --- | --- | --- | --- | | 400 | `invalid_auto_policy` | An id that starts with auto: or inferit/auto but names no policy: "Unknown auto policy \`auto:fast\`; use auto, auto:cheap or auto:best." | no | | 400 | `invalid_request` | A hint with a bad value (the message names the field and its range), or min\_context / min\_quality with a named model | no | | 503 | `no_eligible_model` | No model can serve this request right now. The message says why, and error.reasons counts each reason (and lists the models for the offer reasons). | only when health is the only cause | | 503 | `no_available_offers` | Candidates exist, but every attempt failed before the first byte; or, with x402, no candidate fits the payment (the payment stays in your balance). | 10 s | `error.reasons` counts every model considered by its first failing check ([the reasons above](https://inferit.cc/docs/routing.md#fit)), and `error.reasons.models` lists the models for `no_offer`, `no_healthy_offer`, `below_min_discount` and `over_max_price`. _503 no\_eligible\_model (example)_ ```json { "error": { "message": "No model can serve this request right now: 2 have no healthy seller, 1 has a context window under 300,000 tokens, 16 have no seller on the whitechain rail, 8 have no published quality score.", "type": "service_unavailable", "code": "no_eligible_model", "reasons": { "considered": 27, "unscored": 8, "not_servable": 0, "context_too_small": 1, "needs_tools": 0, "needs_vision": 0, "unsupported_input": 0, "below_min_quality": 0, "no_offer": 16, "no_healthy_offer": 2, "below_min_discount": 0, "over_max_price": 0, "models": { "no_offer": ["…"], "no_healthy_offer": ["…", "…"], "below_min_discount": [], "over_max_price": [] } } } } ``` ## The quality ranking **Read on 2026-10-06.** score = the model's Artificial Analysis Intelligence Index, rounded to the nearest integer. Each catalog model is matched to the row the source publishes under the model's own id (its default configuration, e.g. 'Qwen3.6 27B (Reasoning)'); sourceName and sourceId record the match. Models the source does not list, or lists only under a different release than the catalog's, are left out (no fallback map is used in this table). estimatedBySource marks values the source itself labels as estimated. A score describes the model as its vendor released it. Sellers often serve a quantized build (for example 4-bit or 8-bit weights, shown as the offer's `quantization` when the seller declares it), which can answer somewhat differently; the ranking does not measure each seller's build. - **Artificial Analysis Intelligence Index**, read 2026-10-06: [artificialanalysis.ai/leaderboards/models](https://artificialanalysis.ai/leaderboards/models). Version: v4.3 (the leaderboard label; the methodology note on artificialanalysis.ai/models reads v4.3.2). | Model (catalog id) | Score | Name at the source | | --- | --- | --- | | `moonshotai/kimi-k2.6` | 27 | Kimi K2.6 (Reasoning) | | `z-ai/glm-5.1` | 26 | GLM-5.1 (Reasoning) | | `moonshotai/kimi-k2-thinking` | 22 | Kimi K2 Thinking (the source marks it estimated) | | `qwen/qwen3.6-27b` | 21 | Qwen3.6 27B (Reasoning) | | `qwen/qwen3.6-35b-a3b` | 18 | Qwen3.6 35B A3B (Reasoning) | | `deepseek/deepseek-v3.2` | 16 | DeepSeek V3.2 (Non-reasoning) (the source marks it estimated) | | `google/gemma-4-31b-it` | 15 | Gemma 4 31B (Reasoning) | | `z-ai/glm-4.6` | 15 | GLM-4.6 (Non-reasoning) (the source marks it estimated) | | `openai/gpt-oss-120b` | 12 | gpt-oss-120b (High) | | `qwen/qwen3-235b-a22b-2507` | 12 | Qwen3 235B A22B 2507 Instruct (the source marks it estimated) | | `qwen/qwen3-coder` | 12 | Qwen3 Coder 480B A35B Instruct (the source marks it estimated) | | `meta-llama/llama-4-maverick` | 10 | Llama 4 Maverick (the source marks it estimated) | | `openai/gpt-oss-20b` | 9 | gpt-oss-20b (High) | | `meta-llama/llama-3.3-70b-instruct` | 8 | Llama 3.3 Instruct 70B (the source marks it estimated) | | `mistralai/mistral-small-3.2-24b-instruct` | 8 | Mistral Small 3.2 (the source marks it estimated) | | `qwen/qwen-2.5-72b-instruct` | 8 | Qwen2.5 Instruct 72B (the source marks it estimated) | | `meta-llama/llama-3.1-8b-instruct` | 7 | Llama 3.1 Instruct 8B (the source marks it estimated) | | `qwen/qwen3-14b` | 7 | Qwen3 14B (Non-reasoning) (the source marks it estimated) | | `google/gemma-3-27b-it` | 5 | Gemma 3 27B Instruct | Catalog models without a score (auto never routes to them; name them to use them): - `qwen/qwen-2.5-14b-instruct`: Not listed by Artificial Analysis (it lists Qwen2.5 Instruct 72B, Qwen2.5 Coder 32B and 7B) nor by the LMArena text leaderboard (checked 2026-10-06). - `ifm/k2-horizon-7b`: Released 2026-09 by MBZUAI's IFM; not listed with an Intelligence Index value by Artificial Analysis (checked 2026-10-18), so model auto does not route to it until it is scored. - `mistralai/mistral-nemo`: Not listed with an Intelligence Index value by Artificial Analysis. - `deepseek/deepseek-v4-pro`: Catalog release is 0423 (OpenRouter); the source lists V4 Pro 0424 and V4 Pro 0813 only, so the match is not certain. - `deepseek/deepseek-v4-flash`: Catalog release is 0423 (OpenRouter); the source lists V4 Flash 0420 and V4 Flash 0731 only, so the match is not certain. - `anthropic/claude-sonnet-5.5`: Closed model: a reference row, not servable; needs no score. - `openai/gpt-6.1-sol`: Closed model: a reference row, not servable; needs no score. - `google/gemini-3.8-flash`: Closed model: a reference row, not servable; needs no score. The table is kept with the catalog: when the catalog takes a new price snapshot, the scores are read again the same day. The same table, and the models auto can choose from now, are at `GET /v1/routing` as JSON ([API reference](https://inferit.cc/docs/api-reference.md#get-v1-routing)). ## What it does not do - It chooses from the request's size and features, never from what it says. - Tools and images are model-level flags from the catalog snapshot: a model supports the feature, and a given seller's server may still not. - Hints are per request. A key cannot carry a default policy or price limit in this version. - Audio and file parts go only to a model you name. ## Name a model instead Send a catalog id or an alias (`GET /v1/models` lists them) and Inferit picks only the seller: the cheapest healthy seller of that model, as it always has. `max_price_per_m` works with named models too: when no healthy offer of the model is within it, the answer is `503 no_available_offers`, with `retry-after`. When no seller of the model serves a context window big enough for the request, the answer is `400 context_length_exceeded`. `min_context` and `min_quality` do not apply to a named model. A named model needs no score: unscored models are served by name, so when auto answers `no_eligible_model`, a model with a live offer (a `best_price` in `GET /v1/models`) still answers by name. --- Canonical page: https://inferit.cc/docs/routing All pages as markdown: https://inferit.cc/llms.txt --- Source: https://inferit.cc/docs/api-reference.md # API reference > Inferit API reference: every endpoint, authentication with an API key or x402, money in µ, errors, response headers, and the on-chain calls that have no endpoint. Base URL: `https://api-production-c74b9.up.railway.app` (this site's current API). Inference is OpenAI-compatible; everything else is plain JSON. Agents can read the same in one file: [agents.md](https://inferit.cc/agents.md). ## Authentication - **Inference** takes an API key: `Authorization: Bearer ik_…` or `x-api-key: ik_…`. Without either, it takes an x402 payment instead ([below](https://inferit.cc/docs/api-reference.md#x402)). - **Account routes** (keys, balance, usage, seller) take the session token from sign-in as `Authorization: Bearer `. Sessions last 24 h. Balance and usage also accept your API key. - **Public routes** (models, prices, marketplace, stats, rails) need no auth and are cacheable. ## Money API amounts are integers in millionths of a dollar, sent as strings: "10000" = $0.01, paid as 0.01 ITC. Fields ending in `Micro` hold such amounts. ITC (Inferit Test Credit) is the token you pay with: one ITC per dollar of price. So `"1500000"` = $1.50 (1.50 ITC). Prices are per 1M tokens: `84000` = $0.084 per 1M tokens. The site shows the same prices in dollars per 1M tokens ([units](https://inferit.cc/docs.md#units)). Prices are **all-in** (the seller's price plus the platform fee) unless a field says otherwise. Percentages are numbers with two decimals; a discount is rounded down so it is never overstated. What one request costs, and the rounding, is in [Core concepts](https://inferit.cc/docs.md#request-cost); the `x-inferit-buyer-cost-micro` header is the authoritative figure. ## Inference ### POST `/v1/chat/completions` Auth: API key OpenAI Chat Completions. Send `"model": "auto"` and Inferit picks the model ([below](https://inferit.cc/docs/api-reference.md#auto)), or name a model (a catalog or seller-listed id, or an alias) and Inferit picks the seller. Supports `stream: true` (SSE relayed byte for byte). Before routing, your escrow balance (under your ceiling) must cover the worst case: input estimate plus the output limit at the top-ranked offer. The output limit is the smallest of `max_tokens`, `max_completion_tokens` and the model's `context_length` (from `GET /v1/models`), or 1,024 when you send neither, times `n` for several choices. The seller is held to it: a long answer without a limit stops at 1,024 tokens with `finish_reason: "length"`. You are then charged the metered cost. A closed model (`open_weight: false` in `/v1/models`) is a list-price-only row that no seller can list, so a request for it answers `404 model_not_servable`. _example_ ```bash curl https://api-production-c74b9.up.railway.app/v1/chat/completions \ -H "Authorization: Bearer $INFERIT_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "qwen/qwen-2.5-14b-instruct", "messages": [{"role": "user", "content": "Hello"}] }' # x-inferit-model in the response names the model that answered ``` ### POST `/min{N}/v1/chat/completions` Auth: API key Same, but only routes to offers at least N% below list (0–100). Also available as the `x-min-discount` header or a per-key setting; the strictest wins. ### POST `/anthropic/v1/messages` Auth: — Not implemented yet: returns `501` with a docs link. See [Claude Code](https://inferit.cc/docs/guides/claude-code.md). ### Model auto `"model": "auto"` (also `auto:cheap`, `auto:best`, and the `inferit/` prefix) lets Inferit pick the model: among the models with a healthy seller that fit the request, the best value on a published quality ranking for this request's price, then the cheapest healthy seller of it. Optional hints, as body fields or headers: `max_price_per_m` (`x-inferit-max-price-per-m`, µ per 1M tokens all-in; named models too), `min_context` (`x-inferit-min-context`) and `min_quality` (`x-inferit-min-quality`, 0–100). Policies, the choice, the ranking and every error: [Automatic routing](https://inferit.cc/docs/routing.md). ### GET `/v1/routing` Auth: — How model auto chooses, as data: the policies and their weights, the hints, the quality ranking as committed (method, sources, dates, every score and the models left out), and the models auto can choose from now for a reference request, in its order. Public, cached for 60 s. _GET /v1/routing (abridged)_ ```json GET /v1/routing { "policies": [{ "id": "auto:balanced", "model": "auto", "aliases": ["auto:balanced", "inferit/auto"], "name": "Inferit Auto: best value", "lambda": 6, "description": "…" }, …], "hints": [{ "body": "max_price_per_m", "header": "x-inferit-max-price-per-m", "unit": "µ per 1M tokens, all-in", "range": "1..1000000000000", "appliesTo": "auto and named models", … }, …], "quality": { "asOf": "2026-10-06", "method": "…", "sources": [ … ], "models": [{ "id": "…", "score": 21, … }], "leftOut": [ … ] }, "reference": { "inputTokens": 3000, "outputTokens": 1000, "rail": "whitechain" }, "candidates_now": [{ "model": "…", "score": 21, "healthy_offers": 1 }], "docs": "https://inferit.cc/docs/routing" } ``` ### Response headers On every inference call: | Header | Meaning | | --- | --- | | `x-request-id` | Request id, also in your usage log | | `x-inferit-model` | The catalog id of the model that served the request: the one Inferit picked with model auto, or the one you named | | `x-inferit-route` | `direct` for a named model; `auto:balanced`, `auto:cheap` or `auto:best` for model auto | | `x-inferit-auto-choice` | Model auto only: 1 when the first choice served the request, 2 or more when failover moved it to another model | | `x-inferit-attempts` | Offers tried (failover happens only before the first byte) | | `x-inferit-buyer-cost-micro` | What this request cost you, in µ (a micro-ITC). A stream's final cost is known only after its last chunk; see your usage log. | | `x-inferit-offer` | Opaque hash of the offer that served you, not the seller's identity. On Whitechain the settlement itself is public; see [On-chain visibility](https://inferit.cc/docs/security-trust.md#on-chain) | | `x-inferit-rail` | Rail the request is funded and settled on | | `x-inferit-network` | Settlement network, on every response: `whitechain-sepolia` | ### Errors Errors use OpenAI's shape, `{"error":{"message","type","code"}}`. Branch on `code`: | Status | Code | When | | --- | --- | --- | | 400 | `invalid_request` | The body does not parse or a field is invalid, a hint included (type invalid\_request\_error) | | 400 | `invalid_auto_policy` | A model id that starts with auto: or inferit/auto but names no policy; use auto, auto:cheap or auto:best | | 400 | `invalid_address` | POST /v1/faucet or sign-in with an address that is not 0x-prefixed 20-byte hex | | 401 | `invalid_api_key` | A wrong or revoked API key | | 401 | `missing_credentials` | An account route (keys, balance, usage, seller) without a session or key | | 400 | `context_length_exceeded` | A named model whose sellers all serve a smaller context window than this request needs; shorten it or lower max\_tokens | | 402 | `insufficient_funds` | With a key: the worst case exceeds your escrow balance or ceiling, or the ceiling has expired | | 402 | `spend_limit_exceeded` | With a key: the key has reached its own spend limit | | 404 | `model_not_found` | The model is neither in the catalog nor listed by a seller (see GET /v1/models), or send model auto | | 404 | `model_not_servable` | A closed model: a reference row (servable: false) that no seller can list | | 404 | `faucet_disabled` | This server sponsors no faucet | | 429 | `rate_limit_exceeded` | Too many requests from this IP or paying address, or the faucet’s hourly server budget; honour retry-after | | 429 | `faucet_cooldown` | This address claimed ITC less than 24 h ago; retry-after says when | | 501 | `not_implemented` | /anthropic/v1/messages and legacy /v1/completions | | 503 | `no_available_offers` | No healthy offer right now; honour retry-after | | 503 | `no_eligible_model` | Model auto: no model can serve this request right now; error.reasons counts why (see Automatic routing) | | 503 | `rail_unavailable` | The chain could not be read to check your funding (or, on seller routes, your registration); nothing was charged; honour retry-after (5 s). Without retry-after, your selected rail is not enabled here: pick another with PUT /v1/buyer/rail | | 503 | `funding_busy` | A settlement landed while your funding was being read; nothing was charged; retry after 1 s (retry-after: 1) | | 503 | `faucet_pending` | The mint was sent but is not confirmed yet (retry-after 15); check the balance before claiming again | | 503 | `faucet_unavailable` | The faucet cannot mint right now; retry after 60 s | | 503 | `x402_settlement_pending` | The x402 deposit was sent but not confirmed in time; if it lands it is your balance | | 503 | `x402_unavailable` | The x402 path failed before anything was sent; nothing was charged | | 402 | `invalid_exact_stellar_*` | x402 on Stellar: the payment was refused (in the 402 error field); the suffix says why, e.g. \_balance\_over\_limit, \_wrong\_amount, \_signature\_expires\_too\_soon | | 503 | `x402_busy` | x402 on Stellar: too many payments are settling right now; nothing was used or charged; retry after 5 s | | 400 | `trustline_missing` | POST /v1/faucet/stellar: the G… account has no trustline to ITC; the error carries the changeTrust to send | | 400 | `account_not_found` | POST /v1/faucet/stellar: the G… account does not exist yet; fund it from friendbot first | | 400 | `unsupported_recipient` | POST /v1/faucet/stellar with a contract address (C…): the faucet sends to G… accounts only | | 401 | `stellar_key_not_a_signer` | Stellar sign-in: the account no longer accepts the key that signed (its master key weight is 0 or below its threshold) | | 404 | `stellar_not_enabled` | A Stellar sign-in or payout route on a server without the Stellar rail | Inference with no key at all answers `402`: the x402 challenge, not an error. Rate limits (hosted defaults): 1,200 requests a minute per IP on every route, 30 a minute on sign-in; over them, `429 rate_limit_exceeded` with `retry-after`. Responses carry no RateLimit headers. ```json { "error": { "message": "Your available balance on whitechain does not cover the worst-case cost of this request.", "type": "insufficient_funds", "code": "insufficient_funds" } } ``` ## x402: pay per request, no key One keyless request: the agent posts with model auto and no key; Inferit answers 402 with a quote of at least $0.01; the agent resends the same body with a PAYMENT-SIGNATURE; Inferit answers 200 and names the model. Each keyless call prepays at least $0.01 and is charged its exact price. **Two ways to pay.** With an API key, each request is charged to your prepaid balance: no quote, no payment step (only a `402 insufficient_funds` when the balance or the ceiling is too low, or `402 spend_limit_exceeded` when the key is at its limit). Without a key, you get a `402` quote and pay for that one request with x402. Standard x402 v2, `exact` scheme, settled into the escrow and credited to the payer. x402 can express $0.000001, but every x402 payment is an on-chain transaction that costs gas, so the API works as a prepaid meter: each payment is at least $0.01 (0.01 ITC), it is credited to the payer's own escrow balance, and each request is charged its exact µ cost against that balance. Settlement to sellers is batched on chain. The facilitator pays the gas, so an agent needs no WBT. The walkthrough and client code are on [Agents](https://inferit.cc/agents) and in [agents.md](https://inferit.cc/agents.md). Standard x402 v2 clients work once the asset is allowed in their spend controls; sign with a plain key (EOA), since smart-wallet signatures are not accepted. The asset is ITC (EIP-3009). ### POST `/v1/chat/completions` Auth: none → 402 With no `Authorization` or `x-api-key` header: `402` with a `PAYMENT-REQUIRED` header (base64 JSON) and the same document as the body. It offers one requirement: `scheme: "exact"`, `network: "eip155:"`, `asset` = the token, `payTo` = the escrow, `amount` = the worst-case all-in cost of this exact body (at least $0.01 = 0.01 ITC, since each payment is an on-chain transaction; the request is then charged its exact µ cost), `maxTimeoutSeconds` and `extra: { name, version }`, the token's EIP-712 domain: `name: "Inferit Test Credit"`, `version: "1"` (the domain version, not the contract revision: the token is TestCredit contract rev. 2). The quote is pinned to the body and the routing headers for 120 s. The same applies to `/min{N}/v1/chat/completions`. With model auto, the quote is priced for the model auto picks, and the 402 carries `x-inferit-model` and `x-inferit-route`; the paid retry tries that model first ([x402 and auto](https://inferit.cc/docs/routing.md#x402)). ### POST `/v1/chat/completions` Auth: PAYMENT-SIGNATURE The same body with a `PAYMENT-SIGNATURE` header (base64 JSON payload with an EIP-3009 authorization; `X-PAYMENT` is accepted too). The API verifies it, settles it first with `depositWithAuthorization`, then serves the request against the payer's escrow balance (streaming included). The response carries `PAYMENT-RESPONSE`, base64 of `{ success: true, transaction, network, payer }`, plus the usual `x-inferit-*` headers. A payment that does not verify gets a fresh `402` with the reason in `error`. If the request fails after the payment settled, the credit stays in the payer's escrow balance and the error says so (an `error.x402` object with `credited`, `payer`, `amount` and `transaction`; a funding `402` at that point becomes `503`, so the client does not pay again). `503 x402_settlement_pending`: the deposit was sent but its receipt did not arrive in time; if it lands it is the payer's escrow balance. `503 x402_unavailable`: nothing was sent and nothing was charged. ### POST `/v1/faucet` Auth: none Inferit's ITC faucet (ITC, not WBT), free and sponsored. Body `{ address }`: the API mints 1,000 ITC to that address with `faucetTo` and pays the gas, so the address needs no WBT. At most once per 24 h per address (`429 faucet_cooldown`), 10 calls an hour per IP and 120 sponsored mints an hour per server (`429 rate_limit_exceeded`). `503 faucet_pending` (`retry-after: 15`): the mint was sent but is not confirmed yet; check the balance before you claim again. `404 faucet_disabled` when the server does not sponsor the faucet. _200 response_ ```json { "address": "0xYourAddress", "amountMicro": "1000000000", "token": { "address": "0x2E67…7fBB", "symbol": "ITC", "decimals": 6 }, "network": "eip155:1874", "transaction": "0x…", "explorerUrl": "https://explorer.testnet.whitechain.io/tx/0x…", "next": "Pay for inference with x402: POST …/v1/chat/completions without credentials …" } ``` ### GET `/.well-known/x402` Discovery: the paid resources and the requirement a client signs for (scheme, network, asset, payTo, extra), the minimum payment, the facilitator address and the faucet. `404` when x402 is off. ### On Stellar While `GET /v1/rails` lists a rail with `"id": "stellar"`, the 402 also lists a Stellar entry and these routes answer. The walkthrough and client code: [Pay on Stellar](https://inferit.cc/docs/payments/stellar.md). ### POST `/v1/chat/completions` Auth: PAYMENT-SIGNATURE (Stellar) The 402's Stellar entry: `scheme: "exact"`, `network: "stellar:testnet"`, `asset` = the ITC contract (`C…`), `payTo` = Inferit's treasury (`G…`), `amount` in base units (7 decimals: 10 per millionth of a dollar), paid exactly, and `extra.areFeesSponsored: true`. The paid retry carries one SAC `transfer` signed by a `G…` account's own key; Inferit pays the network fee. Once it lands it is credited to the payer's balance with Inferit and the request is served, charged at most that payment. A call without a key never spends what earlier payments left: an API key made after a Stellar sign-in with the same key does ([Stellar sign-in](https://inferit.cc/docs/api-reference.md#auth-stellar), then `POST /v1/keys`). A payment that would take the balance past its limit is refused with `invalid_exact_stellar_balance_over_limit`. `503 x402_settlement_pending`: the transaction was submitted and its outcome is not known yet (`error.x402.transaction`); if it lands it is credited, checked again within minutes. `503 x402_busy` and `503 x402_unavailable`: nothing was sent and nothing was charged. ### GET `/v1/faucet/stellar` Auth: none What the Stellar faucet gives (asset, amount, once per 24 h per address) and how to add the trustline. `404 faucet_disabled` when it is off. ### POST `/v1/faucet/stellar` Auth: none Body `{ address }`, a `G…` account with a trustline to ITC: sends 1,000 ITC, once per 24 h per address (`429 faucet_cooldown`), within the same per-IP and per-server hourly limits as the ITC faucet. `400 account_not_found`, `trustline_missing`, `trustline_not_authorized` or `trustline_limit` say what to fix first; `400 unsupported_recipient` for a contract address (`C…`). `503 faucet_pending` (`retry-after: 15`): sent, not confirmed yet; the next claim checks it before anything new is sent. ## Marketplace (public) ### GET `/v1/models` OpenRouter-shaped model rows plus `pricing` (list price) and `best_price` (best all-in offer, or `null`). Two encodings of the same price sit side by side: `prompt` and `completion` are decimal strings in ITC per token (`"0.0000001"`), as OpenRouter writes them; `input_per_m`, `output_per_m` and `cache_read_per_m` are integer µ per 1M tokens (`"100000"`). `best_price.discount_pct` is the best all-in price (fee included) against list. The list includes list-price-only rows: `best_price: null` means no seller offers that model right now. The first three rows are model auto (`auto`, `auto:cheap`, `auto:best`; `owned_by: "inferit"`), each with an `auto` object: `policy`, `pick`, `candidates` and `ranking` (`as_of`, `url`), computed for a reference request of 3,000 input and 1,000 output tokens. `GET /v1/models/auto` returns one row. Each servable model with listed offers also carries `live`: `healthy_sellers` and `sellers` (counts), `uptime_24h` (0 to 1), `ttft_p50_ms` and `ttft_p95_ms` (time to first token over the last 24 h: the median across offers of each offer's own p50 and p95) and `updated_at`. A figure with no data yet is `null`, never an estimate; demo offers are not counted. Other catalog rows have `live: null`; the three auto rows have no `live`. Every model row says where it comes from: `listed_by` is `"catalog"` (the curated catalog, `catalog: true`) or `"seller"` (`catalog: false`): an open-weight model a seller listed with [POST /v1/seller/models](https://inferit.cc/docs/api-reference.md#post-v1-seller-models). A seller-listed row has `open_weight: true`, its `aliases`, `context_length` and `license`, plus `hf_repo` (the Hugging Face repo it was checked against, or `null`) and `license_source` (`huggingface` or `seller`). It has no list price: `pricing` is `null`, `best_price` comes from its live offers only and `best_price.discount_pct` is `null`. Model auto never picks it (it has no quality score), and a `x-min-discount` floor excludes it. Seller-listed rows come after the catalog's. _live (annotated)_ ``` GET /v1/models (one row, abridged) { "id": "qwen/qwen-2.5-14b-instruct", "context_length": 32768, "aliases": ["qwen2.5:14b-instruct", "qwen2.5:14b", "qwen2.5-14b-instruct", "Qwen/Qwen2.5-14B-Instruct"], "pricing": { "input_per_m": "100000", "output_per_m": "200000", … }, // list price "best_price": { "input_per_m": "73500", "output_per_m": "147000", … }, // all-in "live": { "healthy_sellers": 1, "sellers": 2, "uptime_24h": null, // 0..1, null until there is data "ttft_p50_ms": null, // time to first token, last 24 h "ttft_p95_ms": null, "updated_at": "2026-10-13T09:00:00.000Z" } } ``` ### GET `/v1/models/:id` One row of `/v1/models`, by id or alias, catalog or seller-listed. The id contains `/`: send it as is or URL-encoded (`%2F`). ### GET `/v1/models/:id/endpoints` The offers that serve one model, healthy ones first, then by all-in price, with `updated_at`; one row per offer: `seller` (the seller's wallet address, shortened, or `null` for a seller account with no wallet on file), `offer_id` (the same opaque id a response names in `x-inferit-offer`), `price` (`input_per_m` and `output_per_m`, all-in, integer µ per 1M tokens as decimal strings), `context_length`, `quantization` (or `null`), `healthy`, `uptime_24h`, `ttft_p50_ms` and `ttft_p95_ms`, each `null` when unknown. Never a seller's endpoint URL or volume. Demo offers are left out unless the server routes paid traffic to them; then they are listed with `demo: true`. URL-encode the id. _example (annotated)_ ``` GET /v1/models/qwen%2Fqwen-2.5-14b-instruct/endpoints { "model": "qwen/qwen-2.5-14b-instruct", "updated_at": "2026-10-13T09:00:00.000Z", "endpoints": [{ "seller": "0x45A9…7CDE", // the seller's wallet, shortened (null: no wallet on file) "offer_id": "…", "price": { "input_per_m": "73500", "output_per_m": "147000" }, // all-in, µ per 1M tokens "context_length": 32768, "quantization": null, "healthy": true, "demo": false, // true only on a server that routes to demo offers "uptime_24h": null, // 0..1, null until there is data "ttft_p50_ms": null, "ttft_p95_ms": null }] } ``` ### GET `/v1/prices` List and best all-in price per model (list `null` for a seller-listed model). ### GET `/api/marketplace` Per model: best all-in input/output price, discount vs list, sellers, healthy sellers, warm sellers (no cold start now), 24 h requests and volume, uptime, TTFT p50. ### GET `/api/markets/:model` Aggregated order book: price levels with offer count, healthy count and the combined daily caps of the offers at each level. Never seller identities, endpoints or per-offer volume. URL-encode the model id. ### GET `/api/stats` Rolling 24 h totals: requests, spend, savings vs list, tokens, offers, sellers. ### GET `/v1/rails` Settlement on Whitechain: network, chain id, escrow and token addresses, operator, owner, guardian, escrow version, health. ### GET `/v1/providers/resale-allowlist` Providers whose terms permit API-key resale, each with an evidence URL. Empty by default. ### GET `/health` Liveness, the build's git SHA, the network and chain id. Answers 503 when the database or the settlement rail is unhealthy (RPC down, escrow paused, operator low on gas). ### GET `/metrics` JSON operations metrics: settlement backlog, batches awaiting finality, chain head lag, operator gas runway, circuit-breaker headroom, connector session counts, and healthy and warm offers per core model when the operator names core models. May require a bearer token on hosted deployments. ### GET `/llms.txt` The API's own summary for agents, with the live models and prices and both ways to pay. This site's index of every page as markdown is a different file: [/llms.txt](https://inferit.cc/llms.txt) on the docs host. The two examples below show the response shape. The live values are on [/models](https://inferit.app/models). _example (annotated)_ ``` GET /api/marketplace { "feeBps": 500, "markets": [{ "modelId": "qwen/qwen-2.5-14b-instruct", "name": "Qwen: Qwen2.5 14B Instruct", "openWeight": true, "licenseId": "apache-2.0", "listInputPerM": "100000", // µ per 1M tokens: 0.10 ITC per 1M "listOutputPerM": "200000", "bestInputPerM": "84000", // all-in, healthy offers only "bestOutputPerM": "168000", "bestDiscountPct": 16, "sellers": 2, "healthySellers": 1, "requests24h": 0, "volume24hMicro": "0", "uptime24hPct": null, // null until there is data "ttftP50Ms": null }] } ``` _example (annotated)_ ``` GET /api/markets/qwen%2Fqwen-2.5-14b-instruct { "modelId": "qwen/qwen-2.5-14b-instruct", "summary": { ...same shape as a marketplace row... }, "levels": [ { "inputPerM": "84000", "outputPerM": "168000", "offers": 1, "healthyOffers": 1, "capacityMicro": null }, { "inputPerM": "90000", "outputPerM": "180000", "offers": 1, "healthyOffers": 0, "capacityMicro": "1000000" } ] } ``` ## Sign-in ### POST `/v1/auth/evm/challenge` Body `{ address }`. Returns `{ message, nonce, expiresAt }`: a one-time EIP-4361 message to sign with the wallet (an EIP-191 signature). It is an off-chain text signature: no transaction, no gas. ### POST `/v1/auth/evm/verify` Body `{ message, signature }`. Verifies the signature and returns `{ token, expiresAt, account }`: a session token for the account routes, valid for 24 h, for both the Buy and the Sell workspace. ### POST `/v1/auth/stellar/challenge` While the Stellar rail is on. Body `{ address }`, a `G…` account exactly as the wallet shows it. Returns `{ message, nonce, expiresAt, method: "sep53" }`: a one-time text message to sign as a SEP-53 signed message (Freighter, Hana, xBull). No transaction, no fee. `404 stellar_not_enabled` when the rail is off. ### POST `/v1/auth/stellar/verify` Body `{ message, signature }` (base64 or hex). Returns a session like the EVM one; its account's rail is `stellar`, so an API key made with it spends the Stellar balance. The account's signers on Stellar are checked: `401 stellar_key_not_a_signer` when the account no longer accepts the key that signed, `503 stellar_unavailable` when Stellar cannot be read (the same signature can be retried). ### POST `/v1/account/stellar-payout/challenge` Auth: session Body `{ address }`, a `G…` account: a message naming this Inferit account, to be signed (SEP-53) by that address's wallet. Then `POST /v1/account/stellar-payout/verify` with `{ message, signature }` records it as the account's Stellar payout address; `DELETE /v1/account/stellar-payout` removes it. ## Keys ### POST `/v1/keys` Auth: session Body `{ name?, spendLimitMicro?, minDiscountPct? }`. Returns the key once in `key`. ### GET `/v1/keys` Auth: session Your keys (prefix only, never the secret). ### DELETE `/v1/keys/:id` Auth: session Revoke immediately. ## Buyer ### GET `/v1/balance` Auth: session or API key Available, cap, spent, deposit, expiry, unsettled charges (`pendingMicro`) and usage settled on-chain but not yet final (`pendingFinalityMicro`). Available subtracts both. ### PUT `/v1/buyer/rail` Auth: session Body `{ rail: "whitechain" }`. Selects Whitechain settlement for future requests (`"credit"` exists only on local development APIs). ### GET `/v1/usage?limit&cursor` Auth: session or API key Per-request token counts, costs, latency, rail and settlement status. `model` is the model that served the request; `requestedModel` is `auto:balanced`, `auto:cheap` or `auto:best` when you sent model auto, else `null`. Paginate with `nextCursor`. Each row carries `finality`: `pending` until its settlement batch is finalized on-chain, then `finalized`. Rows never carry the seller's identity, a transaction hash or a batch id; your own settlements are listed with explorer links in the Buy workspace. ### GET `/v1/usage/export.csv` Auth: session or API key The same as CSV, with `requestedModel` as the last column. Never contains prompts or completions. ## Seller ### POST `/v1/seller/offers` Auth: session Body `{ model, kind: "endpoint" | "upstream_key", endpointUrl, authToken?, upstreamProvider?, upstreamKey?, pricing, capDailyMicro?, licenseAck }`. `pricing` is `{ mode: "per_token", inputPerM, outputPerM, cacheReadPerM? }` or `{ mode: "multiplier", multiplierBps }` (10,000 = list price). The API checks the licence, the resale allowlist and an SSRF guard, sends a live 1-token probe, and requires you to be registered on your rail. Optional availability fields: `availability` (`always_on`, `scale_to_zero` or `intermittent`), `coldStartMs` and `healthUrl` (both required for `scale_to_zero`), `warmWindowMs`, `maxContextTokens` and `quantization`; see [availability](https://inferit.cc/docs/sellers.md#availability). A connector offer uses `endpointUrl` `connector:///v1` with no `authToken`, and answers `409 node_offline` unless the seller app on that machine is connected and serving the model. `model` is a catalog model or one a seller listed ([open listing](https://inferit.cc/docs/api-reference.md#post-v1-seller-models)); a seller-listed model is priced `per_token` only and served from your own machine or endpoint (`kind: "endpoint"`; an `upstream_key` offer on it is `403 resale_not_allowed`), and every other check is the same. ### POST `/v1/seller/models` Auth: session or seller key Open listing: list an open-weight model that is not in the catalog, so that any seller can offer it. Body `{ hfRepo? | id?, name?, contextLength, licenseId?, licenseAck?, aliases }`. With `hfRepo` (a Hugging Face repo id such as `Org/Model-7B-Instruct`, or its huggingface.co link) the API asks Hugging Face: the repo must be public, ungated and a text-generation model, and its licence is read from the model card; the model id is the repo id in lowercase. Without one, `id` is a lowercase `/` and `licenseId` names the licence of the weights (one of `apache-2.0`, `mit`, `bsd-3-clause`, the Llama community licences, `gemma`, `qwen`, `modified-mit`, `cc-by-4.0`, `cc-by-sa-4.0`, `openrail`, or `other` for a custom licence you checked). A licence that does not permit commercial serving (non-commercial, research-only, closed) is refused (`400 license_not_listable`); a conditional one, or one the API cannot verify, needs `licenseAck: true` (`400 license_ack_required`). `contextLength` is 256 to 10,000,000 tokens (at most the model's own window when Hugging Face reports it). `aliases` are your machine's local names for the model (at most 5 a request, 10 a model; the Sell workspace sends the local name), which the `inferit-seller` app matches exactly. An alias is never a Hugging Face repo id other than the model's own (list that repo as its own model) nor a closed model's name, and no id or alias ends in `/endpoints`. Refused: `409 catalog_model` for a catalog model or a name close to one (the error names the catalog id to offer instead), `400 closed_model` for a hosted-API model, `403 hf_repo_gated` for a gated or private repo, `404 hf_repo_not_found`, `400 not_a_chat_model`, `409 alias_taken`, `503 hf_unavailable` when Hugging Face does not answer. Limits per account: 10 new models a day (`429 model_limit_daily`), 50 in all (`409 model_limit_total`), 30 Hugging Face checks an hour (`429 hf_lookup_limit`). Answers `201` with `{ model, created: true }`, or `200` with `created: false` when the id is listed already: your aliases are added to it. Your connected machines are told at once, so the app (0.3.3 or newer) serves the model without a restart. Then list an offer on it with [POST /v1/seller/offers](https://inferit.cc/docs/api-reference.md#post-v1-seller-offers), priced per token (it has no list price to multiply). _example_ ``` POST /v1/seller/models { "hfRepo": "Org/Model-7B-Instruct", "contextLength": 8192, "aliases": ["model-7b:latest"] } 201 { "created": true, "model": { "id": "org/model-7b-instruct", "name": "Org: Model-7B-Instruct", "hfRepo": "Org/Model-7B-Instruct", "contextLength": 8192, "licenseId": "apache-2.0", "licenseSource": "huggingface", // read from the model card "aliases": ["model-7b:latest"], "status": "active", "createdAt": "2026-10-19T12:00:00.000Z", "listedByYou": true } } ``` ### GET `/v1/seller/models` Auth: session or seller key The models your account listed: `id`, `name`, `hfRepo`, `contextLength`, `licenseId`, `licenseSource`, `aliases`, `status`, `createdAt`. ### GET `/v1/seller/offers` Auth: session Your offers, including your own endpoint URLs and health. ### PATCH `/v1/seller/offers/:id` Auth: session Pause/resume, reprice, change cap or endpoint. ### DELETE `/v1/seller/offers/:id` Auth: session Delist; stored secrets are destroyed (hard delete). ### POST `/v1/seller/nodes` Auth: session Body `{ name }` (at most 64 letters, digits, spaces and `. : @ ( ) - _`). Adds a machine: mints a connection token for the `inferit-seller` app ([seller quickstart](https://inferit.cc/docs/sellers/quickstart.md)). Returns `node` (with its `offerEndpointUrl`), the token once in `token`, and `connectUrl`. Needs the session from wallet sign-in. `409 too_many_nodes` at the account's limit (five by default). See [connector mode](https://inferit.cc/docs/sellers.md#connector). ### GET `/v1/seller/nodes` Auth: session Your machines. Each has `id`, `name`, `tokenPrefix`, `createdAt`, `online` (connected now), `lastSeenAt` (or `null`), `agent` (the app that runs it: `{ name, version, os, arch }`, or `null` for an older app), `detected` (what the app found on the local model server at its last connection: `local` name, `server` (`ollama`, `lmstudio`, `vllm`, `llamacpp` or `custom`), `model` (the catalog or seller-listed id it matched, or `null`: not on the market yet) and, when known, `contextLength`, `quantization`, `sizeBytes` and `chat: false` for a model the server says is not a chat model) and `models` (the model ids it serves). Also `offerEndpointUrl`, the `endpointUrl` for its offers. _example (annotated)_ ``` GET /v1/seller/nodes (one machine, abridged) { "nodes": [{ "id": "node_…", "name": "home-pc", "tokenPrefix": "icn_AbCd…wxyz", "createdAt": "2026-10-13T09:00:00.000Z", "online": true, "lastSeenAt": "2026-10-13T09:05:12.000Z", "agent": { "name": "inferit-seller", "version": "…", "os": "darwin", "arch": "arm64" }, "detected": [ { "local": "qwen2.5:14b-instruct", "server": "ollama", "model": "qwen/qwen-2.5-14b-instruct", "contextLength": 32768, "quantization": "Q4_K_M", "sizeBytes": 8988110976 }, { "local": "my-finetune:latest", "server": "ollama", "model": null } ], "models": ["qwen/qwen-2.5-14b-instruct"], "offerEndpointUrl": "connector://node_…/v1" }], "connectUrl": "wss://…/v1/seller/connect" } ``` ### PATCH `/v1/seller/nodes/:id` Auth: session Body `{ name }`. Renames a machine; only its owner can. The token and the connection are unchanged. ### DELETE `/v1/seller/nodes/:id` Auth: session Revoke: the token stops working, the connection closes at once and its offers leave routing. ### GET `/v1/seller/connect` Auth: connection token The WebSocket (wss) the seller app opens in connector mode. Not for direct use: the open-source [inferit-seller](https://github.com/InferitAI/inferit-seller) app speaks its protocol (version 1). Its `hello` may carry, besides the required fields, `agent` (`{ name: "inferit-seller", version, os, arch }`) and `detected` (up to 200 entries, as in `GET /v1/seller/nodes`); an app that sends neither still connects. Both are shown to the machine's owner only; routing never reads them: the market serves the models the `hello` declares. ### GET `/v1/seller/earnings` Auth: session Settled, pending and withdrawable earnings, with the settled part split into `pendingFinalityMicro` and `finalizedMicro`. ## On-chain calls (no endpoint) Moving money in or out of the escrow is a transaction on Whitechain Sepolia, not an API call. The app sends these from your wallet; a transaction you send yourself costs gas in WBT. The contract view, with every check, is on [Whitechain escrow](https://inferit.cc/docs/payments/whitechain.md#calls). | Action | Call | Gas | | --- | --- | --- | | [Deposit and set a ceiling](https://inferit.cc/docs/payments/whitechain.md#deposit) | `approve(escrow, amount)` on ITC, then `depositAndSetCap(amount, cap, expiry)` | WBT, from your wallet | | Change the ceiling | `setSpendingCap(cap, expiry)`, or the relayed `setSpendingCapBySig` | WBT, or the relayer's | | [Withdraw a deposit](https://inferit.cc/docs/payments/whitechain.md#withdraw) | `requestWithdraw(amount)`, then `executeWithdraw()` after the delay | WBT, from your wallet | | [Register as a seller](https://inferit.cc/docs/sellers.md#steps) | `registerSeller(payout)` from the seller wallet | WBT, from your wallet | | [Withdraw seller payouts](https://inferit.cc/docs/sellers.md#payouts) | `withdrawEarnings()`, paid to the registered payout wallet | WBT, from your wallet | | [Pay with x402](https://inferit.cc/docs/payments/whitechain.md#x402) | `depositWithAuthorization`, submitted by the facilitator with your signature | None for the payer | | [Claim ITC](https://inferit.cc/docs/api-reference.md#faucet) | `POST /v1/faucet` (sponsored), or `faucet()` on ITC from your wallet | None, or WBT from your wallet | --- Canonical page: https://inferit.cc/docs/api-reference All pages as markdown: https://inferit.cc/llms.txt --- Source: https://inferit.cc/docs/guides/opencode.md # OpenCode > Use Inferit as an OpenAI-compatible provider in OpenCode, with model auto or a named model. OpenCode supports any OpenAI-compatible provider through the AI SDK's openai-compatible package, so Inferit works as a custom provider. ## 1. Get a key Create one in the [Buy workspace](https://inferit.app/buy) ([Quickstart](https://inferit.cc/docs/quickstart.md), steps 1 to 6) and export it. OpenCode reads it from the environment through `{env:…}`. ```bash export INFERIT_API_KEY='ik_...' ``` ## 2. Add the provider Put this in `opencode.json` in your project (or the global config). It lists two models: `auto`, where Inferit picks the model, and one catalog model by name. Add one entry under `models` per catalog id you want to use; ids are listed on [Models](https://inferit.app/models). Optionally, give a model a `limit` (`{"context": …, "output": …}`) so OpenCode knows how much it can send: use the largest `context_length` a healthy seller serves, from `GET /v1/models/{id}/endpoints`. The catalog's window in `GET /v1/models` can be longer than any seller serves. _opencode.json_ ``` { "$schema": "https://opencode.ai/config.json", "provider": { "inferit": { "npm": "@ai-sdk/openai-compatible", "name": "Inferit", "options": { "baseURL": "https://api-production-c74b9.up.railway.app/v1", "apiKey": "{env:INFERIT_API_KEY}" }, "models": { "auto": { "name": "Inferit auto (Inferit picks the model)", "limit": { "context": 131072, "output": 4096 } }, "qwen/qwen-2.5-14b-instruct": { "name": "qwen/qwen-2.5-14b-instruct (Inferit)" } } } }, "model": "inferit/qwen/qwen-2.5-14b-instruct" } ``` ## 3. Check it One request from the command line, without the interface: ```bash opencode run --model inferit/qwen/qwen-2.5-14b-instruct "Say hello in five words." ``` ## Model auto, or a named model With `"auto"` as the model, Inferit picks the model: the best value on a published quality ranking for this request, at that model's cheapest healthy seller ([Automatic routing](https://inferit.cc/docs/routing.md)). The response names the model that answered, in its `model` field and the `x-inferit-model` header. Auto needs a ranked model with a live seller. `GET /v1/routing` lists the models it can choose from now in `candidates_now`; while that list is empty, a request with auto answers `503 no_eligible_model`. Then name a catalog model with a live seller instead, such as `qwen/qwen-2.5-14b-instruct`, and Inferit picks the seller. The samples on this page send auto while it has a candidate, and that model otherwise. ## Optional: a discount floor To only accept offers at least 30% below list, use `https://api-production-c74b9.up.railway.app/min30/v1` as the `baseURL`. Requests with no qualifying offer fail at once with `503 no_available_offers` instead of routing to a pricier seller. ## Notes - Streaming, tool calls and other Chat Completions fields are passed through to the seller's OpenAI-compatible server unchanged. - What a model supports (tool calling, context length) depends on how the seller serves it. Each seller's context length is on the model's market page and in `GET /v1/models/{id}/endpoints`. - OpenCode needs a seller that serves a long context: its system prompt and tool definitions come to about 10,000 tokens per request, plus room for the answer. When no healthy seller of the model serves that much, Inferit answers `503` and names the largest context on offer. - OpenCode sends its own system prompt and tool definitions with every request, so even a short question carries a long input. Each request is charged at the serving seller's price; your usage log in the Buy workspace lists them. ## Checked On 2026-10-13, no live seller of `qwen/qwen-2.5-14b-instruct` served more than 8,192 tokens of context, and `opencode run` with this config was refused with `503` (no seller serves the context it asks for). It needs a seller serving a longer context (see Notes); the model's catalog window is 32,768. --- Canonical page: https://inferit.cc/docs/guides/opencode All pages as markdown: https://inferit.cc/llms.txt --- Source: https://inferit.cc/docs/guides/cursor.md # Cursor > Use Inferit models in Cursor through the OpenAI base URL override. Cursor can send chat requests for custom models to any OpenAI-compatible base URL. Inferit plugs in there. ## Setup 1. Create a key in the [Buy workspace](https://inferit.app/buy) ([Quickstart](https://inferit.cc/docs/quickstart.md), steps 1 to 6). 2. In Cursor, open **Settings → Models**. Under the OpenAI API key section, paste your `ik_…` key and enable **Override OpenAI Base URL** with `https://api-production-c74b9.up.railway.app/v1`. 3. Add a custom model whose name is an Inferit catalog id with a live offer, e.g. `qwen/qwen-2.5-14b-instruct`, and enable it. 4. Pick that model in chat and send a message. Usage appears in the Buy workspace. Your API must be publicly reachable Cursor may make these requests from its own servers rather than from your machine, so a `localhost` API typically will not work. Use a deployed API or a public HTTPS tunnel while testing. ## Limits - Cursor's menus and settings move between releases; the names above may differ slightly in your version. - Some Cursor features (for example tab completion) use Cursor's own models and do not go through a custom base URL. - The key override applies to all OpenAI-named models in Cursor while it is enabled. --- Canonical page: https://inferit.cc/docs/guides/cursor All pages as markdown: https://inferit.cc/llms.txt --- Source: https://inferit.cc/docs/guides/langchain.md # LangChain > Use Inferit from LangChain in Python and JavaScript: an API key, the OpenAI-compatible base URL, model auto or a named model, and pay per request with x402 from LangChain JS. LangChain's ChatOpenAI takes a base URL, so Inferit works as its model in Python and in JavaScript. Chains, agents and tools built on it run unchanged. ## 1. Get an API key Create a key in the [Buy workspace](https://inferit.app/buy) ([Quickstart](https://inferit.cc/docs/quickstart.md), steps 1 to 6) and export it. The key spends your prepaid balance in ITC. ```bash export INFERIT_API_KEY='ik_...' ``` The base URL is `https://api-production-c74b9.up.railway.app/v1`. Any OpenAI-compatible client works with it (chat completions, streaming included). ## 2. Python `langchain-openai`'s `ChatOpenAI` with Inferit's base URL. `model_name` in the reply's metadata is the model that answered. _chat.py_ ```python # pip install langchain-openai import os from langchain_openai import ChatOpenAI llm = ChatOpenAI( base_url="https://api-production-c74b9.up.railway.app/v1", api_key=os.environ["INFERIT_API_KEY"], model="qwen/qwen-2.5-14b-instruct", # "auto": Inferit picks the model ) reply = llm.invoke("Say hello in five words.") print(reply.content) print(reply.response_metadata.get("model_name")) # the model that answered ``` ## 3. JavaScript `@langchain/openai` takes the base URL under `configuration`, which it passes to the OpenAI client. _chat.mjs_ ```javascript // npm i @langchain/openai @langchain/core import { ChatOpenAI } from '@langchain/openai'; const llm = new ChatOpenAI({ model: 'qwen/qwen-2.5-14b-instruct', // "auto": Inferit picks the model apiKey: process.env.INFERIT_API_KEY, configuration: { baseURL: 'https://api-production-c74b9.up.railway.app/v1' }, }); const reply = await llm.invoke('Say hello in five words.'); console.log(reply.content); console.log(reply.response_metadata?.model_name); // the model that answered ``` ## Model auto, or a named model With `"auto"` as the model, Inferit picks the model: the best value on a published quality ranking for this request, at that model's cheapest healthy seller ([Automatic routing](https://inferit.cc/docs/routing.md)). The response names the model that answered, in its `model` field and the `x-inferit-model` header. Auto needs a ranked model with a live seller. `GET /v1/routing` lists the models it can choose from now in `candidates_now`; while that list is empty, a request with auto answers `503 no_eligible_model`. Then name a catalog model with a live seller instead, such as `qwen/qwen-2.5-14b-instruct`, and Inferit picks the seller. The samples on this page send auto while it has a candidate, and that model otherwise. ## Pay per request with x402 (JavaScript) With no API key, LangChain JS can pay for each request with x402: give the OpenAI client a `fetch` that answers the API's `402` with the standard x402 v2 client. The OpenAI client always sends an `Authorization` header, so the wrapper removes it first; with it, the API would read the request as an API-key call. Each payment is at least 0.01 ITC, is credited to the paying address's balance, and each request is charged its exact cost ([agents.md](https://inferit.cc/agents.md), [API reference](https://inferit.cc/docs/api-reference.md#x402)). The client caps one payment at 1 ITC; that is a setting in your client, not a rule of the contract. _chat-x402.mts_ ```typescript // npm i @langchain/openai @langchain/core @x402/fetch @x402/evm viem import { ChatOpenAI } from '@langchain/openai'; import { wrapFetchWithPayment, x402Client } from '@x402/fetch'; import { ExactEvmScheme } from '@x402/evm/exact/client'; import { generatePrivateKey, privateKeyToAccount } from 'viem/accounts'; const account = privateKeyToAccount((process.env.AGENT_KEY ?? generatePrivateKey()) as `0x${string}`); // Inferit's faucet gives this address 1,000 free ITC (the claim costs nothing). await fetch('https://api-production-c74b9.up.railway.app/v1/faucet', { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify({ address: account.address }), }); // The standard x402 v2 client pays only in tokens it was told about: allow ITC, // and cap one payment at 1 ITC (1000000 base units, 6 decimals). const ITC = { network: 'eip155:1874', asset: '0x2E672dFE33EA977FD064E01aDe7d8c73B3Be7fBB' } as const; const client = new x402Client() .register('eip155:*', new ExactEvmScheme(account)) .setSpendControls({ allowedAssets: [{ ...ITC, maxAmountPerPayment: '1000000' }] }); const paidFetch = wrapFetchWithPayment(fetch, client); // The OpenAI client always sends an Authorization header. Drop it, so the API // answers with a 402 quote, which paidFetch pays and retries with PAYMENT-SIGNATURE. const x402Fetch: typeof fetch = (input, init = {}) => { const headers = new Headers(init.headers); headers.delete('authorization'); return paidFetch(input, { ...init, headers }); }; const llm = new ChatOpenAI({ model: 'qwen/qwen-2.5-14b-instruct', apiKey: 'x402', // never sent: x402Fetch removes it maxTokens: 64, // the quote is the worst case for this body: a small limit keeps it small configuration: { baseURL: 'https://api-production-c74b9.up.railway.app/v1', fetch: x402Fetch }, }); console.log((await llm.invoke('Say hello in five words.')).content); ``` The x402 sample is JavaScript only. From Python, the exchange can be signed by hand, as in the Python sample on [Agents](https://inferit.cc/agents); or use an API key. ## Checked The Python and JavaScript samples (with an API key) ran against the hosted API on 2026-10-13, with a named model (auto had no candidate that day). The x402 variant was run up to the API's `402` quote: the request reached the API with no `Authorization` header and the x402 client read the quote. The paid retry is the same exchange as on [Agents](https://inferit.cc/agents). --- Canonical page: https://inferit.cc/docs/guides/langchain All pages as markdown: https://inferit.cc/llms.txt --- Source: https://inferit.cc/docs/guides/vercel-ai-sdk.md # Vercel AI SDK > Use Inferit from the Vercel AI SDK as an OpenAI-compatible provider: an API key, the base URL, model auto or a named model, and pay per request with x402 through a custom fetch. The AI SDK's OpenAI-compatible provider takes a base URL, a key and, optionally, a fetch of your own. With Inferit's base URL, generateText, streamText and the rest work as with any provider. ## 1. Get an API key Create a key in the [Buy workspace](https://inferit.app/buy) ([Quickstart](https://inferit.cc/docs/quickstart.md), steps 1 to 6) and export it. The key spends your prepaid balance in ITC. ```bash export INFERIT_API_KEY='ik_...' ``` The base URL is `https://api-production-c74b9.up.railway.app/v1`. Any OpenAI-compatible client works with it (chat completions, streaming included). ## 2. Add Inferit as a provider `createOpenAICompatible` from `@ai-sdk/openai-compatible`, with Inferit's base URL and your key. `response.modelId` is the model that answered. _chat.mjs_ ```javascript // npm i ai @ai-sdk/openai-compatible import { createOpenAICompatible } from '@ai-sdk/openai-compatible'; import { generateText } from 'ai'; const inferit = createOpenAICompatible({ name: 'inferit', baseURL: 'https://api-production-c74b9.up.railway.app/v1', apiKey: process.env.INFERIT_API_KEY, }); const { text, response } = await generateText({ model: inferit('qwen/qwen-2.5-14b-instruct'), // "auto": Inferit picks the model prompt: 'Say hello in five words.', }); console.log(text); console.log(response.modelId); // the model that answered ``` ## Model auto, or a named model With `"auto"` as the model, Inferit picks the model: the best value on a published quality ranking for this request, at that model's cheapest healthy seller ([Automatic routing](https://inferit.cc/docs/routing.md)). The response names the model that answered, in its `model` field and the `x-inferit-model` header. Auto needs a ranked model with a live seller. `GET /v1/routing` lists the models it can choose from now in `candidates_now`; while that list is empty, a request with auto answers `503 no_eligible_model`. Then name a catalog model with a live seller instead, such as `qwen/qwen-2.5-14b-instruct`, and Inferit picks the seller. The samples on this page send auto while it has a candidate, and that model otherwise. ## Pay per request with x402 With no API key, the provider can pay for each request with x402. Leave out `apiKey`, so no `Authorization` header is sent and the API answers with a `402` quote, and pass the standard x402 v2 client's fetch as the provider's `fetch`: it signs the quote and resends the same body. Each payment is at least 0.01 ITC, is credited to the paying address's balance, and each request is charged its exact cost ([agents.md](https://inferit.cc/agents.md), [API reference](https://inferit.cc/docs/api-reference.md#x402)). The client caps one payment at 1 ITC; that is a setting in your client, not a rule of the contract. _chat-x402.mts_ ```typescript // npm i ai @ai-sdk/openai-compatible @x402/fetch @x402/evm viem import { createOpenAICompatible } from '@ai-sdk/openai-compatible'; import { wrapFetchWithPayment, x402Client } from '@x402/fetch'; import { ExactEvmScheme } from '@x402/evm/exact/client'; import { generateText } from 'ai'; import { generatePrivateKey, privateKeyToAccount } from 'viem/accounts'; const account = privateKeyToAccount((process.env.AGENT_KEY ?? generatePrivateKey()) as `0x${string}`); // Inferit's faucet gives this address 1,000 free ITC (the claim costs nothing). await fetch('https://api-production-c74b9.up.railway.app/v1/faucet', { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify({ address: account.address }), }); // The standard x402 v2 client pays only in tokens it was told about: allow ITC, // and cap one payment at 1 ITC (1000000 base units, 6 decimals). const ITC = { network: 'eip155:1874', asset: '0x2E672dFE33EA977FD064E01aDe7d8c73B3Be7fBB' } as const; const client = new x402Client() .register('eip155:*', new ExactEvmScheme(account)) .setSpendControls({ allowedAssets: [{ ...ITC, maxAmountPerPayment: '1000000' }] }); const paidFetch = wrapFetchWithPayment(fetch, client); // No apiKey: the provider sends no Authorization header, so the API answers with // a 402 quote, which paidFetch pays and retries with PAYMENT-SIGNATURE. const inferit = createOpenAICompatible({ name: 'inferit', baseURL: 'https://api-production-c74b9.up.railway.app/v1', fetch: paidFetch }); const { text } = await generateText({ model: inferit('qwen/qwen-2.5-14b-instruct'), prompt: 'Say hello in five words.', maxOutputTokens: 64, // the quote is the worst case for this body: a small limit keeps it small }); console.log(text); ``` `streamText` works the same way: the payment is settled before the stream starts. ## Checked The API-key sample ran against the hosted API on 2026-10-13, with a named model (auto had no candidate that day). The x402 variant was run up to the API's `402` quote: the request reached the API with no `Authorization` header and the x402 client read the quote. The paid retry is the same exchange as on [Agents](https://inferit.cc/agents). --- Canonical page: https://inferit.cc/docs/guides/vercel-ai-sdk All pages as markdown: https://inferit.cc/llms.txt --- Source: https://inferit.cc/docs/guides/litellm.md # LiteLLM > Use Inferit from LiteLLM: the SDK call with the openai/ prefix and Inferit’s base URL, and a proxy config with model auto and a named model. LiteLLM sends any model whose name starts with openai/ to an OpenAI-compatible base URL, so Inferit works in the LiteLLM SDK and behind the LiteLLM proxy. ## 1. Get an API key Create a key in the [Buy workspace](https://inferit.app/buy) ([Quickstart](https://inferit.cc/docs/quickstart.md), steps 1 to 6) and export it. The key spends your prepaid balance in ITC. ```bash export INFERIT_API_KEY='ik_...' ``` The base URL is `https://api-production-c74b9.up.railway.app/v1`. Any OpenAI-compatible client works with it (chat completions, streaming included). ## 2. The SDK Prefix the Inferit model id with `openai/`: LiteLLM strips the prefix and sends the rest unchanged, slashes included (`openai/qwen/qwen-2.5-14b-instruct` sends `qwen/qwen-2.5-14b-instruct`). `response.model` is the model that answered. _chat.py_ ```python # pip install litellm import os import litellm # "openai/" tells LiteLLM to send the rest of the name, unchanged, to an # OpenAI-compatible base URL. "auto": Inferit picks the model. response = litellm.completion( model="openai/qwen/qwen-2.5-14b-instruct", api_base="https://api-production-c74b9.up.railway.app/v1", api_key=os.environ["INFERIT_API_KEY"], messages=[{"role": "user", "content": "Say hello in five words."}], ) print(response.choices[0].message.content) print(response.model) # the model that answered ``` ## 3. The proxy To give several apps one endpoint, list Inferit in the proxy's config: one entry for model auto and one per catalog model you want to name. The proxy reads your Inferit key from `INFERIT_API_KEY`. It also needs a master key of its own (`LITELLM_MASTER_KEY`), which your apps send to it: recent LiteLLM versions refuse to start the proxy without one. _config.yaml_ ```yaml # litellm --config config.yaml (pip install 'litellm[proxy]') general_settings: master_key: os.environ/LITELLM_MASTER_KEY # what your apps send to the proxy model_list: - model_name: inferit-auto # Inferit picks the model litellm_params: model: openai/auto api_base: https://api-production-c74b9.up.railway.app/v1 api_key: os.environ/INFERIT_API_KEY - model_name: inferit-named # one catalog model; Inferit picks the seller litellm_params: model: openai/qwen/qwen-2.5-14b-instruct api_base: https://api-production-c74b9.up.railway.app/v1 api_key: os.environ/INFERIT_API_KEY ``` _call the proxy_ ```bash curl http://localhost:4000/v1/chat/completions \ -H "Authorization: Bearer $LITELLM_MASTER_KEY" \ -H 'content-type: application/json' \ -d '{"model":"inferit-named","messages":[{"role":"user","content":"Say hello in five words."}]}' ``` ## Model auto, or a named model With `"auto"` as the model, Inferit picks the model: the best value on a published quality ranking for this request, at that model's cheapest healthy seller ([Automatic routing](https://inferit.cc/docs/routing.md)). The response names the model that answered, in its `model` field and the `x-inferit-model` header. Auto needs a ranked model with a live seller. `GET /v1/routing` lists the models it can choose from now in `candidates_now`; while that list is empty, a request with auto answers `503 no_eligible_model`. Then name a catalog model with a live seller instead, such as `qwen/qwen-2.5-14b-instruct`, and Inferit picks the seller. The samples on this page send auto while it has a candidate, and that model otherwise. This guide pays with an API key. To pay per request with x402 and no key, see [Agents](https://inferit.cc/agents). ## Checked The SDK sample and the proxy config ran against the hosted API on 2026-10-13, with a named model (auto had no candidate that day). --- Canonical page: https://inferit.cc/docs/guides/litellm All pages as markdown: https://inferit.cc/llms.txt --- Source: https://inferit.cc/docs/guides/crewai.md # CrewAI > Use Inferit as the model of CrewAI agents: an LLM with Inferit’s base URL and API key, with model auto or a named model. CrewAI's LLM class takes a base URL and a key, so each agent in a crew can run on Inferit. ## 1. Get an API key Create a key in the [Buy workspace](https://inferit.app/buy) ([Quickstart](https://inferit.cc/docs/quickstart.md), steps 1 to 6) and export it. The key spends your prepaid balance in ITC. ```bash export INFERIT_API_KEY='ik_...' ``` The base URL is `https://api-production-c74b9.up.railway.app/v1`. Any OpenAI-compatible client works with it (chat completions, streaming included). ## 2. Give your agents an Inferit LLM Prefix the Inferit model id with `openai/`, so CrewAI uses its OpenAI-compatible client, and pass Inferit's base URL and your key. Agents that share one `LLM` share its model; give an agent its own `LLM` to send it to another model. _crew.py_ ```python # pip install crewai import os from crewai import LLM, Agent, Crew, Task llm = LLM( model="openai/qwen/qwen-2.5-14b-instruct", # "auto": Inferit picks the model base_url="https://api-production-c74b9.up.railway.app/v1", api_key=os.environ["INFERIT_API_KEY"], ) greeter = Agent( role="Greeter", goal="Greet people in as few words as possible", backstory="You write very short greetings.", llm=llm, ) task = Task(description="Say hello in five words.", expected_output="A five-word greeting.", agent=greeter) print(Crew(agents=[greeter], tasks=[task]).kickoff()) ``` ## Model auto, or a named model With `"auto"` as the model, Inferit picks the model: the best value on a published quality ranking for this request, at that model's cheapest healthy seller ([Automatic routing](https://inferit.cc/docs/routing.md)). The response names the model that answered, in its `model` field and the `x-inferit-model` header. Auto needs a ranked model with a live seller. `GET /v1/routing` lists the models it can choose from now in `candidates_now`; while that list is empty, a request with auto answers `503 no_eligible_model`. Then name a catalog model with a live seller instead, such as `qwen/qwen-2.5-14b-instruct`, and Inferit picks the seller. The samples on this page send auto while it has a candidate, and that model otherwise. ## Notes - A crew sends several requests per task (the agent's reasoning steps, tool calls, retries). Each is priced and charged on its own; your usage log in the [Buy workspace](https://inferit.app/buy) lists every one. - Tools need a model and a seller that serve tool calls; what a model supports depends on how its seller serves it. - This guide pays with an API key. To pay per request with x402 and no key, see [Agents](https://inferit.cc/agents). ## Checked The crew above ran against the hosted API on 2026-10-13, with a named model (auto had no candidate that day). --- Canonical page: https://inferit.cc/docs/guides/crewai All pages as markdown: https://inferit.cc/llms.txt --- Source: https://inferit.cc/docs/payments/whitechain.md # Whitechain escrow > How the MarketEscrow contract on Whitechain Sepolia bounds what the operator can settle from a buyer, how x402 payments and gasless deposits credit the signer, who pays gas, and the live parameters. Inferit settles on Whitechain. Buyer funds sit in the MarketEscrow contract; the operator settles usage in batches, but only inside limits the buyer set and the contract is designed to enforce. ## Network Whitechain Sepolia is an OP Stack L2: chain id `1874`, RPC `https://rpc.testnet.whitechain.io`, explorer [explorer.testnet.whitechain.io](https://explorer.testnet.whitechain.io). Gas is paid in WBT, Whitechain's native token, from the [Whitechain faucet](https://faucet.testnet.whitechain.io). You need WBT only for transactions you send yourself: deposits, seller registration and withdrawals. The settlement token is **ITC (Inferit Test Credit)**, the credit you pay for inference with. It has 6 decimals, so one base unit is exactly one µ ($0.000001 = 0.000001 ITC), and 1 ITC counts as one dollar in prices. Inferit's ITC faucet gives 1,000 ITC per address per 24 h, free, and the token enforces the limit. The API's sponsored faucet ([`POST /v1/faucet`](https://inferit.cc/docs/api-reference.md#faucet)) mints with `faucetTo(address)` and pays the gas, so the claim needs no WBT. The token's own `faucet()` also works, sent from your wallet, so it uses a little WBT. - **Network name**: Whitechain Sepolia - **Chain ID**: 1874 - **RPC URL**: https://rpc.testnet.whitechain.io - **Currency symbol (gas)**: WBT - **Block explorer**: https://explorer.testnet.whitechain.io - **ITC token (6 decimals)**: 0x2E672dFE33EA977FD064E01aDe7d8c73B3Be7fBB [Open the Buy workspace](https://inferit.app/buy) ### Live deployment Read from the contract itself, so this always matches what is deployed. Every address below links to Blockscout, where the escrow's verified source and every transaction can be checked. Whitechain Sepolia, chain id 1874, as deployed on 2026-10-04 (the page reads the live values from the contract): | Contract or role | Address | | --- | --- | | MarketEscrow v0.3 | [0x705dD9eCffa888FbcF2849eAE2D3b136eb78B7e0](https://explorer.testnet.whitechain.io/address/0x705dD9eCffa888FbcF2849eAE2D3b136eb78B7e0) | | ITC (6 decimals) | [0x2E672dFE33EA977FD064E01aDe7d8c73B3Be7fBB](https://explorer.testnet.whitechain.io/address/0x2E672dFE33EA977FD064E01aDe7d8c73B3Be7fBB) | | Owner and fee recipient (2-of-3 Safe) | [0x69ADd11c8c12C26bbB5be93a330853C4eac7F18b](https://explorer.testnet.whitechain.io/address/0x69ADd11c8c12C26bbB5be93a330853C4eac7F18b) | | Guardian (can only pause) | [0x4fF520e5fA18dcfC67E2c14cf81172c0CE2F1Bf0](https://explorer.testnet.whitechain.io/address/0x4fF520e5fA18dcfC67E2c14cf81172c0CE2F1Bf0) | | Settlement operator (the API's hot key; can only settle) | [0x639C007216D1020d6448d60E695F199a0d4404Ab](https://explorer.testnet.whitechain.io/address/0x639C007216D1020d6448d60E695F199a0d4404Ab) | | x402 facilitator key (pays gas only; no role in the escrow) | [0xc8c8E79E2547ba1D81FAC12c84867B1DbD83e602](https://explorer.testnet.whitechain.io/address/0xc8c8E79E2547ba1D81FAC12c84867B1DbD83e602) | | Parameter | Value | | --- | --- | | `operatorDelay` | 24 h | | `settleLimit` | 1,000 ITC per 3,600 s | | `withdrawDelay` | 1 h | | `maxFeeBps` | 1000 (10%, immutable) | | `AUTH_CREDIT_TTL` | 30 days | ## Roles and limits - **Owner: a 2-of-3 Safe.** Sets the fee recipient, the guardian and the settlement limit, proposes operator changes, and unpauses. It cannot move buyer funds or change the fee cap or the withdrawal delay. Ownership changes are two-step. One team member holds all three signer keys. - **Operator** (the API's hot key): can call `settle` within the rules below and, in v0.3, credit a front-run x402 authorization to its signer out of the escrow's unattributed balance ([below](https://inferit.cc/docs/payments/whitechain.md#x402)); nothing else. A new operator takes effect only after a timelock (24 h on the hosted deployment), so a compromised admin key cannot swap it instantly. - **Guardian**: can pause deposits and settlement in an emergency, nothing else. Only the owner can unpause. - **Circuit breaker**: the total the operator can settle per window, across all buyers, is capped by `settleLimit`. A leaked operator key can therefore settle at most each buyer's remaining cap, and no more than the window limit in total, before the owner pauses it. - **Sellers**: register and change their payout from their own wallet only. No API key can redirect earnings. - **Facilitator key** (v0.3, the API's second hot key, separate from the operator): submits x402 payments with `depositWithAuthorization` and mints sponsored ITC with `faucetTo`. Anyone may make those two calls, so the key has no role in the escrow: it pays gas and nothing else. It cannot settle, and it cannot send a payment anywhere but the signer's own escrow balance. ## Calls _MarketEscrow / TestCredit_ ``` // buyer TestCredit.approve(escrow, amount) // ITC, 6 decimals MarketEscrow.depositAndSetCap(amount, cap, expiry) // or deposit() + setSpendingCap() MarketEscrow.depositWithPermit(buyer, amount, cap, expiry, deadline, v, r, s, termsSignature) // v0.3: gasless, relayed (EIP-2612) MarketEscrow.depositWithAuthorization(from, value, validAfter, validBefore, nonce, v, r, s) // v0.3: x402 (EIP-3009) MarketEscrow.requestWithdraw(amount) // starts the delay MarketEscrow.executeWithdraw() // after withdrawDelay; cancelWithdraw() also available // seller MarketEscrow.registerSeller(payout) // from the seller wallet; payout = msg.sender if zero MarketEscrow.withdrawEarnings() // pays the registered payout // views buyerState(buyer) -> (deposit, cap, spent, expiry, pendingWithdraw, withdrawReadyAt) sellerState(seller) -> (registered, payout, earnings) ``` ## Deposits and the spending cap A buyer deposits with two transactions from its own wallet, so both cost a little WBT: `approve` on the ITC token, then `depositAndSetCap(amount, cap, expiry)`. The deposit stays the buyer's until it is settled or withdrawn. The cap (the ceiling) is the total the operator may ever settle from you, counted cumulatively from `spent`. Setting it again replaces the cap but keeps `spent`, so raising a 100 ITC cap to 150 after spending 40 leaves 110 of headroom. After `expiry`, nothing more can be settled from you until you set a new cap, so the API stops accepting new usage a settlement margin (at least five minutes) before the expiry. The app suggests a cap equal to your deposit, at most 25 ITC, expiring in 7 days. A relayed, gasless variant (`setSpendingCapBySig`, EIP-712) exists for wallets that cannot send transactions. ## x402 and gasless deposits (v0.3) `MarketEscrow` v0.3 adds two ways to deposit without the buyer sending a transaction. Both are relayed: someone else submits the buyer's signature and pays the gas. Both are blocked while the escrow is paused, like every deposit. Agents should start at [Agents](https://inferit.cc/agents) or [agents.md](https://inferit.cc/agents.md); this section is the contract view. ### depositWithAuthorization (x402) The buyer signs an EIP-3009 `TransferWithAuthorization` for the token, naming the escrow as the recipient. This is exactly what a standard x402 client signs for the `exact` scheme. The API's facilitator submits it: _MarketEscrow.depositWithAuthorization (v0.3)_ ``` depositWithAuthorization(from, value, validAfter, validBefore, nonce, v, r, s) // blocked while paused require (from, nonce) not credited before // authorizationCredited(from, nonce) if token.authorizationState(from, nonce) is unused: // the normal path: anyone may call (the facilitator does) token.transferWithAuthorization(from, escrow, value, validAfter, validBefore, nonce, v, r, s) // the token checks the signature, the validity window and the nonce; // a signature that names any other recipient fails else: // recovery: the token already executed it require caller is the operator or the owner require the signature recovers to "from" over TransferWithAuthorization(from, to = escrow, ...) under token.DOMAIN_SEPARATOR() require unattributedBalance() >= value // balance - (totalDeposits + totalEarnings + feeAccrued) // recovered = true credit "from": deposit += value cap += value; expiry = max(expiry, now + AUTH_CREDIT_TTL) // if the old cap had expired: cap = spent + value, expiry = now + AUTH_CREDIT_TTL emit Deposited(from, value), SpendingCapSet(from, cap, expiry), DepositedWithAuthorization(from, value, nonce, recovered) ``` - **Credited to the signer, for spending.** The payment raises both the deposit and the cap by `value`, so the operator can settle the request it paid for. It also pushes the cap's expiry to at least now + `AUTH_CREDIT_TTL`, an immutable constructor parameter (30 days by default). Money paid through x402 is meant to be spent, so it is never stranded behind an expired cap. Whatever the request does not use stays as the buyer's balance, withdrawable like any deposit. - **A prepaid meter, not a payment per µ.** x402 amounts are in token base units, so a payment of 1 µ is expressible. But each payment is an on-chain transaction that costs gas, so the API asks for at least 0.01 ITC (10 000 µ) per payment. The payment tops up the payer's escrow balance; each request is charged its exact µ cost against it, and settlement to sellers is batched. - **If the old cap had expired,** the payment starts fresh terms: the cap becomes `spent + value`, so headroom the buyer let lapse is not revived. Like any cap change it uses up the buyer's escrow nonce, so an outstanding `setSpendingCapBySig` signature stops being valid. - **Front-running cannot steal a payment.** An authorization is public once it is sent. If someone submits it to the token's `transferWithAuthorization` directly, the tokens still land in the escrow, because the signature fixes the recipient. They are not attributed to anyone yet, and nobody can withdraw them. The **operator or the owner** then credits them to the signer with the same call (`recovered = true`). The escrow checks the signature itself, that the same `(from, nonce)` was never credited, and that the unattributed balance covers the amount. Recovery is limited to those two roles because the token cannot tell a used authorization from a cancelled one; they first check that the token's `AuthorizationUsed` came with a transfer to the escrow in the same transaction. For a payment the API is serving, it runs that check and sends the recovery from the operator key itself, then serves the request. - **Solvency.** v0.3 holds `token.balanceOf(escrow) ≥ totalDeposits + totalEarnings + feeAccrued`, and all three are readable on chain. The difference is `unattributedBalance()`. It grows only when tokens are sent to the escrow directly, such as a front-run authorization, and only a recovered credit can attribute it. - **Token.** ITC v2 (TestCredit) implements EIP-3009 like Circle's FiatToken v2: `transferWithAuthorization`, `receiveWithAuthorization`, `cancelAuthorization`, `authorizationState`, with one EIP-712 domain (name "Inferit Test Credit", version "1") shared with EIP-2612 `permit`. A prepaid balance charged by the µ: a worked example at example prices | Line | What | Amount | | --- | --- | --- | | Prepaid | One x402 payment, the minimum | $0.01 | | Request | One request · 1,000 in · 500 out | minus $0.000168 | | Balance | Stays yours: spend it or withdraw it | $0.009832 | Settled. The seller is paid its share of the $0.000168 in the next batch on Whitechain Sepolia: one transaction, one line per seller. Example: a seller asking $0.08 / $0.16 per 1M tokens before the fee. 1,000 input and 500 output tokens cost $0.00016 plus the 5% fee, $0.000008: $0.000168. $0.000001 is a millionth of an ITC. ### depositWithPermit (gasless deposit) The buyer signs two messages and sends no transaction: an EIP-2612 `permit` that lets the escrow pull the amount, and the deposit terms (amount, cap, expiry) under the escrow's own EIP-712 domain. A relayer submits both and pays the gas: _MarketEscrow.depositWithPermit (v0.3)_ ``` depositWithPermit(buyer, amount, cap, expiry, deadline, v, r, s, termsSignature) // blocked while paused if caller != buyer: // relayed: the buyer also signs the terms require termsSignature is buyer's EIP-712 signature (the escrow's domain) over DepositWithPermit(buyer, amount, cap, expiry, nonce = nonces(buyer), deadline) token.permit(buyer, escrow, amount, deadline, v, r, s) // EIP-2612; a permit someone already submitted is tolerated require token.allowance(buyer, escrow) >= amount pull amount from buyer, credit it as buyer's deposit set buyer's cap and expiry, as depositAndSetCap does // consumes buyer's escrow nonce ``` This is the gasless version of `depositAndSetCap`. The cap and expiry are the ones the buyer signed, so a relayer or a front-runner cannot choose them, and the usual rules for raising and lowering a cap apply. It needs a token with `permit`: ITC v2 has it. The Buy workspace deposits with `depositAndSetCap`. ### The facilitator key The hosted API submits x402 payments, and sponsored faucet mints for agents that hold no WBT (`faucetTo`), from `WHITECHAIN_FACILITATOR_KEY`. It is a hot key separate from the settlement operator, funded with WBT for gas only. It has no role in the escrow, so a leak costs at most its WBT. Every payment it submits is still credited to the wallet that signed it. It cannot recover a front-run authorization; that takes the operator or the owner. The operator's bounds (caps, registered sellers, the fee cap, the circuit breaker) are unchanged. ## Settlement The API meters each request in µ (a micro-ITC) and groups unsettled charges into batches. A buyer is settled once their unsettled usage reaches 0.10 ITC or their oldest charge reaches the maximum age, whichever comes first (by default 1 hour; the cadence a server runs is in `GET /metrics`, `settlement.cadence`), and at once when a withdrawal, a lower cap or the cap's expiry is near. Each batch is one `settle` transaction: _checks the contract performs_ ``` settle(bytes32 batchId, Line[] lines) // operator only Line { buyer, seller, sellerAmount, fee } require seller is registered require fee * 10_000 <= sellerAmount * maxFeeBps // maxFeeBps immutable, <= 1000 (10%) require block.timestamp <= buyer.expiry require buyer.spent + sellerAmount + fee <= buyer.cap require buyer.deposit >= total for the buyer require settled in this window + batch total <= settleLimit // circuit breaker require batchId not used before // idempotent // any failing line reverts the whole batch ``` Effects: your deposit is debited, the seller's earnings credited and the fee accrued, with `LineSettled` and `BatchSettled` events. Your own escrow events, with explorer links, are in the [Buy workspace](https://inferit.app/buy). ## Finality Whitechain is an OP Stack L2. A settlement is first included by the sequencer (unsafe, a soft confirmation), becomes safe once its batch is posted to Ethereum (typically within about 30 minutes), and finalized once that Ethereum block is final (about 13 minutes later). Only finalized is irreversible; "pending finality" means included but not yet finalized. The site shows each settlement as **pending finality** until its block is at or below the chain's finalized head, then as **finalized**. ## Who pays gas - Buyers: `approve` and `depositAndSetCap`, an ITC `faucet()` claim sent from their own wallet, and withdrawals. - Sellers: `registerSeller` and `withdrawEarnings`. - The operator: every `settle` batch. Buyers do not pay gas per request. - The facilitator key (v0.3): every x402 payment (`depositWithAuthorization`) and every sponsored faucet mint. An agent paying with x402 needs no WBT at all until it wants to withdraw. A relayed `depositWithPermit` is paid for by whoever relays it. Gas on an OP Stack chain includes a small L1 data fee, paid in WBT like the rest of the gas. ## What is public Everything in the escrow is public chain data. `LineSettled` names the buyer and seller addresses of every line with its amounts, `buyerState` and `sellerState` show any account's deposit, cap, spent and earnings, and `SellerRegistered` links a seller to its payout address. Anyone can list sellers and their volume, and a buyer can match its own requests to the seller that served them. See [On-chain visibility](https://inferit.cc/docs/security-trust.md#on-chain). x402 payments are public too: each one is a `DepositedWithAuthorization` event naming the paying wallet, and its settlement lines are ordinary `LineSettled` events. ## Withdrawals `requestWithdraw` starts a fixed delay (immutable per deployment; see the live value above). Usage you already consumed can still settle during the delay, which is what lets the API serve requests before they settle. After the delay, `executeWithdraw` returns the funds. The contract is designed so withdrawals keep working while deposits and settlement are paused. See [Security & trust](https://inferit.cc/docs/security-trust.md) for what this does and does not protect against. --- Canonical page: https://inferit.cc/docs/payments/whitechain All pages as markdown: https://inferit.cc/llms.txt --- Source: https://inferit.cc/docs/payments/stellar.md # Pay on Stellar > How an agent pays Inferit per request with x402 on Stellar: the network, the ITC asset and its contract, free XLM and the trustline, the faucet, the client code, where the balance is kept and the limits. An agent can pay Inferit per request with x402 on Stellar: one transfer of ITC to Inferit's treasury account, signed by the agent, with the network fee paid by Inferit. No account with Inferit and no API key. ## Network x402 names the network `stellar:testnet` (a CAIP-2 id). Every payment is signed for its passphrase. The 402 lists one entry per network Inferit takes payments on: Whitechain (`eip155:1874`) and Stellar. A client that registers only the Stellar scheme pays with the Stellar entry. | What | Value | | --- | --- | | Network id | `stellar:testnet` | | Passphrase | `Test SDF Network ; September 2015` | | Soroban RPC | `https://soroban-testnet.stellar.org` | | Horizon | `https://horizon-testnet.stellar.org` | | Explorer | [stellar.expert/explorer/testnet](https://stellar.expert/explorer/testnet) | | Free XLM for a new account | `https://friendbot.stellar.org?addr=G…` (friendbot) | ## The asset Payments on Stellar are in ITC, the same credit Inferit prices in on Whitechain: one ITC is one dollar of price. On Stellar, ITC is a classic asset issued by Inferit's issuing account, and x402 moves it through its Stellar Asset Contract (the asset's contract address, `C…`). The contract is derived from the asset itself: `new Asset(code, issuer).contractId(passphrase)` in stellar-sdk. So a client can check the contract it is asked to pay against the code and issuer it pinned. ITC on Stellar has 7 decimals; Inferit's API amounts are whole millionths of a dollar (6 decimals). So the API asks for 10 base units per millionth of a dollar: the minimum payment, $0.01 (10,000 millionths), is `"100000"` on Stellar. What arrives is credited as the base units divided by 10, rounded down, so an amount below 10 base units is never credited. One ITC is 10,000,000 base units. ### Live values Read from `GET /v1/rails` (the rail with `"id": "stellar"`), so this always matches the API. Each address links to the explorer. ## A payer account 1. **A key.** Any ed25519 Stellar key: its public key (`G…`) is the payer. `Keypair.random()` in stellar-sdk makes one, and `createEd25519Signer` from `@x402/stellar` signs with it. Stellar addresses are case-sensitive: never lower-case one. 2. **Free XLM.** Friendbot creates the account with free XLM: `https://friendbot.stellar.org?addr=G…`. The XLM pays the account's reserve and the trustline below. x402 payments cost the agent no XLM: Inferit pays their network fee. 3. **A trustline to ITC.** A Stellar account holds an asset only after it opts in: one `changeTrust` operation for ITC, with the code and issuer from `GET /v1/rails`. 4. **ITC from Inferit's faucet.** `POST /v1/faucet/stellar` with `{"address":"G…"}` sends ITC to the address, once per address per 24 h, at no charge. Without the trustline the faucet answers with an error that says how to add it. It sends to `G…` accounts only, the accounts x402 payments here come from. ## How a payment works 1. Call `POST /v1/chat/completions` with no `Authorization` header. It answers `402 Payment Required`; the `PAYMENT-REQUIRED` header (base64 JSON) and the body carry the same document. Its Stellar entry in `accepts`: scheme `exact`, network `stellar:testnet`, `asset` = the ITC contract (`C…`), `payTo` = Inferit's treasury account (`G…`), `amount` in base units, `maxTimeoutSeconds`, and `extra.areFeesSponsored: true`. 2. The amount is the worst-case cost of this exact request body, as on Whitechain: the input estimate plus the output limit, all-in, and never less than $0.01; then times 10 for the 7 decimals. The quote is pinned for 120 s. The transfer must be exactly this amount. 3. The client builds the contract call `transfer(from, payTo, amount)` on the ITC contract, simulates it, and signs only its authorization entry. The signature is valid until a ledger number: the current ledger plus `maxTimeoutSeconds` divided by about 5 seconds a ledger. It resends the same body with the transaction in the `PAYMENT-SIGNATURE` header. 4. Inferit's API checks the payment with the official x402 facilitator code (`@x402/stellar@2.28.0`): one transfer, of ITC, from the signer to the treasury, of exactly the amount, on this network, before its ledger expiry. It then wraps the transaction in one from its own fee-payer account, pays the fee in XLM and submits it. If the payment does not verify, the API answers 402 again, with the reason in `error`. 5. Once the transfer is in a ledger, it is credited to the payer's balance with Inferit: base units divided by 10, rounded down. Each payment is credited once; a replayed payment is refused. 6. The request is served (streaming included) and charged its exact cost against that balance, never more than this one payment. The response carries `PAYMENT-RESPONSE` (base64: the Stellar transaction hash, the network and the payer) and `x-inferit-buyer-cost-micro`, the cost in millionths of a dollar. 7. Every call without a key gets its own 402 and its own payment, and is charged against that payment only: what a payment does not spend adds to your balance ([spending it](https://inferit.cc/docs/payments/stellar.md#balance)). ## The client code ### TypeScript, with the official x402 fetch client A brand-new key works: friendbot funds the account, the faucet gives it ITC, and the agent never pays a network fee for a payment. Pinned versions: `@x402/fetch@2.28.0`, `@x402/stellar@2.28.0` and `@stellar/stellar-sdk@16.4.1`. _agent.mts_ ```typescript // npm i @x402/fetch@2.28.0 @x402/stellar@2.28.0 @stellar/stellar-sdk@16.4.1 // then: npx tsx agent.mts (Node 22+) import { Asset, BASE_FEE, Horizon, Keypair, Networks, Operation, TransactionBuilder } from '@stellar/stellar-sdk'; import { decodePaymentResponseHeader, wrapFetchWithPayment, x402Client } from '@x402/fetch'; import { createEd25519Signer } from '@x402/stellar'; import { ExactStellarScheme } from '@x402/stellar/exact/client'; const API = 'https://api-production-c74b9.up.railway.app'; const NETWORK = 'stellar:testnet'; // pinned: the one network this agent pays on const horizon = new Horizon.Server('https://horizon-testnet.stellar.org'); // A brand-new key works: friendbot gives it free XLM, and Inferit pays the network fee of every payment. // Your balance with Inferit belongs to the key that pays: set STELLAR_SECRET_KEY to keep using one (the key you sign in // with on Inferit, to see and spend that balance). const keypair = process.env.STELLAR_SECRET_KEY ? Keypair.fromSecret(process.env.STELLAR_SECRET_KEY) : Keypair.random(); const address = keypair.publicKey(); // case-sensitive: never lower-case a Stellar address if (!process.env.STELLAR_SECRET_KEY) console.log('new key', address, '- keep it to reuse its balance: STELLAR_SECRET_KEY=' + keypair.secret()); // 1. The asset: code and issuer from the API, its contract checked against them. Pin both in real code. const rails = await (await fetch(`${API}/v1/rails`)).json(); const d = rails.rails.find((r: { id: string }) => r.id === 'stellar').details; const [code, issuer] = d.asset.split(':'); const ITC = new Asset(code, issuer); const SAC = ITC.contractId(Networks.TESTNET); if (d.network !== NETWORK || d.assetContract !== SAC) throw new Error('unexpected Stellar network or asset'); // 2. Create the account with free XLM, then opt in to ITC with a trustline. await fetch(`https://friendbot.stellar.org?addr=${address}`); const trust = new TransactionBuilder(await horizon.loadAccount(address), { fee: BASE_FEE, networkPassphrase: Networks.TESTNET }) .addOperation(Operation.changeTrust({ asset: ITC })) .setTimeout(60) .build(); trust.sign(keypair); await horizon.submitTransaction(trust); // 3. ITC from Inferit's faucet, once per address per 24 h. const faucet = await fetch(`${API}/v1/faucet/stellar`, { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify({ address }), }); console.log('faucet', faucet.status, await faucet.text()); // 4. The standard x402 v2 client with a Stellar signer. It pays only in ITC, and at most 1 ITC // (10000000 base units, 7 decimals) for one request, whatever the server quotes. const client = new x402Client() .register(NETWORK, new ExactStellarScheme(createEd25519Signer(keypair.secret(), NETWORK))) .setSpendControls({ allowedAssets: [{ network: NETWORK, asset: SAC, maxAmountPerPayment: '10000000' }] }); const fetchWithPayment = wrapFetchWithPayment(fetch, client); // 5. Call the API with no key: 402 -> sign -> paid retry, all inside fetchWithPayment. const res = await fetchWithPayment(`${API}/v1/chat/completions`, { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify({ model: 'qwen/qwen-2.5-14b-instruct', messages: [{ role: 'user', content: 'Say hello in five words.' }], max_tokens: 64, // the quote is the worst case for this body, so a small max_tokens keeps it small }), }); const body = await res.json(); console.log(res.status, body.choices?.[0]?.message?.content ?? body); console.log('model', res.headers.get('x-inferit-model')); const receipt = res.headers.get('PAYMENT-RESPONSE'); if (receipt) console.log(decodePaymentResponseHeader(receipt)); // the Stellar transaction, the network and the payer console.log('cost', res.headers.get('x-inferit-buyer-cost-micro'), 'millionths of a dollar; the rest stays your balance'); // A call without a key never draws on that balance: an API key made after signing in with this key spends it. ``` The `setSpendControls` line is configuration of the standard client, not a patch: the client only pays in tokens it knows, and the ITC contract is not on its built-in list. Its `maxAmountPerPayment` (`"10000000"`, 1 ITC, $1) is the most the client signs for one request: a setting in your client, not a rule the API enforces. A complete agent, with the account, the trustline, the faucet, checks on what it is asked to pay and a printed receipt: [stellar-x402-agent](https://github.com/InferitAI/inferit-examples/tree/main/stellar-x402-agent) in inferit-examples. ### curl: see the Stellar entry without paying _the 402, without paying_ ```bash curl -s https://api-production-c74b9.up.railway.app/v1/chat/completions \ -H 'content-type: application/json' \ -d '{"model":"qwen/qwen-2.5-14b-instruct","messages":[{"role":"user","content":"Hi"}],"max_tokens":64}' \ | jq '.accepts[] | select(.network == "stellar:testnet")' # scheme "exact", network, asset (the contract, C…), payTo (the treasury, G…), amount (7 decimals), # maxTimeoutSeconds, extra.areFeesSponsored: true ``` ## Where the money is - **The treasury.** Every payment on Stellar goes to Inferit's treasury account, the `payTo` of the Stellar entry. Inferit holds what your requests have not spent, as your balance in its ledger, under your Stellar address. - **Unlike Whitechain.** On Whitechain a payment lands in the MarketEscrow contract, under limits the contract enforces ([Whitechain escrow](https://inferit.cc/docs/payments/whitechain.md#x402)). On Stellar the `exact` scheme allows one plain transfer to `payTo`, so the balance is kept by Inferit's API, and the limits below are the API's. - **Spending it.** x402 payments add to your balance; a call without a key never draws on it. An API key does: sign in with the same Stellar key (`POST /v1/auth/stellar/challenge`, then `/verify` with the message signed as a SEP-53 message, or [Buy](https://inferit.app/buy) with a Stellar wallet), make a key with `POST /v1/keys`, and each request with that key is charged its exact cost against the balance. Once a payment would take the balance past $25, x402 payments are refused (`invalid_exact_stellar_balance_over_limit`) until a key spends it down. Withdrawals from it are planned. - **Sellers.** A request paid on Stellar goes to the cheapest healthy seller of the model on Inferit, whichever network the seller registered on. What the seller is owed is recorded under the address it signed in with. ## Limits | What | Default | Why | | --- | --- | --- | | Minimum payment | $0.01 (0.01 ITC, `"100000"`) | Each payment is a transfer on the ledger whose fee Inferit pays | | Most per payment | $5 (5 ITC, `"50000000"`) | Inferit holds what a payment does not spend, so each payment stays small | | Most a balance may reach | $25 (25 ITC) | A payment that would take your balance past it is refused before it settles: nothing is transferred. An API key from a Stellar sign-in spends the balance ([Spending it](https://inferit.cc/docs/payments/stellar.md#spending)) | | Amount | Exactly the quote | The `exact` scheme: a transfer of any other amount is refused | | Signature validity | `maxTimeoutSeconds` (120 s), counted in ledgers of about 5 s | The authorization entry names its last valid ledger | | Quote pin | 120 s, per request (path, routing headers and JSON body) | The paid retry verifies against the quote it was shown; a changed request gets a new 402 | | Signer | A Stellar account key (`G…`), x402 version 2 | `createEd25519Signer` signs the authorization entry; the facilitator pays the fee | | x402 payments | 30 paid attempts a minute per paying address, 60 per IP | Payments from one address are handled one at a time | | Client ceiling (the code above) | $1 per payment | Your own setting, in the client's spend controls | The API reports its own limits in `GET /v1/rails` (`maxPaymentMicro`, `maxBalanceMicro`; [Live values](https://inferit.cc/docs/payments/stellar.md#live)). Agents should start at [Agents](https://inferit.cc/agents) or [agents.md](https://inferit.cc/agents.md); the whole x402 exchange is in the [API reference](https://inferit.cc/docs/api-reference.md#x402-stellar). ## What is public Each payment is a Stellar transaction: the payer's address, the treasury, the asset and the amount are public on the ledger, and Inferit's fee-payer account is the transaction's source. Your balance with Inferit and what each request cost are in Inferit's own ledger, not on chain: the response headers and your requests are the record. --- Canonical page: https://inferit.cc/docs/payments/stellar All pages as markdown: https://inferit.cc/llms.txt --- Source: https://inferit.cc/docs/sellers/quickstart.md # Sell from your own PC in 10 minutes > Sell inference on Inferit from your own computer: run a model in Ollama or LM Studio, connect it with the open-source inferit-seller app (one command, no open port or domain), set a price in dollars per 1M tokens and list it. Paid in ITC. Run a model in Ollama or LM Studio, connect your computer to Inferit with one command, and set your price in dollars per 1M tokens. The seller app dials out to Inferit, so your computer needs no public address, open port or domain. Open source The seller app, `inferit-seller`, is open source (Apache-2.0) at [github.com/InferitAI/inferit-seller](https://github.com/InferitAI/inferit-seller), so you can read what runs on your machine. Buyers pay, and sellers are paid, in ITC (Inferit Test Credit) on Whitechain Sepolia. ## What you need - A computer that can run the model you want to sell: macOS, Linux or Windows, with a GPU or Apple silicon and enough memory for it. - A local model server: [Ollama](https://ollama.com) or LM Studio (vLLM and the llama.cpp server work too). - Node.js 20 or newer (it brings `npx`). Or Docker instead. - A browser wallet (MetaMask or Rabby) on Whitechain Sepolia, with a little WBT, Whitechain's gas token, for one registration transaction. Get it from the [Whitechain faucet](https://faucet.testnet.whitechain.io) (it asks for a GitHub account; [Selling inference](https://inferit.cc/docs/sellers.md#steps) has the details). Without it the Sell workspace cannot register you, and Inferit refuses a listing from an unregistered wallet. ## 1. Run a model Pick a ranked model your computer can run ([ranking](https://inferit.cc/docs/routing.md)). Requests sent with model auto only go to ranked models, so a ranked model with no seller yet gets those requests first. On an 8 GB machine try Llama 3.1 8B; on 16 GB or more, gpt-oss-20b. Load it in your model server. Another open-weight model works too: you list it from the Sell workspace first ([how](https://inferit.cc/docs/sellers/quickstart.md#not-in-catalog)). The seller app finds Ollama on port 11434, LM Studio on 1234, vLLM on 8000 and the llama.cpp server on 8080, all on 127.0.0.1. _Ollama_ ```bash # Ollama (ollama.com): download a ranked model by its Ollama name. ollama pull llama3.1:8b ollama list # what the seller app will find on http://127.0.0.1:11434 ``` _LM Studio_ ```bash # LM Studio: download the model in the app, then start its local server # (Developer tab, or from a terminal): lms server start # http://127.0.0.1:1234/v1 ``` ## 2. Sign in and register Open the [Sell workspace](https://inferit.app/sell) and sign in with your wallet (an off-chain signature, no gas). Then register your payout wallet on the escrow contract: one transaction from your wallet, paid in WBT, done once. An offer cannot go live before it. **App:** [Sell workspace](https://inferit.app/sell) · **Contract:** [`registerSeller(payout)`](https://inferit.cc/docs/payments/whitechain.md#calls) ## 3. Add a machine Under **Your machines**, choose **Add a machine** and name it (for example `home-pc`). The workspace creates a connection token for it (`icn_…`) and shows the command to run, with the token filled in. **The token is shown once.** Copy the command before you close the dialog, and keep it out of chats, screenshots and git. The token can only connect this machine: it cannot list offers, read earnings or create keys. If it leaks, revoke the machine and add it again. Each computer needs its own token: two copies of the app with one token keep replacing each other's connection. **API:** [`POST /v1/seller/nodes`](https://inferit.cc/docs/api-reference.md#post-v1-seller-nodes) ## 4. Run the command On the computer with the model, paste the command for its system; the Sell workspace shows the same commands with your token in place of `icn_YOUR_TOKEN`. _macOS and Linux (Terminal)_ ```bash npx -y inferit-seller connect --token icn_YOUR_TOKEN && npx -y inferit-seller install-service ``` _Windows (PowerShell)_ ```powershell npx.cmd -y inferit-seller connect --token icn_YOUR_TOKEN; if ($?) { npx.cmd -y inferit-seller install-service } ``` _Docker_ ```bash docker run -d --restart unless-stopped --name inferit-seller \ -e INFERIT_TOKEN=icn_YOUR_TOKEN \ --add-host=host.docker.internal:host-gateway \ ghcr.io/inferitai/inferit-seller ``` The Docker command is written for a macOS or Linux shell; in PowerShell, put it on one line without the `\` line breaks. On Linux, see [No local server found](https://inferit.cc/docs/sellers/quickstart.md#no-server) first. `connect` checks the token with Inferit and saves `~/.inferit-seller/config.json`, readable only by you (mode 0600): the token, the connection address, the API address and the machine's name. `install-service` makes the app start when you log in and restart if it stops. Each time it starts, the app finds your model server and its models, then connects: - macOS: a LaunchAgent, `~/Library/LaunchAgents/cc.inferit.seller.plist` (`RunAtLoad` and `KeepAlive`). - Linux: a systemd user unit, `inferit-seller.service` (`Restart=always`). - Windows: a Task Scheduler task, `InferitSeller`, that runs at logon. - Docker: no service; `--restart unless-stopped` brings the container back with Docker. On Windows the command calls `npx.cmd`: PowerShell's default policy refuses to run `npx`'s script form, and Windows PowerShell 5.1 has no `&&`, hence the `if ($?)`. ## 5. Check it Once the app connects, the workspace shows the machine **online**, with the models it found. Each is either matched to a model on the market, which you can sell, or marked **not in the catalog yet**: any open-weight chat model can be listed with **List this model**, then sold ([list any open-weight model](https://inferit.cc/docs/sellers/quickstart.md#not-in-catalog)). From a terminal on the machine: ```bash npx -y inferit-seller status # config, local servers and models found, market connection npx -y inferit-seller doctor # each check, with a fix for any that fails # Windows (PowerShell): npx.cmd in place of npx ``` `doctor` checks that your model server answers, that it has models and which match the catalog, that Inferit is reachable, and that the token is accepted. Once you have listed a price, it also checks that each listing's context limit is within what your server serves. For each check that fails it says what to do. ## 6. Set your price and list For each matched model, the workspace asks for a price in dollars per 1M tokens, input and output (paid in ITC). Next to it the form shows: - what a buyer pays for it: your full price plus the 5% marketplace commission, which the buyer pays on top; - the model's catalog list price, for comparison; - a **context limit**, when your server runs the model with less context than the catalog lists (Ollama often serves 4096 or 8192 tokens of a model that allows 32768). It is filled in with what the seller app reports, and Inferit sends longer prompts to other sellers. Keep it at most what your server serves ([raise it](https://inferit.cc/docs/sellers/quickstart.md#context) to sell longer prompts). For example, a seller asking $0.04 per 1M input tokens and $0.06 per 1M output tokens for Llama 3.1 8B (list $0.05 and $0.08) keeps that full price, and a buyer pays $0.042 and $0.063 per 1M tokens. **List** sends a live 1-token probe to your machine over its connection and, if it answers, creates the offer, pointing at your machine. The offer then takes a buyer's request whenever it is the cheapest healthy offer on Inferit for it. _the same, with the API_ ```bash # What "List" sends (the session from wallet sign-in). The API takes prices as integers in millionths of a # dollar per 1M tokens: "40000" = $0.04 per 1M tokens. curl -s -X POST https://api-production-c74b9.up.railway.app/v1/seller/offers \ -H "Authorization: Bearer $SESSION" \ -H 'content-type: application/json' \ -d '{ "model": "meta-llama/llama-3.1-8b-instruct", "kind": "endpoint", "endpointUrl": "connector://node_…/v1", "pricing": { "mode": "per_token", "inputPerM": "40000", "outputPerM": "60000" }, "availability": "intermittent", "licenseAck": true }' # endpointUrl: your machine's address on Inferit (GET /v1/seller/nodes lists it). # availability "intermittent": a computer that is on part of the day. ``` **App:** [Sell workspace](https://inferit.app/sell) · **API:** [`POST /v1/seller/offers`](https://inferit.cc/docs/api-reference.md#post-v1-seller-offers) Payment: usage settles in batches on chain, what you are owed accrues in the escrow, and `withdrawEarnings()` sends it to your payout wallet in ITC ([payouts](https://inferit.cc/docs/sellers.md#payouts)). The seller that serves a request sees it: follow the seller rules of the [acceptable use policy](https://inferit.cc/legal/acceptable-use), including no logging, retaining or training on buyer requests. ## The seller app's commands ```bash inferit-seller connect --token icn_… [--api ] [--name ] # check the token, save ~/.inferit-seller/config.json inferit-seller start # run in the foreground (config file or environment) inferit-seller install-service # start at login, restart if it stops inferit-seller uninstall-service # remove that inferit-seller status # config, local servers and models, market connection inferit-seller doctor # checks with plain-English fixes inferit-seller --version inferit-seller --help # Run any of them with npx (nothing to install): # npx -y inferit-seller # or install the app once from npm: # npm i -g inferit-seller # or run it straight from its source repository (needs Git): # npx -y github:InferitAI/inferit-seller ``` `--upstream ` names the model server yourself (an OpenAI-compatible base URL, such as `http://127.0.0.1:11434/v1`) instead of detecting it. The environment variables of the earlier sidecar still work: `CONNECT_URL`, `CONNECT_TOKEN`, `UPSTREAM_BASE_URL`, `MODEL_MAP`, `MODEL_META` and the rest ([connector mode](https://inferit.cc/docs/sellers.md#connector)). When `MODEL_MAP` is unset, the app builds it from the models it matched. Your machines are listed in the Sell workspace: online or offline, when each was last seen, the app's version and the models found. You can rename a machine, or revoke it: its token stops working, its connection closes at once and its offers leave routing. ## Troubleshooting ### Sleep, reboots and changing networks While the computer sleeps or is off, your offers take no requests; after a 60-second grace they show as offline, and buyers are served by other sellers. When it wakes, the app reconnects by itself, waiting a little longer after each failed try, up to about a minute. After a reboot the service starts the app again when you log in. - If the machine still shows offline a few minutes after waking, run `doctor`. Under the service, an app that has had no connection for 10 minutes exits so the service starts a fresh copy (`INFERIT_WATCHDOG_MINUTES` changes the wait, `0` turns it off); run in a terminal, it logs an error and keeps trying. You can also restart it yourself: `uninstall-service` then `install-service`, or log out and back in. - To keep selling, stop the computer sleeping while it is plugged in: on macOS in System Settings (Energy, or Battery then Options), on Windows in Settings, System, Power, and on Linux in your desktop's power settings. On macOS and Linux, `install-service --keep-awake` keeps the computer awake while the app runs. - On Linux, a user service starts at login. `install-service` also turns on lingering so it starts at boot; if it says it could not, run `sudo loginctl enable-linger $USER` once. - A computer that is on only part of the day suits `"availability": "intermittent"`: being offline then does not count against the offer's health ([availability](https://inferit.cc/docs/sellers.md#availability)). ### Unhealthy after an idle spell Ollama unloads a model after 5 idle minutes by default, and loading a 14B model again can take a minute on a laptop. Inferit's health check gives up after about 15 s, so a check that comes after an idle spell fails and the offer shows as unhealthy. The seller app keeps each Ollama model it sells loaded while it runs (`INFERIT_KEEP_WARM`, on by default), so the model stays in memory, and `doctor` shows the last cold-load time. With keep-warm off, set `OLLAMA_KEEP_ALIVE` for the Ollama server (for example `1h`) and restart Ollama. ### Laptop on battery Keep a laptop plugged in while it sells. On battery it sleeps when the lid closes and shuts down when the battery runs out, whatever the app does, and a sleeping or shut-down computer cannot sell: buyers are served by other sellers until it is back. ### Context smaller than the catalog A model server may run a model with less context than the model allows: Ollama uses 4096 tokens in many versions unless it is told otherwise. A listing must not accept longer prompts than your server serves, or the server cuts them. The seller app reads the served context from your server (Ollama says it only while the model is loaded, so the app checks again every minute) and the listing form fills in the limit. `doctor` warns when a listing's limit is above it. - To sell longer prompts with Ollama, set `OLLAMA_CONTEXT_LENGTH` for the Ollama server (for example `32768`, as far as memory allows) and restart Ollama. In the Ollama app the same setting is the context length in its settings. A longer context uses more memory: if the model no longer fits, Ollama runs part of it on the CPU and answers more slowly. - Then raise the listing's limit: under **Offers** in the Sell workspace, choose **Edit** and enter the new context limit. Keep it at most what the server serves (`ollama ps` shows it while the model is loaded). - In LM Studio, load the model with a longer context length; vLLM and the llama.cpp server take it as a start option. _Ollama: a longer context_ ```bash # macOS (the Ollama app): set it, then quit and reopen Ollama. launchctl setenv OLLAMA_CONTEXT_LENGTH 32768 # Linux (the systemd service): sudo systemctl edit ollama, add the two lines below, then sudo systemctl restart ollama # [Service] # Environment="OLLAMA_CONTEXT_LENGTH=32768" # Or, running it yourself: OLLAMA_CONTEXT_LENGTH=32768 ollama serve ollama ps # CONTEXT shows what a loaded model is served with ``` ### List any open-weight model The app matches each local model name against the market's models (`GET /v1/models`, fields `id` and `aliases`), ignoring case and a `:latest` tag: for example Ollama's `qwen2.5:14b-instruct` is `qwen/qwen-2.5-14b-instruct`. A chat model it cannot match is reported as **not in the catalog yet**. Any open-weight model whose licence allows paid serving can be listed, and once it is listed any seller can sell it: 1. In the Sell workspace, open your machine's **Models** and choose **List this model** beside it. 2. Check the form. The **Hugging Face repo** is filled in when the local name carries one (an Ollama `hf.co/Org/Model:Q4_K_M` pull, a vLLM or LM Studio `Org/Model` name); with a repo, Inferit checks that it is public and ungated and reads its licence from the model card. Without one (weights that are not on Hugging Face), name the model `your-name/model-name` and pick its licence. The **context** is what your server serves. 3. Confirm the licence when asked: a licence with conditions (the Llama and Gemma licences, for example) or one Inferit cannot read needs your confirmation that it allows paid hosted serving and that you meet its conditions. 4. Wait a few seconds: the market tells the app, which maps your local model to the new listing and serves it without a restart (app 0.3.3 or newer; restart an older app, or update it). The price form opens on the machine's card: price it in dollars per 1M tokens as in [step 6](https://inferit.cc/docs/sellers/quickstart.md#price). A seller-listed model has no list price, so the form shows no list comparison and buyers see no discount for it. - Refused: non-commercial and research-only licences, closed models (a hosted API is not open weights), gated or private repos, models that are not chat models, and a catalog model or a name close to one, such as its base model (the answer names the catalog model: offer it when it is the model you serve). - Limits: 10 new models per account a day, 50 in all. - The app reads your server's models when it starts. After you download another model, restart it (`uninstall-service` then `install-service`) so it reports the new one. - If your local model is a catalog model under another name, map it yourself. `MODEL_MAP` replaces the automatic matching (the app then serves only what it names), so list every model you serve. Map a model only to the id of that same model: you are responsible for what you serve. ```bash # Serve a local model under the market id it is (example values). MODEL_MAP='{"meta-llama/llama-3.1-8b-instruct":"my-llama-build"}' \ npx -y inferit-seller start ``` ### Why no port, domain or proxy The app opens one outbound, authenticated WebSocket (wss, port 443) to Inferit and answers requests over it, and it calls your model server on 127.0.0.1 only. Nothing on your computer listens to the internet, so you need no open port, domain, certificate, reverse proxy or tunnel, and Ollama needs no change to its host settings. A home router, NAT or a VPN is fine as long as the computer can reach HTTPS sites. A network that blocks WebSockets, such as some company proxies, is not. ### "No local server found" - Start your model server: open the Ollama app (or run `ollama serve`), or start LM Studio's local server. - A server on another port: pass `--upstream http://127.0.0.1:/v1` to `connect`. - Docker: the container reaches your computer's model server at `host.docker.internal`. On Linux, Ollama listens on 127.0.0.1 only by default, which a container cannot reach that way; run the container with `--network host` and `-e UPSTREAM_BASE_URL=http://127.0.0.1:11434/v1` instead of `--add-host`. `docker logs inferit-seller` shows what the app found. ### Windows - "Running scripts is disabled on this system": type `npx.cmd`, not `npx`, as in the command above. - `spawn git ENOENT` (only with the `github:` command): install Git for Windows, open a new PowerShell window and run the command again, or use `npx -y inferit-seller`, which needs no Git. More on how selling works (licences, health, availability, payouts and what buyers see) is on [Selling inference](https://inferit.cc/docs/sellers.md). --- Canonical page: https://inferit.cc/docs/sellers/quickstart All pages as markdown: https://inferit.cc/llms.txt --- Source: https://inferit.cc/docs/sellers.md # Selling inference > Sell inference on Inferit at your own price in dollars per 1M tokens, from your own computer with the open-source seller app or from an https endpoint: licences, registration, health checks, availability and payouts to your own wallet in ITC. Anyone can sell inference on Inferit: a seller serves a model from hardware it controls, at its own price in dollars per 1M tokens. A seller is paid per request, to the payout wallet it registers, whenever it is the cheapest healthy offer, in ITC. Selling from your own computer? Start with [Sell from your own PC in 10 minutes](https://inferit.cc/docs/sellers/quickstart.md): Ollama or LM Studio, one command with the open-source `inferit-seller` app, and a price in dollars. No public address, open port or domain. This page is the reference behind it. Which offers are listed and healthy right now is on [the models page](https://inferit.app/models). Buyers who send model auto reach a model only when it is on the quality ranking ([automatic routing](https://inferit.cc/docs/routing.md#ranking)); unranked models get the requests that name them. ## What you can list - **Your own computer, with the seller app.** The open-source `inferit-seller` app (Apache-2.0, [github.com/InferitAI/inferit-seller](https://github.com/InferitAI/inferit-seller)) runs next to your model server, dials out to Inferit and takes requests over that connection ([connector mode](https://inferit.cc/docs/sellers.md#connector)): no tunnel, no open port, no certificate. [The seller quickstart](https://inferit.cc/docs/sellers/quickstart.md) walks through it. - **Your own endpoint.** Any OpenAI-compatible server you run, such as vLLM, Ollama or SGLang, behind HTTPS on a domain you control. You give a base URL and an optional bearer token; the token is stored AES-256-GCM encrypted. It must be a server you run: URLs on known hosted providers are rejected. Putting a hosted provider's API behind a proxy on your own domain is still key resale and is not allowed, even though the API cannot prove where an endpoint runs. Every listing and the traffic it serves must follow the [acceptable use policy](https://inferit.cc/legal/acceptable-use), including its seller rules: no logging, retaining or training on buyer requests, and no inflated usage. **On a rented GPU** (a marketplace machine you rent by the hour), the owner of that machine can read the prompts it serves, as well as you. Prefer verified hosts. **Images and other media.** Inferit forwards media only as inline `data:` URLs or `https:` URLs on public host names; it refuses private, loopback and metadata addresses. A vision server that fetches media URLs itself (vLLM does) can still be pointed at any public URL, so limit what it may fetch (in vLLM, its allowed media domains, and no redirects), or accept inline media only. ## Licences Every catalog model has a licence class. **Permissive** (Apache-2.0, MIT) lists freely. **Conditional** (for example the Llama community licence, Qwen licence, Gemma terms, modified MIT) requires you to acknowledge the conditions. **Not allowed** (non-commercial weights, closed models) is rejected. The summaries on this site are not legal advice; read the linked licence. A model that is not in the catalog can be listed first, if its weights are open and its licence allows paid serving: the same licence classes apply, and Inferit reads the licence from the Hugging Face model card when you name the repo ([list any open-weight model](https://inferit.cc/docs/sellers/quickstart.md#not-in-catalog), or [POST /v1/seller/models](https://inferit.cc/docs/api-reference.md#post-v1-seller-models)). A model a seller listed has no list price, so it is priced per token. ## Steps How a seller is paid: serve any model with Ollama, LM Studio, vLLM, llama.cpp or any OpenAI-compatible server; list it at your price per 1M tokens; when yours is the cheapest healthy offer the request is routed to you; its price is paid to your wallet in ITC. 1. Get a little WBT, Whitechain's gas token, from the [Whitechain faucet](https://faucet.testnet.whitechain.io) (sign in with GitHub). Registration and withdrawals are transactions your wallet sends; payouts arrive in ITC. 2. Register your payout wallet on the escrow: `registerSeller(payout)`, sent from your own wallet on Whitechain Sepolia. An offer cannot go live before this. 3. Sign in with the same wallet (one sign-in serves both workspaces) and list an offer: the model, your endpoint URL and bearer token, your price in dollars per 1M input and output tokens, and an optional daily cap. 4. The API checks the licence, resolves your host and rejects private and link-local addresses (SSRF guard), then sends a live 1-token probe. If it answers, the offer is active. **App:** [Sell workspace](https://inferit.app/sell) · **Contract:** [`registerSeller(payout)`](https://inferit.cc/docs/payments/whitechain.md#calls) · **API:** [`POST /v1/seller/offers`](https://inferit.cc/docs/api-reference.md#post-v1-seller-offers) _your endpoint_ ```bash # Any OpenAI-compatible server you run works: vLLM shown; Ollama or SGLang too. # vLLM checks the bearer token itself (--api-key) and answers to the catalog id. SELLER_TOKEN="$(openssl rand -hex 24)" vllm serve meta-llama/Llama-3.1-8B-Instruct \ --served-model-name meta-llama/llama-3.1-8b-instruct \ --host 127.0.0.1 --port 8000 --api-key "$SELLER_TOKEN" # Put it behind HTTPS on a domain you control (Caddy fetches the certificate). caddy reverse-proxy --from gpu.example.com --to 127.0.0.1:8000 # Check it answers a chat completion, as the listing probe will. curl -s https://gpu.example.com/v1/chat/completions \ -H "Authorization: Bearer $SELLER_TOKEN" \ -H 'content-type: application/json' \ -d '{"model":"meta-llama/llama-3.1-8b-instruct","max_tokens":1, "messages":[{"role":"user","content":"hi"}]}' # Then list https://gpu.example.com/v1 with SELLER_TOKEN as its bearer token, # in the Sell workspace or with "list an offer" below. ``` ## API path (no browser) The same steps without the app, for a script or an agent. The escrow address is on [Whitechain escrow](https://inferit.cc/docs/payments/whitechain.md#live); the request and response fields are in the [API reference](https://inferit.cc/docs/api-reference.md#post-v1-seller-offers). _register (on chain)_ ```bash # 1. Register the payout wallet on MarketEscrow # (a transaction from the seller wallet: needs a little WBT). # Foundry's cast; any EVM client works (viem: writeContract). cast send 0x705dD9eCffa888FbcF2849eAE2D3b136eb78B7e0 \ "registerSeller(address)" 0xYourPayoutAddress \ --rpc-url https://rpc.testnet.whitechain.io \ --private-key "$SELLER_KEY" ``` _sign in_ ```bash # 2. Sign in with the same wallet: an off-chain EIP-4361 text signature, no gas. curl -s -X POST https://api-production-c74b9.up.railway.app/v1/auth/evm/challenge \ -H 'content-type: application/json' \ -d '{"address":"0xYourSellerAddress"}' # -> {"message": "...", "nonce": "...", "expiresAt": "..."} # Sign "message" with the seller key (an EIP-191 signature), then: curl -s -X POST https://api-production-c74b9.up.railway.app/v1/auth/evm/verify \ -H 'content-type: application/json' \ -d '{"message":"","signature":"0x"}' # -> a session token: export SESSION=... ``` _list an offer_ ```bash # 3. List an offer. Prices are integers in millionths of a dollar per 1M tokens # (string or number): "40000" = $0.04 per 1M tokens. curl -s -X POST https://api-production-c74b9.up.railway.app/v1/seller/offers \ -H "Authorization: Bearer $SESSION" \ -H 'content-type: application/json' \ -d '{ "model": "meta-llama/llama-3.1-8b-instruct", "kind": "endpoint", "endpointUrl": "https://gpu.example.com/v1", "authToken": "", "upstreamModel": null, "pricing": { "mode": "per_token", "inputPerM": "40000", "outputPerM": "60000" }, "capDailyMicro": null, "licenseAck": true }' # upstreamModel: the name your server knows the model by, when it is not # the catalog id (Ollama: "llama3.1:8b"); null sends the catalog id. # licenseAck: boolean; true acknowledges a conditional licence (false is # enough for a permissive one). The API probes the endpoint before it # activates the offer; 409 seller_not_registered until step 1 lands. ``` ## Connector mode: no public URL A computer behind NAT, a VPN or a home router can sell without a tunnel. The seller app, `inferit-seller` (open source, Apache-2.0), opens one authenticated WebSocket (wss) to the API and answers requests over it; it listens on 127.0.0.1 only. In its hello it reports its version and system and the models it found on your server, which the Sell workspace shows. The step-by-step version, with the Sell workspace's **Add a machine**, is [the seller quickstart](https://inferit.cc/docs/sellers/quickstart.md). 1. Signed in with your wallet, mint a connection token: `POST /v1/seller/nodes`. The token (`icn_…`) is shown once and only opens that connection: it cannot list offers, read earnings or create keys. An account can hold five tokens at a time by default. 2. Run the app with the token: `connect --token` saves it, `install-service` keeps the app running across logins and reboots (or set `CONNECT_URL` and `CONNECT_TOKEN` yourself). After a drop it reconnects by itself, waiting longer after each failed try, up to about a minute. 3. List the offer with `endpointUrl` set to its `connector://…/v1` address and no `authToken`. The app must be connected and serving that model, or listing answers `409 node_offline`. While the app is disconnected, its offers take no requests; after a 60-second grace they show as offline. `GET /v1/seller/nodes` lists your machines (online, last seen, the app's version, the models found and served), `PATCH /v1/seller/nodes/:id` renames one, and `DELETE /v1/seller/nodes/:id` revokes its token: its connection closes at once and its offers leave routing. The API has a switch for connector mode: if listing answers `503 connector_disabled`, it is off on that server, so list an https endpoint instead. _connector mode_ ```bash # 1. Mint a connection token (the session from "sign in" above). curl -s -X POST https://api-production-c74b9.up.railway.app/v1/seller/nodes \ -H "Authorization: Bearer $SESSION" \ -H 'content-type: application/json' \ -d '{"name":"gpu-box-1"}' # -> {"node": {"id": "node_…", "offerEndpointUrl": "connector://node_…/v1", …}, # "token": "icn_…", "connectUrl": "wss://…/v1/seller/connect"} # The token is shown once: keep it out of git and logs. # 2. Run the seller app on the machine, in front of Ollama, LM Studio, vLLM or # the llama.cpp server. It finds the server and its models by itself. npx -y inferit-seller connect --token "" npx -y inferit-seller install-service # Or configure it by environment instead (example values): MODEL_MAP maps # catalog ids to the names your server uses. UPSTREAM_BASE_URL=http://127.0.0.1:11434/v1 \ MODEL_MAP='{"meta-llama/llama-3.1-8b-instruct":"llama3.1:8b"}' \ CONNECT_URL="" CONNECT_TOKEN="" NODE_NAME=gpu-box-1 \ npx -y inferit-seller start # 3. List as in "list an offer", with # "endpointUrl": "connector://node_…/v1" and no "authToken". ``` ## Pricing Set a price in dollars per 1M input and output tokens, and optionally cache reads, or a percentage of the catalog list price. That is what you are paid: you keep your full price. Buyers pay your price plus a 5% marketplace commission; the contract caps it at 10%. A daily cap limits how much you take per day; the order book shows it summed with the other offers at your price level. ## Health and routing Buyers are routed to the cheapest healthy offer that meets their filters. A failed request or probe marks your offer unhealthy and schedules the next probe on a backoff ladder of 1, 2, 5, 10, 30 and then 60 minutes; one success restores it. Failover happens only before the first byte, so a stream you start is never handed to someone else midway. Offers that sleep when idle or are online only part of the day follow the rules below. ## Availability and cold starts Each offer says how it is available, in its `availability` field ([API reference](https://inferit.cc/docs/api-reference.md#post-v1-seller-offers)): - **`always_on`** (the default) declares an endpoint that should answer at any time; nothing guarantees it does. While healthy it gets a short probe every 5 minutes by default. - **`scale_to_zero`** is an https endpoint that sleeps when idle, such as a serverless GPU app that scales to zero. It needs `coldStartMs`, your measured p90 wake time (at most 140,000), and `healthUrl`, a URL on the same origin that answers without waking the model: `{"ok":true,"models":{"":{"ready":true}}}`. Routine probes call `healthUrl`. A 1-token probe, sent with `x-inferit-probe: deep`, runs only after 24 hours with no successful request, or to bring an unhealthy offer back. A request that reaches a sleeping offer waits up to `coldStartMs` longer for its first byte, 140 seconds in all at most. The first failed wake does not count against health; a second within 10 minutes does. - **`intermittent`** is for connector mode on a machine that is online only some of the time, such as a home computer that sleeps. Its offers take requests only while the app is connected, being offline does not count against health, and it is probed every 15 minutes while connected. If you serve less context than the catalog lists, for example a quantised build on a small GPU, set `maxContextTokens` (and `quantization`, if you like): requests too long for your window skip your offer. At equal price, an offer that answers with no cold start is tried first; it never beats a cheaper one. ## What buyers see From the order book: price levels, offer counts and the combined daily caps per level. Per model, `GET /v1/models/:id/endpoints` lists each offer with your wallet address shortened (`0x45A9…7CDE`), its all-in price, context length, quantization, health, 24 h uptime and time to first token ([API reference](https://inferit.cc/docs/api-reference.md#get-v1-models-id-endpoints)). Never your endpoint URL, your machine's address or your individual volume. The `x-inferit-offer` header is an opaque hash. Settlement is a separate matter: **on Whitechain, settlement is public.** Every `LineSettled` event names the buyer and your seller address with the amount, and `sellerState` shows your unwithdrawn earnings, so anyone can total your volume and a buyer can match its own requests to your address. If you prefer to keep marketplace payments separate from your other on-chain activity, use a dedicated business wallet for selling. See [On-chain visibility](https://inferit.cc/docs/security-trust.md#on-chain). ## Payouts You are paid for every request you serve. Usage is settled on chain in batches within the hour (the live setting is `settlement.cadence` in `GET /metrics`). Your earnings build up in the escrow, and `withdrawEarnings()` sends them to your payout wallet whenever you choose, with no waiting period; only your wallet can change that address. It is one transaction from your wallet, using a little WBT for gas. Every settlement and withdrawal links to the explorer from the Sell workspace. Payouts are in ITC (Inferit Test Credit). **App:** [Sell workspace](https://inferit.app/sell) · **Contract:** [`withdrawEarnings()`](https://inferit.cc/docs/payments/whitechain.md#calls) · **API:** [`GET /v1/seller/earnings`](https://inferit.cc/docs/api-reference.md#get-v1-seller-earnings) --- Canonical page: https://inferit.cc/docs/sellers All pages as markdown: https://inferit.cc/llms.txt --- Source: https://inferit.cc/docs/security-trust.md # Security & trust > What the Inferit escrow on Whitechain is designed to enforce, what the API keeps private, what is public on-chain, and what is not verified yet. A marketplace asks buyers to trust an operator with money and sellers with traffic. This page separates what the escrow contract is designed to enforce from what is policy, and lists what we do not verify yet. ## Custody bounds The [MarketEscrow contract on Whitechain](https://inferit.cc/docs/payments/whitechain.md), not our database, limits what the operator can do with buyer funds. It is designed so that: - The operator can settle at most each buyer's remaining cap, counted cumulatively, and nothing after the cap expires. - A per-window circuit breaker (`settleLimit`) caps what the operator can settle in total across all buyers, so a leaked operator key is bounded twice: per buyer by the cap, and overall by the window limit. - A new operator only takes effect after a timelock (24 h on the hosted deployment). - The owner is a 2-of-3 Safe. One team member holds all three signer keys. A separate guardian can pause in an emergency but cannot unpause or move funds. - Settlement can only pay registered sellers. - The fee on each line is bounded by an immutable maximum of 10% of the seller amount (the default fee is 5%). - Settlement batches are idempotent: replaying a batch id is rejected. - Buyer withdrawals wait a fixed delay and keep working while deposits and settlement are paused. - Seller payout addresses are set by the seller's own wallet, never by an API key or the operator. - x402 payments (`depositWithAuthorization`) and relayed permit deposits are credited only to the wallet that signed them. The facilitator key that submits them has no role in the escrow and pays gas only. An x402 payment raises the payer's cap by exactly the amount paid, so the operator can settle no more than the payer authorised. - An x402 authorization that someone submits straight to the token still pays the escrow. Only the operator or the owner can then credit it, only to its signer, and never more than the escrow's unattributed balance. The live values (the owner Safe and its signers, the guardian, the operator, the timelock and the window limit) are read from the contract on the [Whitechain escrow](https://inferit.cc/docs/payments/whitechain.md#live) page. Each API key's spend limit is enforced by Inferit's API, off chain; the contract enforces the wallet's ceiling. **What the bound does not cover:** within your cap, the operator decides what to charge you based on its metering. Keep caps sized to what you are willing to spend before you next check your usage. The app suggests a cap of at most 25 ITC for that reason. ## What the API and order book publish Public endpoints publish aggregated price levels only: price, number of offers, number of healthy offers and remaining daily capacity. The API and the order book never publish seller wallets, endpoint URLs, upstream providers or per-offer volume, and the `x-inferit-offer` header is an opaque hash. One known exception: if the escrow does not know a seller as registered (only after a chain reset or redeploy), the reason shown on that failed usage row names the seller's Whitechain address. These promises cover what Inferit itself publishes. The chain publishes its own data, described next. ## On-chain visibility **Whitechain settlement is public.** `MarketEscrow` is an ordinary contract on a public chain, so anyone can read its events and views: - Every settlement line: `LineSettled(batchId, buyer, seller, sellerAmount, fee)`, with buyer and seller as indexed topics. Who paid which seller, and how much per line, is public. - Each seller's address and payout address (`SellerRegistered`), unwithdrawn earnings (`sellerState(seller)`) and withdrawals (`EarningsWithdrawn`). Summing `LineSettled` gives a seller's total volume. - Each buyer's deposit, cap, spent and expiry (`buyerState(buyer)` and the deposit, cap and withdrawal events). A buyer can therefore filter `LineSettled` by its own address and match the amounts against its usage log to find the wallet of the seller behind its requests. Buyers and sellers who prefer to keep marketplace activity separate from their other on-chain activity can use a dedicated wallet for it. Public settlement is also what makes the market auditable: anyone can compute the market's totals from these same events. ## Data handling - Prompts and completions are relayed to the seller, never stored by Inferit. Usage records hold token counts, costs, latency and status. - Request and response bodies are not logged; logs redact credentials. - API keys and seller connection tokens (connector mode) are stored as peppered SHA-256 hashes and shown once. - Seller endpoint tokens and upstream keys are encrypted with AES-256-GCM. Deleting an offer destroys the ciphertext. - The operator and facilitator keys are read only from the environment and never committed. x402 signatures are never logged. The full list, including retention, is in the [privacy notice](https://inferit.cc/legal/privacy). ## What we do not verify yet Be clear-eyed about these before routing anything sensitive: - **Source code.** The market's code is private, so nobody outside the team can review it. Inferit's open-source projects are the [x402 facilitator for Whitechain](https://github.com/InferitAI/whitechain-x402-facilitator) and the seller app, [inferit-seller](https://github.com/InferitAI/inferit-seller) (Apache-2.0), the code that runs on a seller's machine ([seller quickstart](https://inferit.cc/docs/sellers/quickstart.md)). - **Model authenticity.** Nothing proves a seller runs the model they list, at the precision they imply. A seller could serve a smaller or more aggressively quantized model. There is no TEE attestation or output fingerprinting yet. - **Token counts.** Usage comes from the seller server's reported `usage`. The market does not re-tokenize to check it. Your cap limits the damage; it does not prevent over-reporting. - **Confidentiality from sellers.** The seller's server sees your prompts in plain text, as any inference provider does. When a seller serves from a rented GPU machine, the owner of that machine can read the prompts it serves too. Do not send data you would not give an unknown host. - **Self-hosting.** Nothing proves an endpoint offer is self-hosted. The API rejects endpoint URLs on known hosted providers, but that list is incomplete, and a seller can put a proxy to a hosted API behind their own domain. Such a listing is key resale and is not allowed, but the API cannot detect it. - **Seller accountability.** There are no seller bonds or slashing yet. A bad seller is handled by health checks and delisting, not by losing stake. - **Operator key.** The owner is a 2-of-3 Safe, but the operator is a single hot key held by the API. It is bounded by the caps, the circuit breaker and the timelock, not by a multisig. - **The x402 facilitator is ours.** Inferit's API settles [x402 payments](https://inferit.cc/agents) with its own built-in x402 v2 facilitator, self-hosted and operated by Inferit (key `0xc8c8…e602`). whitechain-x402-facilitator is a separate open-source facilitator for other Whitechain merchants; Inferit operates a public instance of it. The party that sells you the request is also the one that submits your payment. The contract limits what that can do (the credit goes to your own escrow balance), but no third party checks the quote you are shown: cap what your client will sign. - **Finality.** The API marks usage settled once the settle transaction is included. On an OP Stack chain only finalized blocks are irreversible; the site shows settlements as pending finality until then. - **Licence compliance.** Licence classes and summaries are our reading of the model cards; sellers remain responsible for meeting the terms. ## Reporting a problem If you find a way to move funds outside the bounds above, or to learn anything the API promises not to publish (beyond what the chain itself shows, described under [On-chain visibility](https://inferit.cc/docs/security-trust.md#on-chain)), please report it privately via [GitHub private vulnerability reporting](https://github.com/InferitAI/whitechain-x402-facilitator/security) (see the [security policy](https://inferit.cc/security)) before it is fixed. --- Canonical page: https://inferit.cc/docs/security-trust All pages as markdown: https://inferit.cc/llms.txt --- Source: https://inferit.cc/blog.md # Blog > Build notes from Inferit, a market for LLM inference priced in µ and settled on Whitechain Sepolia. RSS: https://inferit.cc/blog/rss.xml - [The first public x402 v2 facilitator for Whitechain](https://inferit.cc/blog/first-x402-facilitator-whitechain.md) · 2026-10-19 · whitechain-x402-facilitator is open source, live on Whitechain Sepolia. How it settles, how to use it, what comes next. (markdown: https://inferit.cc/blog/first-x402-facilitator-whitechain.md) --- Canonical page: https://inferit.cc/blog All pages as markdown: https://inferit.cc/llms.txt --- Source: https://inferit.cc/blog/first-x402-facilitator-whitechain.md # The first public x402 v2 facilitator for Whitechain > whitechain-x402-facilitator is open source, live on Whitechain Sepolia. How it settles, how to use it, what comes next. Sahil Massey · 2026-10-19 · 7 min read ![Card headed 'Postage due.': 10,000 micro-dollars (10 000 µ) to deliver this request, the 0.01 ITC of the facilitator's first settlement on 2026-10-04. Rows: PAYMENT-SIGNATURE, EIP-3009, sign 10 000 µ and resend; gas, paid by the facilitator, the agent holds 0 WBT; paid to, the merchant's own address.](/blog/first-x402-facilitator-whitechain/hero.png) On 2026-10-04 an agent holding 0 WBT paid 0.01 ITC to a merchant's API on Whitechain Sepolia. It paid through the official x402 fetch client, the merchant ran the official x402 express middleware, and whitechain-x402-facilitator settled the payment on chain. That was the facilitator's first settlement: [0xc1e9c255…](https://explorer.testnet.whitechain.io/tx/0xc1e9c255d7ac63c99a68406a3a0226cf717654a25f55c73c0454f9ae82e33615). whitechain-x402-facilitator is the first public x402 v2 facilitator for Whitechain, live on Whitechain Sepolia. It is open source under Apache-2.0, at release v0.1.0. Any x402 server can point at the hosted service, and anyone can run their own copy. ## A facilitator verifies and settles the payment [x402](https://www.x402.org) puts payment into HTTP. A server answers an unpaid request with `402 Payment Required` and a price. The client signs a payment for that amount and sends the same request again, with a `PAYMENT-SIGNATURE` header. The server passes the signed payment to a facilitator, which checks it and settles it on chain. The facilitator is the one piece of infrastructure in that loop. whitechain-x402-facilitator is that piece for Whitechain, WhiteBIT's EVM L2: `/verify`, `/settle` and `/supported`, built on the official `@x402/core` and `@x402/evm` packages. The scope of "first" is deliberate. An earlier x402-style facilitator, AgentPay, ran x402 v1 on Whitechain's legacy L1 testnet. whitechain-x402-facilitator is the first public x402 v2 one: hosted for anyone to use, in the v2 wire format the official SDKs send. ## The payer pays the merchant; the facilitator pays the gas ![Fig. 1, one x402 payment: agent, merchant, facilitator, Whitechain Sepolia. 1, request. 2, 402 Payment Required with price and payTo. 3, the same request, signed (PAYMENT-SIGNATURE, EIP-3009). 4, verify, then settle. 5, on chain: transferWithAuthorization moves ITC from agent to merchant, gas paid by the facilitator. 6, 200 and the answer.](/blog/first-x402-facilitator-whitechain/fig-1-payment-flow.png) *Fig. 1. One x402 payment through whitechain-x402-facilitator on Whitechain Sepolia. Source: the facilitator's README, read 2026-10-19.* 1. The agent calls the merchant's API, with no account and no API key. 2. The merchant answers `402 Payment Required`. Its `PAYMENT-REQUIRED` header names the price, the token and the merchant's own address (`payTo`). 3. The agent signs an EIP-3009 `transferWithAuthorization` for that amount, off chain. It resends the same request with the signature in `PAYMENT-SIGNATURE`. 4. The merchant's x402 middleware calls the facilitator's `/verify`, serves the request, then calls `/settle`. 5. The facilitator submits the signed authorization to the token and pays the gas in WBT. The answer carries the transaction hash in `PAYMENT-RESPONSE`. The token moves once, from the agent straight to the merchant's `payTo`. The signature fixes the recipient, the amount, a validity window and a nonce. So the facilitator can submit the payment or refuse it; it cannot send the tokens anywhere else. Its key holds only WBT, for gas. The agent needs ITC and no WBT. The checks are the official `@x402/evm` implementation: the EIP-712 signature, the balance, the nonce, and a simulation before anything is broadcast. The facilitator adds policy around them: rate limits, daily gas budgets, a gas cap per settlement and a sanctions denylist. ## A merchant changes three settings Any x402 v2 resource server works. The facilitator speaks the wire format of `@x402/core`'s `HTTPFacilitatorClient`, so the official `@x402/express`, `@x402/hono` and `@x402/next` middleware use it unmodified. Three settings are Whitechain's own: the facilitator URL, the network `eip155:1874`, and an explicit token price, because the x402 SDK has no "$" default asset for Whitechain yet. | | | | --- | --- | | Facilitator URL | `https://x402-facilitator-production-ff5f.up.railway.app` | | Network | Whitechain Sepolia, `eip155:1874` | | Scheme | `exact`, EIP-3009 `transferWithAuthorization` | | Token | ITC, [0x2E672dFE…7fBB](https://explorer.testnet.whitechain.io/address/0x2E672dFE33EA977FD064E01aDe7d8c73B3Be7fBB), 6 decimals | | Cost | No charge on Whitechain Sepolia, within rate limits and a daily gas budget | An Express merchant charging 0.01 ITC (10 000 µ; a µ is a millionth of an ITC) per request. It reads the token's EIP-712 name and version from the contract: ```ts import express from "express"; import { createPublicClient, http } from "viem"; import { paymentMiddleware, x402ResourceServer } from "@x402/express"; import { HTTPFacilitatorClient } from "@x402/core/server"; import { ExactEvmScheme } from "@x402/evm/exact/server"; const url = "https://x402-facilitator-production-ff5f.up.railway.app"; const server = new x402ResourceServer(new HTTPFacilitatorClient({ url })) .register("eip155:1874", new ExactEvmScheme()); const asset = "0x2E672dFE33EA977FD064E01aDe7d8c73B3Be7fBB"; // ITC const rpc = createPublicClient({ transport: http("https://rpc.testnet.whitechain.io") }); const { domain } = await rpc.getEip712Domain({ address: asset }); // the token's EIP-712 name and version const ITC = { asset, extra: { name: domain.name, version: domain.version } }; const app = express(); app.use(paymentMiddleware({ "GET /weather": { accepts: { scheme: "exact", network: "eip155:1874", payTo: "0xYourMerchantAddress", price: { ...ITC, amount: "10000" } } } }, server)); // 0.01 ITC app.get("/weather", (_req, res) => res.json({ city: "Lisbon", temperatureC: 24 })); app.listen(4021); ``` `@x402/hono` takes the same routes and `x402ResourceServer`, and so does `@x402/next`. In the week of 2026-10-04 the facilitator had 98 tests, including interop runs of the official x402 express, hono and fetch packages against it. The full programs and the HTTP API are in [the facilitator's docs](https://github.com/InferitAI/whitechain-x402-facilitator/tree/main/docs). ## An agent allows one token Agents never call the facilitator. They talk to the merchant and sign. The official x402 fetch client pays once ITC is allowed in its spend controls. Recent clients pay only the assets they know, so the agent names the token and caps each payment. ```ts import { wrapFetchWithPaymentFromConfig } from "@x402/fetch"; import { ExactEvmScheme } from "@x402/evm/exact/client"; import { privateKeyToAccount } from "viem/accounts"; const account = privateKeyToAccount(process.env.AGENT_PRIVATE_KEY as `0x${string}`); const fetchWithPayment = wrapFetchWithPaymentFromConfig(fetch, { schemes: [{ network: "eip155:1874", client: new ExactEvmScheme(account) }], spendControls: { // allow ITC, at most 0.10 ITC per payment allowedAssets: [{ network: "eip155:1874", asset: "0x2E672dFE33EA977FD064E01aDe7d8c73B3Be7fBB", maxAmountPerPayment: "100000" }], }, }); const res = await fetchWithPayment("http://localhost:4021/weather"); // 402 -> signed -> 200 console.log(await res.json()); ``` The agent's wallet needs ITC and no WBT. A fresh address can claim 1,000 ITC from Inferit's sponsored faucet, at most once per 24 h, without sending a transaction itself: ```sh curl -X POST https://api-production-c74b9.up.railway.app/v1/faucet \ -H 'content-type: application/json' -d '{"address":"0xYourAgentAddress"}' ``` ## Check it yourself The live service describes itself at `/supported`. This was its answer on 2026-10-19: ```sh curl -s https://x402-facilitator-production-ff5f.up.railway.app/supported # {"kinds":[{"x402Version":2,"scheme":"exact","network":"eip155:1874"}], # "extensions":["eip2612GasSponsoring"], # "signers":{"eip155:*":["0xA0AF38939cE09438393Bbc238Ae9f2989e123045"]}} ``` The signer is the facilitator's gas key, [0xA0AF3893…3045](https://explorer.testnet.whitechain.io/address/0xA0AF38939cE09438393Bbc238Ae9f2989e123045). Its first settlement is [0xc1e9c255…](https://explorer.testnet.whitechain.io/tx/0xc1e9c255d7ac63c99a68406a3a0226cf717654a25f55c73c0454f9ae82e33615), dated 2026-10-04. - **Code:** [InferitAI/whitechain-x402-facilitator](https://github.com/InferitAI/whitechain-x402-facilitator), Apache-2.0. - **Docs:** [the HTTP API, architecture and operations](https://github.com/InferitAI/whitechain-x402-facilitator/tree/main/docs). - **Live service:** `https://x402-facilitator-production-ff5f.up.railway.app`, with its status at [/health](https://x402-facilitator-production-ff5f.up.railway.app/health). - **Self-host:** a Dockerfile and one gas key. Inferit runs the public instance, with rate limits and a daily gas budget. - **Agents paying Inferit:** [the agents' guide](https://inferit.cc/agents.md). ## Inferit's API keeps its own facilitator Inferit is a peer-to-peer market for AI inference, and agents pay it per request with x402 on the same network and token. The facilitator came out of that work, and I split it out so any Whitechain merchant and any agent can use it. Inferit's market API does not route payments through it. Inferit's API runs its own x402 v2 facilitator on Whitechain Sepolia, self-hosted and operated by Inferit. Its payments work differently: they go into `MarketEscrow` with `depositWithAuthorization`, credited to the wallet that signed, not to a merchant's address. The agent side is the same for both: the official x402 fetch client, Whitechain Sepolia and ITC. Inferit runs both facilitators, so neither is an independent facilitator. The open-source one is not an official Whitechain or WhiteBIT service. ## What comes next - x402 in USDC (Portal-bridged USDC.e) on Whitechain mainnet, planned. - x402's Permit2 transfer method, and with it the `upto` scheme and USDT, planned once the x402 Permit2 proxy contracts are deployed on Whitechain. The facilitator takes EIP-3009 tokens today. [Read the facilitator →](https://github.com/InferitAI/whitechain-x402-facilitator) --- Canonical page: https://inferit.cc/blog/first-x402-facilitator-whitechain All pages as markdown: https://inferit.cc/llms.txt --- Source: https://inferit.cc/security.md # Security policy > How to report a vulnerability in Inferit: contact, scope and safe harbour for good-faith research. We welcome reports of vulnerabilities in Inferit. This page says how to reach us, what is in scope and how we treat good-faith research. - **Updated**: 2026-10-07 - **Network**: Whitechain Sepolia - **Report to**: [GitHub private vulnerability reporting](https://github.com/InferitAI/whitechain-x402-facilitator/security) - **First reply**: We aim to acknowledge within three business days. - **Disclosure**: Once a fix is live, or after 90 days. No public issue before then, please. - **Bounty**: No paid bug bounty at this stage. - **Contracts**: MarketEscrow and TestCredit on Whitechain Sepolia. - **Safe harbour**: Good-faith research that follows this policy is authorised ([details](https://inferit.cc/security.md#safe-harbor)). ## How to report Report privately via [GitHub private vulnerability reporting](https://github.com/InferitAI/whitechain-x402-facilitator/security). Include what you found, the affected component and address or URL, steps to reproduce and the impact you expect. Please do not open a public issue or post details before we have had a reasonable chance to fix the problem (we suggest 90 days, or sooner once a fix is live). On GitHub, the Report a vulnerability button opens a private advisory that only the maintainers can read (you need a GitHub account). The repository is whitechain-x402-facilitator, the open-source companion project maintained by the same team; reports about any part of Inferit are welcome there. We aim to acknowledge reports within three business days. There is no paid bug bounty at this stage. ## Scope In scope - The MarketEscrow and TestCredit contracts on Whitechain Sepolia (addresses on the [Whitechain escrow](https://inferit.cc/docs/payments/whitechain.md#live) page), especially any way to move funds outside the bounds described in [Security & trust](https://inferit.cc/docs/security-trust.md#custody). - The Inferit API: authentication, API keys, sessions, routing, metering and settlement. - The x402 facilitator and the sponsored ITC faucet ([Pay per request with x402](https://inferit.cc/agents.md)): any way to be served without paying, to replay or redirect a payment, to credit a payment to anyone but its signer, or to make the facilitator key spend gas on payments that never verify. - This website, including the wallet flows and what the site asks your wallet to sign. - The inferit-seller app ([seller quickstart](https://inferit.cc/docs/sellers/quickstart.md)) and connector mode, and anything that would let one party learn what the API promises not to publish. Out of scope - Third-party services: the Whitechain network, RPC, [explorer](https://explorer.testnet.whitechain.io) and WBT faucet, wallets, and our hosting providers. Report those to their operators. - Denial of service, volumetric or load testing, and spam. - Social engineering, phishing or physical attacks against people. - Issues that need a compromised device or browser, or that only affect outdated browsers. - Missing headers or best-practice notes without a demonstrated impact. - The fact that settlement data is public on-chain; that is by design. ## Safe harbour If you research in good faith and follow this policy, we consider your research authorised, will not pursue or support legal action against you for it, and will work with you to understand and fix the issue. Good faith means you: - use only tokens, accounts and wallets you control; - do not access, change or keep other people's data beyond the minimum needed to show the issue; - do not degrade the service for others, and stop and tell us if you reach data that is not yours; - give us reasonable time to fix the issue before disclosing it. If in doubt about whether something is allowed, ask first. ## Custody and trust What the MarketEscrow contract is designed to enforce, what is policy and what we do not verify yet are set out in [Security & trust](https://inferit.cc/docs/security-trust.md). The live values (the owner Safe and its signers, the guardian and the operator) are read from the contract on the [Whitechain escrow](https://inferit.cc/docs/payments/whitechain.md#live) page. --- Canonical page: https://inferit.cc/security All pages as markdown: https://inferit.cc/llms.txt --- Source: https://inferit.cc/legal/terms.md # Terms of use > Terms for the Inferit testnet on Whitechain Sepolia: test tokens with no value, provided as is, acceptable use incorporated. These terms govern your use of the Inferit website, API and smart contracts on the Whitechain Sepolia test network (together, the "service"), operated by the Inferit project team ("we", "us"). By using the service you agree to them. - **Updated**: 2026-10-07 - **Network**: Whitechain Sepolia ## Testnet only, no monetary value - The service runs on Whitechain Sepolia, a public **test network**. It is a demonstration and development service, not a commercial offering. - ITC (Inferit Test Credit, the test credit used to pay for requests) and test WBT (Whitechain's gas token) have **no monetary value**. They cannot be bought from us, sold, redeemed or exchanged for money or any other asset, and nothing in the service is an offer to do so. Prices shown in dollars are test units (1 ITC counts as one test dollar). - Do not send real funds or tokens from any main network to any address shown in the service. - We may pause, reset, redeploy or retire the contracts, the API and its database at any time. Test balances, keys and usage history may be lost when that happens. ## What the service is Inferit is a marketplace that routes OpenAI-compatible inference requests from buyers to independent sellers who serve models from their own infrastructure, and settles usage through the MarketEscrow contract on Whitechain. Sellers are third parties, not our agents or subcontractors. We do not run the models, do not control what a seller's server returns, and do not review model outputs. Outputs can be wrong, incomplete or unsuitable for your purpose; you are responsible for how you use them. ## Provided as is, without warranties The service is provided **"as is" and "as available"**, without warranties of any kind, express or implied, including warranties of merchantability, fitness for a particular purpose, non-infringement, accuracy, availability or security. In particular: - The smart contracts are **unaudited testnet software**. Their documentation describes how they are designed to behave; bugs may make them behave differently. - Settlement on Whitechain is final only once its block is finalized; earlier states can in principle be reorganised. See [Finality](https://inferit.cc/docs/payments/whitechain.md#finality). - Public blockchains, wallets, RPC endpoints, explorers and faucets are operated by third parties and may fail or change. ## Acceptable use The [Acceptable use policy](https://inferit.cc/legal/acceptable-use.md) is part of these terms. If you break it, or these terms, we may revoke your API keys, stop routing requests to or from your account, delist your offers and report unlawful activity to the authorities. ## Your responsibilities - Keep your wallet and API keys secure. You are responsible for activity under your keys and wallet. - Set spending caps you are comfortable with; within your cap, charges follow the metered usage reported for your requests. - Sellers must have the right to serve the models they list under those models' licences; that right is the seller's responsibility, and its terms are between the seller and the model's licensor, not us. Sellers must run the endpoint they list themselves (no resale of another provider's API), and must not log, retain or train on buyer requests. - Do not send personal data, secrets or other sensitive content in prompts: sellers see prompts in plain text. ## Eligibility and restricted jurisdictions You must be at least 18 years old and able to agree to these terms. You may not use the service if you are located in, or a resident or national of, a country or region subject to comprehensive sanctions, or if you are listed on, or owned or controlled by someone listed on, a sanctions list maintained by the United Nations, the European Union, the United Kingdom or the United States. You may not use the service to evade sanctions or export controls. ## No financial advice The service is not financial, investment, legal or tax advice. ## Limitation of liability To the maximum extent permitted by law, we are not liable for any indirect, incidental, special, consequential or punitive damages, or for any loss of data, profits, tokens or goodwill, arising from or related to the service. Because the testnet service is free and its tokens have no value, our total liability for any claim relating to it is limited to the greatest extent the applicable law allows. Nothing in these terms limits liability that cannot be limited by law. ## Changes and termination We may change these terms, or change, suspend or end the service, at any time. The date at the top shows the latest version; continuing to use the service after a change means you accept it. You may stop using the service at any time. ## Governing law and disputes These terms are governed by the law of the place where we are established, without regard to conflict-of-laws rules. If a dispute comes up, raise it with us first through the contact on the [About page](https://inferit.cc/about.md#contact), so we can try to settle it directly. Nothing in these terms takes away rights you have under the mandatory law of the place where you live. --- Canonical page: https://inferit.cc/legal/terms All pages as markdown: https://inferit.cc/llms.txt --- Source: https://inferit.cc/legal/privacy.md # Privacy notice > What the Inferit testnet processes: wallet addresses, hashed API keys, usage metadata and IP logs. The API never stores prompt bodies; the seller that serves a request sees it. How the Inferit project team handles data when you use the Inferit testnet website and API. In short: we keep what is needed to authenticate you, meter usage and settle it on-chain, and never store the content of your prompts or completions. - **Updated**: 2026-10-07 - **Network**: Whitechain Sepolia ## What we process | Data | Why | How it is kept | | --- | --- | --- | | Wallet addresses | Sign-in (you sign a message with your wallet), linking your account to the escrow, routing settlement | Stored with your account. Also public on the blockchain (see below). | | API keys | Authenticating inference requests | Only a peppered SHA-256 hash and a short display prefix are stored. The full key is shown to you once. | | Session tokens | Keeping you signed in for 24 hours | Signed tokens kept only in your browser's local storage; they expire after 24 h. | | Usage metadata | Billing, your usage log and CSV export, settlement | Time, model, token counts, cost, latency, settlement status. No prompt or completion text. | | x402 payments | Paying for a request without an API key, and refusing a payment that is presented twice | The paying wallet address, the authorization's amount, nonce and expiry, the deposit transaction and its status. The signature itself is never stored or logged. The deposit is also public on the blockchain. | | Seller offer data | Listing and routing to your endpoint | Endpoint URL (shown only to you), price, health. Endpoint tokens and upstream keys are encrypted (AES-256-GCM). | | Email addresses | Hackathon signups: sending you your API key and, if you agreed, Inferit updates | Stored with your signup until you ask us to delete it. Only the Inferit team can read the list. | | IP addresses | Rate limiting and abuse prevention | In server logs and the in-memory rate limiter. Logs are kept for up to 30 days. | ## Hackathon signups When you sign up at a hackathon, we store the email you give us to send you your API key and, if you agreed, Inferit updates. With it we keep when you signed up and a one-way hash of your network address, used to limit repeated signups. We keep your email until you ask us to delete it. To ask, message us on X at [x.com/inferit\_](https://x.com/inferit_). ## Prompts and completions Request and response bodies are **relayed, never stored or logged** by Inferit. To answer a request, the API forwards it to the seller whose offer it was routed to, and that seller sees the prompt in plain text. Sellers are separate parties that run their own servers; today every seller is run by the Inferit team. Sellers agree not to log, retain or train on buyer requests, but we cannot technically verify this, so do not send personal or sensitive data in prompts. ## Public blockchain data Deposits, spending caps, withdrawals, seller registrations and every settlement line are transactions on Whitechain Sepolia, a public blockchain. They show wallet addresses and amounts to anyone, permanently. Neither we nor anyone else can delete or change them. Use a dedicated wallet if you do not want this activity linked to your other addresses. ## Your browser The site uses no analytics or advertising trackers. The landing pages (home, docs, blog) set no cookies. The app (Buy, Sell, Models, Metrics) sets two first-party functional cookies. Neither holds an identifier or anything about you: - `inferit_ws` holds `buy` or `sell`: the workspace you used last, so the app's home opens it. It lasts 1 year. - `inferit_ws_entry` holds `1`. The app's home sets it when nothing is remembered yet, so that after you sign in the app can open your wallet's own workspace once. It is cleared on use and lasts at most 10 minutes. The site also uses your browser's local storage for your theme, your session and, in development builds, the API address. When you use wallet features, your browser talks directly to the Whitechain RPC and block explorer, which are operated by third parties under their own policies. ## Service providers The website is hosted on Vercel; the API and its database on Railway. They process data on our behalf to run the service. Model inference is performed by the independent seller that serves each request. ## Retention - Server logs, including IP addresses: up to 30 days. - Hackathon signup emails: until you ask us to delete them. - Accounts, hashed keys and usage records: while the testnet runs. Testnet resets may delete them earlier. - Revoked keys and deleted offers: the secret material is destroyed at once; the key hash or offer record may remain for billing history. - On-chain data: permanent, outside our control. ## Your choices and rights You can revoke keys yourself in the [Buy](https://inferit.app/buy) workspace and delete offers in the [Sell](https://inferit.app/sell) workspace. This testnet build lists no privacy address, so requests for a copy or deletion of your account data cannot be sent here. Revoking your keys and deleting your offers needs no request. Deletion covers off-chain data only: transactions on Whitechain are public and permanent, and nobody, including us, can delete them. Depending on where you live, you may also have the right to object to processing or to complain to a data protection authority. --- Canonical page: https://inferit.cc/legal/privacy All pages as markdown: https://inferit.cc/llms.txt --- Source: https://inferit.cc/legal/acceptable-use.md # Acceptable use policy > What you may not do with Inferit, including zero tolerance for child sexual abuse material. This policy applies to everyone who uses Inferit: buyers sending requests, sellers serving them, and anyone using the website or API. It is part of the [Terms of use](https://inferit.cc/legal/terms.md). - **Updated**: 2026-10-07 - **Network**: Whitechain Sepolia ## Zero tolerance: child sexual abuse material You must not use the service to create, request, distribute or store child sexual abuse material, or any sexual content involving minors, including text, fictional or synthetic content. We terminate access immediately, preserve the relevant records and report it to the competent authorities (including the NCMEC CyberTipline where applicable). There are no warnings for this. ## Prohibited uses - Anything illegal where you or the seller are, or content that facilitates a crime. - Malware, phishing, fraud, scams, spam, or generating content to deceive people about who made it where that is unlawful. - Harassment, threats, incitement to violence, or content that promotes terrorism or violent extremism. - Non-consensual intimate imagery, doxxing, stalking, or processing other people's personal data without a lawful basis. - Infringing intellectual property or other rights. - Evading sanctions or export controls, money laundering, or financing terrorism. - Uses the model's licence forbids. Several open-weight licences carry their own use policies (for example the Llama and Gemma policies); they apply to requests for those models. - Attacking the service or its users: probing for vulnerabilities outside the [security policy](https://inferit.cc/security.md), denial of service, evading rate limits, abusing faucets, or accessing accounts, keys or data that are not yours. ## Additional rules for sellers - Serve only models you have the right to serve, under their licence terms. Having that right is your responsibility: its terms are between you and the model's licensor, not Inferit. - Run the endpoint you list yourself. Reselling another provider's API, or proxying it behind your own domain, is not allowed. - Do not log, retain, inspect beyond what is needed to serve the request, or train on buyer requests and responses. - Report the token usage you actually served; do not inflate it. ## Enforcement If we believe this policy has been broken we may, without notice, revoke API keys, stop routing requests to or from an account, delist offers, and report unlawful activity to the authorities. Because settlement runs on a public smart contract, we cannot reverse transactions that are already on-chain. ## Reporting abuse This testnet build lists no abuse address. Unlawful material can be reported to the authorities where you live. Security vulnerabilities go through the [security policy](https://inferit.cc/security.md). --- Canonical page: https://inferit.cc/legal/acceptable-use All pages as markdown: https://inferit.cc/llms.txt