# Vault

> The Vault operations of the Hub REST API (6 operations).

URL: https://docs.synap.live/docs/reference/hub-api/vault · Generated from Synap-core/backend@c31e261ab (main)

Paths are relative to `/api/hub` on a pod.

## POST /vault/request

Request a secret from the Vault

AI requests access to a vault secret — creates a pending proposal and emits an urgent notification for user approval.

Request body (`application/json`): VaultRequestRequest

| Field | Type | Required | Description |
|---|---|---|---|
| `workspaceId` | string |  |  |
| `agentUserId` | string |  |  |
| `channelId` | string |  |  |
| `sourceMessageId` | string |  |  |
| `secretType` | string | yes | Secret class (e.g. api_key, oauth_token). |
| `service` | string | yes | Service the secret unlocks (e.g. github). |
| `purpose` | string | yes | Human-readable rationale shown to the user. |
| `accessLevel` | string |  | Defaults to 'read'. |
| `ttl` | number |  | Minutes the grant lives. Defaults to 60. |

Responses:

- `200`: Pending proposal id
- `400`: Bad request
- `403`: Forbidden
- `500`: Internal error

## GET /vault/request/{proposalId}

Poll a vault access request outcome

Returns the proposal status (pending/approved/rejected) and, once approved, the vault:// reference granted by the user.

Parameters:

| Name | In | Type | Required | Description |
|---|---|---|---|---|
| `proposalId` | path | string | yes |  |

Responses:

- `200`: Request outcome
- `403`: Forbidden
- `404`: Not found
- `500`: Internal error

## POST /vault/redeem

Redeem a granted vault reference to its value

Resolves a vault:// reference the authenticated agent has an active grant for, consuming one grant use. 403 if no redeemable grant exists for this principal.

Request body (`application/json`): object

| Field | Type | Required | Description |
|---|---|---|---|
| `ref` | string | yes |  |

Responses:

- `200`: Resolved secret value
- `400`: Bad request
- `403`: No redeemable grant
- `404`: Secret not found / unresolvable
- `500`: Internal error

## GET /vault/secrets

List credential metadata

Returns metadata for secrets owned by the acting user in scope. NEVER returns decrypted values — reading a value requires the request → proposal → grant flow.

Parameters:

| Name | In | Type | Required | Description |
|---|---|---|---|---|
| `workspaceId` | query | string |  |  |

Responses:

- `200`: Secret metadata list
- `403`: Forbidden
- `500`: Internal error

## POST /vault/secrets

Store a credential in the Vault

Server-encrypts and stores a secret owned by the resolved acting user. Writes a secret_audit_log row recording the agent actor. Does NOT return the value.

Request body (`application/json`): object

| Field | Type | Required | Description |
|---|---|---|---|
| `workspaceId` | string |  |  |
| `name` | string | yes |  |
| `type` | "password" \| "api_key" \| "credential" \| "note" \| "card" \| "identity" \| "ssh_key" \| "certificate" \| "env_variable" \| "database" \| "oauth" |  |  |
| `service` | string |  |  |
| `value` | string \| object | yes |  |
| `description` | string |  |  |
| `url` | string |  |  |
| `agentUserId` | string |  |  |

Responses:

- `200`: Stored secret metadata
- `400`: Bad request
- `403`: Forbidden
- `500`: Internal error

## DELETE /vault/secrets/{id}

Soft-delete a credential

Soft-deletes a vault secret (sets deletedAt/deletedBy). Write-gated on the secret's own workspace (editor+) or its owner for a pod-wide secret. Never hard-deletes — grants and audit rows reference it. Requires hub-protocol.write.

Parameters:

| Name | In | Type | Required | Description |
|---|---|---|---|---|
| `id` | path | string | yes |  |

Responses:

- `200`: Soft-deleted
- `400`: Bad request
- `403`: Forbidden
- `404`: Not found
- `500`: Internal error
