Skip to content

Documentation

These are ZippChat's protocol and API documents. They aim to be complete enough that you can write your own client, or your own server, and interoperate with the real ones.

Where these pages come from

The site holds no copies. Every page under Protocol, API, Client guides and Deploy is rendered at build time from its canonical file in one of the project's repositories, and says so in a banner at the top:

Banner Means
Canonical specification The source of truth. If the code disagrees, that is a bug, and it is listed in the spec errata.
Reference Kept current with the code it describes, but not a protocol spec.
Partly out of date Useful protocol content, mixed with descriptions of an older client or API. The code wins.
Older endpoint notes Predates the REST reference, which wins where both cover an endpoint. Published because it still documents endpoints the reference does not.

Where the two repositories split the work:

Topic Canonical source
Cryptographic protocols, encryption modes, push design, permissions, hosting model ProjectInfo/ — encryption modes, E2EE, push, hosting model
REST endpoints, request and response shapes Server/docs/api.md — REST API reference
Attachment flows Server/docs/client-media.md — attachments and media
Deployment Server/docs/deployment-k3s.md — k3s deployment
Where any of the above disagrees with the code ProjectInfo/spec-errata.md

Some older specs are known to be wrong and are deliberately not published — for instance the first gateway event table and the original channel and voice endpoint notes, which predate client-side encryption. Links to them from other pages lead to the repository.

If you are writing a client

  1. Read the hosting model: a client talks to one instance at a time, and what "the server can read this" means depends on whose server it is.
  2. Authenticate with the REST API. Generate a stable per-device id and send it on login — the key server files keys per device.
  3. Implement the 1:1 protocol — X3DH, then the Double Ratchet — with the exact parameters in the errata. ZippChat's info strings, header encoding and ratchet bootstrap are its own, so an off-the-shelf Double Ratchet library will not interoperate.
  4. Publish a key bundle and one-time prekeys to the key server.
  5. Implement both channel encryption modes: secure (rolling epoch keys, granted per device) and persistent (a server-escrowed key).
  6. Connect to the gateway. On every hello, discard cached messages and refetch over REST — there is no resume.
  7. Encrypt attachments on the device; the media service stores sealed blobs.
  8. For voice, configure LiveKit end-to-end encryption with the room_key from the voice token, and refuse to join without it.
  9. Optionally register for push wakes. A wake carries no content; the device fetches and decrypts.

If you are writing a server

The REST reference and the specs above define the wire contract. The reference implementation is five Go services (api, keyserver, media, voice, worker) behind one reverse proxy; self-hosting describes what it needs to run. A compatible server must at minimum:

  • keep ciphertext opaque — never require plaintext for secure channels or DMs;
  • verify signed prekey signatures on upload and serve bundles per device;
  • fan out gateway events with the {"op":"event","type":…,"data":…} envelope;
  • return the voice room_key with every voice token, or voice runs in the clear;
  • send push wakes that carry nothing but {"v":"1","t":"wake"}.