Token Vault
API Reference

Agent Credentials API

Reference for GET /api/agents/credentials — auth forms, the 307 redirect contract, list mode, response schemas, and the full error catalogue.

GET /api/agents/credentials

Retrieve a credential the calling agent has been granted. On success Token Vault validates the grant and ABAC policies, then answers with a 307 redirect to your webhook's /v1/credential; the agent's HTTP client follows it and receives the credential directly from the webhook. Use a client that follows redirects (curl -L; Python requests follows by default).

Loading diagram...

Authentication

The agent's tvagent_… key, one of three ways (checked in this order):

MethodExampleNotes
Authorization headerAuthorization: Bearer tvagent_…Preferred
x-agent-key headerx-agent-key: tvagent_…For clients that reserve Authorization
?key= query param?key=tvagent_…Deprecated — keys end up in server logs; use a header

A tvsess_… OAuth session token works identically on the MCP endpoint — see OAuth 2.1 for MCP Clients.

Parameters

ParameterInRequiredDescription
servicequerynoService name, e.g. github. Omit to list all active grants instead of retrieving one.

Response — single credential (service set)

Token Vault answers 307 Temporary Redirect with a Location pointing at your webhook, which returns:

200 OK — served by your webhook, not Token Vault
{
  "token": {
    "accessToken": "ghp_…",
    "refreshToken": "ghr_…",
    "serviceName": "github",
    "tokenType": "pat",
    "createdAt": "2026-02-01T10:00:00Z"
  }
}

Exact fields depend on token type — a TOTP token returns a current one-time code as accessToken, a raw GCP credential returns a short-lived minted token. See the brokering guides.

Response — list mode (service omitted)

Token Vault answers directly (no redirect, no credential material):

200 OK
{
  "grants": [
    {
      "serviceName": "github",
      "grantExpiresAt": null,
      "refreshPolicy": "none",
      "sourceGroupId": null
    },
    {
      "serviceName": "google",
      "grantExpiresAt": "2026-08-01T12:00:00Z",
      "refreshPolicy": "auto",
      "sourceGroupId": "grp_ab12"
    }
  ]
}

Expired grants are filtered out. sourceGroupId is set when the grant came from a token group.

Errors

HTTPcodeWhen
401MISSING_KEYNo key in header or query
403INVALID_KEYMalformed or revoked key
403AGENT_INACTIVEAgent is suspended or deleted
403POLICY_DENIEDAn ABAC rule blocked the request — body carries policy, rule, reason
403GRANT_EXPIREDThe grant existed but has expired (it is deleted on this request)
400INVALID_SERVICEService name contains /
404NO_GRANTNo active grant for service
423VAULT_LOCKEDThe vault owner has locked the vault
502WEBHOOK_NOT_CONFIGUREDNo webhook is bound to this vault
403 — policy denial body
{
  "error": "Access denied by policy",
  "policy": "office-hours",
  "rule": "time_window",
  "reason": "Outside allowed window 09:00-18:00 Europe/London",
  "code": "POLICY_DENIED"
}

If your webhook is offline, the agent's redirect fetch fails at the webhook — that is the kill switch doing its job.

Ready to try it?

Sign up free with Google — your credentials stay on your own webhook, and the quickstart gets an agent fetching its first credential in about ten minutes.

On this page