> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.mixlayer.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.mixlayer.com/_mcp/server.

# Vercel Workload Identity

> Authenticate Vercel deployments without Mixlayer API-key environment variables

Vercel can issue a short-lived OIDC token to builds and Functions. Mixlayer verifies the deployment's team, project, and environment claims and exchanges the token for a short-lived Mixlayer access token, so you do not need to store a Mixlayer API key in Vercel.

## 1. Enable Vercel OIDC

In the Vercel dashboard, open the project and go to **Settings > Security > Secure backend access with OIDC federation**. Select the **Team** issuer mode, which scopes the issuer to your team.

Record the team slug from the Vercel team URL and the stable team and project IDs from the project settings. Use the IDs in Mixlayer policy because team and project names can change.

## 2. Configure the Mixlayer provider

Create an OIDC provider in [Workload Identity](https://console.mixlayer.com/app/workload-identity):

| Setting          | Value                                 |
| ---------------- | ------------------------------------- |
| Issuer URI       | `https://oidc.vercel.com/[TEAM_SLUG]` |
| Allowed audience | `https://api.mixlayer.com`            |
| JWKS source      | OIDC discovery                        |

Replace `[TEAM_SLUG]` with the slug from your Vercel team URL. The Vercel helper exchanges the deployment token for a Vercel-signed token with the Mixlayer-specific audience above.

Map stable identifiers and the deployment environment:

```text
mixlayer.subject    = assertion.sub
attribute.owner_id  = assertion.owner_id
attribute.project_id = assertion.project_id
attribute.environment = assertion.environment
```

Admit only the expected team and project:

```cel
attribute.owner_id == "team_..." &&
attribute.project_id == "prj_..."
```

If only production deployments should authenticate, include the environment in the admission condition:

```cel
attribute.owner_id == "team_..." &&
attribute.project_id == "prj_..." &&
attribute.environment == "production"
```

Use `true` as the final authorization rule and grant only the permissions the deployment needs.

> **Warning**
>
> Do not authorize only by Vercel's issuer and audience. Restrict admission with
> the stable team and project IDs.

## 3. Exchange a token from a Vercel Function

Store the non-secret Mixlayer provider ID in a Vercel environment variable named `MIXLAYER_IDENTITY_PROVIDER_ID`, then install Vercel's OIDC helper:

```bash
pnpm add @vercel/oidc
```

Call `getVercelOidcToken()` inside the request handler. In a Function, the token is available only in the request context and cannot be read at module initialization.

**`file=`**

```typescript file=app/api/mixlayer/route.ts
import { getVercelOidcToken } from "@vercel/oidc";

export async function POST() {
  const identityProviderId = process.env.MIXLAYER_IDENTITY_PROVIDER_ID;
  if (!identityProviderId) {
    return new Response("Missing MIXLAYER_IDENTITY_PROVIDER_ID", { status: 500 });
  }

  const subjectToken = await getVercelOidcToken({
    audience: "https://api.mixlayer.com",
  });
  const exchange = await fetch(
    "https://api.mixlayer.com/v1/workload_identity/token",
    {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({
        grant_type: "urn:ietf:params:oauth:grant-type:token-exchange",
        subject_token_type: "urn:ietf:params:oauth:token-type:jwt",
        subject_token: subjectToken,
        identity_provider_id: identityProviderId,
      }),
    },
  );

  if (!exchange.ok) {
    return new Response(await exchange.text(), { status: exchange.status });
  }

  const { access_token: accessToken } = await exchange.json();
  const inference = await fetch(
    "https://mixlayer.ai/v1/chat/completions",
    {
      method: "POST",
      headers: {
        Authorization: `Bearer ${accessToken}`,
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        model: "qwen/qwen3.5-4b-free",
        messages: [{ role: "user", content: "Hello from Vercel" }],
      }),
    },
  );

  return new Response(inference.body, {
    status: inference.status,
    headers: { "Content-Type": "application/json" },
  });
}
```

Vercel supplies the original OIDC token to the Function in the `x-vercel-oidc-token` request header. The helper reads it and requests the custom-audience token without requiring you to handle either step directly.

## Builds and local development

During a Vercel build, the original token is available as `VERCEL_OIDC_TOKEN`. Use the same helper to request the custom-audience token, then follow the [shared OIDC exchange example](/workload-identity-federation#exchange-an-oidc-token):

```bash
export MIXLAYER_SUBJECT_TOKEN="$(
  node --input-type=module -e '
    import { getVercelOidcToken } from "@vercel/oidc";
    process.stdout.write(await getVercelOidcToken({
      audience: "https://api.mixlayer.com",
    }));
  '
)"
```

For local development, `vercel env pull` writes a development OIDC token to `.env.local`. Development tokens identify the local user and last longer than preview or production tokens. Use a separate development provider or admission policy, and do not grant a downloaded development token production access.

## Troubleshooting

* Confirm the Vercel project uses the **Team** issuer mode and that the provider issuer includes the exact team slug.
* Confirm the allowed audience is `https://api.mixlayer.com` and request the same audience from `getVercelOidcToken()`.
* Compare `owner_id`, `project_id`, and `environment` with the admission condition.
* Call `getVercelOidcToken()` inside the Function handler, not at module scope.
* If a team or project is renamed, the name-based `iss` and `sub` values change. Update the provider issuer after a team-slug change; continue using stable IDs for admission.
* Do not log either the Vercel OIDC token or the Mixlayer access token.