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¶
- 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.
- Authenticate with the REST API. Generate a stable per-device id and send it on login — the key server files keys per device.
- 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.
- Publish a key bundle and one-time prekeys to the key server.
- Implement both channel encryption modes:
secure(rolling epoch keys, granted per device) andpersistent(a server-escrowed key). - Connect to the gateway. On every
hello, discard cached messages and refetch over REST — there is no resume. - Encrypt attachments on the device; the media service stores sealed blobs.
- For voice, configure LiveKit end-to-end encryption with the
room_keyfrom the voice token, and refuse to join without it. - 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
securechannels 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_keywith every voice token, or voice runs in the clear; - send push wakes that carry nothing but
{"v":"1","t":"wake"}.