|
1 | 1 | --- |
2 | 2 | title: Introduction to Chat API |
3 | 3 | 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"] |
6 | 6 | --- |
7 | 7 |
|
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. |
26 | 9 |
|
27 | 10 | --- |
28 | 11 |
|
29 | | -## What you can build |
| 12 | +## What you need in your app |
30 | 13 |
|
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 | |
46 | 19 |
|
47 | 20 | ```mermaid |
48 | 21 | 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 |
59 | 26 | ``` |
60 | 27 |
|
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)**. |
69 | 29 |
|
70 | 30 | --- |
71 | 31 |
|
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) |
106 | 33 |
|
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. |
130 | 40 |
|
131 | 41 | --- |
132 | 42 |
|
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 |
171 | 44 |
|
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: |
173 | 46 |
|
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)) |
175 | 50 |
|
176 | 51 | --- |
177 | 52 |
|
178 | | -## SDKs and tools |
| 53 | +## Auth notes |
179 | 54 |
|
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. |
191 | 56 |
|
192 | 57 | --- |
193 | 58 |
|
194 | 59 | ## Next steps |
195 | 60 |
|
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