Create a new API key
/portal/v1/accounts/{accountSlug}/applications/{appSlug}/environments/{envSlug}/api-keysIssues a new API key in the active Application, scoped to the current Environment. The full cnpy_-prefixed secret is returned exactly once in the key field of the response and is never recoverable afterward — only a masked key_preview and metadata persist. access_mode: "scoped" requires a non-empty scopes array and enforces it on every authorization check; access_mode: "full_access" forbids scopes and bypasses RBAC entirely within the Application. Pass expires_at (ISO 8601) for an expiring key or omit it for none. Supports Idempotency-Key for safe retries, emits an api_key.created event, and is rate-limited to 20 requests per minute per Application.
Authentication
AuthorizationJWT access token. Never send alongside X-API-Key: a request carrying both is refused.
api_keys.manageDeveloper ConsoleCreate, edit, rotate, and delete API keys. Granted through an administrator role in the Admin Workspace; a valid token without it is refused with 403.
Request body
application/json
namestring Required API key name
descriptionstring Optional API key description
access_modeenum Required Required. `scoped` enforces the `scopes` array on every authorization check (deny if the requested permission isn't listed). `full_access` bypasses RBAC entirely within the key's Application — every permission is granted. Pick `scoped` whenever possible; `full_access` should be a deliberate choice (use cases: bootstrap automation, trusted backend services that legitimately need App-wide access). `scoped` requires a non-empty `scopes` array; `full_access` forbids `scopes`.
scopesstring[] Optional Permission scopes this key is authorized for. Required and must be non-empty when `access_mode` is `scoped`. Must be omitted when `access_mode` is `full_access`.
expires_atstring Optional Expiration date (ISO 8601). Omit for no expiration.
Responses
application/json
data *ApiKeyCreatedResponseDto
application/json
error *ApiErrorBodyDto
application/json
error *ApiErrorBodyDto
Errors
When the request can't be completed, the response body includes a stable error code you can branch on.
account.capability_requiredForbiddenThe signed-in user's administrator roles do not grant the capability this endpoint requires.
Ask an account administrator to grant a role carrying the capability named in the Authentication section, then retry.
Returned object
curl -X POST "https://auth.canopy-io.com/portal/v1/accounts/{accountSlug}/applications/{appSlug}/environments/{envSlug}/api-keys" \ -H "Authorization: Bearer $CANOPY_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "name": "string", "description": "string", "access_mode": "scoped", "scopes": [ "string" ], "expires_at": "string" }'
{ "data": { "id": "string", "name": "string", "description": "string", "key": "string", "key_preview": "string", "access_mode": "scoped", "scopes": [ "string" ], "expires_at": "2026-04-20T12:00:00.000Z", "created_at": "2026-04-20T12:00:00.000Z" } }
Tell us how we can improve this guide.