---
title: "Upload or reconcile a saved key bundle"
method: POST
path: "/devices/keys/upload"
tags: ["E2EE"]
---

# Upload or reconcile a saved key bundle

`POST /devices/keys/upload`

## Request

- Base URL: `https://api.shopseen.com/v1`
- URL: `https://api.shopseen.com/v1/devices/keys/upload`
- Auth: HTTP bearer

Stores the user's identity key, signed prekey, one-time prekey batch, and Kyber prekey batch (post-quantum hybrid). Identical retries preserve consumed prekeys. A different identity or signed prekey requires explicit recovery; never automatically revoke saved keys. A prekey material conflict returns key_prekey_conflict; an owner-bound client may verify allocation bounds and retry with fresh IDs while retaining private records.

## Request body

- object
  - `owner_user_id` string, uuid: Must match the authenticated account when supplied
  - `existing_only` boolean: Legacy unbound material may only reconcile an existing matching registry
  - `identity_key_pub` string, required: Base64-encoded 33-byte libsignal IdentityKey
  - `signed_prekey` object, required
    - `id` integer, required
    - `public` string, required: base64 33 bytes
    - `signature` string, required: base64 64 bytes
  - `one_time_prekeys` object[], required
    - `id` integer, required
    - `public` string, required: base64 33 bytes
  - `kyber_prekeys` object[], required
    - `id` integer, required
    - `public` string, required: base64 ~1568 bytes (Kyber1024)
    - `signature` string, required: base64 64 bytes

## Response `200`

Keys uploaded

- object
  - `message` string
  - `one_time_prekey_count` integer
  - `kyber_prekey_count` integer

## Other responses

- `400`: Validation error (byte lengths, batch size, key ids)
- `409`: Different active identity/signed key (key_bundle_conflict) or prekey material (key_prekey_conflict)

---

[API](https://skmtc.dev/shopseen/apis/a-side-api.md) - [All operations](https://skmtc.dev/shopseen/apis/a-side-api/llms.txt) - [OpenAPI document](https://skmtc.dev/shopseen/apis/a-side-api/revisions/f37f989e90da?raw)
