Skip to content

API - System, Federation, and WebSocket

Source of truth:

  • d3chat/backend/app/main.py
  • d3chat/backend/app/federation/inbox.py
  • d3chat/backend/app/websocket/router.py

System Routes

GET /health

Returns:

{ "status": "ok" }

GET /api/v1/config

Public config consumed by frontend branding/login/register views.

Fields:

  • app_name
  • app_description
  • registration_mode
  • brand_primary_color
  • brand_accent_color

GET /.well-known/d3chat-server

Federation identity descriptor:

  • domain
  • signing_key_public
  • api_base_url
  • protocol_version

Federation Routes

POST /federation/inbox

Single ingress endpoint for signed server-to-server events.

Required headers:

  • X-D3Chat-Origin
  • X-D3Chat-Timestamp
  • X-D3Chat-Signature

Validation flow:

  1. header presence
  2. replay-window check (5 minutes)
  3. per-origin Redis rate limit (100 req/min)
  4. origin discovery + public key lookup
  5. signature verification
  6. event dedup by event_id (Redis NX with 24h TTL)
  7. dispatch by type

Supported event families include:

  • message.relay
  • sender_key.distribute
  • channel.invite
  • channel.join
  • channel.leave

GET /federation/user-lookup?username=<name>

Signed endpoint for remote servers to resolve local users.

Returns:

{
"found": true,
"username": "alice",
"user_id": "<uuid>",
"server_domain": "chat.example.com"
}

or { "found": false }.

WebSocket Route

GET /ws?ticket=<one-time-ticket>

Auth model:

  • ticket issued from POST /api/v1/auth/ws-ticket
  • ticket consumed atomically (getdel) and expires quickly

On connect:

  • subscribes user to all channel topics where user is member

Client message types handled:

  • typing.start
  • typing.stop
  • presence.update
  • subscribe

Server pub/sub fan-out includes:

  • message.new
  • message.edit
  • message.delete
  • typing events
  • key-health events like keys.low_otp
  • channel creation notices like channel.new

Invalid/expired ticket closes socket with code 4001.