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

# Vaults and credentials

> Store connector credentials in vaults and grant agents access to them.

Vaults group credentials within your organization. All endpoints require an
`x-api-key` header. Secret values are accepted on create or rotation but are
never returned.

## Create a vault

```
POST /v1/vaults
```

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
curl -X POST "https://api.herm.run/v1/vaults" \
  -H "Content-Type: application/json" \
  -H "x-api-key: $PRISM_API_KEY" \
  -d '{
    "displayName": "Acme production connectors",
    "metadata": { "customerId": "customer_123" }
  }'
```

The response is a vault object:

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "id": "vault_123",
  "type": "vault",
  "displayName": "Acme production connectors",
  "metadata": { "customerId": "customer_123" },
  "archivedAt": null,
  "createdAt": "2026-07-23T18:00:00.000Z",
  "updatedAt": "2026-07-23T18:00:00.000Z"
}
```

## Manage vaults

| Method   | Endpoint                       | Behavior                                                     |
| -------- | ------------------------------ | ------------------------------------------------------------ |
| `GET`    | `/v1/vaults`                   | List active vaults, newest first.                            |
| `GET`    | `/v1/vaults/{vaultId}`         | Get an active or archived vault.                             |
| `POST`   | `/v1/vaults/{vaultId}/archive` | Archive a vault. Idempotent.                                 |
| `DELETE` | `/v1/vaults/{vaultId}`         | Permanently delete an empty vault and its agent attachments. |

Deleting a vault is permanent. Delete every credential first so its stored value
is removed, then delete the empty vault. A non-empty vault returns `409 conflict`.
Archiving keeps a vault available for inspection but prevents new credentials or
agent attachments.

## Create a static bearer credential

```
POST /v1/vaults/{vaultId}/credentials
```

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
curl -X POST "https://api.herm.run/v1/vaults/vault_123/credentials" \
  -H "Content-Type: application/json" \
  -H "x-api-key: $PRISM_API_KEY" \
  -d '{
    "displayName": "Linear MCP",
    "auth": {
      "type": "static_bearer",
      "mcpServerUrl": "https://mcp.example.com/linear",
      "token": "secret-token"
    }
  }'
```

The response redacts `token`:

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "id": "credential_123",
  "type": "vault_credential",
  "vaultId": "vault_123",
  "displayName": "Linear MCP",
  "metadata": null,
  "auth": {
    "type": "static_bearer",
    "mcpServerUrl": "https://mcp.example.com/linear"
  },
  "archivedAt": null,
  "createdAt": "2026-07-23T18:01:00.000Z",
  "updatedAt": "2026-07-23T18:01:00.000Z"
}
```

## Create an MCP OAuth credential

Use `mcp_oauth` when you already have access and refresh tokens from an OAuth
flow:

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "displayName": "Customer OAuth connection",
  "auth": {
    "type": "mcp_oauth",
    "mcpServerUrl": "https://mcp.example.com/service",
    "accessToken": "access-token",
    "expiresAt": "2026-07-23T19:00:00.000Z",
    "refresh": {
      "tokenEndpoint": "https://auth.example.com/oauth/token",
      "clientId": "client-id",
      "refreshToken": "refresh-token",
      "tokenEndpointAuth": {
        "type": "client_secret_basic",
        "clientSecret": "client-secret"
      }
    }
  }
}
```

`tokenEndpointAuth.type` can be `none`, `client_secret_basic`, or
`client_secret_post`. Responses redact access tokens, refresh tokens, and client
secrets.

## Manage credentials

| Method   | Endpoint                                                  | Behavior                                                 |
| -------- | --------------------------------------------------------- | -------------------------------------------------------- |
| `GET`    | `/v1/vaults/{vaultId}/credentials`                        | List active credentials.                                 |
| `GET`    | `/v1/vaults/{vaultId}/credentials/{credentialId}`         | Get an active or archived credential with redacted auth. |
| `PATCH`  | `/v1/vaults/{vaultId}/credentials/{credentialId}`         | Update display metadata or rotate secret values.         |
| `POST`   | `/v1/vaults/{vaultId}/credentials/{credentialId}/archive` | Archive a credential. Idempotent.                        |
| `DELETE` | `/v1/vaults/{vaultId}/credentials/{credentialId}`         | Permanently delete a credential.                         |

Rotate a static bearer token without changing its MCP server URL:

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
curl -X PATCH "https://api.herm.run/v1/vaults/vault_123/credentials/credential_123" \
  -H "Content-Type: application/json" \
  -H "x-api-key: $PRISM_API_KEY" \
  -d '{
    "auth": {
      "type": "static_bearer",
      "token": "replacement-token"
    }
  }'
```

Credential auth type is immutable. For MCP OAuth credentials, `PATCH` can
replace `accessToken`, `expiresAt`, and `refresh.refreshToken`.

## Attach vaults to an agent

```
GET /v1/agents/{agentId}/vaults
PUT /v1/agents/{agentId}/vaults
```

`GET` returns the attached vaults, the agent's `updatedAt`, and connection status
for the latest version's MCP servers. Use that timestamp for optimistic
concurrency when replacing the attachment set:

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
curl -X PUT "https://api.herm.run/v1/agents/agent_123/vaults" \
  -H "Content-Type: application/json" \
  -H "x-api-key: $PRISM_API_KEY" \
  -d '{
    "vaultIds": ["vault_123"],
    "expectedUpdatedAt": "2026-07-23T18:02:00.000Z"
  }'
```

`PUT` replaces the complete attachment set. Send an empty `vaultIds` array to
detach all vaults. A stale `expectedUpdatedAt` returns `409 conflict`; reload the
agent vault state before retrying.

MCP server status is one of:

| Status        | Meaning                                                  |
| ------------- | -------------------------------------------------------- |
| `public`      | No attached credential matches the server URL.           |
| `connected`   | Exactly one usable credential matches.                   |
| `reconnect`   | The matching OAuth credential is expired or invalid.     |
| `conflict`    | Multiple attached credentials match the same server URL. |
| `unavailable` | A matching credential is temporarily unavailable.        |

## Errors

| Status | Error              | When                                                              |
| ------ | ------------------ | ----------------------------------------------------------------- |
| `400`  | `validation_error` | The request is malformed or a field is invalid.                   |
| `404`  | `not_found`        | The vault, credential, or agent is not in your organization.      |
| `409`  | `conflict`         | Agent vault access changed before an attachment update completed. |
| `502`  | `server_error`     | The credential operation could not be completed.                  |
