Skip to main content

Workload token exchange

Exchange a workload’s OIDC id_token — a GitHub Actions token, a GCP or AWS workload identity token, an Azure managed-identity token — for a short-lived KnoxCall phantom token, using RFC 8693 token exchange. Nothing long-lived is stored in the pipeline.
This is not the OAuth 2.1 token endpoint. POST https://api.knoxcall.com/oauth/token mints management-API access tokens for /v1/*. This endpoint lives on your tenant’s data-plane subdomain under /v1/oauth/token, and mints phantom tokens for /v1/ai/<agent> and /v1/mcp/<slug>. The two are separate endpoints with separate credentials.
The endpoint is unauthenticated by design — the subject token is the credential, and verifying it is what the endpoint is being asked to do. Prerequisite: an OIDC binding An exchange only succeeds against a binding you have configured (the agent’s Federation section, or the admin API). A binding pins:
  • the trusted issuer, whose JWKS is fetched over HTTPS from its published discovery document;
  • the required attribute conditions — for example a specific repository, ref or environment;
  • the capability scope and TTL of the token that gets minted.
A binding with zero attribute conditions is refused. A binding that matched any token from an issuer would hand a KnoxCall credential to every repository on GitHub. Request application/x-www-form-urlencoded (JSON is also accepted).
Response
expires_in is the binding’s access_token_ttl_seconds, default 900. scope is a JSON serialisation for visibility only — the enforceable copy is bound into the token’s capability HMAC and cannot be edited after minting. What resource changes A resource-bound token is confined to exactly that MCP server: the canonical resource URI is bound into the capability scope, so the HMAC covers it. The MCP plane requires a tool-kind token, and the AI plane refuses a token with no agent — so the kind narrows to match what you asked for, and never widens. Single use A given subject_token can be exchanged once. A replay returns invalid_grant, which is what stops a leaked CI log from being worth anything. Errors RFC 6749-shaped: { "error": "...", "error_description": "..." }. Rate limits 30 requests/minute per (client IP, issuer, subject) and 60/minute per client IP. The client IP is deliberately part of the subject bucket: iss and sub come from an unverified JWT and are public for the primary use case, so keying on the claims alone would let anyone who knows your repository name lock out your real CI runs. See Limits. Example — GitHub Actions
See Tokens & DPoP for the conceptual overview.