> ## Documentation Index
> Fetch the complete documentation index at: https://docs.mnemom.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# AAP Attestation Tokens

> Mnemom-signed JWS tokens that prove a canonical card's identity. Verifiable offline against /v1/.well-known/jwks.json, no Mnemom credentials needed.

An **AAP attestation token** is a Mnemom-signed JWS (JSON Web Signature) committing to a canonical card's identity tuple — `(agent_id, content_hash, version, composed_at, card_kind)`. Any consumer holding the public key from `<api>/v1/.well-known/jwks.json` can verify it offline, without ever holding a Mnemom credential.

The attestation is the cryptographic glue between three Phase 5 surfaces:

* The [**A2A AgentCard export**](/concepts/a2a-export) attaches a fresh attestation as an extension on every public read.
* The [**transparency log**](/concepts/transparency-log) stores the attestation alongside the canonical identity for durable historic verification.
* The [**`mnemom verify-card` CLI**](/guides/verify-card) consumes the JWKS + log to verify offline.

## Wire format

JWS Compact Serialization (RFC 7515):

```
<base64url(header)>.<base64url(payload)>.<base64url(signature)>
```

| Section | Shape |
| - | - |
| **Header** | `{ "alg": "EdDSA", "kid": "<key_id>", "typ": "AAP-Attestation/v1" }` |
| **Payload** | See [the schema](/specifications/attestation-token) — `iss`, `sub`, `iat`, `exp`, `content_hash`, `version`, `composed_at`, `card_kind`, optional `smolt_id`, optional `historic_backfill` |
| **Signature** | Ed25519 over `<base64url(header)>.<base64url(payload)>` |

## What it commits to

The payload binds the identity. A change to **any** of these fields produces a different attestation:

| Claim | Source |
| - | - |
| `content_hash` | `canonical_*_cards.content_hash` |
| `version` | `canonical_*_cards.version` |
| `composed_at` | `canonical_*_cards._composition.composed_at` |
| `card_kind` | `alignment` or `protection` |
| `sub` | `agents.agent_id` |

The token **doesn't carry the card body** — consumers fetch the body separately (via [`/v1/agents/{id}/a2a-agent-card`](/concepts/a2a-export) or `GET /v1/agents/{id}/state`) and check the body's `content_hash` matches the attestation's `content_hash`.

## Verification

The full verification flow ([`mnemom verify-card`](/guides/verify-card) executes this for you):

1. Fetch `https://api.mnemom.ai/v1/.well-known/jwks.json` (the API host — not the `iss` claim's host; see note below).
2. Locate the key with `kid` matching the token's header.
3. Verify the Ed25519 signature.
4. Check `iss` matches the expected issuer (`https://mnemom.ai` for production — this is a domain-identity check, not a fetchable location).
5. Check `now() < exp` (the verifier may apply a small clock-skew grace; default 60 seconds).
6. Check the canonical card body's `content_hash` matches the attestation's `content_hash`.

<Note>
  The token's `iss` claim (`https://mnemom.ai`) and the JWKS host (`api.mnemom.ai`) are deliberately different: `iss` names Mnemom as the issuing identity, while the JWKS is served from the API host that also serves everything else in this section. Don't construct the JWKS URL from `iss` — always use `https://api.mnemom.ai/v1/.well-known/jwks.json` (or the `jwks_uri` given alongside the token, e.g. in the [A2A export](/concepts/a2a-export)).
</Note>

If you'd benefit from a code reference, the CLI verifier lives at [`mnemom-platform/cli/src/commands/verify-card.ts`](https://github.com/mnemom/mnemom-platform/blob/main/cli/src/commands/verify-card.ts) (the API's own verifier is internal, but any JOSE/EdDSA library implements the same six steps above).

## Key rotation + JWKS lifetime

The JWKS includes the **active** key plus **recently-retired** keys still inside their verification window. Once the retirement window plus the token-TTL plus a small grace has elapsed, the retired key drops out of the JWKS.

| Window | Default | Configurable via |
| - | - | - |
| Token TTL | 1 hour | `AAP_ATTESTATION_TTL_SECONDS` |
| Retirement grace | 25 hours | `AAP_ATTESTATION_RETIREMENT_WINDOW_SECONDS` |

AAP signing-key rotation is a **Mnemom-platform operation**, performed by Mnemom staff on a scheduled cadence (and on demand for incident response) — it is not a customer- or operator-callable endpoint. You don't rotate the platform's AAP signing keys yourself; the rotation, retirement window, and key publication are managed for you.

What you *can* rely on: the retired key remains verifiable for any token signed before its `retired_at` timestamp, and the current public keys are always discoverable from the published JWKS. (To rotate *your own* agent's API key — a different operation — see [Agent key rotation](/guides/agent-key-rotation).)

## Relationship to the transparency log

Tokens are short-lived (1-hour TTL by default). The durable record is the [transparency log](/concepts/transparency-log): every canonical card identity ever composed has a row in `card_attestations` with the full signed token + a Merkle inclusion proof. Beyond the token's expiry, consumers query the log — not the token.

## See also

* [Schema reference](/specifications/attestation-token) — canonical wire format
* [`mnemom verify-card`](/guides/verify-card) — operator CLI for offline verification
* [Transparency log](/concepts/transparency-log) — durable record beyond the TTL window
* [A2A AgentCard export](/concepts/a2a-export) — where the attestation surfaces on the public discovery API


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.