REST API
The API is a Cloudflare Worker. All application endpoints are under /v1 and require
authentication. Values are always ciphertext — the API neither encrypts nor decrypts.
Authentication
Send one of:
Authorization: Bearer <jwt>— a Stytch B2B session JWT (web sessions).Authorization: Bearer skt_…— a service token. Its storedroleismember(runtime credential) oradmin(passes admin-gated routes, for headless provisioning).owneris never issued to a token.x-seekrit-dev-user: <email>— local dev only, when the worker runs withAUTH_MODE=dev.
Errors use { "error": { "code": "...", "message": "..." } } with a matching HTTP status
(400, 401, 403, 404, 409, 500). Organizations you don't belong to return 404.
Health
| Method | Path | Description |
|---|---|---|
GET | /health | Liveness check (no auth). |
Identity
| Method | Path | Description |
|---|---|---|
GET | /v1/me | The current user and their organizations. |
GET | /v1/me/keys | Your public key and passphrase-encrypted private key. |
PUT | /v1/me/keys | Upload your keys (one-time key setup). |
Organizations
| Method | Path | Description |
|---|---|---|
GET | /v1/orgs | List organizations you can access. |
POST | /v1/orgs | Create an organization (creator becomes owner). |
GET | /v1/orgs/:orgId | Get one organization and your role. |
GET | /v1/orgs/:orgId/members | List members (includes public keys, for granting). |
Applications & environments
| Method | Path | Description |
|---|---|---|
GET | /v1/orgs/:orgId/apps | List applications. |
POST | /v1/orgs/:orgId/apps | Create an application. (admin) |
GET | /v1/orgs/:orgId/apps/:appId | Get an application and its environments. |
DELETE | /v1/orgs/:orgId/apps/:appId | Delete an application. (admin) |
GET | /v1/orgs/:orgId/apps/:appId/envs | List environments. |
POST | /v1/orgs/:orgId/apps/:appId/envs | Create an environment (body includes the wrapped DEK). (admin) |
GET | /v1/orgs/:orgId/envs/:envId | Get an environment. |
DELETE | /v1/orgs/:orgId/envs/:envId | Delete an environment. (admin) |
An environment is owned by either an application or a group; applicationId
and groupId are both present on the row, with the unused one null.
Groups
A group is a reusable, org-scoped secret bag. Its environments (matched by slug) reuse the same secret and key-grant endpoints above.
| Method | Path | Description |
|---|---|---|
GET | /v1/orgs/:orgId/groups | List groups. |
POST | /v1/orgs/:orgId/groups | Create a group. (admin) |
GET | /v1/orgs/:orgId/groups/:groupId | Get a group and its environments. |
DELETE | /v1/orgs/:orgId/groups/:groupId | Delete a group. (admin) |
GET | /v1/orgs/:orgId/groups/:groupId/envs | List a group's environments. |
POST | /v1/orgs/:orgId/groups/:groupId/envs | Create a group environment (body includes the wrapped DEK). (admin) |
Composition
Which groups an application environment pulls in, and their precedence.
| Method | Path | Description |
|---|---|---|
GET | /v1/orgs/:orgId/envs/:envId/groups | List composed groups (slug, name, position). |
POST | /v1/orgs/:orgId/envs/:envId/groups | Compose a group { groupId, position? }. (admin) |
DELETE | /v1/orgs/:orgId/envs/:envId/groups/:groupId | Remove a composed group. (admin) |
Resolve
| Method | Path | Description |
|---|---|---|
GET | /v1/resolve | The full layered environment for the calling principal. |
For a service token, the org + app + environment come from the token itself. For
a user session pass ?env=<envId>. Repeat ?with=<groupSlug>:<envSlug> to
resolve specific groups at a different slug. Returns { scope, layers }, where
layers are ordered lowest-precedence first (composed groups → the app
environment) and each carries its environmentId, secret ciphertexts, and the
DEK wrapped to the caller. The client decrypts and merges; the server sees only
ciphertext.
Resolve is edge-cached per principal, so a fleet of identical containers or CI
jobs sharing one service token is served from cache without re-querying the
database. Responses reflect secret writes, key changes, and composition
changes within seconds (a write invalidates the cache; a short TTL is the
backstop). Because the cache key includes the calling principal, one caller
never receives another's wrapped DEK. Successful resolves are metered for
usage/billing but are not written to the audit log; a denied resolve is
audited (env.resolve_denied).
Secrets
Values are opaque ciphertext blobs produced by the client.
| Method | Path | Description |
|---|---|---|
GET | /v1/orgs/:orgId/envs/:envId/secrets | List secrets (with ciphertext). |
PUT | /v1/orgs/:orgId/envs/:envId/secrets/:name | Create or update a secret (appends a version). |
DELETE | /v1/orgs/:orgId/envs/:envId/secrets/:name | Delete a secret. |
Key grants
| Method | Path | Description |
|---|---|---|
GET | /v1/orgs/:orgId/envs/:envId/key | The calling principal's own wrapped DEK. |
GET | /v1/orgs/:orgId/envs/:envId/keys | List all grants for the environment. (admin) |
POST | /v1/orgs/:orgId/envs/:envId/keys | Grant a wrapped DEK to a principal. (admin) |
DELETE | /v1/orgs/:orgId/envs/:envId/keys/:grantId | Revoke a grant. (admin) |
Service tokens
| Method | Path | Description |
|---|---|---|
GET | /v1/orgs/:orgId/tokens | List service tokens. (admin) |
POST | /v1/orgs/:orgId/tokens | Register a token (client sends hash + public key; role defaults to member, pass admin for a provisioning token; optional environmentId binds it to an app environment). (admin) |
DELETE | /v1/orgs/:orgId/tokens/:tokenId | Revoke a token. (admin) |
A service token may read or write secrets only for environments it holds a key grant for — its bound environment and the group slices composed into it. It cannot address other environments in the org.
Audit
| Method | Path | Description |
|---|---|---|
GET | /v1/orgs/:orgId/audit | Paginated audit entries. (admin) Query: cursor, limit, action, resourceType. |
Token creation is client-driven: the client generates the keypair and token string locally and submits only the token id, a SHA-256 hash, and the public key. The server never sees the token secret.