Skip to main content
Five endpoints under /api/keys create, list, read, change and revoke your keys. Settings, API keys does the same in the dashboard. Signed in, you can call all five. A key needs the API keys group at the level shown, as described in API key permissions. A full access key has it. A workspace key can call all five, for the keys of its own workspace, as described in What a workspace key can manage.

The no-escalation rule

A key never makes or changes a key into more than it has itself. With API keys write, a key can make a key only when every group of the new key is at or under its own level, its scope is inside its own, and, when the calling key expires, the new key expires no later. It can change or revoke only keys already within its own access, and it can change itself only to narrow it. Anything past that answers 403 with code: "key_escalation", and the message names what was too much. Signed in, you can do anything to your own keys. A computer’s own key manages no keys at all.

What a workspace key can manage

A workspace key with API keys access manages the keys of its own workspace, under the no-escalation rule. It can make keys for its workspace, list and read them, change them and revoke them. It never reaches past its workspace:
  • A key for all your workspaces, including a POST with no body, answers 403 with code: "key_escalation". The message names what was too much, such as it would reach more than this key’s one workspace., or it would have full access. when a restricted workspace key leaves out permissions.
  • Another workspace, or a computer in one, answers 403 with code: "workspace_scope_mismatch" and This API key cannot access this workspace (workspace_scope_mismatch).
  • A one-computer key, even for a computer in its workspace, is not a workspace key’s to make, change or revoke. Those calls answer 403 with code: "account_key_required".
  • A key outside its workspace answers 404 with { "error": "Key not found" }, as if it did not exist.
A workspace key never manages people, whatever its permissions, as described in What a workspace-scoped key can do. So a restricted key for one workspace can’t be given Members write. Making one with Members write, or changing a key to one, answers 400 with code: "invalid_permissions", whoever asks. Set Members to read or none. The key of an Invoicing client lists its workspace’s keys but makes, changes and revokes none. Changing or revoking a key with it answers 403 with code: "client_key". So does making one, once the request passes every other check. A request that fails one first, such as a key for all your workspaces (key_escalation) or a bad body (400), gets that check’s answer. It makes none because your own key list leaves a client’s workspace out and would never show a key it made.

Create a key

Send a JSON body. Every field is optional. A body with none of them makes an unnamed full access key for all your workspaces that never expires.
string
What the key is for, such as CI or Contractor. Left out, the key has no name. With computer_id and no name, it is named Key for <computer name>. Three names are kept for Orgo and refused with 400 and code: "reserved_name": Bops on iPhone, any name starting Computer key for, and any name starting Bops runner on.
string | object
What the key may call. Left out, or "full": full access. "read_only": read in every group. An object of group to level makes a custom key, such as { "computers": "write", "control": "write" }. A group left out is none. Groups and levels are listed in API key permissions. An unknown group or level is refused with 400 and code: "invalid_permissions". So is Members write on a key with workspace_id, as described in What a workspace key can manage.
integer
Days until the key expires, a whole number from 1 to 365. Send this or expires_at, not both.
string
When the key expires, as an ISO 8601 date and time such as 2027-03-03T00:00:00Z. It must be in the future and at most a year away. With neither expires_in_days nor expires_at, the key never expires. Expiry is described in Key expiry and rotation.
string
A workspace UUID. The key then reaches only that workspace. You must own the workspace or be a member with write access. Left out, the key reaches all your workspaces. Making a workspace key revokes the computer keys of that workspace’s computers, as described in When Orgo revokes a computer key. The workspace of an Invoicing client gets its key only from Settings, Invoicing: naming it answers 409 with code: "managed_key".
string
The UUID of one Linux computer. The key then reaches only that computer. Its instance_id also works, including one it had before a wake. Send this or workspace_id, not both. Only you signed in, or a key for your whole account, can make one. A workspace key gets 403 with code: "account_key_required". One-computer keys are rolling out, as described in One-computer keys for contractors and embeds.
Always send a JSON body, even {}. A POST with no body at all deletes your unnamed account-wide key and makes a new one. Older clients rely on that.
Each account can send at most 30 requests that create or change a key in each clock hour. A request counts even when it is then refused, for example for a bad body or by the no-escalation rule. More answers 429 with code: "rate_limited" and retry_after in seconds, also sent as Retry-After.

Example

Set $WORKSPACE_ID to the workspace the key is for.

Response

The key’s value is in key, and again in apiKey for older clients. It is shown once. Orgo keeps only a digest and an encrypted copy.
A key made with computer_id also carries "scope": "computer" and computer: { "id", "name", "os", "workspace_id" }.

The key object

GET, PATCH and the create answer describe a key with these fields. None of them is the key’s value.
string
The key’s id. Use it in /api/keys/{id}.
string | null
The key’s name.
string
Where it reaches: account (all your workspaces), workspace or computer.
string | null
The one workspace it reaches. For a one-computer key, that computer’s workspace. null for all workspaces and for a computer’s own key.
string | null
The first 12 characters of the value, then …. Use it to tell keys apart.
string
When it was made.
string | null
When it last signed in. An expired key’s stays where it was.
object | null
Its level in every group. null for full access.
string
full, read_only or custom: the preset its permissions match.
string | null
When it expires. null for never.
boolean
true once expires_at has passed. The key signs in nowhere. It stays listed until you delete it, except a one-computer key, which Orgo deletes soon after it expires.
boolean
Only on a computer’s own key, always true. That key answers access: "full" but calls only its fixed list, described in What a computer key can call.
object | null
On a computer’s own key and a one-computer key: the computer it is for, { "id", "name" }. null on a computer’s own key whose computer is gone.
string | null
Only on a computer’s own key: when its secret last changed.

List keys

Returns your keys under keys, newest first. A workspace key sees only the keys of its workspace. Keys of your Invoicing clients are left out.
string
Only that workspace’s keys, including keys for one of its computers. A workspace you don’t own or belong to, or an id no workspace has, answers 403 with { "error": "You do not have access to this workspace." }.
string
Only the keys bound to that computer: its own key and its one-computer keys. Its UUID, or a current or past instance_id. No such computer answers 404 with code: "computer_not_found". A computer in a workspace you don’t own or belong to answers 403 with { "error": "You do not have access to this workspace." }.
apiKey and keyInfo describe the old unnamed key, for older clients. Over an API key, apiKey is always null. one_computer_keys says whether one-computer keys are available yet.

Get a key

Returns the key object. A key that is not yours, or is outside the calling key’s scope, answers 404 with { "error": "Key not found" }.

Change a key

Send only what changes. The key’s value stays the same, so nothing that uses it needs updating. Returns the key object as it is now.
string | null
A new name, or null for none. The kept names listed under name in Create a key are refused.
string | object
"full", "read_only", or an object of group to level. The object replaces every group: a group left out becomes none.
integer
A new expiry, 1 to 365 days from now.
string | null
A new expiry date, at most a year away, or null to remove the expiry. A new expiry gets its own reminder emails.
string | null
Move the key to one workspace, or null for all workspaces. Moving a key into a workspace revokes the computer keys of that workspace’s computers, as a new workspace key does. A one-computer key keeps its computer: sending workspace_id for it answers 400 with code: "computer_scope_fixed". Make a new key instead.
No key’s computer can change. A PATCH with computer_id, for any key, answers 400 with code: "computer_scope_fixed". Some keys can’t be changed:
  • A computer’s own key belongs to Orgo. Changing it answers 409 with { "error": "Orgo manages this computer’s key. It can only be revoked.", "code": "managed_key" }.
  • The key of an Invoicing client changes workspace only in Settings, Invoicing (409, code: "managed_key"). No other key moves into a client’s workspace either (409, code: "managed_key").
  • A one-computer key is changed only by you signed in, or by a key for your whole account. A workspace key gets 403 with code: "account_key_required".
  • The Bops for iPhone key keeps its name (409, code: "managed_key").
  • A restricted key cannot change a key the Bops app signed in with (403, code: "key_escalation").
Change requests share the limit of 30 each clock hour described in Create a key.

Revoke a key

The key stops working at once. Answers { "success": true }.
  • Only you signed in, or a full access key for all your workspaces that never expires, can revoke a computer’s own key. The computer forgets the key, and Orgo then takes it off the computer. A restricted or expiring key for all your workspaces gets 403 with code: "key_escalation". A workspace key gets 404, as for any key outside its workspace, since a computer key belongs to no workspace.
  • Revoking a one-computer key that could control its computer (full access, or Control write) changes that computer’s screen password. This is described in Revoking changes the screen password.
  • A restricted key cannot revoke a key the Bops app signed in with.
  • A one-computer key is revoked only by you signed in, or by a key for your whole account. A workspace key gets 403 with code: "account_key_required".
DELETE /api/keys?id={id} does the same. Without id it answers 400 with { "error": "Missing id query param" }.

Errors

Codes from the key endpoints

Every body is { "error": "…" }, with code when the table shows one. Match on code, not on the message.

Codes any endpoint can return to a key

These come from signing in with the key, before any endpoint runs. Every endpoint a key can call answers them with the status and code shown. The Computer Use API and threads put the same status, message and code in their OpenAI style envelope. The other authentication errors, such as Invalid API key, are listed in Authentication.