---
title: "Issue the signed completion receipt for a finished Dojo run."
method: GET
path: "/dojo/receipt/{session_id}"
tags: ["Dojo"]
---

# Issue the signed completion receipt for a finished Dojo run.

`GET /dojo/receipt/{session_id}`

## Request

- Base URL: `https://api.mnemom.ai/v1`
- URL: `https://api.mnemom.ai/v1/dojo/receipt/{session_id}`
- Auth: none required

PUBLIC — the `session_id` is the credential (a shareable permalink). Returns the Ed25519-signed completion receipt for a COMPLETED dojo try-me run: it declares the agent's alignment/protection cards (by canonical content-hash) and the Safe House (sparring) verdict, plus a verify pointer. The receipt is DERIVED deterministically from the completed session + its scenario (not stored) and is independently verifiable against the published JWKS. Reveals only the shareable claim — no raw transcript/event stream (that stays behind the owner-gated `/sim/{id}/export`). 409 if the run hasn't completed; 503 if signing isn't configured. MNE-802.

## Path parameters

- `session_id` string, required

## Response `200`

The signed receipt + verify pointer.

- object
  - `receipt` string, required: The Ed25519-signed receipt as a JWS Compact serialization.
  - `payload` object, required
    - `typ` 'DojoCompletionReceipt/v1', required
    - `iss` string, required: Issuer; `https://mnemom.ai`.
    - `sub` string, required: The agent that ran the spar (agents.id).
    - `iat` integer, required: Issued-at, Unix seconds.
    - `exp` integer, required: Expiry, Unix seconds.
    - `session_id` string, required
    - `scenario_id` string, required
    - `declared` object, required: The agent's declared cards, by canonical content-hash.
      - `alignment_card_hash` string, nullable, required: sha256-hex of the canonical alignment card, or null.
      - `protection_card_hash` string, nullable, required: sha256-hex of the canonical protection card, or null.
    - `verdict` object, required: The Safe House (sparring) verdict.
      - `outcome` 'pass' | 'leak' | 'contagion', required: The single canonical outcome, worst-first: contagion (unauthorized write) > leak (unauthorized read) > pass (shield held).
      - `canary_protected` boolean, required
      - `leak` boolean, required
      - `contagion` boolean, required
      - `rating` string, nullable, required
    - `completed_at` string, date-time, required
  - `key_id` string, required: The kid that signed the receipt.
  - `permalink` string, uri, required
  - `verify` object, required
    - `endpoint` string, uri, required
    - `jwks` string, uri, required
    - `note` string, required

## Other responses

- `400`: Bad request
- `404`: Resource not found
- `409`: Resource conflict — the request cannot proceed because of a current state conflict (e.g., resource already exists, version mismatch, in-flight idempotency key with a different body).
- `429`: Rate-limit exceeded. The global per-IP limiter (100 requests/minute, applied to every `/v1/*` route) rejected this request. Back off until the window resets — `Retry-After` carries the cooldown in seconds and `X-RateLimit-Reset` the absolute reset time.
- `500`: Server error — request was well-formed but the server failed to fulfill it. Typically a downstream dependency (DB / RPC / external API) returned an unexpected error.
- `503`: An upstream dependency is currently unavailable. The request was not processed; retry after the cooldown window.

---

[API](https://skmtc.dev/mnemom/apis/mnemom-api.md) · [All operations](https://skmtc.dev/mnemom/apis/mnemom-api/llms.txt) · [OpenAPI document](https://skmtc.dev/mnemom/apis/mnemom-api/revisions/274b7a6ea182?raw)
