API - Key and Crypto Routes
Source of truth: d3chat/backend/app/routers/keys.py
Prefix: /api/v1/keys
All routes below require Bearer auth.
Device Key Bundles
POST /keys/upload
Upserts key bundle by device_id.
Request:
{ "device_id": "<uuid>", "identity_key": "base64", "signed_pre_key": "base64", "signed_pre_key_signature": "base64", "one_time_pre_keys": ["base64", "base64"]}GET /keys/{user_id}/bundles
Returns all device bundles for user and consumes one OTP per bundle when available.
Also emits keys.low_otp Redis event when remaining OTPs for a device fall below 10.
GET /keys/{device_id}/bundle
Returns one bundle for a specific device with same OTP-consumption behavior.
POST /keys/one-time
Appends more OTP keys to existing bundle.
Request:
{ "device_id": "<uuid>", "one_time_pre_keys": ["base64", "base64"]}X3DH Setup Storage (DM)
POST /keys/channels/{channel_id}/x3dh-setup
Stores initiator handshake metadata in Redis (30 days TTL).
Request:
{ "initiator_identity_key": "base64", "ephemeral_public_key": "base64", "used_one_time_key": true}GET /keys/channels/{channel_id}/x3dh-setup
Fetches stored setup for responder to derive same session key.
Sender Keys (Groups)
POST /keys/channels/{channel_id}/sender-keys
Upserts sender key for device_id in channel.
Request:
{ "device_id": "<uuid>", "sender_key_public": "base64", "chain_key": "base64"}Behavior:
- resets
message_numberto 0 on update - relays
sender_key.distributeevent for federated channels
GET /keys/channels/{channel_id}/sender-keys
Returns all sender keys registered for channel.