INVITE ONLY
OBSERVATORY

Docs · Reference

Read the relay field by field.

Every request the shipped clients make, with the exact shapes the server reads — and, field by field, what it can never read.

Point at the base URL

every path below is relative to
https://api.qeryx.com/api/v1

Authorization: Bearer <jwt>   # on every authenticated request

This reference documents the surface the shipped clients speak today, mirrored from the server's own request structures. A field that is not listed is not read — the server rejects unknown fields on credential payloads rather than silently accepting them.

Authenticate

An account is a Serpent ID and a password. The register payload has two fields; that is the complete identity surface the relay ever learns.

POST /auth/register Create an account: a Serpent ID and a password. Nothing else.
POST /auth/login Authenticate; returns a bearer token.
POST /auth/refresh Rotate the token before it expires.
POST /auth/logout End the server session.
auth/register
{
  "serpent_id": "string   — 3–64 chars: letters, digits, - and _",
  "password":   "string   — 8–128 chars"
}

// 200 —
{
  "token":      "<jwt>",
  "user_id":    "<uuid — internal routing id>",
  "profile_id": "PROFILE-XXXXXXXX-XXXXXXXX"
}

The password is stored as an Argon2id hash (m=512 MiB, t=2, p=4 — RFC 9106). The Profile ID is derived on your device; the server stores it verbatim and routes by it.

Publish and fetch keys

Everything under /keys is public material. The relay is a bulletin board for public keys; private keys never appear in any payload on this page.

POST /keys/bundle Publish your public key bundle: identity, ML-KEM-1024, X25519, signed prekeys.
GET /keys/bundle/by-profile/:profile_id Fetch a peer's public bundle by Profile ID.
POST /keys/signing Publish your ML-DSA-87 signing public key.
GET /keys/signing/by-profile/:profile_id Fetch a peer's signing public key.

Bundles are signed (the signed-prekey binding closes the classic substitution attack), identity keys are appended to the KTS transparency log, and the safety-number ritual in Key verification lets two humans confirm the relay served the same keys to both sides.

Open a session

A session opens with one round trip: init carries the hybrid handshake, respond completes it. The server validates structure and bindings; the secrets are born on the two devices.

POST /sessions/init Open the hybrid handshake with a peer.
POST /sessions/respond Answer an initiated handshake.
GET /sessions/:peer_id Read the session state shared with one peer.
sessions/init
{
  "responder_id":         "<uuid>",
  "handshake_init":       "<base64 — serialized hybrid HandshakeInit>",
  "bell_transcript":      "<base64 — canonical Q-Entangle-Bell v1 bytes>",
  "bell_transcript_hash": "<base64 — SHA3-256 of the canonical bytes>",
  "bell_op_sig":          "<base64 — ML-DSA-87 operator signature>"
}

The server recomputes SHA3-256 over the transcript bytes and rejects the request if the hash binding does not hold — a session cannot be persisted around the check.

This is not QKD. Not quantum networking. Not quantum teleportation. We do not violate the no-communication theorem. We bind a key-derivation function to a verifiable physical measurement no classical adversary can fabricate in advance.

Send a message

The envelope the relay carries is ciphertext plus routing. Group names, subjects, avatars, and all content are end-to-end encrypted; the relay holds only opaque routing identifiers; sender identifiers are stripped from the stored message row (sealed-sender v2), though the relay still authenticates the sender at send time. Undelivered messages queue with routing metadata under a published retention ladder.

POST /messages Relay one ciphertext envelope.
GET /messages Drain queued envelopes. Query: since=<ISO 8601>.
POST /messages/sealed Sealed-sender v2 envelope — sender identifier blinded (rolling out).
POST /messages/receipts Post delivery / read receipts.
DELETE /messages/:message_id Delete an envelope.
messages
{
  "recipient_id":      "PROFILE-… or <uuid>",
  "encrypted_content": "<base64 — ciphertext; opaque to the relay>",
  "nonce":             "<base64>",
  "message_type":      "text | image | video | file | location | voice",
  "reply_to_id":       "<uuid, optional>",
  "conversation_id":   "<string, optional — group routing>",
  "idempotency_key":   "<string, optional — client-side dedup>"
}

encrypted_content and nonce are opaque bytes to the relay. message_type is a routing hint for notifications; the content behind it is indistinguishable ciphertext.

Audit the transparency log

The endpoints an auditor uses. Inclusion proofs, auditor keys, signed audit receipts, and the current build attestation are readable without any special access — verification is a public capability, not a support ticket.

POST /kts/append Append an identity key to the transparency log.
GET /kts/proof/by-uuid/:uuid Fetch an inclusion proof for a logged key.
GET /kts/auditors List the external auditor cosigning keys.
GET /fsor/audit Fetch a signed audit receipt.
GET /fsor/audit/latest-batch Read the latest public audit batch.
GET /attestation/current Read the current build attestation.

KTS is an append-only key log anchored by a 2-of-3 multi-witness quorum (verify-only today — operator equivocation is detected, not prevented) plus three external Ed25519 auditor slots that ship dormant: all three hold placeholder keys, so no external cosignature is carried yet. Registry expansion is release-gated.

Hold the socket open

realtime delivery
GET /ws
Authorization: Bearer <jwt>

# ?token=<jwt> is accepted as a fallback and deprecated —
# tokens in URLs end up in logs.

One socket carries typed frames, dispatched on msg_type: delivery (delivered, delivery_ack, read), call signaling (call_ready, call_accept, call_reject, call_end and their video variants), group media control, and transparency gossip. Message payloads inside frames are the same opaque ciphertext as the REST surface.

Push on the reference.

Is there a third-party app program or API keys?

Not today. This reference exists so you can verify what the shipped clients send — and what the relay can read — not to onboard bots. There are no bots and no server-side AI in the core product, by design.

Because the API surface is the privacy claim. Anyone can read these shapes, capture their own traffic, and confirm the two match. A privacy policy asks for trust; a field list can be checked.

The relay enforces per-route rate limits (auth endpoints are the strictest). Exact thresholds are operational tuning and move with load; the error you get is HTTP 429 with a retry hint.