---
title: "Store the customer's wrapped share of a threshold key"
method: PUT
path: "/v1/keys/{key_id}/client-share"
tags: ["Key Custody"]
---

# Store the customer's wrapped share of a threshold key

`PUT /v1/keys/{key_id}/client-share`

## Request

- Base URL: `https://api.1claw.co`
- URL: `https://api.1claw.co/v1/keys/{key_id}/client-share`
- Auth: HTTP bearer

Stores ciphertext the vault cannot open: the customer's share of a
2-party threshold signing key, wrapped in the browser under the
passkey's WebAuthn PRF output (`passkey_prf`, one wrap per credential
and share generation). `recovery_code` wraps are refused: the recovery
code seals the offline kit in the browser. The vault keeps the blob and
its salt and returns them only to the owning user. Human users only;
the passkey must have reported PRF support at registration.

A stored wrap is never overwritten: if a wrap for this credential and
generation already exists the call answers 409. To replace it, delete
the old wrap first (`DELETE /v1/keys/{key_id}/client-share/{share_id}`,
which needs re-authentication).

## Request body

- PutClientShareRequest
  - `wrap_kind` 'passkey_prf', required: Sidecar wraps are stored through `PUT /v1/keys/{key_id}/client-share/holder`. `recovery_code` is refused: the recovery code seals the offline kit in the browser, and 1Claw holds nothing it can open.
  - `credential_id` string, uuid, nullable: Required for `passkey_prf`; the passkey id from `GET /v1/auth/passkeys`.
  - `wrapped_share` string, required: Base64 ciphertext (≤ 4 KiB). Opaque to the vault.
  - `salt` string, required: Base64 PRF salt, 16–64 bytes. For `wrap_version` 2, the account's salt from `GET /v1/keys/tss/prf-salt`; for 1, random per key.
  - `generation` integer: Share generation this wrap holds. Defaults to the key's current one; during a refresh, the pending one (the new device share).
  - `wrap_version` 1 | 2: 1 = per-key salt (keys created before the master wrap). 2 = the per-account master wrap: account PRF salt, wrap key HKDF'd per (key_id, share index). Every passkey wrap of one key must use the same salt and version (409 otherwise), so any of the user's passkeys opens it with one touch.

## Response `201`

Share stored

- ClientShareResponse
  - `id` string, uuid
  - `key_id` string, uuid
  - `key_kind` 'agent_signing_key' | 'treasury_wallet'
  - `wrap_kind` 'passkey_prf' | 'recovery_code' | 'sidecar'
  - `credential_id` string, uuid, nullable
  - `holder_id` string, uuid, nullable
  - `wrapped_share` string: Base64, exactly as stored.
  - `salt` string: Base64.
  - `wrap_version` 1 | 2
  - `generation` integer
  - `created_at` string, date-time
  - `updated_at` string, date-time

## Other responses

- `400`: Invalid request
- `401`: Authentication required or invalid
- `403`: Insufficient permissions
- `404`: Resource not found
- `409`: A wrap for this credential and generation already exists, the generation is neither the key's current nor its pending one, or the salt or wrap version disagrees with the key's other passkey wraps.

---

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