API7 Docs
AISIX AI GatewayOpen-Source AISIX Gateway Admin APIList Provider Keys

List Provider Keys

GET /admin/v1/provider_keys

GET /admin/v1/provider_keys

Interactive request editor loads with JavaScript.

Authorization

AdminBearer
AuthorizationBearer <token>

Admin key from config.admin.admin_keys.

In: header

Response Body

application/json

application/json

application/json

curl -X GET "http://127.0.0.1:3001/admin/v1/provider_keys"

OK

[
  {
    "id": "string",
    "revision": 0,
    "value": {
      "adapter": "openai",
      "api_base": "string",
      "api_key": "string",
      "apis": {
        "messages": {
          "base": "string"
        },
        "responses": {
          "base": "string"
        }
      },
      "display_name": "string",
      "provider": "",
      "request": {
        "default_body_fields": {},
        "default_headers": {
          "property1": "string",
          "property2": "string"
        },
        "forward_client_headers": [
          "string"
        ],
        "param_constraints": {
          "temperature_max": 0,
          "temperature_min": 0
        },
        "param_renames": {}
      },
      "response": {
        "content_list_to_string": false,
        "error_envelope": "string",
        "reasoning_field": "string",
        "stream_done_marker": "required"
      },
      "secret": "string",
      "strip_headers": [
        "authorization",
        "cookie",
        "set-cookie",
        "x-api-key"
      ],
      "telemetry_tags": {
        "featured": false
      },
      "tls": {
        "ca_cert": "string",
        "verify": true
      }
    }
  }
]
Complete operation details and schema variants

GET /admin/v1/provider_keys

List Provider Keys

List all configured provider key resources.

Parameters

Responses

  • 200: OK
  • [].id (string, required): Resource ID, as assigned by the active resource source.
  • [].revision (integer, required): Monotonic resource revision: the etcd mod_revision of the entry, or the load generation in file mode.
  • [].value (object, required): Stored provider key configuration.
  • allOf variant 1
  • [].value.adapter (object, optional): Upstream API protocol family used when provider-specific dispatch is unavailable.
  • allOf variant 1
  • [].value.api_base (string,null, optional): Override base URL for the upstream provider. Required for custom or OpenAI-compatible providers that should not use a built-in vendor endpoint.
  • [].value.api_key (string, optional): Upstream provider's API key. The gateway receives plaintext so it can authenticate to the upstream provider. Protect the configuration store and transport accordingly.
  • [].value.apis (object, optional): API surfaces this upstream serves natively, beyond the one its adapter already implies, and the base URL each one lives at.

One upstream account often exposes more than one protocol, on different paths of the same host — an OpenAI-compatible /v1/chat/completions under …/v1 and an Anthropic-compatible /v1/messages under …/anthropic, both authenticated by the same credential. api_base can only name one of them, so without this field every request the declared path cannot serve gets translated instead — losing whatever the target protocol carries that the canonical chat shape does not (prompt-cache breakpoints, thinking blocks). Declaring the second entry here lets each inbound protocol reach its own native path under the one credential.

Each surface resolves on its own terms; see [ProviderApis]. Surfaces this map has no key for — embeddings, audio, images, videos, files/batches/fine-tuning, rerank — always use api_base, exactly as before.

  • allOf variant 1
  • [].value.apis.messages (object, optional): Anthropic-wire /v1/messages (and /v1/messages/count_tokens).
  • allOf variant 1
  • [].value.apis.messages.base (string,null, optional): Base URL this surface is served at. Omit when it is the same one api_base names — an entry with no base still carries the declaration that the surface exists.

Deliberately NOT length-constrained, matching api_base. The lenient read schema keeps every constraint but the open-object one, so a minLength here would make an empty string skip the whole Provider Key row — and with it every model that references the key — where the same empty string on api_base is the control plane's documented way to clear an override. An empty value is treated as "no override" at resolution time instead.

  • [].value.apis.responses (object, optional): OpenAI-wire /v1/responses.
  • allOf variant 1
  • [].value.apis.responses.base (string,null, optional): Base URL this surface is served at. Omit when it is the same one api_base names — an entry with no base still carries the declaration that the surface exists.

Deliberately NOT length-constrained, matching api_base. The lenient read schema keeps every constraint but the open-object one, so a minLength here would make an empty string skip the whole Provider Key row — and with it every model that references the key — where the same empty string on api_base is the control plane's documented way to clear an override. An empty value is treated as "no override" at resolution time instead.

  • [].value.display_name (string, required): Operator-facing label, unique within the gateway. Surfaces in the Admin API list view and in dashboard UIs that wrap this resource.
  • [].value.provider (string, optional): Upstream provider identifier, such as "deepseek", "openai", or a model catalog ID. The gateway uses this value for provider-specific dispatch and base URL validation.
  • [].value.request (object, optional): Per-key request-shape overrides applied by supported provider paths before dispatch to the upstream provider.
  • allOf variant 1
  • [].value.request.default_body_fields (object, optional): apply_default_body_fields input. Top-level body fields added when the caller did not set them. serde_json::Map preserves insertion order on serialize, matching the etcd round-trip.
  • [].value.request.default_headers (object, optional): Top-level headers added to the outbound request when the caller did not set them. Values may reference the request context with ${...} variables, such as "${request.api_key.team_id}"; a header whose variables do not all resolve is dropped rather than sent blank. See [crate::header_template] for the closed variable vocabulary.

"When the caller did not set them" includes the gateway itself: an entry naming the slot this ProviderKey's credential occupies is not applied. Use forward_client_headers to put the caller's own credential there instead.

  • [].value.request.forward_client_headers (array, optional): Inbound client headers forwarded to the upstream, as single-* glob patterns matched case-insensitively against the header name ("anthropic-beta", "x-trace-*", "authorization"). Empty — the default — forwards nothing, which is the behavior of every standard-protocol endpoint before AISIX-Cloud#1167.

A header the caller sends more than once is forwarded with its first value only; the upstream receives one well-formed header rather than a list this gateway never interpreted. An HTTP/2 caller may split cookie across several header fields, and only the first of them is forwarded.

A header named here reaches the upstream whatever the gateway would otherwise do with it. Naming a credential slot — authorization, proxy-authorization, x-api-key, api-key, x-goog-api-key, cookie, and the AWS SigV4 trio x-amz-security-token / x-amz-date / x-amz-content-sha256 — hands the upstream the caller's own credential in place of the one this ProviderKey would inject there, never both. That is what lets an internal service that already authorizes on the end user's Authorization keep doing so unchanged. Any OTHER header the gateway had already set is left alone: it selects how the exchange works, not who it is from.

A credential slot, and traceparent / tracestate, are forwarded only when a pattern names them exactly — a glob such as "*" or "x-*" is a statement about the operator's own headers, not consent to hand a third party the caller's credential or to graft the caller's trace onto that party's telemetry.

Two cases where a named header still does not reach the upstream. A default_headers entry of the same name wins it for every name except a credential slot: both are operator configuration and the static one is the more specific choice, but in a credential slot the forwarded value is precisely the one that was asked for, so it takes the slot from the static entry. And on an AWS Bedrock provider the request signer owns authorization, x-amz-date, x-amz-content-sha256, x-amz-security-token, x-amz-target and x-amzn-bedrock-accept, and drops any supplied value — a value there would not authenticate anyone: it either loses to the signer or breaks the signature.

Naming a credential slot needs a data plane new enough to honor it; an older one refuses those names outright, so the pattern has no effect there rather than a different one.

Headers whose forwarding would break the exchange rather than change who it comes from are never forwarded whatever the patterns say: host, the hop-by-hop headers that describe the caller's own connection, and the gateway's x-aisix-* namespace. The headers describing a body this gateway re-serializes or a response shape it parses (content-type, content-length, accept, anthropic-version, x-stainless-*) are excluded for the same reason. traceparent and tracestate are forwarded only when a pattern names them exactly — a glob is not read as consent to graft the caller's trace onto the upstream's telemetry.

  • [].value.request.param_constraints (object, optional): Parameter constraints applied to the outbound request. If omitted, no clamping is applied.
  • allOf variant 1
  • [].value.request.param_constraints.temperature_max (number,null, optional): Upper bound for temperature. Values above this are clamped to this value. If omitted, no upper bound is applied.
  • [].value.request.param_constraints.temperature_min (number,null, optional): Lower bound for temperature. Values below this are clamped to this value. If omitted, no lower bound is applied.
  • [].value.request.param_renames (object, optional): apply_param_renames input. Top-level body keys named on the left are renamed to the right. Leave empty to preserve request parameter names.
  • [].value.response (object, optional): Per-key response-shape overrides applied by provider bridges that support response transformation.
  • allOf variant 1
  • [].value.response.content_list_to_string (boolean, optional): When true, the request-body messages[*].content array of text blocks gets flattened to a single string before dispatch.
  • [].value.response.error_envelope (string,null, optional): Stored error-envelope preference for compatibility with control-plane configuration. The proxy does not currently apply this field.
  • [].value.response.reasoning_field (string,null, optional): Path used to extract reasoning content from the provider response. If omitted or empty, no reasoning field is lifted. Example: "delta.reasoning_content".
  • [].value.response.stream_done_marker (object, optional): Stream [DONE] terminator expectation. If omitted, either presence or absence of the terminator is accepted.
  • allOf variant 1
  • oneOf variant 1: Required
  • oneOf variant 2: Optional
  • oneOf variant 3: None
  • [].value.secret (string, optional): Accepted as an alternative spelling of api_key. Provide the credential under exactly one of the two names.
  • [].value.strip_headers (array, optional): Inbound headers removed before passthrough forwarding.
  • [].value.telemetry_tags (object, optional): Telemetry tags carried alongside the key for metric and log emission.
  • allOf variant 1
  • [].value.telemetry_tags.branded_provider (string,null, optional): Branded provider slug for catalog entries, such as "openai" or "anthropic". Bring-your-own providers leave this field unset.
  • [].value.telemetry_tags.byo_label (string,null, optional): Operator-defined label for bring-your-own entries, such as an internal team name. Catalog entries leave this field unset.
  • [].value.telemetry_tags.featured (boolean, optional): Whether this provider is surfaced in the featured list.
  • [].value.telemetry_tags.kind (object, optional): Provider-key category, such as "catalog" for curated providers or "byo" for bring-your-own providers.
  • allOf variant 1
  • [].value.telemetry_tags.pk_label (string,null, optional): Operator-defined label for this provider key, such as "production" or "shared-test".
  • [].value.tls (object, optional): TLS settings for connections to this key's api_base. Omit to use the gateway's deployment-wide trust settings.
  • allOf variant 1
  • [].value.tls.ca_cert (string,null, optional): PEM-encoded certificate authority certificates trusted as issuers for this endpoint, in addition to the gateway's default trust store. A bundle containing several certificates is accepted.
  • [].value.tls.verify (boolean, optional): Whether the endpoint's certificate is verified. Setting this to false accepts any certificate, including one presented by an intercepting party, and is intended only for test environments.
  • anyOf variant 1: api_key
  • anyOf variant 2: secret
  • 401: Missing or invalid admin key
  • error_msg (string, required): Human-readable error message.
  • 500: Configuration store operation failed Response fields (application/json): identical to GET /admin/v1/provider_keys, response 401 above.

cURL

curl -X GET 'http://127.0.0.1:3001/admin/v1/provider_keys'