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

# Handoff Ledger

> Signed, hash-chained session handoff entries — the substrate for cross-agent context continuity.

<Note>
  All handoff endpoints require **Bearer token** authentication.
</Note>

The Handoff Ledger is a hash-chained audit trail for session context. When an agent completes a
unit of work and hands control to the next agent (or a human), it creates a **handoff entry**:
a structured record of what was done, what was protected, what risks were identified, and what
should happen next. Each entry is Ed25519-signed and linked to its predecessor via a hash chain,
so any tampering (reorder, delete, mutate) is cryptographically detectable.

***

## POST /v1/handoff

Append a signed handoff to a workspace's chain. The server resolves `prev_handoff_id` and
`prev_signature` from the latest entry in the workspace — a client cannot fork the chain by
supplying stale prev links.

<Note>
  **POST** `https://api.prysm1.com/v1/handoff` · Auth required
</Note>

### Request Body

<ParamField body="workspace_id" type="string" required>
  The workspace this handoff belongs to. Anchors the chain.
</ParamField>

<ParamField body="objective" type="string" required>
  What this agent session accomplished (1–500 chars).
</ParamField>

<ParamField body="from_tool" type="string">
  The agent/tool handing off (e.g. `"cursor"`, `"claude-code"`).
</ParamField>

<ParamField body="to_tool" type="string">
  The agent/tool receiving (e.g. `"claude-code"`, `"human"`).
</ParamField>

<ParamField body="files_touched" type="string[]">
  List of file paths modified in this session.
</ParamField>

<ParamField body="constraints" type="string[]">
  Constraints the next agent must respect (e.g. `"Do not modify public API"`).
</ParamField>

<ParamField body="risks" type="object[]">
  Identified risks: `[{"id": "r1", "description": "Auth regression risk"}]`.
</ParamField>

<ParamField body="validation" type="object[]">
  How to verify this work is correct: `[{"id": "v1", "description": "All auth tests green"}]`.
</ParamField>

<ParamField body="recommended_next_action" type="string">
  What the receiving agent should do first.
</ParamField>

<ParamField body="action_kind" type="string">
  Type of work: `edit` | `refactor` | `deploy` | `review` | `setup`. Default: `edit`.
</ParamField>

<ParamField body="est_cost" type="number">
  Estimated cost in USD for this session (informational; recorded in the signed receipt).
</ParamField>

### Response

Returns the full signed receipt. Key fields:

<ResponseField name="id" type="string">Unique handoff ID (`ho_...`).</ResponseField>
<ResponseField name="workspace_id" type="string">Echoed workspace ID.</ResponseField>
<ResponseField name="objective" type="string">Echoed objective.</ResponseField>
<ResponseField name="prev_handoff_id" type="string | null">Previous entry's ID (null for first entry).</ResponseField>
<ResponseField name="risk" type="object">Risk assessment: `score`, `tier` (`auto`/`confirm`/`approve`/`block`), `factors`.</ResponseField>
<ResponseField name="subject" type="string">The canonical JSON string that was signed.</ResponseField>
<ResponseField name="signed" type="boolean">True when an Ed25519 signing key is provisioned.</ResponseField>
<ResponseField name="created_at" type="string">ISO 8601 timestamp.</ResponseField>

<RequestExample>
  ```bash cURL theme={null}
  curl -X POST https://api.prysm1.com/v1/handoff \
    -H "Authorization: Bearer prysm_sk_..." \
    -H "Content-Type: application/json" \
    -d '{
      "workspace_id": "ws-myrepo",
      "objective": "Refactored auth module — split JWT validation into auth_jwt.py",
      "from_tool": "cursor",
      "to_tool": "claude-code",
      "files_touched": ["backend/main.py", "backend/auth_jwt.py"],
      "constraints": ["Do not change the public /v1/auth endpoint signature"],
      "risks": [{"id": "r1", "description": "Auth regression on legacy API keys"}],
      "validation": [{"id": "v1", "description": "Run python test_auth.py — all 14 assertions green"}],
      "recommended_next_action": "Add integration tests for the new auth_jwt module"
    }'
  ```

  ```python Python theme={null}
  import prysm

  h = prysm.handoffs.create(
      workspace_id="ws-myrepo",
      objective="Refactored auth module",
      from_tool="cursor",
      to_tool="claude-code",
      files_touched=["backend/main.py", "backend/auth_jwt.py"],
  )
  print(h["id"], h["risk"]["tier"])
  ```
</RequestExample>

<ResponseExample>
  ```json 200 theme={null}
  {
    "id": "ho_9f3c2a1b8e7d4f5a",
    "workspace_id": "ws-myrepo",
    "objective": "Refactored auth module — split JWT validation into auth_jwt.py",
    "from_tool": "cursor",
    "to_tool": "claude-code",
    "prev_handoff_id": "ho_1a2b3c4d5e6f7g8h",
    "risk": {"score": 24, "tier": "auto", "factors": ["edit_action"]},
    "signed": true,
    "created_at": "2026-06-15T14:30:00+00:00"
  }
  ```
</ResponseExample>

***

## GET /v1/handoff/{handoff_id}

Fetch a single signed handoff by ID.

<Note>
  **GET** `https://api.prysm1.com/v1/handoff/{handoff_id}` · Auth required
</Note>

<ParamField path="handoff_id" type="string" required>
  The `ho_...` ID returned by `POST /v1/handoff`.
</ParamField>

<RequestExample>
  ```bash cURL theme={null}
  curl https://api.prysm1.com/v1/handoff/ho_9f3c2a1b8e7d4f5a \
    -H "Authorization: Bearer prysm_sk_..."
  ```
</RequestExample>

<ResponseExample>
  ```json 200 theme={null}
  {
    "id": "ho_9f3c2a1b8e7d4f5a",
    "workspace_id": "ws-myrepo",
    "objective": "Refactored auth module",
    "signed": true,
    "created_at": "2026-06-15T14:30:00+00:00"
  }
  ```

  ```json 404 theme={null}
  {"error": "handoff_not_found", "message": "Handoff 'ho_...' not found."}
  ```
</ResponseExample>

***

## GET /v1/handoff/chain/{workspace_id}

Fetch the full ordered handoff chain for a workspace and verify its cryptographic integrity.

<Note>
  **GET** `https://api.prysm1.com/v1/handoff/chain/{workspace_id}` · Auth required
</Note>

<ParamField path="workspace_id" type="string" required>
  The workspace whose chain to retrieve.
</ParamField>

### Response

<ResponseField name="object" type="string">`handoff.chain`</ResponseField>
<ResponseField name="workspace_id" type="string">Echoed workspace ID.</ResponseField>
<ResponseField name="count" type="integer">Total entries in the chain.</ResponseField>
<ResponseField name="data" type="object[]">Ordered entries (oldest first).</ResponseField>

<ResponseField name="verification" type="object">
  Integrity verdict: `ok` (bool), `n` (entries verified), `first_broken_index` (null if intact),
  `reasons` (list of break descriptions), `signing_enabled` (bool).
</ResponseField>

<ResponseField name="pubkey_endpoint" type="string">URL to fetch the public signing key for offline verification.</ResponseField>

<RequestExample>
  ```bash cURL theme={null}
  curl https://api.prysm1.com/v1/handoff/chain/ws-myrepo \
    -H "Authorization: Bearer prysm_sk_..."
  ```
</RequestExample>

<ResponseExample>
  ```json 200 theme={null}
  {
    "object": "handoff.chain",
    "workspace_id": "ws-myrepo",
    "count": 3,
    "data": [
      {"id": "ho_aaa", "objective": "Initial setup", "signed": true, "created_at": "..."},
      {"id": "ho_bbb", "objective": "Auth refactor", "signed": true, "created_at": "..."},
      {"id": "ho_ccc", "objective": "Deploy to staging", "signed": true, "created_at": "..."}
    ],
    "verification": {
      "ok": true,
      "n": 3,
      "first_broken_index": null,
      "reasons": [],
      "signing_enabled": true
    },
    "pubkey_endpoint": "https://api.prysm1.com/v1/proof/pubkey"
  }
  ```
</ResponseExample>
