Account, keys and webhooks ›
Create api key
POST
/v1/api-keysMakes a key that may do what it is given and nothing else: a preset, or actions named. A key used to make one makes only a weaker one: no action it lacks, no sandbox or template it does not reach, no later expiry, and addresses inside its own. The key is made in the organization the caller acts in, a team or the person's own, and acts in it for good. A person signed in to the site whose account has two-factor sign-in on sends a code from the app too, as code.
RequestTypeScript
- import { Agental } from "agental-sdk";
- const agental = new Agental();
- const key = await agental.apiKeys.create({ name: "ci", preset: "ci" });
Answer201 Created · CreatedApiKey
No JSON body.
The key, and its secret, which is returned this once.
Headers
AuthorizationrequiredBearer key | An API key that may make this call. |
Body
namerequiredstring | e.g. "ci-github" |
preset"read-only" | "full-sandbox" | "ci" | "admin" | read-only: every read but secrets and mail. full-sandbox: sandbox.read, exec, file.read, file.write, agent.prompt, ssh, desktop, host, snapshot.read, snapshot.write and sandbox.stop. ci: full-sandbox, and sandbox.create, sandbox.fork, sandbox.resume and sandbox.delete-own. admin: * , everything. Send this or actions, not both. e.g. "ci" |
actionsarray of "sandbox.read" | "sandbox.create" | "sandbox.fork" | "sandbox.update" | "sandbox.auto-stop" | "sandbox.stop" | "sandbox.resume" | "sandbox.delete" | "sandbox.delete-own" | "exec" | "file.read" | "file.write" | "agent.prompt" | "ssh" | "desktop" | "host" | "network.write" | "secret.read" | "secret.write" | "email.read" | "email.send" | "email.manage" | "snapshot.read" | "snapshot.write" | "template.read" | "template.write" | "key.manage" | "account.read" | "account.admin" | "members.read" | "members.admin" | "*" | The actions the key may do, named. Send this or preset, not both. e.g. ["email.read","email.send"] |
sandboxIdsarray of string | Limits the key to these sandboxes, and to those on templateIds. It always reaches the sandboxes it makes. Every other sandbox, snapshot and route of the account answers it 404. |
templateIdsarray of string | Limits the key to these templates and the sandboxes on them, and to those in sandboxIds. A sandbox it makes without naming a template goes on the account's default template when that is on the list, else on the one template on the list; with several on the list and not the default, it has to name one. e.g. ["tpl_coding_agent"] |
expiresAtstring | When the key stops working, and is refused with 401 key_expired. Left out, never. e.g. "2026-11-15T00:00:00Z" |
allowFromarray of string | IPv4 and IPv6 addresses and ranges the key may be used from, 100 at most: an address alone is that one computer, and a range is written as 203.0.113.0/24 or 2001:db8::/48. An IPv4 address written the IPv6 way, as ::ffff:203.0.113.7, is that IPv4 address. Empty, or left out, is anywhere. A request from any other address is refused with 403 key_address_forbidden. A sandbox reaches the API from its server's shared IPv4 address, which changes when it moves, so limit a key used inside a sandbox with sandboxIds instead. On a network with IPv6 the API sees your IPv6 address, so a list of IPv4 addresses alone refuses you there. e.g. ["203.0.113.0/24","2001:db8::/48"] |
codestring | For a person signed in to the site whose account has two-factor sign-in on: the six digits the authenticator app shows now, or one of the backup codes, which is then used up. A key outlives the session that made it, so it is not made without one. A call made with an API key needs none, and its code is not read. e.g. "482913" |
Returns
201 The key, and its secret, which is returned this once.
Errors and other answers
| 400 | invalid_request neither preset nor actions was sent, or both were; expiresAt is not in the future; or an entry of allowFrom is no address or range, and the message says which. |
| 400 | code_required a person signed in, with two-factor sign-in on, sent no code. |
| 400 | invalid_code the code is not right. |
| 400 | code_used six digits from the app that were used already. |
| 402 | billing_required the account is on the free plan with no card saved, where plans are required. Save one, or start a plan, in the console first; the message gives its address. |
| 403 | key_action_forbidden the key used lacks key.manage. |
| 403 | key_exceeds_caller the new key would be stronger than the key used to make it, and the message says how. |
| 403 | not_a_member the key used is of someone no longer in the team it acts in. |
| 404 | not_found a sandbox or template named is not one of the account's, or not one the key used reaches. |
| 409 | name_taken another key has this name, or the name is the one kept for the seeded dev key. |
| 429 | rate_limited five wrong codes from this session in a quarter of an hour, on this call or another that asks for one. |
Every error answers { "error": { "code", "message" } }; a key without the action a call needs answers 403 key_action_forbidden, naming it.