Every API here is available over the APIs.io API and to AI agents over MCP.
openapi: 3.2.0
info:
title: AIMEAT Protocol App Grants 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: App Grants
description: Scoped H-2 application grants — approve/revoke an app's access to an owner's data areas and fleet
paths:
/v1/app-grants/scopes:
get:
operationId: appGrantScopes
summary: Grantable app scope vocabulary (machine-readable)
description: 'The complete scope vocabulary an app may request in the H-2 grant flow, with per-scope
descriptions and a `default` flag for the undeclared-app default set. Public — apps and
agentic coders check this BEFORE declaring ``: requesting any
name outside this vocabulary fails the whole authorize with INVALID_SCOPE. Note: file
deletion is covered by `storage:write` (there is no `storage:delete` scope) and
`memory:delete` is NOT in the default set.
`provenance:write` is unusual and worth reading twice: it does NOT gate a route family. It
gates the act of ASSERTING how content was made — the optional `ai_provenance` block on the
write tools, and POST /v1/provenance. Recording what the node OBSERVED needs no permission
at all and happens whether anyone asks or not; what an owner grants here is the ability to
state that a person wrote or reviewed something, which is exactly the claim that decides
whether a visible AI label is owed. An app without it can still write; its writes are simply
recorded as the node saw them.'
tags:
- App Grants
responses:
'200':
description: '{ scopes: [{ scope, description, description_keys, default }], declare_with, notes[] }. `description_keys` is the ordered locale-key chain (app-context override first, then the shared scope-sentence tree) a client resolves against /locales/{lang}.json to show the sentence in the viewer''s language; `description` stays the English fallback.'
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