create(body: KeyCreate, options?: RequestScope): Promise<CreatedKeyResource>Mints a key for the workspace and resolves the only key shape that ever carries secret. The plaintext is handed over exactly once, only a hash is stored, and no endpoint or dashboard screen can produce it again. Write it to your secret store before you read anything else off the result. prefix is the leading portion of that secret and is safe to log.
Requested scopes pass through two independent reductions. First a ceiling: a key can never mint a key stronger than itself, and any resource:level above what the calling key holds rejects the whole request with 403 auth.scope_ceiling_exceeded while creating nothing. Whatever survives is then clamped silently to the workspace role of the calling key owner, so a requested write can land as read, or as none if the owner cannot read that resource at all. Read scopes back off the response rather than assuming you got what you asked for.
body.projectIds fences the key to specific projects and takes project ids, not slugs. Omit it or send an empty array for a workspace-wide key. If the calling key is itself fenced, the field becomes mandatory and must be a non empty subset of the caller own projects, otherwise the call fails with 403 auth.key_project_restricted.
Example
const created = await envless.keys.create({
name: 'ci-deploy',
scopes: { variables: 'read', projects: 'read' }
})
await Bun.write('/run/secrets/envless', created.secret)
console.log(created.prefix, created.scopes)Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
body.name | string | Yes | Label for the key, 4 to 34 characters. |
body.scopes | Record<string, string> | No | Map of resource to none, read or write, where write implies read. |
body.projectIds | Array<string> | No | Project ids the key is fenced to, empty or omitted for workspace-wide. |
options.signal | AbortSignal | No | Cancels the request. |
Returns
CreatedKeyResource, a KeyResource plus the one time plaintext secret.
Worth knowing
- Omitting
scopesis legal and produces a key with every resource atnone. It authenticates but can call nothing exceptme.get. - There is no rotate method. To roll a credential, create the replacement, deploy it, wait until
lastUsedAton the old key stops advancing, then calldeleteon the old id. - A workspace is capped at 100 live keys and the next create rejects with 409
key.limit_reached.
Required scopes
keys:write
Underlying endpoint
POST /keys
Request and response schema, every error code, and a live playground.
In Python
envless.keys.create()
The same method in envless-sdk, the Python SDK, with the same request, retries and errors.
In Ruby
Envless.keys.create
The same method in envless-sdk, the Ruby gem, with the same request, retries and errors.
In PHP
$envless->keys->create()
The same method in envless/sdk, the PHP SDK, with the same request, retries and errors.