API reference
23 operations in secrets. Raw spec: openapi.json.
GET
/api/v1/secrets/foldersGET /api/secrets/folders — metadata-only category tree.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
client_id | query | — | No | Client-scope tree; omitted = org-scope tree. |
Responses
| Status | Description |
|---|---|
200 |
Security: bearer
POST
/api/v1/secrets/folderssecrets_folders_create
Request body
CreateSecretFolderRequest
Responses
| Status | Description |
|---|---|
200 | |
409 | slug already exists in this scope |
422 | validation error |
Security: bearer
PATCH
/api/v1/secrets/folders/{id}secrets_folders_update
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string | Yes |
Request body
UpdateSecretFolderRequest
Responses
| Status | Description |
|---|---|
200 | |
404 | folder not visible in scope |
409 | the shipped default is immutable; fork instead |
Security: bearer
DELETE
/api/v1/secrets/folders/{id}secrets_folders_delete
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string | Yes |
Responses
| Status | Description |
|---|---|
200 | deleted |
404 | folder not visible in scope |
409 | seed refusal or non-empty subtree |
Security: bearer
POST
/api/v1/secrets/folders/{id}/forkPOST /api/secrets/folders/{id}/fork — fork-the-seed customization (a NEW row graph in the client's scope, never edit-in-place, ADR 0004).
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string | Yes |
Request body
ForkSecretFolderRequest
Responses
| Status | Description |
|---|---|
200 | |
404 | source folder or client not visible in scope |
409 | a fork of that slug already exists |
Security: bearer
GET
/api/v1/secrets/grantsGET /api/secrets/grants — the grant matrix reads for admins (Owner or Admin only; grants are policy data, not vault contents).
Responses
| Status | Description |
|---|---|
200 | |
403 | grant administration is Owner/Admin only |
Security: bearer
PUT
/api/v1/secrets/grantsPUT /api/secrets/grants — upserts ONE role × folder grant row (can_edit implies read). Owner/Admin only.
Request body
SetSecretGrantRequest
Responses
| Status | Description |
|---|---|
200 | |
403 | grant administration is Owner/Admin only |
404 | folder or role not visible in scope |
422 | validation error |
Security: bearer
DELETE
/api/v1/secrets/grantsDELETE /api/secrets/grants?role_id=&folder_id= — revoke one grant.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
role_id | query | string | Yes | |
folder_id | query | string | Yes |
Responses
| Status | Description |
|---|---|
200 | deleted |
403 | grant administration is Owner/Admin only |
404 | grant not found |
Security: bearer
GET
/api/v1/secrets/recordsGET /api/secrets/records — metadata-only vault rows.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
client_id | query | — | No | Client-scope records; omitted = org-scope. |
folder_id | query | — | No |
Responses
| Status | Description |
|---|---|
200 |
Security: bearer
POST
/api/v1/secrets/recordsPOST /api/secrets/records — seals fields with coordinate AAD; instant-first (IF1–IF3) when an idempotency key rides the request.
Request body
CreateSecretRecordRequest
Responses
| Status | Description |
|---|---|
200 | |
403 | restricted category gate denied |
409 | title already exists in this folder / idempotency key reused |
422 | validation error |
Security: bearer
POST
/api/v1/secrets/records/bulkPOST /api/secrets/records/bulk — the chunked worker path.
Request body
BulkSecretIngestRequest
Responses
| Status | Description |
|---|---|
200 | |
403 | restricted category gate denied |
422 | chunk over cap / validation error |
429 | org write budget exhausted |
Security: bearer
GET
/api/v1/secrets/records/{id}GET /api/secrets/records/{id} — metadata only.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string | Yes |
Responses
| Status | Description |
|---|---|
200 | |
404 | record not visible in scope |
Security: bearer
PATCH
/api/v1/secrets/records/{id}PATCH /api/secrets/records/{id} — metadata + field rotation/clear (`value: null` clears — A5); instant-first envelope (IF1–IF3).
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string | Yes |
Request body
UpdateSecretRecordRequest
Responses
| Status | Description |
|---|---|
200 | |
403 | restricted category gate denied |
404 | record not visible in scope |
409 | title collision / version conflict / idempotency key reused |
422 | validation error |
Security: bearer
DELETE
/api/v1/secrets/records/{id}DELETE /api/secrets/records/{id} — records retire; their fields cascade; the audit keeps the trail.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string | Yes |
Responses
| Status | Description |
|---|---|
200 | deleted |
403 | restricted category gate denied |
404 | record not visible in scope |
Security: bearer
GET
/api/v1/secrets/records/{id}/fileGET /api/secrets/records/{id}/file — the reveal-file path (document kind ONLY): requires `secrets:edit` + the category gate (the same posture as field reveal), decrypts the object-store ciphertext, and emits `secret.revealed` in-commit with the read. The response is the sole carrier of the plaintext bytes.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string | Yes |
Responses
| Status | Description |
|---|---|
200 | |
403 | restricted category gate denied |
404 | record or object not found |
409 | record has no stored file |
Security: bearer
PUT
/api/v1/secrets/records/{id}/filePUT /api/secrets/records/{id}/file — document-kind ONLY. Seals the uploaded bytes (AAD-bound to the record coordinate), PUTs the ciphertext to the object store behind the core-store S3/local seam, and pins the pointer + hash + byte length on the record in the same tx (event emitted in-commit).
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string | Yes |
Request body
string
Responses
| Status | Description |
|---|---|
200 | |
403 | restricted category gate denied |
404 | record not visible in scope |
422 | record is not document-kind / body over cap |
Security: bearer
GET
/api/v1/secrets/records/{id}/linksGET /api/secrets/records/{id}/links
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string | Yes |
Responses
| Status | Description |
|---|---|
200 |
Security: bearer
POST
/api/v1/secrets/records/{id}/linksPOST /api/secrets/records/{id}/links — typed labels via the seam; broken targets ride the asset-docs semantic (never cascade-deleted).
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string | Yes |
Request body
CreateLinkRequest
Responses
| Status | Description |
|---|---|
200 | |
403 | restricted category gate denied |
404 | secret record or link target not visible in scope |
Security: bearer
POST
/api/v1/secrets/records/{id}/revealPOST /api/secrets/records/{id}/reveal — the ONLY plaintext path, mirroring `/passwords/{id}/reveal`: requires `secrets:edit`, runs inside the org tx so the reveal event commits atomically with the read, decrypts with coordinate AAD first (falling back to the legacy seal for rows the deterministic importer forwarded) and the response is the sole carrier of the decrypted fields.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string | Yes |
Responses
| Status | Description |
|---|---|
200 | |
403 | reveal requires secrets:edit (and a category grant on restricted chains) |
404 | record not visible in scope |
Security: bearer