Secrets API
Org-scoped encrypted secrets (the strongbox service): store
provider keys and app credentials once, reference them by name everywhere
(e.g. the AI provider proxy reads provider keys from here at request time).
list / create / update return
metadata only — never values. But get and
rotate return the decrypted cleartext value.
Treat any credential that can call them as able to read every secret it can
name: scope keys narrowly, audit reads via the audit endpoint,
and never log the response.
Well-known scopes
Secret names are free-form, but one prefix carries platform behavior:
a secret named app:NAME (flat, no further colons —
e.g. app:DATABASE_URL) is merged into the environment of
any app your org self-deploys
on its own runners. The merge receipt lists names only, and your value
wins over any pipeline default of the same name.
Endpoints
| Method | Path | SDK (client.secrets) | Returns value? |
|---|---|---|---|
| GET | /v1/orgs/{org_id}/secrets | list | metadata only |
| POST | /v1/orgs/{org_id}/secrets | create | metadata only |
| GET | /v1/orgs/{org_id}/secrets/{name} | get | cleartext |
| PUT | /v1/orgs/{org_id}/secrets/{name} | update | metadata only |
| DELETE | /v1/orgs/{org_id}/secrets/{name} | delete | — |
| POST | /v1/orgs/{org_id}/secrets/{name}/rotate | rotate | cleartext (new value) |
| GET | /v1/orgs/{org_id}/audit | audit | access log |
Secret names are validated server-side: 1–256 chars from
[A-Za-z0-9._-]; duplicates return 409 DUPLICATE_NAME.
SDK Examples
// Create (response is metadata — the value is write-only here)
await client.secrets.create(orgId, {
name: 'anthropic-api-key',
value: process.env.ANTHROPIC_KEY!,
});
// List — names + metadata, no values
const secrets = await client.secrets.list(orgId);
// Read the decrypted value (CLEARTEXT — handle with care)
const { value } = await client.secrets.get(orgId, 'anthropic-api-key');
// Rotate to a fresh random value, returned once
const rotated = await client.secrets.rotate(orgId, 'webhook-signing-key');
// Who read what, when
const audit = await client.secrets.audit(orgId);
client.secrets().create(org_id, &CreateSecretRequest {
name: "anthropic-api-key".into(),
value: std::env::var("ANTHROPIC_KEY")?,
}).await?;
let value = client.secrets().get(org_id, "anthropic-api-key").await?; // cleartext
let audit = client.secrets().audit(org_id).await?;