seekrit

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 stored role is member (runtime credential) or admin (passes admin-gated routes, for headless provisioning). owner is never issued to a token.
  • x-seekrit-dev-user: <email> — local dev only, when the worker runs with AUTH_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

MethodPathDescription
GET/healthLiveness check (no auth).

Identity

MethodPathDescription
GET/v1/meThe current user and their organizations.
GET/v1/me/keysYour public key and passphrase-encrypted private key.
PUT/v1/me/keysUpload your keys (one-time key setup).

Organizations

MethodPathDescription
GET/v1/orgsList organizations you can access.
POST/v1/orgsCreate an organization (creator becomes owner).
GET/v1/orgs/:orgIdGet one organization and your role.
GET/v1/orgs/:orgId/membersList members (includes public keys, for granting).

Applications & environments

MethodPathDescription
GET/v1/orgs/:orgId/appsList applications.
POST/v1/orgs/:orgId/appsCreate an application. (admin)
GET/v1/orgs/:orgId/apps/:appIdGet an application and its environments.
DELETE/v1/orgs/:orgId/apps/:appIdDelete an application. (admin)
GET/v1/orgs/:orgId/apps/:appId/envsList environments.
POST/v1/orgs/:orgId/apps/:appId/envsCreate an environment (body includes the wrapped DEK). (admin)
GET/v1/orgs/:orgId/envs/:envIdGet an environment.
DELETE/v1/orgs/:orgId/envs/:envIdDelete 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.

MethodPathDescription
GET/v1/orgs/:orgId/groupsList groups.
POST/v1/orgs/:orgId/groupsCreate a group. (admin)
GET/v1/orgs/:orgId/groups/:groupIdGet a group and its environments.
DELETE/v1/orgs/:orgId/groups/:groupIdDelete a group. (admin)
GET/v1/orgs/:orgId/groups/:groupId/envsList a group's environments.
POST/v1/orgs/:orgId/groups/:groupId/envsCreate a group environment (body includes the wrapped DEK). (admin)

Composition

Which groups an application environment pulls in, and their precedence.

MethodPathDescription
GET/v1/orgs/:orgId/envs/:envId/groupsList composed groups (slug, name, position).
POST/v1/orgs/:orgId/envs/:envId/groupsCompose a group { groupId, position? }. (admin)
DELETE/v1/orgs/:orgId/envs/:envId/groups/:groupIdRemove a composed group. (admin)

Resolve

MethodPathDescription
GET/v1/resolveThe 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.

note

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.

MethodPathDescription
GET/v1/orgs/:orgId/envs/:envId/secretsList secrets (with ciphertext).
PUT/v1/orgs/:orgId/envs/:envId/secrets/:nameCreate or update a secret (appends a version).
DELETE/v1/orgs/:orgId/envs/:envId/secrets/:nameDelete a secret.

Key grants

MethodPathDescription
GET/v1/orgs/:orgId/envs/:envId/keyThe calling principal's own wrapped DEK.
GET/v1/orgs/:orgId/envs/:envId/keysList all grants for the environment. (admin)
POST/v1/orgs/:orgId/envs/:envId/keysGrant a wrapped DEK to a principal. (admin)
DELETE/v1/orgs/:orgId/envs/:envId/keys/:grantIdRevoke a grant. (admin)

Service tokens

MethodPathDescription
GET/v1/orgs/:orgId/tokensList service tokens. (admin)
POST/v1/orgs/:orgId/tokensRegister 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/:tokenIdRevoke 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

MethodPathDescription
GET/v1/orgs/:orgId/auditPaginated audit entries. (admin) Query: cursor, limit, action, resourceType.
note

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.