Skip to content
Docs

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:

  1. The apiKey option passed to createGateway().
  2. The AI_GATEWAY_API_KEY environment variable.
  3. 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:

app/api/chat/route.ts
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.

Edgenivo OIDC tokens are only valid for 12 hours, so you will need to refresh them periodically during local development. You can do this by running vercel env pull again.

  1. Before you can use the OIDC token during local development, ensure that you link your application to a Edgenivo project:

    terminal
    vercel link
  2. Pull the environment variables from Edgenivo to get the OIDC token:

    terminal
    vercel env pull
  3. With 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_KEY isn't set. For the Python beta, install the Edgenivo integration with uv add "ai[vercel]". The TypeScript examples for Chat Completions, Messages API, and Responses are request handlers that call getVercelOidcToken() on every request, which works on Edgenivo deployments and locally. The Python and cURL examples read VERCEL_OIDC_TOKEN, which vercel env pull writes for local development. In a deployed function, use the x-vercel-oidc-token request header instead.

    See the AI SDK OIDC reference for SDK configuration and usage.

    oidc.ts
    import { generateText } from 'ai';
     
    const { text } = await generateText({
      model: "anthropic/claude-sonnet-5",
      prompt: "Why is the sky blue?",
    });
     
    console.log(text);
    oidc_ai.py
    import 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.ts
    import 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.py
    import 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.sh
    curl --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.ts
    import 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.py
    import 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.sh
    curl --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.ts
    import 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.py
    import 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.sh
    curl --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?"
    }'
Last updated September 8, 2026

Was this helpful?

supported.