Skip to content

Commit 0d47515

Browse files
committed
Streamline Chat API docs and sync OpenAPI 2.166
Refresh multi-language getting started and Chat XDK guides, add media and groups how-tos, scope troubleshooting to encryption, expand API reference nav by default, and update the bundled OpenAPI specification to 2.166 with Activity API guidance for live chat events.
1 parent bd4eb9b commit 0d47515

10 files changed

Lines changed: 20083 additions & 19932 deletions

docs.json

Lines changed: 1685 additions & 1583 deletions
Large diffs are not rendered by default.

openapi.json

Lines changed: 16625 additions & 16012 deletions
Large diffs are not rendered by default.

xchat/cryptography-primer.mdx

Lines changed: 93 additions & 86 deletions
Large diffs are not rendered by default.

xchat/getting-started.mdx

Lines changed: 639 additions & 533 deletions
Large diffs are not rendered by default.

xchat/groups.mdx

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
---
2+
title: Group conversations
3+
sidebarTitle: Groups
4+
description: Multi-participant Chat conversations, keys, and encrypted metadata
5+
keywords: ["Chat groups", "group DM", "conversation keys", "group name encryption"]
6+
---
7+
8+
Group chats use the **same encryption model** as 1:1 Chat: one **conversation key** shared by members, wrapped to each member’s **identity public key**, with messages encrypted and signed by the Chat XDK. What changes is **membership**, **how you create the thread**, and often **encrypted title/avatar** fields on the conversation.
9+
10+
1:1 flows are in [Getting Started](/xchat/getting-started). Endpoint details are under **API reference → Conversations and messages**.
11+
12+
---
13+
14+
## How groups differ from 1:1
15+
16+
| Topic | 1:1 | Group |
17+
|:------|:----|:------|
18+
| Identity | Often addressed by peer user id in paths | Conversation id typically starts with `g` |
19+
| Create | Keys + messaging to a user | Create / initialize group APIs, then keys |
20+
| Participants | You + one peer | Many users; membership can change |
21+
| Metadata | Minimal | Name, avatar, etc. may be **ciphertext** (decrypt with the conversation key) |
22+
| Key rotation | Less frequent | Common when people join or leave |
23+
24+
Crypto is still: **Chat XDK** for keys and payloads; **X API** to create the group, publish participant key wraps, send messages, and load events.
25+
26+
---
27+
28+
## Create the group and establish keys
29+
30+
1. Create or initialize the group via the Chat APIs (see **create group conversation** and **initialize chat group** in the sidebar).
31+
2. Load each member’s identity public key and version (`GET` public-key routes under **Encryption keys**).
32+
3. Run **`prepare_conversation_keys`** with **all** members (including yourself)—same helper as 1:1, more rows.
33+
4. Register wraps with **initialize conversation keys** (or the key fields your create/init response expects). Map SDK **`encrypted_key`** → API **`encrypted_conversation_key`**.
34+
5. Keep the **raw** conversation key and **version** for encrypt/decrypt.
35+
36+
Language samples for `prepare_conversation_keys` and the keys POST are in [Getting Started — conversation keys](/xchat/getting-started#4-set-up-conversation-keys) (add every member to the input list).
37+
38+
When membership changes, call **add members** (sidebar) as required by the API, then expect **key-change** traffic: treat it like [key rotation in Getting Started](/xchat/getting-started#6-receive-and-decrypt) (`extract_conversation_keys` / `decrypt_events`, then encrypt with the latest version). Advanced admin signing helpers (`sign_add_members`, `sign_key_change`) are on the [Chat XDK](/xchat/xchat-xdk) if your flow requires them.
39+
40+
---
41+
42+
## Encrypted group metadata
43+
44+
Some conversation fields (for example display **name** or **avatar URL**) may arrive **encrypted** under the conversation key. That is **not** `encrypt_message`; it is the generic Chat XDK **`encrypt` / `decrypt`** pair (UTF-8 string in, base64 ciphertext out, with the **raw** conversation key).
45+
46+
<Tabs>
47+
<Tab title="Python">
48+
```python
49+
# Decrypt a field from the conversation object (name may vary by API shape)
50+
group_name = chat.decrypt(conversation["group_name"], raw_conv_key)
51+
52+
# Encrypt before update if your API accepts ciphertext metadata
53+
encrypted_name = chat.encrypt("Project team", raw_conv_key)
54+
```
55+
</Tab>
56+
<Tab title="TypeScript">
57+
```typescript
58+
const groupName = chat.decrypt(conversation.groupName, rawConvKey);
59+
const encryptedName = chat.encrypt('Project team', rawConvKey);
60+
```
61+
</Tab>
62+
<Tab title="Rust">
63+
```rust
64+
let group_name = chat.decrypt(&conversation_group_name_b64, &raw_conv_key)?;
65+
let encrypted_name = chat.encrypt("Project team", &raw_conv_key)?;
66+
```
67+
</Tab>
68+
<Tab title="Go">
69+
```go
70+
groupName, err := chat.Decrypt(conversationGroupNameB64, convKeyB64)
71+
encryptedName, err := chat.Encrypt("Project team", convKeyB64)
72+
_ = groupName
73+
_ = encryptedName
74+
```
75+
</Tab>
76+
<Tab title="C#">
77+
```csharp
78+
string groupName = chat.Decrypt(conversationGroupNameB64, rawConvKey);
79+
string encryptedName = chat.Encrypt("Project team", rawConvKey);
80+
```
81+
</Tab>
82+
<Tab title="Java">
83+
```java
84+
String groupName = chat.decrypt(conversationGroupNameB64, rawConvKey);
85+
String encryptedName = chat.encrypt("Project team", rawConvKey);
86+
```
87+
</Tab>
88+
</Tabs>
89+
90+
Use the **current** conversation key version that applies to that metadata. If keys rotated, decrypt with the version that was active when the field was written (or follow product rules if metadata is always rewritten on rotation).
91+
92+
---
93+
94+
## Messages and events
95+
96+
Sending and receiving in a group is the same as 1:1 once you have the raw conversation key:
97+
98+
- **Send:** `encrypt_message` → send-message API ([Getting Started](/xchat/getting-started#5-send-a-message))
99+
- **Receive:** events API or [real-time delivery](/xchat/real-time-events)`decrypt_event` / `decrypt_events`
100+
- **Media:** [Media](/xchat/media) with the group conversation id
101+
102+
Always encrypt with the **latest** key version after a membership-driven rotation.
103+
104+
---
105+
106+
## Checklist
107+
108+
1. Create/initialize the group via Chat APIs
109+
2. `prepare_conversation_keys` for **every** member; POST participant key wraps
110+
3. Cache raw key + version; update on key-change events
111+
4. Decrypt group metadata with `decrypt` when fields are ciphertext
112+
5. Send/receive with the same patterns as 1:1

xchat/introduction.mdx

Lines changed: 32 additions & 183 deletions
Original file line numberDiff line numberDiff line change
@@ -1,215 +1,64 @@
11
---
22
title: Introduction to Chat API
33
sidebarTitle: Introduction
4-
description: Build end-to-end encrypted messaging applications with the Chat API
5-
keywords: ["Chat API", "encrypted DM", "end-to-end encryption", "E2EE", "secure messaging", "chat API", "direct messages", "encrypted chat"]
4+
description: End-to-end encrypted messaging on X for developers
5+
keywords: ["Chat API", "encrypted DM", "E2EE", "Chat XDK"]
66
---
77

8-
import { Button } from '/snippets/button.mdx';
9-
10-
The Chat API enables developers to build applications that send and receive **end-to-end encrypted direct messages** on X. Unlike standard DMs, Chat messages are encrypted on the sender's device and can only be decrypted by the intended recipient — not even X can read the message contents.
11-
12-
<CardGroup cols={2}>
13-
<Card title="End-to-end encrypted" icon="lock">
14-
Messages are encrypted on sender's device and only readable by recipients
15-
</Card>
16-
<Card title="Cryptographically signed" icon="signature">
17-
Every message is digitally signed to verify authenticity
18-
</Card>
19-
<Card title="Real-time events" icon="bolt">
20-
Receive chat events via webhooks or persistent streams
21-
</Card>
22-
<Card title="Multi-platform SDKs" icon="cube">
23-
Rust, Python, JavaScript/WASM, Go, .NET, and JVM bindings for encryption operations
24-
</Card>
25-
</CardGroup>
8+
The **Chat API** lets you send and receive **end-to-end encrypted** direct messages on X. Message bodies are encrypted on the client; X routes ciphertext and cannot read plaintext content. Messages are also **signed** so recipients can verify the sender.
269

2710
---
2811

29-
## What you can build
12+
## What you need in your app
3013

31-
Chat enables a wide range of secure messaging applications:
32-
33-
| Use Case | Description |
34-
|:---------|:------------|
35-
| **Customer Service Bots** | Build AI-powered assistants that handle customer inquiries securely |
36-
| **Notification Systems** | Send encrypted transactional messages (order updates, alerts, etc.) |
37-
| **CRM Integrations** | Connect X messaging with your customer relationship tools |
38-
| **Support Ticketing** | Create secure support channels with encrypted conversation history |
39-
| **Automated Responses** | Set up auto-replies and smart routing while maintaining E2EE |
40-
41-
---
42-
43-
## Architecture overview
44-
45-
Building with Chat involves two pieces of your own code working against the X API:
14+
| Piece | Responsibility |
15+
|:------|:---------------|
16+
| **[Chat XDK](/xchat/xchat-xdk)** | Generate keys, encrypt/decrypt, sign/verify, optional Juicebox PIN storage (Python, JS, Rust, Go, C#, Java) |
17+
| **X API access** | Public keys, conversation keys, messages, events, media—via **[XDK](/xdks/python/overview)** (Python/TypeScript) or HTTPS |
18+
| **Delivery** | [Webhooks or activity stream](/xchat/real-time-events) for live events; events API for history |
4619

4720
```mermaid
4821
flowchart LR
49-
subgraph Your App
50-
A[Chat XDK<br/>Encryption/Decryption<br/>+ integrated Juicebox key storage]
51-
C[XDK / HTTP<br/>API Calls]
52-
end
53-
54-
C --> D[X API<br/>/2/chat/*, /2/users/*/public_keys]
55-
D --> E[X Infrastructure]
56-
57-
E --> F[Webhook / Activity Stream]
58-
F --> A
22+
A[Chat XDK] --> B[Your app]
23+
B --> C[X API]
24+
C --> D[Webhook / stream]
25+
D --> A
5926
```
6027

61-
| Component | Purpose | Languages |
62-
|:----------|:--------|:----------|
63-
| **Chat XDK** | Handles all cryptographic operations — key generation, encryption, decryption, signing, verification — and key storage via integrated [Juicebox](/xchat/cryptography-primer#juicebox-distributed-key-storage) | Rust, Python, JavaScript/WASM, Go, .NET, JVM |
64-
| **XDK / HTTP client** | Makes calls to X's `/2/chat/*` and public-key endpoints | Python, TypeScript, or any HTTP client |
65-
66-
<Note>
67-
**Juicebox is built in.** The Chat XDK embeds the Juicebox client — you don't install or call a separate Juicebox SDK. The Juicebox configuration your app needs is returned by the X API itself (see [Authentication and key storage](#authentication-and-key-storage) below), not provisioned out of band.
68-
</Note>
28+
Follow **[Getting Started](/xchat/getting-started)** for a full implementation. For concepts only, see the **[Cryptography primer](/xchat/cryptography-primer)**.
6929

7030
---
7131

72-
## How Chat encryption works
73-
74-
<Steps>
75-
<Step title="Generate encryption keys">
76-
Your app generates an identity keypair (for encrypting/decrypting conversation keys) and a signing keypair (for authenticating messages). These are stored securely via Juicebox.
77-
</Step>
78-
<Step title="Register public keys with X">
79-
You register your public keys with X's API so other users can encrypt messages to you.
80-
</Step>
81-
<Step title="Encrypt outgoing messages">
82-
When sending a message, the Chat XDK encrypts the content using the conversation key and signs it with your signing key.
83-
</Step>
84-
<Step title="Send via X API">
85-
Your app sends the encrypted payload to X using the `/2/chat/conversations/{id}/messages` endpoint.
86-
</Step>
87-
<Step title="Receive encrypted events">
88-
Incoming messages arrive in real time via the X Activity API (webhooks or streams), or by paging `/2/chat/conversations/{id}/events` for history.
89-
</Step>
90-
<Step title="Decrypt and verify">
91-
The Chat XDK decrypts the message using the conversation key and verifies the sender's signature.
92-
</Step>
93-
</Steps>
94-
95-
---
96-
97-
## Key concepts
98-
99-
### End-to-end encryption (E2EE)
100-
101-
Chat uses **end-to-end encryption**, meaning messages are encrypted on your device before being sent to X's servers. Only the intended recipient(s) can decrypt the message — X cannot read the content.
102-
103-
### Conversation keys
104-
105-
Each conversation has a symmetric **conversation key** used to encrypt all messages in that conversation. This key is itself encrypted to each participant using their public identity key, so only authorized participants can decrypt messages.
32+
## How encryption works (overview)
10633

107-
### Digital signatures
108-
109-
Every message is **cryptographically signed** by the sender. This allows recipients to verify that:
110-
- The message hasn't been tampered with
111-
- The message actually came from the claimed sender
112-
113-
### Juicebox key storage
114-
115-
Private encryption keys are stored using **Juicebox**, a distributed PIN-protected key storage system. Your keys are split across multiple independent servers — no single party (including Juicebox operators) can access your keys without your PIN.
116-
117-
---
118-
119-
## Supported event types
120-
121-
The X Activity API supports real-time delivery of chat events:
122-
123-
| Event Type | Description |
124-
|:-----------|:------------|
125-
| `chat.received` | Fired when a user receives a direct message |
126-
| `chat.sent` | Fired when a user sends a direct message |
127-
| `chat.conversation_join` | Fired when a user is added to a group conversation |
128-
129-
These events deliver encrypted message payloads (the `encoded_event` field) that you decrypt using the Chat XDK. See [Real-time events](/xchat/real-time-events) for the full payload structure.
34+
1. Create **identity** and **signing** keypairs; store private keys securely (Juicebox or protected blob).
35+
2. **Publish public keys** so others can wrap conversation keys to you and verify signatures.
36+
3. Share a **conversation key** by posting encrypted copies for each participant.
37+
4. **Encrypt and sign** outbound messages; send only ciphertext to X.
38+
5. **Receive** ciphertext via webhooks, stream, or event history.
39+
6. **Verify and decrypt** with the Chat XDK.
13040

13141
---
13242

133-
## API endpoints
134-
135-
Chat uses the `/2/chat/*` family of endpoints, plus public-key endpoints under `/2/users/`:
136-
137-
| Method | Endpoint | Description |
138-
|:-------|:---------|:------------|
139-
| GET | [`/2/chat/conversations`](/x-api/chat/get-chat-conversations) | List conversations in the inbox |
140-
| GET | [`/2/chat/conversations/{id}`](/x-api/chat/get-chat-conversation) | Get conversation metadata |
141-
| GET | [`/2/chat/conversations/{id}/events`](/x-api/chat/get-chat-conversation-events) | Get message + key-change events (with pagination) |
142-
| POST | [`/2/chat/conversations/{id}/keys`](/x-api/chat/initialize-conversation-keys) | Initialize conversation keys (1:1) |
143-
| POST | [`/2/chat/conversations/{id}/messages`](/x-api/chat/send-chat-message) | Send encrypted message |
144-
| POST | [`/2/chat/conversations/{id}/read`](/x-api/chat/mark-conversation-as-read) | Mark as read |
145-
| POST | [`/2/chat/conversations/{id}/typing`](/x-api/chat/send-typing-indicator) | Send typing indicator |
146-
| POST | [`/2/chat/conversations/group/initialize`](/x-api/chat/initialize-chat-group) | Initialize a group conversation |
147-
| POST | [`/2/chat/conversations/group`](/x-api/chat/create-chat-group-conversation) | Create a group conversation |
148-
| POST | [`/2/chat/conversations/{id}/members`](/x-api/chat/add-members-to-a-chat-group-conversation) | Add members to a group (rotates the key) |
149-
| GET | [`/2/users/public_keys`](/x-api/users/get-public-keys-for-multiple-users) | Get public keys + Juicebox config for multiple users |
150-
| GET | [`/2/users/{id}/public_keys`](/x-api/chat/get-user-public-keys) | Get a user's public keys + Juicebox config |
151-
| POST | [`/2/users/{id}/public_keys`](/x-api/chat/add-public-key) | Register your public keys |
152-
| POST | [`/2/chat/media/upload/initialize`](/x-api/chat/initialize-chat-media-upload) | Initialize media upload |
153-
| POST | [`/2/chat/media/upload/{id}/append`](/x-api/chat/append-chat-media-upload) | Append media data |
154-
| POST | [`/2/chat/media/upload/{id}/finalize`](/x-api/chat/finalize-chat-media-upload) | Finalize media upload |
155-
| GET | [`/2/chat/media/{id}/{media_hash_key}`](/x-api/chat/download-chat-media) | Download encrypted media |
156-
157-
<Tip>
158-
For 1:1 conversations, the `{id}` path parameter on the message, events, keys, read, and typing endpoints accepts the **recipient's user ID** directly — the server derives the canonical conversation ID from the authenticated user and the recipient. Group conversation IDs are prefixed with `g`.
159-
</Tip>
160-
161-
---
162-
163-
## Authentication and key storage
164-
165-
Chat endpoints require **user context authentication**:
166-
167-
| Auth Method | Description |
168-
|:------------|:------------|
169-
| **OAuth 2.0 User Token** | Preferred method. Scopes used across Chat endpoints: `dm.read`, `dm.write`, `tweet.read`, `users.read`, and `media.write` (for media) |
170-
| **OAuth 1.0a User Token** | Alternative authentication method |
43+
## Useful endpoints
17144

172-
The authenticated user is the "sender" for outgoing messages and the "recipient" for incoming events.
45+
Grouped under **API reference** in the sidebar, including:
17346

174-
**Where the Juicebox config comes from.** The public-key endpoints (`GET /2/users/{id}/public_keys` and `GET /2/users/public_keys`) return each user's `juicebox_config` alongside their `public_key` and `signing_public_key` when you request the `juicebox_config` field. Fetch your own record and pass that config to the Chat XDK to unlock your keys — there's no separate provisioning step.
47+
- Public keys — register and fetch
48+
- Conversations and messages — list/get threads, init keys, events, send, typing, read, group membership
49+
- Media — upload and download encrypted attachments ([guide](/xchat/media))
17550

17651
---
17752

178-
## SDKs and tools
53+
## Auth notes
17954

180-
<CardGroup cols={3}>
181-
<Card title="Chat XDK" icon="lock" href="/xchat/xchat-xdk">
182-
Cryptographic SDK for encryption, decryption, and signing
183-
</Card>
184-
<Card title="XDK (Python)" icon="python" href="/xdks/python/overview">
185-
Full-featured Python SDK with chat client
186-
</Card>
187-
<Card title="XDK (TypeScript)" icon="js" href="/xdks/typescript/overview">
188-
TypeScript/JavaScript SDK with chat client
189-
</Card>
190-
</CardGroup>
55+
Use **OAuth 2.0 user context** with DM-related scopes (`dm.read`, `dm.write`, plus `users.read` / `tweet.read` as required; `media.write` for uploads). Chat activity for a user requires that user’s authorization. Juicebox config for PIN storage is returned on **your** public-key record (`juicebox_config` field)—see Getting Started.
19156

19257
---
19358

19459
## Next steps
19560

196-
<CardGroup cols={2}>
197-
<Card title="Cryptography Primer" icon="key" href="/xchat/cryptography-primer">
198-
Understand the encryption concepts behind Chat
199-
</Card>
200-
<Card title="Getting Started" icon="rocket" href="/xchat/getting-started">
201-
Build your first Chat application step-by-step
202-
</Card>
203-
</CardGroup>
204-
205-
<Note>
206-
**Prerequisites**
207-
208-
Before building with Chat, you'll need:
209-
- An approved [developer account](https://developer.x.com/en/portal/petition/essential/basic-info)
210-
- A [Project and App](/resources/fundamentals/developer-apps) in the Developer Console
211-
- OAuth 2.0 credentials with the `dm.read`, `dm.write`, `tweet.read`, `users.read`, and `media.write` scopes
212-
- The Chat XDK for your language (handles encryption and Juicebox key storage)
213-
214-
The Juicebox configuration needed for key storage is returned by the X API's public-key endpoints — no separate provisioning is required.
215-
</Note>
61+
1. [Cryptography primer](/xchat/cryptography-primer) — optional background on E2EE concepts
62+
2. [Getting Started](/xchat/getting-started) — implement keys, send, and receive
63+
3. [Chat XDK](/xchat/xchat-xdk) — encryption SDK reference
64+
4. [Real-time events](/xchat/real-time-events), [Media](/xchat/media), or [Troubleshooting](/xchat/troubleshooting) when you need those topics

0 commit comments

Comments
 (0)