The daemon contract
Download the OpenAPI 3.1 contract for routes, authentication, and response shapes. Some request payloads remain untyped. Remaining setup notes ship with the evaluation package. The schema is public. Request evaluation packages for a configured installation and integration help.
The default local daemon URL is http://127.0.0.1:8090, configured with platformd -listen. The daemon does not terminate TLS by default. For remote access, ask your operator for a protected connection.
The work, approval, entitlement, and receipt list routes return a page. For these routes, pass limit from 1 to 200 and continue with the previous page's cursor. Capabilities, catalogue, and manager-card responses use their own documented array shapes and declare no pagination parameters.
Authenticate with an operator-issued token
Your deployment operator issues a bearer token. Send it in Authorization: Bearer ... or X-AAES-Token. Both headers carry the same proof. Mutual TLS can replace bearer: a verified client certificate whose subject names a registered actor, and a bearer token is then refused. The credential identifies the caller and tenant.
GET /healthz, GET /readyz, and POST /approvals/{channel}/callback are unauthenticated in the contract: no daemon-issued bearer credential is used on them. The callback still authenticates the channel: Slack posts a form body verified by the X-Slack-Signature HMAC; Teams posts a Bot Framework activity whose bearer JWT is verified against the Bot Connector's OpenID metadata with the bot's app ID as required audience.
| Variable | Purpose |
|---|---|
AAES_ENDPOINT | The daemon base URL, configured with platformd -listen. Default: http://127.0.0.1:8090. |
AAES_TOKEN | The operator-issued bearer token. Send it in Authorization: Bearer ... or X-AAES-Token. |
ActionRequest and BrokeredRequest require tenant_id and actor_id. Those fields are claims that must match the token, not a tenant picker. The SDKs fill them. A refusal is JSON with a reason, and a remedy when the daemon can name the smallest satisfying change.
First request to a configured deployment
Ask your operator for a running daemon URL and an operator-issued bearer token for a registered caller. Request an evaluation if you need the binaries, SDKs, or setup notes.
1. Set the connection
Use your operator's URL. The address below is for a daemon running on your own machine. Supply the token through your environment. Do not put it in source code.
export AAES_ENDPOINT="http://127.0.0.1:8090"
: "${AAES_TOKEN:?Set AAES_TOKEN to the token from your deployment operator}"2. Read the capabilities you may use
curl --fail-with-body -sS "$AAES_ENDPOINT/v1/capabilities" \
-H "Authorization: Bearer $AAES_TOKEN"This read lists the caller's permitted capabilities. An empty list means none were returned for this caller.
{
"tenant_id": "your-tenant",
"actor_id": "your-agent",
"capabilities": []
}The identifiers above are illustrative. To discover capabilities you may request access to, call GET /v1/catalogue.
3. Handle errors before proceeding
If authentication or access is refused, check the response and ask your operator to review the token and caller permissions. A connection failure is not an empty capability list. For action decisions, read the refusal reason and any remedy before submitting another request. Automatic retries are permitted only for release-documented operations and failure stages; never use a new effect key merely to get past a conflict or an uncertain result. On the decision routes, a daemon-originated 503 is emitted only before a decision is sealed, so nothing was committed or executed; a failure after the seal arrives as 403 in the route's decision shape, whose receipt is the sealed record of how far the action got. The federated route is the exception: its 503 can follow a sealed decision (a mint or marker failure), but no grant material was released and the live-grant slot was freed, so a retry with the same effect key step is permitted there. A missing response (a timeout, a reset connection, an intermediary's error) is not, by itself, evidence of anything: reconcile first by listing the receipts of the unit of work (GET /v1/receipts?work_id=…) and looking for the step's decision among the intent, effect and effect-id fields the read API publishes. The projection does not carry your correlation identifiers, so when you cannot establish the mapping from the published fields, give the work ID, the effect key step and those identifiers to your operator to find the sealed decision in the journal. A missing receipt is not proof nothing was committed; a duplicate-effect 409 establishes that the original was recorded, not that it succeeded downstream; 409 also covers other state conflicts, so read the reason.
Next: request an action decision
Your operator must first register the capability and caller permissions, configure the policy and work budget, and provide a valid work ID. Use a new effect key for each new action and preserve it when following the documented retry procedure. Actions classified as irreversible require approval by an authorized person.
POST /v1/action records a decision and, when allowed, mints a grant; it does not execute the downstream action. POST /v1/brokered decides and executes through a configured connector. POST /v1/observe reports an effect. Use the OpenAPI contract and SDK examples for the request types in your evaluation release.
Route inventory
These routes belong to the daemon contract. Bearer or X-AAES-Token is required except where the table says otherwise. Download the OpenAPI 3.1 contract for payloads, parameters, and response schemas.
| Family | Method | Route | Purpose |
|---|---|---|---|
| Decision | POST | /v1/action | Record a decision and, when allowed, mint a grant. Does not execute the downstream action. |
| Decision | POST | /v1/brokered | Decide and execute through AAES's connector. |
| Decision | POST | /v1/federate | Federation interface; unavailable in the supplied distribution. Calls return 403 ("no federated backend") before the decision runs until an operator wires a minting backend. |
| Decision | POST | /v1/observe | Report an effect authorized under pass_through custody. |
| Grants | POST | /v1/grants/present | Bind a stored grant to the authenticated caller. |
| Grants | POST | /v1/grants/receipt | Journal the observed effect of a presented grant. |
| Discovery | GET | /v1/capabilities | Read the capabilities this caller may use. |
| Discovery | GET | /v1/catalogue | Read capabilities this caller can request access to. |
| Access | POST | /v1/access-requests | Request access. |
| Access | GET | /v1/access-requests/{id} | Read an access request. |
| Access | POST | /v1/access-requests/{id}/revoke | Revoke an access request. |
| Access | GET | /v1/manager-cards | Read manager cards. |
| Access | POST | /v1/manager-cards/decide | Submit a manager-card decision. |
| Access | GET | /v1/approvals | Read approvals. |
| Access | GET | /v1/approvals/{id} | Read an approval. |
| Access | GET | /v1/entitlements | Read entitlements. |
| Access | POST | /approvals/{channel}/callback | Receive an approval-channel callback. No daemon-issued bearer credential; the channel's own proof is required: Slack's HMAC signature or the Teams Bot Connector JWT with audience validation. |
| Work | GET | /v1/work | Read work items. |
| Work | GET | /v1/work/{id} | Read a work item. |
| Evidence | GET | /v1/receipts | Read receipts. |
| Evidence | GET | /v1/receipts/{id} | Read a receipt. |
| Health | GET | /healthz | Check health. Unauthenticated. |
| Health | GET | /readyz | Check readiness. Unauthenticated. |
Federation: decide here, execute at the application
Federation interface; unavailable in the supplied distribution. The route and SDK method exist, but no federated minting backend is wired in this distribution: calls return 403 ("no federated backend") before the decision runs. Successful issuance requires a separately integrated and validated backend; the contract's documented 200 response describes that conditional behavior.
Where a backend is wired, POST /v1/federate runs the full decision and returns a short-lived federated grant. The agent then calls the application directly with that grant. The downstream request and response payloads travel directly between the workload and the application rather than through AAES; AAES still processes authorization metadata and may return sensitive credential material or issuance instructions.
/v1/actionrecords a decision and, when allowed, mints a grant./v1/brokereddecides and executes through AAES's connector./v1/federatedecides and mints a federated grant for the agent's application call, when a minting backend is wired; refused with 403 in the supplied distribution./v1/observereports an effect for an existing intent authorized underpass_throughcustody; it is not a general-purpose endpoint for arbitrary external events./v1/grants/presentbinds a stored grant./v1/grants/receiptjournals the observed effect.
The operator console
The operator console is served by the AAES process on a separate listener. It is not in the daemon OpenAPI contract, even where names look similar.
Console routes include /api/approvals, /api/spend, /api/records, /api/theme, and /api/settings/appearance, along with the console's agents, capabilities, policies, integrations, and deployment routes.
Other shapes of the same surface
SDKs
Use Go, Python, or TypeScript clients for the daemon. Receipt verification belongs to the offline CLI.
MCP
Expose the daemon through an MCP facade. Policy, capability registrations, and application credentials remain in the daemon.
For offline evidence verification, see the CLI guide. Return to the developer overview for the full integration surface.
