Docs

AISIX 0.13.0

This release is about telling traffic apart and reaching an upstream on its own terms.

Release date: September 1, 2026

This release is about telling traffic apart and reaching an upstream on its own terms. A Provider Key can now declare which API surfaces its endpoint serves natively and where each one lives, so one credential reaches both the OpenAI-compatible path and the Anthropic-compatible path an upstream serves, without a second key or a second model. Every usage record now names the work that was asked for, so an image generation and a video submission are no longer the same undifferentiated OpenAI stream in an exporter or in Logs. A caller the gateway rate-limits gets a response that says what the cap was and when to come back. And a response now reports the gateway model name the caller addressed on every endpoint that serves one, rather than the provider's own id on some of them.

Behavior Changes

  • Existing DeepSeek provider keys reach DeepSeek's own routes after the upgrade, instead of being translated. AISIX now carries a verified declaration of the API surfaces DeepSeek serves — its native /v1/responses and its Anthropic-compatible /anthropic/v1/messages — and applies it once, at upgrade, to provider keys that have no declaration of their own, use the deepseek provider, and still point at https://api.deepseek.com. Those keys report apis_source: catalog. What changes for traffic: a Responses API request is forwarded to DeepSeek's own /v1/responses rather than translated to chat completions, so reasoning output items survive; and an Anthropic-wire request reaches the Anthropic-compatible path, so prompt-cache breakpoints and thinking blocks survive. A key you declared yourself is left untouched.

  • A client reading the model field off a response now sees the gateway model name it asked for, on /v1/messages, /v1/responses, /v1/completions and /v1/embeddings — streamed and buffered alike — and on /v1/videos polls. These paths previously returned the provider's own id, so a model aliased gpt4o-mini came back as gpt-4o-mini-2024-07-18, while /v1/chat/completions already returned the alias. Passthrough routes are unchanged and still relay the provider's response as-is.

  • A gateway rate-limit rejection now carries response headers. A 429 the gateway itself produces describes the single limit that refused it: x-ratelimit-limit, x-ratelimit-remaining, x-ratelimit-reset, x-ratelimit-scope and Retry-After. x-ratelimit-reset and Retry-After are both a delta in seconds. A concurrency rejection now carries a retry hint where it previously carried none. These headers are added only when the gateway refuses the request; a 429 relayed from an upstream is passed through as the upstream sent it. The per-dimension x-ratelimit-limit-requests / -tokens / -concurrent headers on successful responses are unchanged.

  • A Prometheus gauge whose key no longer exists stops reporting its last value. aisix_budget_limit_usd / _spent_usd / _remaining_usd / _reset_seconds / _details_present and aisix_ratelimit_remaining_{requests,tokens} are written only from the request path, so deleting an API key used to freeze its series at whatever it last read — and an alert on budget exhaustion kept firing for a credential that no longer exists. Such a series is now retired to NaN, which Prometheus treats as no value rather than as zero. An alert that compares these gauges no longer matches a deleted key. If you built a dashboard panel that reads a raw value, expect a gap rather than a flat line after a key is deleted.

New Features

  • Native API surfaces on a Provider Key. One upstream account often exposes more than one protocol, on different paths of the same host, under one credential — DeepSeek, Zhipu and Kimi each front an OpenAI-compatible path and an Anthropic-compatible one. api_base can name only one of them, so everything else was translated, losing what the target protocol carries and the canonical chat shape does not. A Provider Key now takes an apis block naming each surface and, optionally, the base URL it lives at:

    {
      "apis": {
        "responses": {},
        "messages": { "base": "https://api.deepseek.com/anthropic" }
      }
    }

    The two surfaces resolve on different terms, because the evidence for them differs. messages is additive: a key whose adapter is already anthropic keeps serving /v1/messages natively whatever the map says, and listing it here adds the route to a key whose adapter is something else. responses is authoritative: once the block exists, /v1/responses is served natively only if it is listed — which is how an operator says "this endpoint has no Responses route" and gets the request translated to chat completions instead of 404'd upstream. With no block at all, both fall back to what the gateway inferred before: /v1/messages from the vendor id or the anthropic adapter, /v1/responses from the vendor id alone. Surfaces the block has no key for — embeddings, audio, images, videos, files, batches, fine-tuning, rerank — always use api_base, exactly as before. Set the block to {} to declare that the endpoint serves nothing beyond its adapter's own surface, or to null to clear the declaration. Configurable in the console on the Provider Keys page, and over the Cloud Admin API on POST and PATCH /provider_keys.

  • Usage records name the operation that was asked for. Every usage event now carries operation — the kind of work a request asked for, chosen by the route it matched and never by caller text: chat, completions, messages, count_tokens, responses, embeddings, rerank, realtime, image_generation, image_edit, transcription, translation, speech, video_generation, files, batches, batch_completion, fine_tuning, mcp, a2a and passthrough. inbound_protocol reports openai for every OpenAI-shaped route, so nothing could previously separate a text chat from an image generation or a video submission short of a regular expression over a captured prompt — which a metadata_only exporter has no prompt for, and which a zero-token video submission does not answer at all. The field reaches your own exporters (OTLP, Datadog, SLS) and the console: Logs filters on the operation and marks each request with it — the conversational endpoints (chat, messages, responses, completions) are left unmarked as the common case — and GET /usage_events and GET /usage_events/export take an operation query parameter and return the field on each item.

Improvements

  • Usage-event and budget metrics name the member, not just their id. aisix_usage_events_emitted_total, aisix_usage_event_drops_total and the five aisix_budget_* gauges now carry user_name beside user_id, matching aisix_proxy_requests_total and the aisix_llm_* families. A usage-event alert or a budget dashboard can name the person it is about without a lookup outside Prometheus.

Fixes

  • aisix_budget_remaining_usd is now published. The gateway could only emit this gauge when the control plane stated the remaining amount in its budget decision, and the decision never carried it — so a series the metric reference documents existed in no 0.12.0 or earlier deployment, and a dashboard panel or alert built on it matched nothing. It now appears alongside aisix_budget_limit_usd and aisix_budget_spent_usd, on the same labels and at the same moments. Upgrading the control plane is enough; no gateway change and no configuration.
  • The sign-in error for a rejected origin no longer misstates what the server trusts, or points you at the wrong component to restart. It said the server trusts only the one address it is configured to serve on; it also trusts that address's localhost/127.0.0.1 twin and every origin in AISIX_TRUSTED_ORIGINS, and the message now offers that second remedy. It also told the operator to restart cp-api, where the check that rejected them runs in the dashboard.
  • The Helm chart's post-install notes no longer name an address the port-forward they tell you to run does not serve, and carried the same overstated claim about trusted origins.

API Changes

No breaking changes. All additions are optional.

EndpointChange
  • POST /provider_keys
New optional request property apis. The 201 response may now carry warnings when a data plane in scope runs a gateway too old to execute a declared surface.
  • PATCH /provider_keys/{provider_key_id}
New optional request property apis; null clears the declaration, {} declares that the endpoint serves nothing beyond its adapter's surface. Response adds apis, apis_source and warnings.
  • GET /provider_keys/{provider_key_id}
Response adds apis, apis_source (catalog or operator) and warnings.
  • GET /environments/{env_id}/usage_events
New optional operation query parameter; each item gains operation.
  • GET /environments/{env_id}/usage_events/export
New optional operation query parameter; each exported item gains operation.

Note that apis is not echoed by the create response, the same as api_base — read it back with GET /provider_keys/{provider_key_id}, whose apis_source reports catalog when AISIX supplied the declaration rather than you.

Upgrade Notes

These notes apply when you upgrade from any release earlier than 0.13.0, including an upgrade that passes over it on the way to a later release.

  • The control plane applies the curated API-surface declaration once, on the first boot after the upgrade, to the provider keys described under Behavior Changes. It is best-effort and idempotent: a boot that cannot complete it retries on the next one, and a key that already carries a declaration is never touched. Set apis yourself on any key whose endpoint you do not want reached natively.
  • If you alert on aisix_budget_* or aisix_ratelimit_remaining_*, review the expressions against the gauge-retirement change above before upgrading.
  • A gateway still running a release before 0.13.0 records no operation, because the gateway is what derives the value from the matched route. While such a gateway is in the fleet, filtering by operation — in Logs, on GET /usage_events, or on an export — excludes its traffic from the results. Its requests are proxied and recorded as before; only the operation filter cannot see them. Upgrading the gateway resolves it for traffic from that point on; rows already recorded without an operation stay outside the filter.