//Secrets Vault

Secrets Vault

Encrypted, versioned secret storage for per-organization credentials and config values.

All endpoints require Authorization: Bearer <jwt>. Write operations additionally require the vault:write scope.

Endpoints

PUT /api/admin/organizations/:org_uuid/secrets/:name

Creates or updates a secret. Secrets are versioned; each write creates a new version.

Input: ~~~json { "value": "sk_live_abc123...", "description": "Stripe live key", "tags": ["billing", "stripe"] } ~~~

Output: ~~~json { "name": "stripe_secret_key", "version": 3, "created_at": "2024-07-11T10:00:00Z" } ~~~

GET /api/admin/organizations/:org_uuid/secrets/:name

Retrieves the latest version of a secret.

Output: ~~~json { "name": "stripe_secret_key", "value": "sk_live_abc123...", "version": 3, "created_at": "2024-07-11T10:00:00Z", "tags": ["billing", "stripe"] } ~~~

GET /api/admin/organizations/:org_uuid/secrets/:name/versions

Lists all versions of a secret (values are not returned).

Output: ~~~json { "versions": [ { "version": 3, "created_at": "2024-07-11T10:00:00Z" }, { "version": 2, "created_at": "2024-06-01T00:00:00Z" }, { "version": 1, "created_at": "2024-05-01T00:00:00Z" } ] } ~~~

GET /api/admin/organizations/:org_uuid/secrets/:name/versions/:version

Retrieves a specific version of a secret.

DELETE /api/admin/organizations/:org_uuid/secrets/:name

Soft-deletes a secret (all versions). The secret can be restored within 30 days.

GET /api/admin/organizations/:org_uuid/secrets

Lists all secret names (not values) for the organization.

Output: ~~~json { "data": [ { "name": "stripe_secret_key", "version": 3, "tags": ["billing"] }, { "name": "sendgrid_api_key", "version": 1, "tags": ["email"] } ] } ~~~

Encryption

All secret values are encrypted at rest using AES-256-GCM with per-organization encryption keys stored in ButtrBase's HSM.

Audit Log

Every read and write operation on the vault is logged to the organization's audit trail.

SDK Examples

Python

~~~python client.put_secret_admin("org-uuid", "stripe_secret_key", "sk_live_abc123...") secret = client.get_secret_by_name("org-uuid", "stripe_secret_key") secrets = client.list_secrets("org-uuid") client.delete_secret("org-uuid", "stripe_secret_key") ~~~

Node.js / TypeScript

~~~typescript await client.putSecret('org-uuid', 'stripe_secret_key', 'sk_live_abc123...'); const secret = await client.getSecret('org-uuid', 'stripe_secret_key'); const secrets = await client.listSecrets('org-uuid'); await client.deleteSecret('org-uuid', 'stripe_secret_key'); ~~~

Go

~~~go _, err := client.PutSecret(ctx, "org-uuid", "stripe_secret_key", "sk_live_abc123...", "Stripe key") secret, err := client.GetSecret(ctx, "org-uuid", "stripe_secret_key") secrets, err := client.ListSecrets(ctx, "org-uuid") ~~~

Rust

~~~rust client.put_secret("org-uuid", "stripe_secret_key", "sk_live_abc123...").await?; let secret = client.get_secret("org-uuid", "stripe_secret_key").await?; let secrets = client.list_secrets("org-uuid").await?; client.delete_secret("org-uuid", "stripe_secret_key").await?; ~~~

Endpoint Summary

| Method | Path | Purpose | |---|---|---| | PUT | /api/admin/organizations/{org}/secrets/{name} | Create / update secret | | GET | /api/admin/organizations/{org}/secrets/{name} | Get latest version | | GET | /api/admin/organizations/{org}/secrets/{name}/versions | List versions | | GET | /api/admin/organizations/{org}/secrets/{name}/versions/{v} | Get specific version | | DELETE | /api/admin/organizations/{org}/secrets/{name} | Soft-delete secret | | GET | /api/admin/organizations/{org}/secrets | List all secrets |

When to Use

  • Storing third-party API keys per customer service
  • Rotate a key in one place and let workers pick up within 5 minutes

Error Reference

| Status | Code | Meaning | |--------|------|---------| | 400 | validation_error | Secret name or value failed validation | | 401 | unauthorized | Missing or invalid Authorization header | | 403 | forbidden | Insufficient vault access scope | | 404 | secret_not_found | Secret path does not exist | | 409 | version_conflict | Concurrent write detected; retry with latest version | | 423 | vault_sealed | Vault is sealed; requires operator unseal |