# secret

Vault-backed secret storage and rotation.

**Amfelt REST API** · v1.13.0 · `https://api.amfelt.com`

---
### POST `/v1/secrets/update` {#updatesecret}

**Update an existing secret.**

Overwrites the credential map of an existing secret. The target key is carried in the body so it may contain slashes. An agent may use only the vault refs of the projects pinned to it, and may write only a ref `<environment>/database/<project id>/<name>` of such a project. Any other key is refused with 403, code permission_denied, and a message naming the rule, never the ref. The operator-bootstrap token is not scoped by this rule and stays organization-wide.

#### Request body _(required)_

`application/json`

| Property | Type | Required | Description |
|---|---|---|---|
| `fields` | object | Yes | The new credential map; replaces stored values. |
| `key` | string | Yes | The vault key of the secret to update; may contain slashes. Examples: `myapp/prod/api_key`. |


#### Responses

**200** — The secret was updated.

`application/json`

| Property | Type | Required | Description |
|---|---|---|---|
| `key` | string | Yes | The vault key of the secret. |
| `version` | integer | Yes | Current version of the secret. |


**400** — The request was malformed or failed validation.

`application/json`

| Property | Type | Required | Description |
|---|---|---|---|
| `code` | string | Yes | Stable, snake_case token identifying the error condition. See ErrorCode for the api's canonical named vocabulary — this field is deliberately not restricted to it, since handlers may emit other ad-hoc codes not listed there (e.g. not_implemented). Examples: `invalid_argument`. |
| `field` | string | No | Optional hint identifying the request field the error refers to, in snake_case (e.g. "slug", "display_name", "token"). Set by handlers that validate multiple fields and want to enable field-targeted UX in clients. Absent when the error does not map to a single field. Examples: `slug`. |
| `message` | string | Yes | Human-readable description of the error. Examples: `limit must be between 1 and 100`. |


**401** — The request lacks valid credentials.

`application/json`

| Property | Type | Required | Description |
|---|---|---|---|
| `code` | string | Yes | Stable, snake_case token identifying the error condition. See ErrorCode for the api's canonical named vocabulary — this field is deliberately not restricted to it, since handlers may emit other ad-hoc codes not listed there (e.g. not_implemented). Examples: `invalid_argument`. |
| `field` | string | No | Optional hint identifying the request field the error refers to, in snake_case (e.g. "slug", "display_name", "token"). Set by handlers that validate multiple fields and want to enable field-targeted UX in clients. Absent when the error does not map to a single field. Examples: `slug`. |
| `message` | string | Yes | Human-readable description of the error. Examples: `limit must be between 1 and 100`. |


**403** — The caller is authenticated but not permitted to perform the request.

`application/json`

| Property | Type | Required | Description |
|---|---|---|---|
| `code` | string | Yes | Stable, snake_case token identifying the error condition. See ErrorCode for the api's canonical named vocabulary — this field is deliberately not restricted to it, since handlers may emit other ad-hoc codes not listed there (e.g. not_implemented). Examples: `invalid_argument`. |
| `field` | string | No | Optional hint identifying the request field the error refers to, in snake_case (e.g. "slug", "display_name", "token"). Set by handlers that validate multiple fields and want to enable field-targeted UX in clients. Absent when the error does not map to a single field. Examples: `slug`. |
| `message` | string | Yes | Human-readable description of the error. Examples: `limit must be between 1 and 100`. |


#### Security

bearer_jwt

---

### POST `/v1/secrets/resolve` {#resolvesecret}

**Resolve a secret.**

Returns the stored payload for the given vault reference. The policy engine gates each resolve; a deny surfaces as 403. An agent may also use only the vault refs of the projects pinned to it: a ref `<environment>/database/<project id>/<name>` of such a project, and the source and target refs the control plane recorded for those projects. Any other ref is refused with 403. Both refusals carry code permission_denied, and a message that never names the ref. The operator-bootstrap token is not scoped by the pinned projects and stays organization-wide.

#### Request body _(required)_

`application/json`

| Property | Type | Required | Description |
|---|---|---|---|
| `purpose` | string | No | Optional opaque audit label. |
| `ref` | string | Yes | The vault reference of the secret to resolve. Examples: `production/llm/anthropic`. |


#### Responses

**200** — The resolved secret payload.

`application/json`

| Property | Type | Required | Description |
|---|---|---|---|
| `classification` | [SecretClassification](#secret-classification) | Yes |  |
| `fields` | object | Yes | The typed credential map. |
| `type` | [SecretType](#secret-type) | Yes |  |
| `version` | integer | Yes | Current version of the secret. |


**400** — The request was malformed or failed validation.

`application/json`

| Property | Type | Required | Description |
|---|---|---|---|
| `code` | string | Yes | Stable, snake_case token identifying the error condition. See ErrorCode for the api's canonical named vocabulary — this field is deliberately not restricted to it, since handlers may emit other ad-hoc codes not listed there (e.g. not_implemented). Examples: `invalid_argument`. |
| `field` | string | No | Optional hint identifying the request field the error refers to, in snake_case (e.g. "slug", "display_name", "token"). Set by handlers that validate multiple fields and want to enable field-targeted UX in clients. Absent when the error does not map to a single field. Examples: `slug`. |
| `message` | string | Yes | Human-readable description of the error. Examples: `limit must be between 1 and 100`. |


**401** — The request lacks valid credentials.

`application/json`

| Property | Type | Required | Description |
|---|---|---|---|
| `code` | string | Yes | Stable, snake_case token identifying the error condition. See ErrorCode for the api's canonical named vocabulary — this field is deliberately not restricted to it, since handlers may emit other ad-hoc codes not listed there (e.g. not_implemented). Examples: `invalid_argument`. |
| `field` | string | No | Optional hint identifying the request field the error refers to, in snake_case (e.g. "slug", "display_name", "token"). Set by handlers that validate multiple fields and want to enable field-targeted UX in clients. Absent when the error does not map to a single field. Examples: `slug`. |
| `message` | string | Yes | Human-readable description of the error. Examples: `limit must be between 1 and 100`. |


**403** — The caller is authenticated but not permitted to perform the request.

`application/json`

| Property | Type | Required | Description |
|---|---|---|---|
| `code` | string | Yes | Stable, snake_case token identifying the error condition. See ErrorCode for the api's canonical named vocabulary — this field is deliberately not restricted to it, since handlers may emit other ad-hoc codes not listed there (e.g. not_implemented). Examples: `invalid_argument`. |
| `field` | string | No | Optional hint identifying the request field the error refers to, in snake_case (e.g. "slug", "display_name", "token"). Set by handlers that validate multiple fields and want to enable field-targeted UX in clients. Absent when the error does not map to a single field. Examples: `slug`. |
| `message` | string | Yes | Human-readable description of the error. Examples: `limit must be between 1 and 100`. |


#### Security

bearer_jwt

---

### POST `/v1/secrets/cache/invalidate` {#invalidatesecretcache}

**Invalidate a secret's cache entry.**

Drops the cached payload for the given vault key so the next resolve fetches a fresh copy from the vault. An agent may use only the vault refs of the projects pinned to it: a ref `<environment>/database/<project id>/<name>` of such a project, and the source and target refs the control plane recorded for those projects. Any other key is refused with 403, code permission_denied, and a message naming the rule, never the ref. The operator-bootstrap token is not scoped by this rule and stays organization-wide.

#### Request body _(required)_

`application/json`

| Property | Type | Required | Description |
|---|---|---|---|
| `key` | string | Yes | The vault key whose cache entry to drop; may contain slashes. Examples: `myapp/prod/api_key`. |


#### Responses

**204** — The cache entry was invalidated.

**400** — The request was malformed or failed validation.

`application/json`

| Property | Type | Required | Description |
|---|---|---|---|
| `code` | string | Yes | Stable, snake_case token identifying the error condition. See ErrorCode for the api's canonical named vocabulary — this field is deliberately not restricted to it, since handlers may emit other ad-hoc codes not listed there (e.g. not_implemented). Examples: `invalid_argument`. |
| `field` | string | No | Optional hint identifying the request field the error refers to, in snake_case (e.g. "slug", "display_name", "token"). Set by handlers that validate multiple fields and want to enable field-targeted UX in clients. Absent when the error does not map to a single field. Examples: `slug`. |
| `message` | string | Yes | Human-readable description of the error. Examples: `limit must be between 1 and 100`. |


**401** — The request lacks valid credentials.

`application/json`

| Property | Type | Required | Description |
|---|---|---|---|
| `code` | string | Yes | Stable, snake_case token identifying the error condition. See ErrorCode for the api's canonical named vocabulary — this field is deliberately not restricted to it, since handlers may emit other ad-hoc codes not listed there (e.g. not_implemented). Examples: `invalid_argument`. |
| `field` | string | No | Optional hint identifying the request field the error refers to, in snake_case (e.g. "slug", "display_name", "token"). Set by handlers that validate multiple fields and want to enable field-targeted UX in clients. Absent when the error does not map to a single field. Examples: `slug`. |
| `message` | string | Yes | Human-readable description of the error. Examples: `limit must be between 1 and 100`. |


**403** — The caller is authenticated but not permitted to perform the request.

`application/json`

| Property | Type | Required | Description |
|---|---|---|---|
| `code` | string | Yes | Stable, snake_case token identifying the error condition. See ErrorCode for the api's canonical named vocabulary — this field is deliberately not restricted to it, since handlers may emit other ad-hoc codes not listed there (e.g. not_implemented). Examples: `invalid_argument`. |
| `field` | string | No | Optional hint identifying the request field the error refers to, in snake_case (e.g. "slug", "display_name", "token"). Set by handlers that validate multiple fields and want to enable field-targeted UX in clients. Absent when the error does not map to a single field. Examples: `slug`. |
| `message` | string | Yes | Human-readable description of the error. Examples: `limit must be between 1 and 100`. |


#### Security

bearer_jwt

---

### POST `/v1/secrets` {#registersecret}

**Register a new secret.**

Stores a new secret in the caller's organization vault and returns the server-generated key. Agent-callable. An agent may use only the vault refs of the projects pinned to it, and may write only a ref `<environment>/database/<project id>/<name>` of such a project. The ref is the body's environment, type and name joined by slashes, so an agent registers type database under a name `<project id>/<name>`. Any other ref is refused with 403, code permission_denied, and a message naming the rule, never the ref. The operator-bootstrap token is not scoped by this rule and stays organization-wide.

#### Request body _(required)_

`application/json`

| Property | Type | Required | Description |
|---|---|---|---|
| `classification` | [SecretClassification](#secret-classification) | Yes |  |
| `environment` | string | Yes | DTAP environment to scope the secret to. Examples: `production`. |
| `fields` | object | Yes | The typed credential map (e.g. host, port, username, password). |
| `name` | string | Yes | Human-readable name of the secret. |
| `rotation_policy` | [RotationPolicy](#rotation-policy) | No |  |
| `type` | [SecretType](#secret-type) | Yes |  |


#### Responses

**201** — The secret was registered.

`application/json`

| Property | Type | Required | Description |
|---|---|---|---|
| `key` | string | Yes | The vault key of the secret. |
| `version` | integer | Yes | Current version of the secret. |


**400** — The request was malformed or failed validation.

`application/json`

| Property | Type | Required | Description |
|---|---|---|---|
| `code` | string | Yes | Stable, snake_case token identifying the error condition. See ErrorCode for the api's canonical named vocabulary — this field is deliberately not restricted to it, since handlers may emit other ad-hoc codes not listed there (e.g. not_implemented). Examples: `invalid_argument`. |
| `field` | string | No | Optional hint identifying the request field the error refers to, in snake_case (e.g. "slug", "display_name", "token"). Set by handlers that validate multiple fields and want to enable field-targeted UX in clients. Absent when the error does not map to a single field. Examples: `slug`. |
| `message` | string | Yes | Human-readable description of the error. Examples: `limit must be between 1 and 100`. |


**401** — The request lacks valid credentials.

`application/json`

| Property | Type | Required | Description |
|---|---|---|---|
| `code` | string | Yes | Stable, snake_case token identifying the error condition. See ErrorCode for the api's canonical named vocabulary — this field is deliberately not restricted to it, since handlers may emit other ad-hoc codes not listed there (e.g. not_implemented). Examples: `invalid_argument`. |
| `field` | string | No | Optional hint identifying the request field the error refers to, in snake_case (e.g. "slug", "display_name", "token"). Set by handlers that validate multiple fields and want to enable field-targeted UX in clients. Absent when the error does not map to a single field. Examples: `slug`. |
| `message` | string | Yes | Human-readable description of the error. Examples: `limit must be between 1 and 100`. |


**403** — The caller is authenticated but not permitted to perform the request.

`application/json`

| Property | Type | Required | Description |
|---|---|---|---|
| `code` | string | Yes | Stable, snake_case token identifying the error condition. See ErrorCode for the api's canonical named vocabulary — this field is deliberately not restricted to it, since handlers may emit other ad-hoc codes not listed there (e.g. not_implemented). Examples: `invalid_argument`. |
| `field` | string | No | Optional hint identifying the request field the error refers to, in snake_case (e.g. "slug", "display_name", "token"). Set by handlers that validate multiple fields and want to enable field-targeted UX in clients. Absent when the error does not map to a single field. Examples: `slug`. |
| `message` | string | Yes | Human-readable description of the error. Examples: `limit must be between 1 and 100`. |


#### Security

bearer_jwt

---

### GET `/v1/secrets/schema/{category}` {#getsecretschema}

**Get the schema for a secret category.**

Returns the field shape for the given secret category. Tenant-agnostic platform metadata read from embedded YAML; no auth required.

#### Parameters

| Name | In  | Required | Type | Description |
| ---- | --- | -------- | ---- | ----------- |
| `category` | path | Yes | string | The secret category (e.g. database, api-key, s3). |

#### Responses

**200** — The base schema for the category.

`application/json`

| Property | Type | Required | Description |
|---|---|---|---|
| `fields` | [SecretFieldSchema](#secret-field-schema)[] | Yes | The field shape for this category (optionally driver-extended). |
| `type` | string | Yes | The secret category this schema describes. Examples: `database`. |


**404** — The specified resource was not found.

`application/json`

| Property | Type | Required | Description |
|---|---|---|---|
| `code` | string | Yes | Stable, snake_case token identifying the error condition. See ErrorCode for the api's canonical named vocabulary — this field is deliberately not restricted to it, since handlers may emit other ad-hoc codes not listed there (e.g. not_implemented). Examples: `invalid_argument`. |
| `field` | string | No | Optional hint identifying the request field the error refers to, in snake_case (e.g. "slug", "display_name", "token"). Set by handlers that validate multiple fields and want to enable field-targeted UX in clients. Absent when the error does not map to a single field. Examples: `slug`. |
| `message` | string | Yes | Human-readable description of the error. Examples: `limit must be between 1 and 100`. |


---

### GET `/v1/secrets/schema/{category}/{driver}` {#getsecretschemawithdriver}

**Get the schema for a secret category merged with a driver extension.**

Returns the base schema merged with any driver-specific extension. Tenant-agnostic platform metadata; no auth required.

#### Parameters

| Name | In  | Required | Type | Description |
| ---- | --- | -------- | ---- | ----------- |
| `category` | path | Yes | string | The secret category (e.g. database, api-key, s3). |
| `driver` | path | Yes | string | The driver name for the merged-schema endpoint (e.g. postgres, mysql). |

#### Responses

**200** — The base schema merged with the driver extension.

`application/json`

| Property | Type | Required | Description |
|---|---|---|---|
| `fields` | [SecretFieldSchema](#secret-field-schema)[] | Yes | The field shape for this category (optionally driver-extended). |
| `type` | string | Yes | The secret category this schema describes. Examples: `database`. |


**404** — The specified resource was not found.

`application/json`

| Property | Type | Required | Description |
|---|---|---|---|
| `code` | string | Yes | Stable, snake_case token identifying the error condition. See ErrorCode for the api's canonical named vocabulary — this field is deliberately not restricted to it, since handlers may emit other ad-hoc codes not listed there (e.g. not_implemented). Examples: `invalid_argument`. |
| `field` | string | No | Optional hint identifying the request field the error refers to, in snake_case (e.g. "slug", "display_name", "token"). Set by handlers that validate multiple fields and want to enable field-targeted UX in clients. Absent when the error does not map to a single field. Examples: `slug`. |
| `message` | string | Yes | Human-readable description of the error. Examples: `limit must be between 1 and 100`. |


---

