---
title: "POST /content-lock/unlock"
method: POST
path: "/content-lock/unlock"
tags: ["encryption"]
---

# POST /content-lock/unlock

`POST /content-lock/unlock`

## Request

- The document declares no server URL.
- Auth: one of:
  - API key in query parameter `auth`
  - API key in header `Authorization`

Verifies the passphrase (even when the session is already ready) and grants content access.
A wrong passphrase leaves everything as it was. The body is never logged.

## Request body

- UnlockSpaceRequest: Request body for `POST /encryption/unlock-with-passphrase` (ADR-008 D15). Carries the user's plaintext passphrase over the loopback API. Per D14 the endpoint is session-JWT gated (not in `PUBLIC_PATHS`) and the handler MUST never log this body — see the rule in `uc-webserver` `api/encryption.rs`. This formally retires the historical "passphrase 不出进程" invariant: under the "same UID = trusted" model (D14) an attacker who can sniff loopback can already dump the master key from daemon memory, so loopback transport adds zero incremental exposure.
  - `passphrase` string, required

## Response `200`

Content unlocked

- ContentLockStatusEnvelope: Canonical success envelope: `{ "data": T, "ts": <unix millis i64> }`. `ts` is `chrono::Utc::now().timestamp_millis()`, set in the webserver handler via [`ApiEnvelope::now`] (the contract carries only the type + the clock helper, not a hard dependency on when the handler reads the clock). `rename_all = "camelCase"` is a no-op for the single-word fields here but is declared for forward-compat. IMPORTANT (utoipa v4): every concrete `ApiEnvelope<X>` that needs a named OpenAPI component is declared in the `#[aliases(...)]` block below. Add a new alias line whenever a new payload type needs enveloping. NEVER register the bare `ApiEnvelope` in `components(schemas(...))` — utoipa errors on a bare generic, and an un-aliased generic inlines an anonymous schema.
  - `data` ContentLockStatusResponse, required: Whether history-derived content may be shown to GUI-class clients (`gui`, `helper`). `unlocked` is computed at read time from the in-memory grant AND the encryption facts (initialised, session ready, background ready), so losing the session revokes visibility without any extra coupling. `generation` changes with every grant change, so a client can tell a stale answer from a current one.
    - `generation` integer, required
    - `unlocked` boolean, required
  - `ts` integer, required: Server time when the response was built (unix epoch milliseconds).

## Other responses

- `403`: Wrong passphrase
- `409`: Setup not completed / space not initialized
- `422`: Space key material corrupted

## Changes

- **2026-10-15** `4c664cabd0c5`: 3 info
  - added the optional property `requestId` to the response with the `403` status
  - added the optional property `requestId` to the response with the `409` status
  - added the optional property `requestId` to the response with the `422` status
- **2026-10-01** `aa64ebd8cf74`: 1 info
  - endpoint added

[Operation history](https://skmtc.dev/uniclipboard/apis/uniclipboard-daemon-api/changes/content-lock/unlock/post.md)

---

[API](https://skmtc.dev/uniclipboard/apis/uniclipboard-daemon-api.md) - [All operations](https://skmtc.dev/uniclipboard/apis/uniclipboard-daemon-api/llms.txt) - [OpenAPI document](https://skmtc.dev/uniclipboard/apis/uniclipboard-daemon-api/revisions/48a01cf04e4c?raw)
