Migrating from another gateway
What carries over unchanged, what is named differently, and what we do not implement.
The swap
Coming from OpenAI directly, or from a gateway that speaks the same format, the diff is three lines.
- baseURL: "https://api.openai.com/v1",
- apiKey: process.env.OPENAI_API_KEY,
- model: "gpt-4o",
+ baseURL: "https://api.multigrid.ai/v1",
+ apiKey: process.env.MULTIGRID_API_KEY,
+ model: "openai/gpt-4o",Model ids are the one thing that always needs touching: ours are namespaced vendor/model. GET /models is public, so you can map your ids before you change any code.
What carries over
The request body is OpenAI’s and validation is deliberately shallow: we check that model is a non-empty string and that messages has at least one entry, and let everything else through. A parameter a vendor added last week reaches them untouched rather than being rejected by us for being unfamiliar.
The routing fields are named the same way OpenRouter names them, on purpose: models for a fallback chain and provider: { order, ignore, allow_fallbacks, sort } for provider preferences. A config carried over keeps working rather than being silently ignored, which would change your bill without changing your code. See provider preferences.
What is different
- Responses carry a
multigridobject. Model, provider, attempts and exact cost. Additive: clients that do not know about it ignore it. - Errors use OpenAI’s envelope with our codes.
{ error: { message, type, code, request_id } }. Existing error handling keeps parsing; thecodevalues are ours. See the error reference. - Streams end with our terminal chunk. Usage and cost arrive on a final chunk before
data: [DONE], so a client that stops reading at the firstfinish_reasonwill miss the numbers but not the answer. HTTP-RefererandX-Titleare read. Both attribution headers land as therefererandtitlerequest tags, filterable in Activity and groupable in Analytics like any other tag, so the labels you have been slicing spend by survive the move without touching a call site. An explicitmetadata.refererormetadata.titlein the body wins over the header. There is no public app leaderboard here for them to feed; they are yours.- Browser calls work, and the spec is machine-readable. Every
/v1endpoint sends CORS headers and answers preflights, so a client-side integration carries over. The OpenAPI 3.1 document at/api/openapi.jsongenerates clients, Postman collections and mocks.
What we do not implement
route is accepted and stripped before the request leaves us: nothing breaks if it arrives, and nothing happens either.
transforms used to be in that sentence with it. One value is implemented now — ["middle-out"], which fits a conversation into a window smaller than it is by dropping whole turns from the middle outward. Any other value is still accepted and inert. See chat completions for what it keeps and what it reports.
There is also no stored, versioned routing policy object to migrate to. Routing is expressed per request, or saved as a preset you call by name.
Checklist
- Map every model id against
GET /models. - Confirm we hold a route for each one:
GET /models/{vendor}/{model}/endpointslists the providers, in the order they will be tried, with prices. - Move gateway-specific fields you were sending into
metadataor delete them.HTTP-RefererandX-Titlecan stay as they are. - Set a spend cap on the new key before you point production at it.
- Run a playground call against each model to confirm we have a working key for its provider on this deployment.
Something here disagrees with what the API actually did? That is a bug in this page, and worth reporting.
Report it