Agents SDK

Vaults

Create, list, update, archive, and delete credential vaults and their credentials. Vaults are workspace-scoped; all endpoints authenticate with the team's API key.

For the concept — how credentials are resolved at session time, injection shapes, OAuth refresh, and multi-tenant patterns — see Credential vaults.

Vault object

Fields returned on vault endpoints.

FieldTypeDescription
idstring (uuid)Stable vault identifier.
namestring1-200 chars. Display name.
descriptionstring | nullUp to 500 chars.
status"active" | "archived"Archived vaults have their encrypted secrets purged but the row is retained for audit.
isDefaultbooleanExactly one active vault per team can be the default.
metadataRecord<string, string>Max 16 pairs; keys ≤ 64 chars, values ≤ 512 chars. Returned in clear text — do not store secrets here.
credentialsCredential[]Present on GET /v1/mcp/vaults/:id.
createdAtstring (ISO 8601)Timestamp.
updatedAtstring (ISO 8601)Timestamp.
archivedAtstring | nullSet when archived.

Credential object

FieldTypeDescription
idstring (uuid)Credential identifier.
vaultIdstring (uuid)Parent vault.
namestring | nullDisplay label.
serverUrlstring (url)The MCP server or upstream API URL this credential authenticates.
serverUrlNormalizedstringLowercased and trailing-slash-stripped form used for matching.
hostPatternstring | nullDerived from serverUrl. Used by the proxy to match outbound requests.
authType"bearer" | "oauth"Secret shape. See the Auth shapes section below.
status"active" | "archived"Archived credentials have their encrypted auth purged.
metadataRecord<string, string>Same caps as vault metadata.
lastResolvedAtstring | nullSet on successful proxy resolve.
lastErrorstring | nullSet on upstream auth failure (e.g. 401). Cleared on next success.
💡 Note — Secret fields (token, accessToken, refreshToken, clientSecret) are write-only. They are never returned in API responses.

Inject rules

The inject field on credential create / update tells the proxy where to put the secret in the outbound request. Defaults to { kind: "header", header: "Authorization", prefix: "Bearer " }, which matches MCP and most modern APIs.

Header — custom name, optional prefix

{
  "kind": "header",
  "header": "X-Subscription-Token",
  "prefix": ""
}

Rendered as X-Subscription-Token: <token>. Use this for Brave, SendGrid, and other APIs with custom header auth.

Query parameter

{
  "kind": "query",
  "param": "key"
}

Rendered as ?key=<token>. Use for Google Maps and other query-auth APIs.

Basic auth

{
  "kind": "basic",
  "username": "api"
}

Rendered as Authorization: Basic base64(username:<token>). The token is used as the password.

Auth shapes

The auth field on credential create / update is a discriminated union.

Bearer

{
  "type": "bearer",
  "token": "lin_api_REAL_TOKEN"
}

OAuth (with optional refresh)

{
  "type": "oauth",
  "accessToken": "xoxp-...",
  "refreshToken": "xoxe-1-...",
  "clientId": "1234567890.0987654321",
  "clientSecret": "abc123def456",
  "tokenEndpoint": "https://slack.com/api/oauth.v2.access",
  "tokenEndpointAuth": "client_secret_post",
  "tokenType": "bearer",
  "expiresAt": "2026-04-24T13:00:00Z",
  "scope": "channels:read chat:write",
  "resource": null
}

All OAuth fields are optional on input, but at least accessToken is required for immediate use. Supply the full refresh block if you want the relay to refresh tokens on your behalf when they near expiry.

Supported tokenEndpointAuth modes: none, client_secret_basic, client_secret_post.

Vault endpoints

List Vaults

GEThttps://relay.an.dev/v1/mcp/vaults

Returns all vaults in the workspace with their nested active credentials.

Response

{
  "vaults": [
    {
      "id": "a1b2c3d4-5678-90ab-cdef-000000000001",
      "name": "Team",
      "description": "Shared workspace credentials",
      "status": "active",
      "isDefault": true,
      "metadata": {},
      "createdAt": "2026-04-01T12:00:00Z",
      "updatedAt": "2026-04-01T12:00:00Z",
      "archivedAt": null,
      "credentials": [
        {
          "id": "c1d2e3f4-5678-90ab-cdef-000000000001",
          "name": "Linear",
          "serverUrl": "https://mcp.linear.app/mcp",
          "serverUrlNormalized": "https://mcp.linear.app/mcp",
          "authType": "bearer",
          "status": "active",
          "hostPattern": "mcp.linear.app",
          "metadata": {},
          "lastResolvedAt": null,
          "lastError": null
        }
      ]
    }
  ]
}
cURL
curl https://relay.an.dev/v1/mcp/vaults \
  -H "Authorization: Bearer YOUR_API_KEY"

Create Vault

POSThttps://relay.an.dev/v1/mcp/vaults

Creates a new vault in the workspace.

Request Body

NameTypeRequiredDescription
namestringRequiredDisplay name, 1-200 chars.
descriptionstring | nullOptionalUp to 500 chars.
metadataRecord<string, string>OptionalMax 16 pairs; keys ≤ 64 chars, values ≤ 512 chars.
Request Body
{
  "name": "Alice",
  "description": "Per-user credentials",
  "metadata": {
    "external_user_id": "usr_abc123"
  }
}

Response

{
  "vault": {
    "id": "a1b2c3d4-5678-90ab-cdef-000000000002",
    "name": "Alice",
    "description": "Per-user credentials",
    "status": "active",
    "isDefault": false,
    "metadata": { "external_user_id": "usr_abc123" },
    "createdAt": "2026-04-24T12:00:00Z",
    "updatedAt": "2026-04-24T12:00:00Z",
    "archivedAt": null
  }
}
cURL
curl -X POST https://relay.an.dev/v1/mcp/vaults \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "name": "Alice", "metadata": { "external_user_id": "usr_abc123" } }'

Returns 201 Created with the new vault.

Get Vault

GEThttps://relay.an.dev/v1/mcp/vaults/:vaultId

Returns a single vault with its active credentials and coverage summary.

Path Parameters

NameTypeRequiredDescription
vaultIdstring (uuid)RequiredVault ID.

Response

{
  "id": "a1b2c3d4-5678-90ab-cdef-000000000002",
  "name": "Alice",
  "description": "Per-user credentials",
  "status": "active",
  "isDefault": false,
  "metadata": { "external_user_id": "usr_abc123" },
  "credentials": [
    {
      "id": "c9d8e7f6-5678-90ab-cdef-000000000011",
      "name": "Linear",
      "serverUrl": "https://mcp.linear.app/mcp",
      "serverUrlNormalized": "https://mcp.linear.app/mcp",
      "hostPattern": "mcp.linear.app",
      "authType": "bearer",
      "status": "active",
      "metadata": {},
      "lastResolvedAt": "2026-04-24T11:59:00Z",
      "lastError": null
    }
  ],
  "coverage": {
    "active": ["mcp.linear.app"],
    "missing": []
  }
}

The coverage field lists which declared hosts in any active deployment are covered vs. missing for this vault.

Update Vault

PATCHhttps://relay.an.dev/v1/mcp/vaults/:vaultId

Updates vault metadata. Supports partial updates: any omitted field is left unchanged.

Path Parameters

NameTypeRequiredDescription
vaultIdstring (uuid)RequiredVault ID.

Request Body

NameTypeRequiredDescription
namestringOptional1-200 chars.
descriptionstring | nullOptionalUp to 500 chars. Pass null to clear.
metadataRecord<string, string>OptionalReplaces the full metadata object.
Request Body
{
  "name": "Alice (archived users)",
  "metadata": { "archived_user": "true" }
}

Archive or Delete Vault

DELETEhttps://relay.an.dev/v1/mcp/vaults/:vaultId

By default, soft-archives the vault: the record stays for audit but encrypted secrets are purged. Pass ?force=true to hard-delete (requires the vault to already be archived or have no active credentials).

Path Parameters

NameTypeRequiredDescription
vaultIdstring (uuid)RequiredVault ID.

Query Parameters

NameTypeRequiredDescription
forcebooleanOptionalIf true, hard-delete the row. Requires prior archive.

Response

{
  "success": true
}

Set Default Vault

POSThttps://relay.an.dev/v1/mcp/vaults/:vaultId/set-default

Marks this vault as the workspace default. Any previously-default vault is un-set in the same transaction. If a thread.run is made without explicit vaultIds, externalUserId, or agent-pinned vaultIds, the default vault is used.

Path Parameters

NameTypeRequiredDescription
vaultIdstring (uuid)RequiredVault ID.

Response

{
  "success": true
}

Credential endpoints

Create Credential

POSThttps://relay.an.dev/v1/mcp/vaults/:vaultId/credentials

Creates a credential in the vault. A vault can hold up to 20 active credentials. Creating a second credential for the same serverUrl returns 409.

Path Parameters

NameTypeRequiredDescription
vaultIdstring (uuid)RequiredParent vault.

Request Body

NameTypeRequiredDescription
namestring | nullOptionalDisplay label, up to 200 chars.
serverUrlstring (url)RequiredMCP server or upstream API URL.
authBearerAuth | OAuthAuthRequiredSee Auth shapes above.
injectInjectRuleOptionalHow to attach the secret. Defaults to { kind: "header", header: "Authorization", prefix: "Bearer " }. See Inject rules below.
metadataRecord<string, string>OptionalSame caps as vault metadata.
Bearer — Request Body
{
  "name": "Linear",
  "serverUrl": "https://mcp.linear.app/mcp",
  "auth": {
    "type": "bearer",
    "token": "lin_api_REAL_TOKEN"
  },
  "metadata": {}
}
OAuth — Request Body
{
  "name": "Slack",
  "serverUrl": "https://mcp.slack.com/mcp",
  "auth": {
    "type": "oauth",
    "accessToken": "xoxp-...",
    "refreshToken": "xoxe-1-...",
    "clientId": "1234567890.0987654321",
    "clientSecret": "abc123def456",
    "tokenEndpoint": "https://slack.com/api/oauth.v2.access",
    "tokenEndpointAuth": "client_secret_post",
    "tokenType": "bearer",
    "expiresAt": "2026-04-24T13:00:00Z",
    "scope": "channels:read chat:write",
    "resource": null
  }
}

Response

{
  "credential": {
    "id": "c9d8e7f6-5678-90ab-cdef-000000000011",
    "vaultId": "a1b2c3d4-5678-90ab-cdef-000000000002",
    "name": "Linear",
    "serverUrl": "https://mcp.linear.app/mcp",
    "serverUrlNormalized": "https://mcp.linear.app/mcp",
    "hostPattern": "mcp.linear.app",
    "authType": "bearer",
    "status": "active",
    "metadata": {},
    "createdAt": "2026-04-24T12:00:00Z",
    "updatedAt": "2026-04-24T12:00:00Z",
    "archivedAt": null,
    "lastResolvedAt": null,
    "lastError": null
  }
}
cURL
curl -X POST https://relay.an.dev/v1/mcp/vaults/VAULT_ID/credentials \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Linear",
    "serverUrl": "https://mcp.linear.app/mcp",
    "auth": { "type": "bearer", "token": "lin_api_REAL_TOKEN" }
  }'

Update Credential

PATCHhttps://relay.an.dev/v1/mcp/vaults/:vaultId/credentials/:credentialId

Replaces the credential's auth payload and/or metadata. Pass the same shape as create.

Path Parameters

NameTypeRequiredDescription
vaultIdstring (uuid)RequiredParent vault.
credentialIdstring (uuid)RequiredCredential ID.

Request Body

NameTypeRequiredDescription
serverUrlstring (url)RequiredSame host as the existing credential.
authBearerAuth | OAuthAuthRequiredNew secret material.
namestring | nullOptionalDisplay label.
injectInjectRuleOptionalReplaces the injection rule (header / query / basic).
metadataRecord<string, string>OptionalReplaces the full metadata object.

Archive or Delete Credential

DELETEhttps://relay.an.dev/v1/mcp/vaults/:vaultId/credentials/:credentialId

By default, soft-archives the credential: the row stays, encrypted secret is purged. Pass ?force=true to hard-delete.

Path Parameters

NameTypeRequiredDescription
vaultIdstring (uuid)RequiredParent vault.
credentialIdstring (uuid)RequiredCredential ID.

Query Parameters

NameTypeRequiredDescription
forcebooleanOptionalIf true, hard-delete the row. Requires prior archive.

Response

{
  "success": true
}

Errors

These endpoints share the standard error format documented on the Errors page. Vault-specific codes:

StatusCodeWhen
400validation_errorBody fails schema (missing/bad fields, metadata caps exceeded).
404not_foundVault or credential doesn't exist in your workspace.
409conflictDuplicate credential for the same host, or hard-delete attempted on an active resource.
422credential_cap_exceededAttempted to create a 21st active credential in a vault.

More resources

  • Credential vaults — concept page with the 3-slot model, worked examples, and resolution order.
  • Tools and MCPs — how MCP servers are declared on the agent.
  • Chat — passing vaultIds and externalUserId at request time.
Vaults API - 21st Agents SDK Docs