> ## Documentation Index
> Fetch the complete documentation index at: https://docs.knoxcall.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Vercel

> Authenticate from Vercel functions to KnoxCall using Vercel OIDC tokens

# Vercel Workload Identity

Vercel issues per-deployment OIDC tokens (`VERCEL_OIDC_TOKEN`) to every function. KnoxCall accepts them via RFC 8693 token exchange.

## 1. Enable OIDC for your Vercel project

Vercel project → **Settings → OIDC Federation → Enable**. The `VERCEL_OIDC_TOKEN` env var is then injected into every deployment.

## 2. Configure the trust binding

Create the binding in the dashboard with **Settings → API → Workload Identity → Connect workload**, or call the admin API on the admin host (`admin.knoxcall.com`). The `/admin/*` routes are authenticated by your logged-in admin/owner session — a session JWT plus the `X-Tenant-ID` header — not an API key against `api.knoxcall.com`.

<Note>
  Creating a binding requires a **recent step-up verification** (passkey, TOTP or
  emailed code) within the last 5 minutes — a binding is a trust that lets an
  external workload mint tenant tokens, so it carries the same bar as creating an
  OAuth client. A `curl` carrying only a session JWT answers
  `403 {"requires_step_up": true}`: verify in the Dashboard (any action that
  prompts for your passkey or TOTP), then replay the request inside the 5-minute
  window. Each verification is single-use, so a retried request needs a fresh one.
  Listing and revoking bindings need no verification — containment must never be
  gated.
</Note>

```bash theme={"dark"}
curl -X POST https://admin.knoxcall.com/admin/oauth/workload-bindings \
  -H "Authorization: Bearer $SESSION_JWT" \
  -H "X-Tenant-ID: $TENANT_ID" \
  -H "Content-Type: application/json" \
  -d '{
    "oauth_client_id": "<your_oauth_client_id>",
    "name": "vercel-acme-prod",
    "issuer": "https://oidc.vercel.com",
    "audience": "knoxcall:api",
    "attribute_conditions": {
      "owner": "acme",
      "project": "api",
      "environment": "production"
    },
    "allowed_scopes": ["routes:read", "secrets:read"],
    "access_token_ttl_seconds": 3600
  }'
```

Lock to your Vercel org (`owner`), project, and environment. The token also carries `aud`, `iss`, `iat`, `exp`, plus deployment metadata (`deployment_id`, `git_commit_sha`).

## 3. Call KnoxCall from your function

```javascript theme={"dark"}
// api/list-routes.js (Vercel Edge or Node function)
import { KnoxCall } from "@knoxcall/sdk";

export default async function handler(req, res) {
  const client = new KnoxCall({ tenant: process.env.KNOXCALL_TENANT });
  const routes = await client.routes.list();
  res.json(routes);
}
```

## Recommendations

* Use separate bindings for `preview` vs `production` environments — preview deployments shouldn't be able to mint production tokens.
* Limit `allowed_scopes` to what the function actually needs.

## Troubleshooting

* **`VERCEL_OIDC_TOKEN` not set** — OIDC isn't enabled on the project, or you're running locally (`vercel dev`). For local dev, set `KNOXCALL_CLIENT_ID` + `KNOXCALL_CLIENT_SECRET` directly.
* **`invalid_grant: no binding matched`** — preview deployments carry `environment: "preview"`; ensure your bindings differentiate.
