---
title: "Request ZK proof"
method: POST
path: "/checkpoints/{checkpoint_id}/prove"
tags: ["Verification"]
---

# Request ZK proof

`POST /checkpoints/{checkpoint_id}/prove`

## Request

- Base URL: `https://api.mnemom.ai/v1`
- URL: `https://api.mnemom.ai/v1/checkpoints/{checkpoint_id}/prove`
- Auth: API key in header `X-Mnemom-Api-Key`

Request a zero-knowledge proof for a checkpoint's verdict derivation. The prover input is built from the stored checkpoint (verdict, concerns, reasoning summary, thinking-block hash, model, card hash and values hash), the same input the sampled and deferred proof paths send. The caller must be a member of the org that governs the checkpoint's agent. Any other caller gets the same 404 as a missing checkpoint. If a proof already exists, returns 200 with its current status and nothing is charged. Failed, dead-lettered and skipped proofs are never re-queued. If the existing proof was deferred, it is resolved and dispatched to the prover and returns 202 with the existing proof_id. Otherwise a pending proof is created and dispatched to the SP1 prover service (202). Each newly queued or deferred-resolved proof is charged in μ (class analyze.zk-proof, one unit, deduplicated per checkpoint) to the billing account of the org that governs the agent. If that billing account cannot be resolved, no proof is queued (503, or 409 when the org has no billing account). A synthetic checkpoint, or one whose stored verdict or concerns the prover cannot read, is refused with 409 and error code proof_inputs_unavailable. A checkpoint that predates the stored card and values hashes is refused with 409 and error code proof_inputs_partial. When no prover is bound on the deployment the request is refused with 503 and error code prover_unavailable. For every refusal no proof is queued and nothing is charged.

## Path parameters

- `checkpoint_id` string, required

## Response `200`

Proof already exists for this checkpoint

- object
  - `proof_id` string
  - `status` string
  - `message` string

## Other responses

- `202`: Proof request accepted: a new proof was queued, or an existing deferred proof was resolved and dispatched (same proof_id)
- `401`: Authentication required
- `403`: Cross-origin write refused (`cross_origin_rejected`). A state-changing request that carries the browser session cookie must come from a first-party origin (`Origin`, or failing that `Referer`) and must not send a form-style body (text/plain, urlencoded, multipart) the operation does not declare. Bearer and API-key callers are never subject to this check.
- `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)
