Models added and retired, pricing and contract changes, SDK releases, and deprecations — dated, in plain language, newest first. A deprecation always names its replacement and the date it can first stop serving.
Google's Gemini Omni Flash renders three- to ten-second clips with native audio from text or a start image and is served on the Gemini Interactions API; it passed funded text-to-video and image-to-video probes before listing. The Kling 3.0 family is now complete: the Standard tier at 720p, the Turbo tier at 1080p with audio included, and Omni, which takes up to four reference images alongside a start and end frame. Kling 3.0 tiers and Omni Flash accept a native three-second clip. Rates are on the price sheet; video prices remain flat per request at each model's longest accepted clip.
POST /videosGET /pricinggemini-omni-flashkling-3kling-3-turbokling-3-omniThe OpenAPI document now carries a status on each operation instead of hinting at it in a summary string. Compatibility surfaces — /chat, /images, /video, /video/status and the session endpoints — are marked as such, with the modern path named beside them. They are deliberately NOT flagged as deprecated: they are kept working indefinitely, so a generated client should not warn on code that is fine. When something genuinely does enter a removal countdown, it appears here with its replacement and the notice window we hold ourselves to before anything stops serving.
GET /openapiPOST /chatPOST /imagesGET /video/statusThe price sheet advertised a discount for repeated requests through a gateway response cache. That cache does not exist and never did: an identical request is executed again and billed again, and no code in the billing path ever read the field. It now returns null, and stays on the wire for the notice window so a client reading it does not break. The caching that IS real is the provider's prompt cache — opt in with routing.caching set to auto, and cache-read input tokens bill at that model's published cached-input rate.
cache_hit_fraction on GET /pricing on GET /pricing. Use routing.caching: "auto" (provider prompt caching), billed at each model's cached-input rate. It keeps serving until at least — we give at least 180 days' notice before removing anything.
GET /pricingEvery video row on the price sheet now carries its basis: the published figure is the model's LONGEST accepted duration, not a typical charge. Shorter requests settle lower — per-second models bill each second up to their cap, and bucketed models bill the nearest supported length. Both of our numbers had always been right and they disagreed, because nothing on the row said which basis it was on.
GET /pricingPOST /videosChat, image and video errors now normalize to the same OpenAI-compatible body whatever went wrong upstream. You get a stable code (provider_timeout, provider_rate_limited, provider_unavailable, provider_model_unavailable, provider_authentication_error), a retryable flag you can branch on, the upstream status, and the provider's own request id when it gives us one. Upstream URLs and anything that looks like a credential are stripped from the message, and a failure that cost you nothing says so.
POST /chat/completionsPOST /images/generationsPOST /videosChoose a reasoning effort or thinking-token budget on supported models. Chat and Responses forward native settings to eligible providers. Unsupported controls return an error; per-token rates stay the same.
POST /chat/completionsPOST /responsesThe published wheel has always enforced 3.10, while this repository and the docs said 3.9 — so anyone on 3.9 followed our own instructions into a resolution error. Everything now states 3.10: what the artifact enforces, and the oldest release still receiving security fixes. The TypeScript client is unaffected.
GET /models has always listed only models with a live route, but Google Imagen 4, Veo 2 and Veo 3 Fast were still named in our comparison pages and documentation long after their routes went dark. They are removed from that copy, and an audit now fails the build when public copy names a model the API does not serve. If you pinned one of these ids, the current Google equivalents are Nano Banana Pro for images and Veo 3.1 or Veo 3.1 Fast for video.
GET /modelsgoogle-imagen-4google-veo-2google-veo-3-fastnano-banana-proveo-3.1veo-3.1-fastVideo generation through the MCP server now keeps its automatic recovery when a tool picks a concrete model on your behalf, instead of acquiring the stricter semantics of an explicitly requested model, and an end-frame request routes only to a model that honours one. The MCP catalog is a curated subset of the REST media catalog priced on the same curve, so a model whose route is dark can no longer be advertised there, and a video price is quoted at the default duration rather than the maximum.
When every eligible model failed before producing a token, the stream wrote its error event and [DONE] and then held the socket open until the client gave up. It closes now. Two contract reminders that go with it: stop reading at [DONE], and treat any streamed frame carrying an error object as terminal — since a stream commits its 200 before a model is selected, that frame is how a failure reaches you.
POST /chat/completionsImage generation takes a storage option. The default, durable, copies the result into NinjaChat storage and returns a permanent URL. Setting it to provider skips that hop for lower latency and returns the provider's temporary URL or an inline base64 payload — good for a pipeline that stores its own output, and not for anything you plan to link to later. In the same pass, a durable request that cannot be persisted now fails and refunds rather than returning a provider URL that expires within a day.
POST /images/generationsImage and video requests that fail validation now return the offending parameter and a sentence a human can act on — which value was rejected and what is accepted instead — rather than raw schema output.
POST /images/generationsPOST /videosBoth new models passed live text, streaming and tool-call probes before being listed. One integration note: neither honours a forced tool_choice upstream, so send auto and let the model decide. GPT-5.5 previously had only a route with a low completion ceiling, which refused any request that asked for reasoning headroom; it now has a direct primary route. Rates for all three are on the price sheet.
GET /pricingclaude-fable-5.1qwen-3.8-flashgpt-5.5Keys minted by the in-page playground are marked as playground keys and pruned to the two most recent, so a few afternoons of experimenting can no longer walk an account into its active-key cap. Keys you create yourself are never touched.
A streaming request now returns its 200 and headers as soon as it is admitted, and sends comment keepalives whenever nothing has been written for a few seconds, so a proxy cannot drop a long-thinking request that had not yet produced output. Because the status is already committed, a failure of every candidate before the first token arrives as an in-band error frame followed by [DONE] instead of an HTTP 502, and a provider that dies mid-answer ends the stream with a partial_stream error rather than a clean finish. finish_reason now uses the OpenAI vocabulary — stop, length, tool_calls, content_filter. The Responses stream gained a response.failed event and returns the full output array on completion.
POST /chat/completionsPOST /responsesThe work between accepting a request and opening the provider connection went from about fourteen sequential internal round trips to about five: admission checks are pipelined, circuit-breaker state is read in one shot, key records are cached briefly, and account, project and access lookups run in parallel. Nothing about routing or billing changed — the same checks run, they just stopped queueing behind each other.
A database index change made every settle-refund and failure-refund fail silently, so chat requests in that window were billed the pre-authorized hold instead of settling down to actual token usage. It is fixed, and the durable refund path is back to reconciling every request. GET /requests/{id} shows what a given request actually settled at; if you see requests from that window billed above their usage, send us the request ids and we will reconcile them.
GET /requests/{id}/chat, /images, /video, /video/status and the session endpoints — along with pricing, network, estimate, batch, compare, battles and pipelines — are served again after briefly returning 410, and are back in the OpenAPI contract. They are supported indefinitely because real integrations depend on them; they are simply not where a new integration should start. /chat in particular is a real translation layer, not an alias: it accepts the retired routing dialect and server-side conversation ids and normalizes them into the modern body.
POST /chatPOST /imagesPOST /videoGET /video/statusPOST /sessionsGET /pricingGET /networkPOST /estimatePOST /batchPOST /compareGET /battlesPOST /pipelinesThe active-key cap was raised from five to twenty-five. It caps live secrets, not usage, so per-service and per-environment keys no longer compete for slots. Hitting it returns a key_limit_reached code and a link to the keys page instead of a bare string.
A shared wallet now has roles. An admin works as before; a viewer keeps read access to dashboards, usage and request logs but cannot mint or rotate a key, change spend limits or auto-reload, add a payment method, or invite anyone. Existing members stay admins, so nothing silently lost access. Only the owner changes a member's role.
Turn it on in Developers → Billing → Security and a fresh emailed code is required before creating or rotating a key, changing spend limits or auto-reload, adding a payment method, storing a provider key, registering a webhook, or inviting a teammate. The grant lasts a few minutes and then expires. Revoking a key or deleting a webhook is deliberately never gated — a kill switch must always work.
The router has one canonical id. The bare alias still works and is canonicalized before validation, as do the model ids we renamed — an alias bills under the id it resolves to, never a different price. Responses now carry a routing block naming the task the request was classified as, the candidates considered, and why each one that lost was eliminated.
POST /chat/completionsPOST /responsesauto → ninja/autoseedance → ninja-1gpt-5.2 → gpt-5deepseek-chat-v3 → deepseek-v3kimi-k2-instruct → kimi-k2A chat request pre-authorizes an estimated maximum and then settles to actual token usage in both directions: under-use is refunded, and usage above the reserve is charged rather than absorbed. The reserve is not a price ceiling — routing.max_cost_usd is, and it is honoured absolutely; usage priced above it is never billed to you. A completed response is never failed to collect a shortfall. Media and video still settle downward only: a cheaper fallback refunds the difference, and a pricier one never charges above the model you asked for.
POST /chat/completionsPOST /responsesChat Completions accepts the OpenAI SDK's own completion-token field and folds it into max_completion_tokens, accepts a single-choice request, and ignores parameters that would be no-ops for us — while genuine use of anything we do not support still fails with a message naming it. Error bodies carry flat message, code and request_id fields beside the nested error object for pre-gateway clients, and the model list mirrors its data array under the older key.
POST /chat/completionsGET /modelsDeveloper Balance top-ups can be paid in crypto through a hosted Coinbase checkout, alongside cards. Pick Card or Crypto in Developers → Billing. Credit is granted only after the completed payment is re-fetched and verified, so a balance can never be credited from a webhook payload alone.
The delivery queue caps how many attempts one account can take from a single drain and runs the rest in parallel, so one slow endpoint can no longer hold up every other tenant's events. Delivery history is retained for about a month and readable from the deliveries endpoint; retries, backoff and dead-lettering are unchanged.
GET /webhooks/deliveriesPOST /webhooksDeepSeek V4 Flash and V4 Pro, Gemini 3.5 Flash and 3.1 Flash Lite, Qwen 3.5 35B A3B, Qwen3 VL 4B/8B, Qwen3 Coder 30B A3B, and Qwen3 235B Instruct are now available. Claude Haiku 4.5, Claude Opus 4.6, GLM 5, and GLM 5.2 gained additional failover. Qwen3 Coder structured JSON stays off for now; text, code, tools, and streaming remain live.
Chat routing skips a provider when its context or completion limit can’t fit the request. GLM 5.1, Claude Sonnet 4.6, Claude Haiku 4.5, Gemini 2.5 Flash, and Gemini 3/3.1 Pro gained more failover. Claude Opus 4.8, Nemotron 3 Nano 30B A3B, Llama 3.3 70B Turbo, and Qwen3 VL 30B/235B are now available.
GLM 5.1, Nemotron Nano 12B v2 VL, and Nemotron 3 Nano Omni are now available. Gemma 4 31B and DeepSeek V3.2 gained an additional DigitalOcean failover route.
Muse Glimmer 30B, GLM 4.7, and Ministral 3 14B gained additional direct failover. Published token rates stay stable across failover — the price you see is the price you pay.
Chat requests are billed on exact token usage — published rates per million tokens for input and output, with discounted cache-read and long-context tiers where they apply. No flat per-request price and no length ceiling. GET /api/v1/pricing publishes the metered rates. The BYOK platform fee is computed on actual metered usage.
GET /pricingYou can now connect your own OpenAI, Anthropic, or Google API key and route requests through it directly — you pay the provider's own rate plus a platform fee instead of NinjaChat's markup. Manage keys from Developers → Billing → Provider keys.
Chat requests route straight to each model's own provider (OpenAI, Google, Mistral, Groq, and others) instead of through a third-party router. One less network hop, and failover stays under our control end to end.
Developers → Usage is now one summary view: daily spend by model, period-over-period deltas, top models by spend, and a lifetime activity streak.
Billing and security emails (spend-limit alerts, low-balance warnings, auto-reload receipts) were redesigned to match the product and render correctly across Gmail, Apple Mail, and Outlook, including dark mode.
Questions about a change? Open the developer console · GET /api/v1/models