atmon docs

REFERENCE/API/KEYS.MD

KeysService

The project's own API keys: mint one, list them, retire one. Minting and retiring take an admin key, because a key that could mint its own reviewer would staff an approval gate rather than satisfy it. Listing carries no key material and is open to any of the project's keys.

Every call is a POST to https://api.atmon.ai/automaton.v1.KeysService/<Call> with a JSON body, and authenticates with Authorization: Bearer <your project key>. Field names in JSON are lowerCamelCase, so the field written tool_slug below is toolSlug on the wire. How to call the API has the whole convention.

Calls

CallRequestResponseSummary
CreateKeyCreateKeyRequestCreateKeyResponseMints a key for the project and returns its plaintext once.
ListKeysListKeysRequestListKeysResponseLists the project's keys, newest first, with no key material.
RevokeKeyRevokeKeyRequestRevokeKeyResponseRetires one of the project's keys.

CreateKey

Mints a key for the project and returns its plaintext once. It requires the admin role, and an expiry already in the past is refused rather than stored, because a key born expired looks like a key that stopped working.

Request CreateKeyRequest, response CreateKeyResponse.

POST /automaton.v1.KeysService/CreateKey HTTP/1.1
Host: api.atmon.ai
Authorization: Bearer amk_your_project_key
Content-Type: application/json

{
  "name": "...",
  "role": "KEY_ROLE_AGENT",
  "expiresAt": "2026-01-31T09:15:00Z"
}

The response:

{
  "key": {
    "id": "...",
    "name": "...",
    "role": "KEY_ROLE_AGENT",
    "createdAt": "2026-01-31T09:15:00Z",
    "revokedAt": "2026-01-31T09:15:00Z",
    "expiresAt": "2026-01-31T09:15:00Z",
    "createdByUserId": "..."
  },
  "plaintext": "..."
}

ListKeys

Lists the project's keys, newest first, with no key material. Open to any of the project's keys.

Request ListKeysRequest, response ListKeysResponse.

POST /automaton.v1.KeysService/ListKeys HTTP/1.1
Host: api.atmon.ai
Authorization: Bearer amk_your_project_key
Content-Type: application/json

{}

The response:

{
  "keys": [{
    "id": "...",
    "name": "...",
    "role": "KEY_ROLE_AGENT",
    "createdAt": "2026-01-31T09:15:00Z",
    "revokedAt": "2026-01-31T09:15:00Z",
    "expiresAt": "2026-01-31T09:15:00Z",
    "createdByUserId": "..."
  }]
}

RevokeKey

Retires one of the project's keys. It requires the admin role, and it refuses the key the request arrived on: revoking that would end the session doing the administration, so a key retires itself with automaton apikey revoke.

Request RevokeKeyRequest, response RevokeKeyResponse.

POST /automaton.v1.KeysService/RevokeKey HTTP/1.1
Host: api.atmon.ai
Authorization: Bearer amk_your_project_key
Content-Type: application/json

{
  "id": "..."
}

The response:

{}

Messages

CreateKeyRequest

CreateKeyRequest mints a key for the authenticated project. It names no project, because a key mints only for its own.

FieldType#Notes
namestring1
roleKeyRole2
expires_atgoogle.protobuf.Timestamp3expires_at must be in the future when it is set. Absent means the key never expires.

CreateKeyResponse

FieldType#Notes
keyProjectKey1
plaintextstring2plaintext is the only time the key exists outside the caller's hands. It is never stored, never logged, and no later read returns it: a lost key is replaced, not recovered.

ListKeysRequest

No fields. The call takes its scope from the authenticated project.

ListKeysResponse

FieldType#Notes
keysrepeated ProjectKey1

ProjectKey

ProjectKey is one API key as a listing shows it. It carries no key material at all: the plaintext exists once, in CreateKeyResponse, and the server stores only its hash.

FieldType#Notes
idstring1
namestring2name is the label whoever minted it wrote, for their own bookkeeping.
roleKeyRole3
created_atgoogle.protobuf.Timestamp4
revoked_atgoogle.protobuf.Timestamp5revoked_at is absent while the key is live.
expires_atgoogle.protobuf.Timestamp6expires_at is absent when the key never expires.
created_by_user_idstring7created_by_user_id is the console user who minted it, empty for every key minted by the CLI and for every key minted before accounts existed. It is bookkeeping, never an authorization: a key minted by a person is a distinct principal from that person, which is what lets separation of duty hold when an agent acts under a key its own reviewer created. The member-removal dialog reads this field, and it is the reason that dialog can list what a departing person's keys are before deciding which of them keep running.

RevokeKeyRequest

RevokeKeyRequest retires one of the project's keys. It is idempotent: a key already revoked keeps its original revocation time.

FieldType#Notes
idstring1

RevokeKeyResponse

No fields. The call takes its scope from the authenticated project.

Enums

KeyRole

KeyRole is what a key may do. The vocabulary is closed, because a role a key could present that the policy gate has never heard of is not a role, it is a hole. Adding one is a recorded decision rather than a field value.

Value#Meaning
KEY_ROLE_UNSPECIFIED0KEY_ROLE_UNSPECIFIED reads as KEY_ROLE_AGENT on a mint, which is what an omitted role means and what every key minted before roles existed reads as.
KEY_ROLE_AGENT1KEY_ROLE_AGENT executes tools, submits jobs, and connects accounts for entities. It is the role an AI holds.
KEY_ROLE_APPROVER2KEY_ROLE_APPROVER resolves approvals and answers asks addressed to approvers. It is a separation of duty rather than an escalation: it grants review, not execution, and not administration.
KEY_ROLE_ADMIN3KEY_ROLE_ADMIN mints and revokes keys, writes the policy document and the principal directory, registers private toolkits, storage backends and telemetry destinations, and resolves approvals. It is the top of the vocabulary, and separation of duty still binds on it: an admin that requested a call may not release it.
KEY_ROLE_VIEWER4KEY_ROLE_VIEWER reads what the governance surfaces show and changes nothing.