Skip to main content
Version: Next

Files API

The Envoy AI Gateway supports the OpenAI-compatible Files API (/v1/files), letting clients upload, list, retrieve, download, and delete files through the gateway. Files are commonly used as inputs to other workflows such as the Batch API and fine-tuning.

Overview​

Unlike chat completions or embeddings — which are stateless and routed per request — a file is a stateful object that lives on one specific upstream backend. A file uploaded to backend A does not exist on backend B, so every request that carries a file id (retrieve, download content, delete) must reach the backend that created the file.

The gateway does this without any server-side database. When a file is created, the gateway encrypts the serving backend's identity and the routing model into the opaque file id it returns to the client. On later requests it decodes the id, routes by the recorded model, and verifies that the request reached the backend that owns the file.

One backend per route rule

The Files API currently supports exactly one backend per AIGatewayRoute rule. A Files request whose matching rule has more than one backendRef is rejected. Multi-backend routing may be added in the future; gateway-issued file ids already carry the owning backend, so existing ids will remain valid.

info

Client-visible file ids (file-...) are not the provider's native ids. The gateway issues its own encrypted, tamper-resistant ids and transparently translates between the two. Always use the id the gateway returns; do not attempt to construct or reuse a provider-native id directly.

Supported Endpoints​

OperationMethod & PathRouted by
UploadPOST /v1/filesmodel form field (required)
ListGET /v1/filesmodel query param (required)
RetrieveGET /v1/files/{file_id}model recorded in the file id
ContentGET /v1/files/{file_id}/contentmodel recorded in the file id
DeleteDELETE /v1/files/{file_id}model recorded in the file id
Provider support

OpenAI (and OpenAI-compatible providers) is the only backend schema supported today. A Files route pointed at a non-OpenAI schema (AWS Bedrock, GCP Vertex AI, Azure OpenAI, Anthropic, Cohere) fails closed with an error. Support for other providers will be added in the future.

The model parameter is required​

Because a file has no model of its own, the gateway uses a model value only to select which route/backend serves the request. It is required for the two operations that do not already carry a file id:

  • Upload — supply model as a multipart form field (the OpenAI SDK sends it via extra_body). The gateway uses it to route the upload, then strips it from the body before forwarding upstream (the OpenAI Files API has no model field).
  • List — supply model as a ?model= query parameter. The gateway uses it to route the list, then strips it from the request before forwarding upstream.

Retrieve, content, and delete do not take a model — the model used at upload time is decoded from the file id.

model selects a route, it does not filter files

model is a routing selector, not a content filter. Files carry no model, so GET /v1/files?model=<model> returns all files on the backend that serves <model>, including files that were uploaded while targeting a different model on the same backend. There is no way to list "only the files created for model X".

Configuration​

The Files API works with any OpenAI or OpenAI-compatible AIServiceBackend. The example below defines a route that matches the gpt-4o-mini model and forwards to OpenAI. This is the same AIGatewayRoute / AIServiceBackend / BackendSecurityPolicy pattern used for chat completions — no Files-specific resource is required.

apiVersion: aigateway.envoyproxy.io/v1beta1
kind: AIGatewayRoute
metadata:
name: envoy-ai-gateway-files
namespace: default
spec:
parentRefs:
- name: envoy-ai-gateway-basic
kind: Gateway
group: gateway.networking.k8s.io
rules:
- matches:
- headers:
- type: Exact
name: x-ai-eg-model
value: gpt-4o-mini
backendRefs:
- name: envoy-ai-gateway-basic-openai
---
apiVersion: aigateway.envoyproxy.io/v1beta1
kind: AIServiceBackend
metadata:
name: envoy-ai-gateway-basic-openai
namespace: default
spec:
schema:
name: OpenAI
backendRef:
name: envoy-ai-gateway-basic-openai
kind: Backend
group: gateway.envoyproxy.io
Raise the buffer limit for uploads

File uploads can be large. Envoy Gateway defaults the client buffer limit to 32KB, which is too small for most uploads. The basic.yaml example configures a ClientTrafficPolicy with a 50MB buffer limit; make sure your gateway does the same. See Basic Usage for the full ClientTrafficPolicy example (including the HTTP/2 window-size settings).

Encryption of file ids​

The gateway encrypts the backend identity and routing model into every file id using AES-GCM with a PBKDF2-derived key — the same mechanism used for MCP session encryption. The key is derived from a seed.

On Kubernetes, configure the seed with the Helm values below. The controller delivers it to the external processors through the filter configuration, which is stored in Secrets, so the seed is not visible in the Envoy Pod spec or process command line.

With aigw run, set the seed with the AIGW_FILE_ID_ENCRYPTION_SEED environment variable. It is also delivered through the filter configuration, not the command line.

When the external processor runs on its own, without the controller or aigw, it uses these flags:

FlagDefaultDescription
--fileIDEncryptionSeeddefault-insecure-seedSeed used to derive the file id encryption key. Change this in production.
--fileIDEncryptionIterations100000PBKDF2 iterations for key derivation.
--fileIDFallbackEncryptionSeed(empty)Optional fallback seed, tried on decode when the primary fails. Enables seed rotation.
--fileIDFallbackEncryptionIterations100000PBKDF2 iterations for the fallback seed.
Never use the well-known default seed

If the seed is left at the well-known default (default-insecure-seed), anyone who knows this public default can decrypt and forge file and batch ids. The external processor logs a warning when it detects the default. Set the seed to a secret, randomly generated value before exposing the gateway to untrusted or multi-tenant clients.

Kubernetes (Helm)​

When deployed with the Helm chart, the controller delivers the seed to every external processor it manages through the filter configuration Secrets. Seed changes are picked up without restarting the Envoy pods. Configure it with the controller.fileIDEncryption values:

Helm valueDefaultDescription
controller.fileIDEncryption.seed""Seed for the id encryption key. When empty, the chart generates a random seed on install, stores it in the Secret <controller fullname>-file-id-encryption, and reuses it on upgrades.
controller.fileIDEncryption.existingSecret""Name of an existing Secret (in the release namespace) holding the seed under the seed key. Takes precedence over seed. Recommended for helm template / GitOps tooling, which cannot look up a previously generated seed.
controller.fileIDEncryption.iterations100000PBKDF2 iterations.
controller.fileIDEncryption.fallback.seed""Previous seed, for rotation.
controller.fileIDEncryption.fallback.iterations100000PBKDF2 iterations for the fallback seed.
Keep the seed stable

File ids embed the owning backend and the provider-native id, so the seed must stay stable. Changing it without setting the fallback to the previous value invalidates every previously issued file and batch id.

To rotate the seed without invalidating existing ids, set the new value as the seed (--fileIDEncryptionSeed / controller.fileIDEncryption.seed) and the old value as the fallback (--fileIDFallbackEncryptionSeed / controller.fileIDEncryption.fallback.seed). Ids issued under the old seed continue to decode while new ids use the new seed.

Usage​

The examples below assume $GATEWAY_URL points at your gateway (for a Kubernetes deployment, see Basic Usage; for the standalone CLI, this is http://localhost:1975 — see aigw run). Replace gpt-4o-mini with a model your route matches.

Upload a file​

The model field selects the backend and is stripped before the request reaches the provider.

curl -s $GATEWAY_URL/v1/files \
-F purpose=batch \
-F model=gpt-4o-mini \
-F file=@batchinput.jsonl

Response:

{
"id": "file-abc123...",
"object": "file",
"bytes": 1234,
"created_at": 1699061776,
"filename": "batchinput.jsonl",
"purpose": "batch"
}

The returned id is a gateway-issued id that encodes the serving backend and model. Use it for all subsequent requests. The id is deterministic: the same file always gets the same id in upload, list, retrieve, and delete responses (for the same routing model).

List files​

The model query parameter selects which route/backend to list from. It is required on the first page; on later pages it may be omitted because the after id carries the model.

curl -s "$GATEWAY_URL/v1/files?model=gpt-4o-mini&limit=20"

Response:

{
"object": "list",
"data": [
{
"id": "file-abc123...",
"object": "file",
"filename": "batchinput.jsonl",
"purpose": "batch"
}
],
"has_more": false,
"first_id": "file-abc123...",
"last_id": "file-abc123..."
}

To paginate, pass the returned last_id as the after parameter on the next request (?after=<last_id>). The gateway decodes it back to the provider-native id before forwarding, and passes has_more through unchanged.

Retrieve a file's metadata​

curl -s $GATEWAY_URL/v1/files/file-abc123...

Response:

{
"id": "file-abc123...",
"object": "file",
"bytes": 1234,
"created_at": 1699061776,
"filename": "batchinput.jsonl",
"purpose": "batch"
}

Download a file's content​

curl -s $GATEWAY_URL/v1/files/file-abc123.../content -o downloaded.jsonl

The content response is the raw file bytes, passed through unchanged.

Delete a file​

curl -s -X DELETE $GATEWAY_URL/v1/files/file-abc123...

Response:

{
"id": "file-abc123...",
"object": "file",
"deleted": true
}

Error responses​

StatusWhen
400 Bad RequestUpload without a model field, list without a ?model= query parameter, or an invalid after id.
404 Not FoundA file id that cannot be decoded (unknown, tampered, or forged), or an unsupported method/path.
500The matched route rule has more than one backend, the file id belongs to a different backend than the one serving the route, or the backend schema is not OpenAI.
502 Bad GatewayThe upstream response contained a file id the gateway could not safely re-encode.

Caveats and limitations​

  • One backend per route rule. Requests are rejected if the matched rule has multiple backendRefs. Moving a model to a different backend makes previously issued file ids unusable.
  • OpenAI schema only. Non-OpenAI backends are rejected. See the provider support warning.
  • model is required for upload and list, and is a routing selector, not a content filter — a list returns all of the selected backend's files regardless of which model they were uploaded under.
  • Same model on multiple routes. Both upload and list route by the model field. If two AIGatewayRoutes declare the same model, Envoy's first-match-wins selects one of them and the other route's files are not reachable via list. Use distinct models per route.
  • Change the encryption seed. With the well-known default fileIDEncryptionSeed, anyone can decrypt and forge file ids. Set a secret, random value (the Helm chart generates one automatically when controller.fileIDEncryption.seed is empty). See Encryption of file ids.
  • File ids are gateway-issued. Client-visible ids are encrypted and are not the provider's native ids. Store and reuse exactly what the gateway returns.

What's Next​