---
title: "Resolve a human-tier review-hold (allow/deny/escalate)"
method: POST
path: "/safe-house/reviews/{review_id}/resolve"
tags: ["Safe House"]
---

# Resolve a human-tier review-hold (allow/deny/escalate)

`POST /safe-house/reviews/{review_id}/resolve`

## Request

- Base URL: `https://api.mnemom.ai/v1`
- URL: `https://api.mnemom.ai/v1/safe-house/reviews/{review_id}/resolve`
- Auth: one of:
  - HTTP bearer
  - API key in header `X-Mnemom-Api-Key`

The human decider for a Safe House review-hold (Wave 4). Customer/human auth (an authenticated org member, or platform staff) — the resolver is ALWAYS the authenticated principal, NEVER read from the body. A `review_id` outside the caller's org fleet returns **404, never 403** (no existence leak). `allow`/`deny` finalize the hold through the gateway (a NEW Ed25519-signed decision row; on `allow`, the decrypted original plus a single-use, content-bound allow-token are returned). `escalate` is **non-terminal**: it records the action, signals higher-tier attention, and leaves the hold `pending`. When the agent's card requires dual-control, a terminal ruling needs **two distinct** resolvers to concur — a same-identity second action returns **409**, and divergent votes escalate.

## Path parameters

- `review_id` string, required

## Request body

- object
  - `decision` 'allow' | 'deny' | 'escalate', required: `allow`/`deny` finalize (single-control) or count toward dual-control concurrence; `escalate` is non-terminal.
  - `reason` string: Optional free-text rationale recorded on the approvals ledger.

## Response `200`

The resolution outcome. Terminal on a finalized `allow`/`deny` (with the allow-token + decrypted content on `allow`); otherwise `pending` (escalated, or awaiting a second dual-control approver).

- object
  - `review_id` string, required
  - `status` 'allowed' | 'denied' | 'pending', required
  - `allow_token` string: Single-use, `content_hash`-bound, short-TTL token honored by the gateway on re-submit. Present only on a finalized `allow`.
  - `content` string: The decrypted original held content. Present only on a finalized `allow`.
  - `awaiting` 'second_approver': Present when dual-control is required and this is the first concurring resolver.
  - `escalated` boolean: True when the action escalated the hold for higher-tier attention (explicit escalate, or divergent dual-control votes).
  - `reason` string

## Other responses

- `400`: Bad request
- `401`: Authentication required
- `403`: Forbidden
- `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.
- `502`: An upstream dependency returned an invalid response.

---

[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)
