API reference
Base URL https://api.multigrid.ai/v1. Everything is JSON over HTTPS. The version is the /v1 in the path, and it is the only one there has been.
Authentication
Send your key as a bearer token. Keys are scoped to a project and can carry their own spend cap and rate limit, so a leaked client key cannot drain the account.
curl https://api.multigrid.ai/v1/models \
-H "Authorization: Bearer $MULTIGRID_API_KEY"Request headers
- Authorization
- `Bearer mg_live_…`. Required on every call except the three public catalogue reads: GET /models, GET /providers and GET /models/{vendor}/{model}/endpoints.
- Idempotency-Key
- Client-generated key. A retry replays the stored answer rather than paying for the same completion twice; the claim is taken before we go upstream, so two simultaneous retries cannot both run.
- X-Multigrid-Cache-Ttl
- Seconds, up to 86400. Opts this request into the exact-match cache — which is off unless you ask for it. Equivalent to `{ "cache": { "ttl": … } }` in the body.
- X-Multigrid-Batch-Name
- On POST /batches only. A label for the job, so it is identifiable in the dashboard. `?name=` does the same thing.
- HTTP-Referer
- OpenRouter's attribution header, accepted so that migrating is a base-URL change and nothing else. Stored as the `referer` request tag, filterable in Activity — unless you set `metadata.referer` yourself, in which case the body wins.
- X-Title
- OpenRouter's app-name header. Stored as the `title` request tag, on the same terms.
Response headers
- X-Multigrid-Request-Id
- Stable id. Pass it to GET /generation to see what the request did.
- x-request-id
- The same value, under the name OpenAI's SDKs and every piece of logging middleware written against them already look for. Both are always written together; neither is more authoritative.
- X-Multigrid-Model
- The model that actually served the request, which is not always the one you asked for.
- X-Multigrid-Provider
- The provider that actually served it.
- X-Multigrid-Attempts
- How many providers were tried before one succeeded.
- X-Multigrid-Cost-Usd
- Exact cost to six decimal places. Absent on a stream, where the cost is not known until the last token — it rides the terminal SSE chunk instead.
- X-Multigrid-Byok
- `true` when your own provider key served it, and we therefore charged you nothing.
- X-Multigrid-Cache
- `hit`, and only on a hit. Absent on every other response.
- X-Multigrid-Idempotent-Replay
- `true` when this is a stored answer replayed against an Idempotency-Key rather than a fresh completion.
- X-RateLimit-Limit
- Requests permitted in the current 60-second window. On successful responses as well as the 429 — an adaptive-concurrency client needs the headroom before it is refused, not after.
- X-RateLimit-Remaining
- How many are left in it.
- X-RateLimit-Reset
- Seconds until the window empties. Relative rather than a timestamp, so no clock agreement is needed.
- X-Multigrid-Batch-Status
- On GET /batches/{id}/results only: the job's status when the download began, so a partial file is explicable.
Inference
/chat/completionsCreate a chat completionThe main inference endpoint. OpenAI-compatible, with optional models, provider, cache and retry fields an ordinary OpenAI SDK passes straight through. The model id may be a plain vendor/model slug, a slug with a :floor, :nitro or :free routing suffix, multigrid/auto (the cheapest model that fits the prompt and the capabilities you need, with the reason in the response), or @preset/name.
Parameters and examples/embeddingsCreate embeddingsVectors from any embedding model in the catalogue, billed per token like everything else.
Parameters and examples/images/generationsGenerate an imageText-to-image through the same key, balance and spend cap. Billed per image rather than per token.
Parameters and examples/video/generationsGenerate a videoBilled per unit of output, against the same balance and the same ceiling.
Parameters and examples/rerankRerank documentsScore a set of documents against a query. Per-unit pricing, not per token.
Parameters and examplesCatalogue
/modelsList modelsThe catalogue in OpenAI's /v1/models shape, with prices as both a per-token decimal and integer micros. No key required — prices are what people compare before they sign up. ?modality=chat|embedding|image|video|rerank narrows it to the ids one endpoint accepts, which is the list worth trusting over any page.
Parameters and examples/models/{vendor}/{model}/endpointsList a model's routesEvery provider that serves one model, with what that route costs and its priority — routes on the same model can be priced differently.
Parameters and examples/providersList providersThe providers we can route to, and what each one is.
Parameters and examplesBatch
/batchesCreate a batchQueue a set of requests to run without holding a connection open. Billed at exactly the same rate as a live call — there is no batch discount. The body is the JSONL file itself, not an uploaded file id: this is not OpenAI's batch API and client.batches.create() will not work against it. ?name= labels the job.
Parameters and examples/batchesList batchesYour jobs, newest first, with counts and status. Capped at 100 with no cursor.
Parameters and examples/batches/{id}Cancel a batchStops dispatch. Items that already ran are still billed and their results stay downloadable.
Parameters and examples/batches/{id}/resultsDownload batch resultsThe completed items, including the ones that failed and why, as JSONL keyed by your own custom_id. ?filter=failed|succeeded narrows it. Readable while the job is still running — X-Multigrid-Batch-Status says how far along it was.
Parameters and examplesObservability
/generationRetrieve one requestWhat a single request actually did, by request id — for when the response body did not survive a crash or a retry loop. Scoped to your own account.
Parameters and examples/usageUsage and costThe same aggregates the Analytics page renders, by day, model and provider, so a finance team can reconcile an invoice without screen-scraping.
Parameters and examples/feedbackSubmit a quality scoreAttach your own score to a request id, so Analytics can put quality next to price. Idempotent — a second score replaces the first.
Parameters and examplesManagement
/keyInspect the calling keyBalance, key cap, account cap and rate limit, so a client can tell which of the four ways it can be refused applies without triggering each one.
Parameters and examples/creditsRetrieve credit balanceThe account balance, derived from the ledger.
Parameters and examples/keysList API keysRequires a provisioning key; an inference key gets a 403 that says so.
Parameters and examples/keysCreate an API keyMint a scoped key with its own spend cap and rate limit. The secret is returned once.
Parameters and examples/keys/{id}Revoke a keyEffective immediately: the key row is read from the database on every request, so there is no cache to wait out.
Parameters and examplesOAuth
/api/oauth/tokenRedeem an authorization codeThe tail of the PKCE flow: an authorization code becomes an ordinary inference key with no expiry. Errors here are RFC 6749 shaped, not ours, so any OAuth library parses them. CORS is open — a single-page app is a first-class caller.
Parameters and examples/api/oauth/clientsList OAuth applicationsThe applications this account has registered. Requires a provisioning key, so every client on the consent screen traces back to an account.
Parameters and examples/api/oauth/clientsRegister an OAuth applicationPublic clients only — PKCE with S256, and no client secret is ever issued or returned.
Parameters and examplesRate limits
There are two, and the tighter one wins: the limit you set on a key yourself, and — when you set none — a default that rises with the account’s trust level as settled payments accumulate. The ceilings are deliberately set above what a real production service reaches, because this limiter is a blast-radius control for a leaked key rather than a quota. What actually bounds your spend is the balance, the per-key spend cap and the account’s monthly ceiling, all three of which are denominated in money.
Every response carries X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset, successes included, so a client can slow down before it is refused rather than after. A 429 adds Retry-After, which is authoritative. For the exact number applying to one key, GET /key reports it alongside your caps and balance.
Calling this from a browser
Every endpoint under /v1 sends Access-Control-Allow-Origin: * and answers preflight OPTIONS, so client-side fetch works. It is safe to open because these endpoints authenticate with a bearer token and never with a cookie, so there is no ambient authority for a hostile page to borrow. The X-Multigrid-* and X-RateLimit-* headers above are all listed in Access-Control-Expose-Headers, so browser JavaScript can read them.
That does not make it a good idea to ship a key you paid for into a web page. Mint a key with its own spend cap for anything a browser holds, or use the OAuth flow so each user brings their own.