POST /v1/organizations creates a separate organization, but it doesn’t give the calling key access to that organization. To manage the new organization’s API keys, use a secret key that belongs to the new organization.
Endpoint summary
A request whose key lacks the required scope returns
403 with auth.insufficient_scope.
Secret-key scopes
A secret key carries a list of scopes, and each endpoint requires one. The scopes are:
Older secret keys that still carry the removed
organizations:manage scope must be rotated or recreated before they can use organization-management endpoints.
See Authentication for the endpoint-to-scope table across the whole API.
POST /v1/organizations
Create an organization. Requires a secret key with the organizations:create scope.
name must be a non-empty string. slug must contain only lowercase letters, digits, and hyphens. A slug that another organization already uses returns 409 with request.conflict. A successful request returns 201 with the organization resource.
GET /v1/organizations/:organizationId
Retrieve organization details as { "data": { ... }, "meta": { ... } }, including status, created_at, and updated_at. Requires a secret key with the organizations:read scope.
PATCH /v1/organizations/:organizationId
Update organization fields. Requires a secret key with the organizations:update scope.
Send name (a non-empty string), status, or both. Allowed status values:
activesuspendeddeleted
POST /v1/organizations/:organizationId/api-keys
Create a publishable or secret key for an organization. Requires a secret key with the api_keys:manage scope.
The response is 201 with the API key resource. The full key appears in data.revealed_key in this response. For a secret key, this is the only time Foil returns the full value, so store it before you discard the response. Publishable keys are public by design, so their resource also carries the full value as display_key on later reads.
The API key resource id uses the key_... format. This is the identifier you should persist for future revoke and rotate calls.
Customer-managed requests can set these fields:
Foil manages rate limits itself, so a request that includes
rate_limit returns 422 with the field error rate_limit: not_allowed. See Rate limits.
Secret key creation requires a non-empty scopes list. For the recommended narrow preset, send ["sessions:read", "sessions:update", "fingerprints:read"]. This preset can’t list sessions or fingerprints, so add sessions:list or fingerprints:list if your integration needs those endpoints. To grant all current and future scopes, set scopes to ["*"].
422 with request.validation_failed and a details.fields entry that names the field.
Origin rules
Each entry inallowed_origins is one of these:
Test keys also accept an exact
http or https origin with any host and port, such as http://localhost:3000, so you can develop against a local server or a device on your network.
A request from an origin that the list doesn’t match, or a request without an Origin header, returns 403 with auth.origin_not_allowed.
GET /v1/organizations/:organizationId/api-keys
List keys for an organization. Requires a secret key with the api_keys:read scope. Responses use { "data": [...], "pagination": { ... }, "meta": { ... } }. Keys are ordered newest first and include revoked keys. The endpoint accepts limit and cursor. See Pagination. Each item includes:
PATCH /v1/organizations/:organizationId/api-keys/:keyId
Update API key metadata. Requires a secret key with the api_keys:manage scope.
Allowed fields:
namefor publishable and secret keysallowed_originsfor publishable keysscopesfor secret keys
allowed_origins for a secret key, scopes for a publishable key, or rate_limit returns 422. A revoked key returns 404.
Key type, environment, client target, and key material are immutable. Rotate a key to change the actual credential value. Changes to scopes and allowed origins take up to about 15 seconds to apply. See Authentication.
DELETE /v1/organizations/:organizationId/api-keys/:keyId
Revokes a key and returns the revoked API key resource inside the normal response envelope, with status 200. Requires a secret key with the api_keys:manage scope.
Pass the API key resource id here, not the pk_... key value.
POST /v1/organizations/:organizationId/api-keys/:keyId/rotations
Rotates a key and returns the replacement key in data, with status 201. Requires a secret key with the api_keys:manage scope. The new full key is only returned in that rotation response under revealed_key.
The replacement has the same type, environment, name, origins, client target, and scopes. The old key stays valid for 24 hours. During that time its status is rotating and its grace_expires_at shows when it stops working. See Authentication.
Pass the API key resource id here, not the actual pk_... or sk_... key value.