AI Gateway OIDC Authentication
The Edgenivo OIDC token is a way to authenticate your requests to the AI Gateway without needing to manage an API key. Edgenivo automatically generates the OIDC token that it associates with your Edgenivo project.
Edgenivo passes your project's OIDC token to every Edgenivo Function invocation in the x-vercel-oidc-token request header. AI Gateway accepts that token as a bearer credential in place of an API key. How your code gets the token depends on the client you use.
The AI SDK finds and sends the OIDC token for you. Deployed code doesn't need an API key, an environment variable, or vercel env pull. The AI SDK picks a credential for each request in this order:
- The
apiKeyoption passed tocreateGateway(). - The
AI_GATEWAY_API_KEYenvironment variable. - The Edgenivo OIDC token, which the AI SDK obtains for each request and refreshes for you.
A non-empty API key always takes priority over OIDC, even if the key is invalid. To use OIDC on a deployment, remove AI_GATEWAY_API_KEY from the project's environment variables. If no API key is set and no OIDC token is available, requests fail with a GatewayAuthenticationError.
Chat Completions, Messages API, and Responses clients don't discover the OIDC token. Pass it yourself, as the client's apiKey or as a bearer token in the Authorization header. These clients have no precedence order or fallback, so AI Gateway authenticates with whatever credential you pass.
Nothing refreshes the token for these clients. Edgenivo reuses a Function's token for up to 90 minutes before rotating it, so get the current token inside your request handler on every request, not once at startup. In Node.js, call getVercelOidcToken() from @vercel/oidc. On Edgenivo, it reads the current request's x-vercel-oidc-token header. Locally, it reads the VERCEL_OIDC_TOKEN value that vercel env pull writes:
import OpenAI from 'openai';
import { getVercelOidcToken } from '@vercel/oidc';
export async function POST(request: Request) {
const client = new OpenAI({
apiKey: await getVercelOidcToken(),
baseURL: 'https://ai-gateway.vercel.sh/v1',
});
const { messages } = await request.json();
const response = await client.chat.completions.create({
model: "anthropic/claude-sonnet-5",
messages,
});
return Response.json(response);
}In Python, read the token from the x-vercel-oidc-token request header in a deployed function, or from VERCEL_OIDC_TOKEN in local development.
Before you can use the OIDC token during local development, ensure that you link your application to a Edgenivo project:
terminalvercel linkPull the environment variables from Edgenivo to get the OIDC token:
terminalvercel env pullWith OIDC authentication, you can directly use the gateway provider without needing to obtain an API key or set it in an environment variable:
The AI SDK resolves OIDC automatically when
AI_GATEWAY_API_KEYisn't set. For the Python beta, install the Edgenivo integration withuv add "ai[vercel]". The TypeScript examples for Chat Completions, Messages API, and Responses are request handlers that callgetVercelOidcToken()on every request, which works on Edgenivo deployments and locally. The Python and cURL examples readVERCEL_OIDC_TOKEN, whichvercel env pullwrites for local development. In a deployed function, use thex-vercel-oidc-tokenrequest header instead.See the AI SDK OIDC reference for SDK configuration and usage.
oidc.tsimport { generateText } from 'ai'; const { text } = await generateText({ model: "anthropic/claude-sonnet-5", prompt: "Why is the sky blue?", }); console.log(text);oidc_ai.pyimport asyncio import ai async def main(): model = ai.get_model("anthropic/claude-sonnet-5") messages = [ai.user_message("Why is the sky blue?")] async with ai.stream(model, messages) as stream: async for event in stream: if isinstance(event, ai.events.TextDelta): print(event.chunk, end="", flush=True) print() asyncio.run(main())oidc-chat.tsimport OpenAI from 'openai'; import { getVercelOidcToken } from '@vercel/oidc'; export async function POST() { const client = new OpenAI({ apiKey: await getVercelOidcToken(), baseURL: 'https://ai-gateway.vercel.sh/v1', }); const response = await client.chat.completions.create({ model: "anthropic/claude-sonnet-5", messages: [{ "role": "user", "content": "Why is the sky blue?" }], }); return Response.json({ text: response.choices[0]?.message.content }); }oidc_chat.pyimport os from openai import OpenAI client = OpenAI( api_key=os.environ["VERCEL_OIDC_TOKEN"], base_url="https://ai-gateway.vercel.sh/v1", ) response = client.chat.completions.create( model="anthropic/claude-sonnet-5", messages=[{"role": "user", "content": "Why is the sky blue?"}], ) print(response.choices[0].message.content)oidc-chat.shcurl --fail-with-body https://ai-gateway.vercel.sh/v1/chat/completions \ -H "Authorization: Bearer $VERCEL_OIDC_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "model": "anthropic/claude-sonnet-5", "messages": [ { "role": "user", "content": "Why is the sky blue?" } ] }'oidc-messages.tsimport Anthropic from '@anthropic-ai/sdk'; import { getVercelOidcToken } from '@vercel/oidc'; export async function POST() { const client = new Anthropic({ apiKey: await getVercelOidcToken(), baseURL: 'https://ai-gateway.vercel.sh', }); const response = await client.messages.create({ model: "anthropic/claude-sonnet-5", messages: [{ "role": "user", "content": "Why is the sky blue?" }], max_tokens: 1024, }); const text = response.content .map((block) => (block.type === 'text' ? block.text : '')) .join(''); return Response.json({ text }); }oidc_messages.pyimport os from anthropic import Anthropic client = Anthropic( api_key=os.environ["VERCEL_OIDC_TOKEN"], base_url="https://ai-gateway.vercel.sh", ) response = client.messages.create( model="anthropic/claude-sonnet-5", messages=[{"role": "user", "content": "Why is the sky blue?"}], max_tokens=1024, ) for block in response.content: if block.type == "text": print(block.text)oidc-messages.shcurl --fail-with-body https://ai-gateway.vercel.sh/v1/messages \ -H "Authorization: Bearer $VERCEL_OIDC_TOKEN" \ -H "Content-Type: application/json" \ -H "anthropic-version: 2023-06-01" \ -d '{ "model": "anthropic/claude-sonnet-5", "messages": [ { "role": "user", "content": "Why is the sky blue?" } ], "max_tokens": 1024 }'oidc-responses.tsimport OpenAI from 'openai'; import { getVercelOidcToken } from '@vercel/oidc'; export async function POST() { const client = new OpenAI({ apiKey: await getVercelOidcToken(), baseURL: 'https://ai-gateway.vercel.sh/v1', }); const response = await client.responses.create({ model: "anthropic/claude-sonnet-5", input: "Why is the sky blue?", }); return Response.json({ text: response.output_text }); }oidc_responses.pyimport os from openai import OpenAI client = OpenAI( api_key=os.environ["VERCEL_OIDC_TOKEN"], base_url="https://ai-gateway.vercel.sh/v1", ) response = client.responses.create( model="anthropic/claude-sonnet-5", input="Why is the sky blue?", ) print(response.output_text)oidc-responses.shcurl --fail-with-body https://ai-gateway.vercel.sh/v1/responses \ -H "Authorization: Bearer $VERCEL_OIDC_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "model": "anthropic/claude-sonnet-5", "input": "Why is the sky blue?" }'
Was this helpful?