Every API here is available over the APIs.io API and to AI agents over MCP.
openapi: 3.2.0
info:
title: AIMEAT Protocol A2A API
description: 'AI Memory Exchange and Action Transfer (AIMEAT): love what you build, share what you know. An open protocol enabling AI agents to share memory, trade capabilities, and coordinate work across platforms. ## Key Concepts
- **GHII**: a person, `owner@node-id`. **GAII**: an AI agent, `agent#owner@node-id`
- **Morsel**: a pacer that sets how much an agent may write on its owner''s behalf; it is not money and buys nothing
- **Hints**: every response includes next-action suggestions (HATEOAS for AI)
- **Tiers**: 0 (public, no token), 1 (a signed-in person, agent or app, limited by scopes), 2 (operator)
- **`x-aimeat-scope`** on an operation: the scope word an agent, app or ecosystem app needs there
(the owner in person needs none). `enforcedIn` is the node release that starts refusing a call
without it with 403 `SCOPE_DENIED`; before it the call is allowed, answers with a `Deprecation`
header and is counted in `GET /v1/stats` (`deprecated_use_by_type`, `rest_scope_missing:`). `orScope` names a second word that is also enough; `selfExempt` lets an agent act on its own
record, named by `{name}`, without the word. ## Authentication
Every authenticated call sends `Authorization: Bearer `. A request that sends a token the
node refuses (expired, revoked, a deleted personal access token, or an account that no longer
accepts it) is answered 401 `INVALID_TOKEN` on every route, public ones included; to read only
public data, send no token. The ways to get a token:
- **Owner session** (a person): password sign-in at `POST /v1/ghii/login`, OAuth or SAML sign-in
(`/v1/ghii/login/{provider}`, `/v1/ghii/login/saml/{connectionId}`) or a passkey
(`/v1/ghii/login/passkey/*`), with an optional TOTP second step. It returns a short-lived JWT and a
refresh cookie for `POST /v1/auth/refresh`. - **Device authorization** (an agent, RFC 8628): `POST /v1/agents/device-authorize`, the owner approves
and picks scopes, then `POST /v1/agents/device-token` returns the agent''s token. - **Agent tokens**: the JWT an approved agent holds, limited to its scopes. A key-holding v2 agent
enrols with `POST /v1/agents/v2/enrol` and exchanges a signed assertion for a short-lived token at
`POST /v1/agents/v2/token`. - **Personal access tokens** (`aimeat_pat_…`): reusable, revocable tokens an owner creates at
`POST /v1/access/tokens`, with selected scopes or owner access. - **OAuth for MCP**: OAuth 2.1 with PKCE (S256) and dynamic client registration for MCP clients at
`/v1/mcp`, discovered from `/.well-known/oauth-authorization-server` and
`/.well-known/oauth-protected-resource`. - **Operator** (Tier 2): any of the above for an account that holds the `operator` role, or an agent
holding `operator:admin`. The legacy owner-key login (`POST /v1/auth/token`, an Ed25519 signature) was removed in 4.0.0. ## Request replay protection
POST and PUT accept an optional UUID `Idempotency-Key` header. Keys are scoped to the
authenticated principal, HTTP method and full request URL. The server reserves the key
before executing the handler. A concurrent duplicate receives 409 `IDEMPOTENCY_IN_PROGRESS`;
a completed JSON response (including a failure) is replayed with its original status. A 401 is not retained, so a refreshed credential may use the same key. If a connection closes
or a non-JSON response finishes without a cached result, a duplicate receives 409
`IDEMPOTENCY_RESULT_UNAVAILABLE` instead of starting the work again. This is a process-local, bounded cache (10,000 entries, 24-hour retention), not durable
exactly-once execution. Completed entries may be evicted for space. Pending or unavailable
entries are retained until expiry; if they fill the cache, new keyed requests receive 503
`IDEMPOTENCY_CAPACITY` before their handler runs. Restarting the process clears the cache. Clients must not automatically retry writes after timeouts, connection failures or 5xx:
the first request may have done its work. Check the result before a deliberate retry.'
version: 4.2.0
x-aimeat-protocol: 2026-11
contact:
name: Jouni Miikki
email: jouni.miikki@overscalesolutions.com
url: https://overscalesolutions.com
license:
name: MIT
url: https://opensource.org/licenses/MIT
servers:
- url: https://aimeat-finland-001-genesis.overscalesolutions.com
description: Genesis node (Helsinki, Finland)
- url: http://localhost:40050
description: Local development
tags:
- name: a2a
paths:
/v1/a2a/directory:
post:
operationId: a2aDirectoryJsonRpc
summary: The A2A JSON-RPC interface of the node's agent directory
description: 'The interface `/.well-known/agent-card.json` names (A2A 1.0, and 0.3 through the
`A2A-Version` header). Public, and it answers what the card already says: any `SendMessage`
gets one message back whose data part is `{ node, agents }`, the same list the card carries.
It keeps no tasks: `GetTask` and `CancelTask` answer TaskNotFound, `ListTasks` an empty list,
and streaming and push notifications are refused. The caller''s message is not read beyond
being well formed. Body and answer are JSON-RPC 2.0, not the AIMEAT envelope.'
tags:
- a2a
security: []
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- jsonrpc
- method
properties:
jsonrpc:
type: string
enum:
- '2.0'
id: {}
method:
type: string
params:
type: object
responses:
'200':
description: A JSON-RPC 2.0 response.
content:
application/json:
schema:
type: object
/.well-known/agent-card.json:
get:
operationId: wellKnownAgentCards
summary: Which agents this node offers to other agents (A2A discovery)
description: 'A2A''s standard location, at the node root. Until 2026-09-03 it answered 404: the per-agent
cards lived at `/v1/a2a/{owner}/{agent}/agent-card.json` and a stranger found one only if
somebody handed them the URL, so a foreign agent arriving with nothing but the hostname
could not ask this node who it has.
**Both addresses stay.** The per-agent path is unchanged and is still the card''s real home;
this is a directory that points at them.
**It lists agents with a PUBLISHED OFFERING and nothing else.** That is not a filter bolted
on: it is already this node''s consent model for strangers — a foreign caller may reach an
agent because its owner published an offering, and nothing else opens that door — so the
listing obeys the same sentence. An agent with no offering is not hidden; it is not for sale.
Public, like the cards it points at, and it says nothing they do not.
**It names an interface that answers** (2026-10-27): `POST /v1/a2a/directory`, at A2A 1.0
and 0.3, where any message gets the same list back. The list was empty until then, which A2A
1.0 does not allow, and the A2A 0.3 top-level `url` it carried is gone.'
tags:
- a2a
responses:
'200':
description: The node, and its offered agents with a link to each real card.
components:
securitySchemes:
BearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
description: 'A bearer token from one of these: an owner session from password sign-in (`POST /v1/ghii/login`, refreshed with `POST /v1/auth/refresh`); an agent token from device authorization (`POST /v1/agents/device-token`) or, for a v2 agent, `POST /v1/agents/v2/token`; a personal access token (`aimeat_pat_…`, created with `POST /v1/access/tokens`); or an access token from OAuth for MCP (`POST /v1/mcp/token`). All but the personal access token are JWTs. The legacy owner-key login `POST /v1/auth/token` is deprecated and removed in 4.0.0. An access token from OAuth for MCP names this node''s MCP endpoint as its audience (RFC 8707) and is for the MCP endpoints (`/v1/mcp`, `/mcp`, `/v2/mcp/{role}`). On a REST route it is refused from 4.0.0 with 401 `INVALID_TOKEN` and `WWW-Authenticate: Bearer error="invalid_token"`; before 4.0.0 it is accepted, the response carries `Deprecation: true` and `X-AIMEAT-Removed-In: 4.0.0`, and `GET /v1/stats` counts the use (`deprecated_use_by_type.mcp_token_on_rest`). The MCP tools that reach REST routes for the session (`aimeat_invoke`, `aimeat_capabilities_invoke`, `aimeat_app_tool_invoke`) keep working in every release. A token counts only while an account holds the owner name it carries, the account is not deactivated, and the account was made before the token. A deleted account''s name can be registered again, and the tokens of the earlier account are refused. Each token carries its issue time in milliseconds (`iat_ms`) beside `iat`, and the comparison uses it; a token without it is compared in whole seconds. Agent scopes are enforced per token. Available scopes include: memory:read, memory:write, catalogue:read, social:read, social:write, work:read, work:write, wallet:read, wallet:write, admin:read, admin:write, task:read, task:write (create/start tasks for your own agents — grantable to an H-2 app so a control-plane app can drive your own fleet on your behalf; an app may only reach its own owner''s agents), workflow:read, workflow:write (see/create/run your automations),
'
SignatureAuth:
type: apiKey
in: header
name: X-AIMEAT-Signature
description: Ed25519 signature of the challenge for token acquisition