Skip to content

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_number to 0 on update
  • relays sender_key.distribute event for federated channels

GET /keys/channels/{channel_id}/sender-keys

Returns all sender keys registered for channel.