AI gateway features
End-user identifier
AI Gateway can attribute a generation to the end user on whose behalf you called it. The same identifier decides whether the request is allowed (force_user) and which per-user budget or request cap applies — so it feeds tracing, access control and limits at once. It works the same way on every endpoint.
Where it comes from
At request time the identifier is resolved in this order — first match wins.
- the
X-Userrequest header (see Custom headers); - the body
userfield on the OpenAI endpoints (/v1/chat/completions,/v1/responses,/v1/embeddings,/v1/images/*), ormetadata.user_idon the Messages API.
If neither is present, the generation is attributed to the API key's default user when the key has one configured. That fallback only fills in attribution — it does not satisfy force_user, and per-user budgets/caps still key off the header/body value.
import { client } from "./client";
// Body field (OpenAI convention)…
await client.chat.completions.create({
model: "gpt-4o-mini",
messages: [{ role: "user", content: "Hello" }],
user: "user_42",
});
// …or the header — works on every endpoint and wins over the body:
await client.chat.completions.create(
{ model: "gpt-4o-mini", messages: [{ role: "user", content: "Hello" }] },
{ headers: { "X-User": "user_42" } },
);Requiring an identifier (force_user)
A key can be set to reject any request that does not carry an end-user identifier.
warning · force_user — the identifier can be mandatory
force_user is on and a request carries neither X-User nor a body user / metadata.user_id, AI Gateway rejects it with 400 before it reaches a provider. A key that does not force the user must instead carry a default user, so every generation resolves to some identifier.Per-user budgets & request caps
The identifier is also the key for per-user spend and rate limits.
note · Per-user budgets & request caps
429. Per-user limits only bind when the request carries a user / X-User; without one, only the key-level limits apply.