@xquik/tweetclaw 1.1.0 → 1.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -43,21 +43,21 @@ AI uses explore → filters spec by category "composition"
43
43
 
44
44
  ### `tweetclaw` (execute API calls)
45
45
 
46
- Execute authenticated API calls. Auth is injected automatically - the LLM never sees your API key.
46
+ Execute authenticated API calls. Auth is injected automatically - the LLM never sees your API key.
47
47
 
48
48
  ```
49
- You: "Search tweets about AI agents"
49
+ You: "Post a tweet saying 'Hello from TweetClaw!'"
50
50
 
51
- AI uses explore → finds /api/v1/x/tweets/search
52
- AI uses tweetclaw calls the endpoint with auth
53
- → Returns tweet results
51
+ AI uses tweetclaw → finds connected account, posts tweet
52
+ Returns { tweetId, success: true }
54
53
  ```
55
54
 
56
55
  ```
57
- You: "Post a tweet saying 'Hello from TweetClaw!'"
56
+ You: "Search tweets about AI agents"
58
57
 
59
- AI uses tweetclaw → finds connected account, posts tweet
60
- Returns { tweetId, success: true }
58
+ AI uses explore → finds /api/v1/x/tweets/search
59
+ AI uses tweetclaw calls the endpoint with auth
60
+ → Returns tweet results
61
61
  ```
62
62
 
63
63
  ## Commands
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "id": "tweetclaw",
3
3
  "name": "TweetClaw",
4
+ "version": "1.2.1",
4
5
  "description": "Post tweets, reply, like, retweet, follow, DM from your chat - full X/Twitter automation powered by Xquik",
5
6
  "configSchema": {
6
7
  "type": "object",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xquik/tweetclaw",
3
- "version": "1.1.0",
3
+ "version": "1.2.1",
4
4
  "description": "Post tweets, reply, like, retweet, follow, DM & more from OpenClaw - full X/Twitter automation via Xquik",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -49,7 +49,7 @@
49
49
  },
50
50
  "devDependencies": {
51
51
  "@eslint/js": "^10.0.1",
52
- "@sinclair/typebox": "^0.34.0",
52
+ "@sinclair/typebox": "^0.34.48",
53
53
  "@types/node": "^25.5.0",
54
54
  "@typescript-eslint/eslint-plugin": "^8.57.0",
55
55
  "@typescript-eslint/parser": "^8.57.0",
@@ -11,7 +11,7 @@ read_when:
11
11
  - Extracting bulk data from X/Twitter (followers, replies, communities)
12
12
  - Downloading tweet media or uploading images
13
13
  - Sending DMs or updating X/Twitter profile
14
- metadata: {"openclaw":{"emoji":"🐦","primaryEnv":"XQUIK_API_KEY","requires":{"env":["XQUIK_API_KEY"]}}}
14
+ metadata: {"openclaw":{"emoji":"🐦","primaryEnv":"XQUIK_API_KEY","requires":{"env":["XQUIK_API_KEY"]},"tags":["twitter","x","automation","social-media","tweets","scraping","giveaway","monitoring","rest-api"]}}
15
15
  ---
16
16
 
17
17
  # TweetClaw
@@ -22,6 +22,27 @@ OpenClaw plugin for X/Twitter automation powered by Xquik. Install via:
22
22
  openclaw plugins install @xquik/tweetclaw
23
23
  ```
24
24
 
25
+ ## When to Use
26
+
27
+ Use TweetClaw when the user wants to:
28
+
29
+ - Post tweets, reply to tweets, or delete tweets
30
+ - Like, retweet, or follow/unfollow users
31
+ - Send DMs on X/Twitter
32
+ - Update their X profile, avatar, or banner
33
+ - Upload media and tweet with images
34
+ - Search tweets or look up user profiles
35
+ - Extract bulk data (followers, replies, communities, spaces)
36
+ - Run giveaway draws from tweet replies
37
+ - Monitor X accounts for new activity
38
+ - Compose algorithm-optimized tweets
39
+ - Analyze a user's writing style
40
+ - Check trending topics on X
41
+ - Download tweet media (images, videos, GIFs)
42
+ - Set up Telegram alerts for monitor events
43
+
44
+ Do NOT use TweetClaw for browsing X in a browser, analytics dashboards, scheduling future posts, or managing X ads.
45
+
25
46
  ## Configuration
26
47
 
27
48
  Set your Xquik API key (get one at [xquik.com/account-manager](https://xquik.com/account-manager)):
@@ -50,12 +71,15 @@ async () => spec.endpoints.filter(e => e.category === 'composition')
50
71
 
51
72
  Execute authenticated API calls. Auth is injected automatically.
52
73
 
53
- Example: "Search tweets about AI agents"
74
+ Example: "Post a tweet saying 'Hello from TweetClaw!'"
54
75
 
55
76
  ```javascript
56
77
  async () => {
57
- const results = await xquik.request('/api/v1/x/tweets/search', { query: { q: 'AI agents' } });
58
- return results;
78
+ const { accounts } = await xquik.request('/api/v1/x/accounts');
79
+ return xquik.request('/api/v1/x/tweets', {
80
+ method: 'POST',
81
+ body: { account: accounts[0].xUsername, text: 'Hello from TweetClaw!' }
82
+ });
59
83
  }
60
84
  ```
61
85
 
@@ -80,16 +104,49 @@ When polling is enabled (default), TweetClaw checks for new events every 60 seco
80
104
 
81
105
  ```
82
106
  You: "Post a tweet saying 'Hello from TweetClaw!'"
83
- Agent uses explore -> finds POST /api/v1/x/tweets
84
- Agent uses tweetclaw -> posts the tweet with auth
107
+ Agent uses tweetclaw -> finds connected account, posts tweet
108
+ ```
109
+
110
+ ### Reply to a tweet
111
+
112
+ ```
113
+ You: "Reply 'Great thread!' to this tweet: https://x.com/user/status/123"
114
+ Agent uses tweetclaw -> posts reply with reply_to_tweet_id
115
+ ```
116
+
117
+ ### Like, retweet, follow
118
+
119
+ ```
120
+ You: "Like and retweet this tweet, then follow the author"
121
+ Agent uses tweetclaw -> likes tweet, retweets, looks up user ID, follows
122
+ ```
123
+
124
+ ### Send a DM
125
+
126
+ ```
127
+ You: "DM @username saying 'Hey, let's collaborate!'"
128
+ Agent uses tweetclaw -> looks up user ID, sends DM
129
+ ```
130
+
131
+ ### Update profile
132
+
133
+ ```
134
+ You: "Change my bio to 'Building cool stuff' and update my avatar"
135
+ Agent uses tweetclaw -> PATCH /api/v1/x/profile, PATCH /api/v1/x/profile/avatar
136
+ ```
137
+
138
+ ### Upload media and tweet with image
139
+
140
+ ```
141
+ You: "Tweet 'Check this out!' with this image: https://example.com/photo.jpg"
142
+ Agent uses tweetclaw -> uploads media, posts tweet with media_ids
85
143
  ```
86
144
 
87
145
  ### Search tweets
88
146
 
89
147
  ```
90
148
  You: "Search tweets about AI agents"
91
- Agent uses explore -> finds GET /api/v1/x/tweets/search
92
- Agent uses tweetclaw -> calls the endpoint
149
+ Agent uses tweetclaw -> calls search endpoint with query
93
150
  ```
94
151
 
95
152
  ### Run a giveaway draw
@@ -99,6 +156,13 @@ You: "Pick 3 random winners from replies to this tweet: https://x.com/..."
99
156
  Agent uses tweetclaw -> creates draw with filters
100
157
  ```
101
158
 
159
+ ### Extract bulk data
160
+
161
+ ```
162
+ You: "Extract the last 1000 followers of @elonmusk"
163
+ Agent uses tweetclaw -> estimates cost, creates extraction job
164
+ ```
165
+
102
166
  ### Monitor an account
103
167
 
104
168
  ```
@@ -106,11 +170,32 @@ You: "Monitor @elonmusk for new tweets and follower changes"
106
170
  Agent uses tweetclaw -> creates monitor with event types
107
171
  ```
108
172
 
109
- ### Compose an optimized tweet
173
+ ### Download tweet media
174
+
175
+ ```
176
+ You: "Download all media from this tweet"
177
+ Agent uses tweetclaw -> returns gallery URL with all media
178
+ ```
179
+
180
+ ### Compose an optimized tweet (free)
181
+
182
+ ```
183
+ You: "Help me write a tweet about our product launch"
184
+ Agent uses tweetclaw -> 3-step compose/refine/score workflow
185
+ ```
186
+
187
+ ### Analyze writing style (free)
188
+
189
+ ```
190
+ You: "Analyze @username's tweet style"
191
+ Agent uses tweetclaw -> returns style analysis with tone, patterns, metrics
192
+ ```
193
+
194
+ ### Browse trending topics (free)
110
195
 
111
196
  ```
112
- You: "Compose a tweet about our product launch"
113
- Agent uses tweetclaw -> 3-step compose/refine/score workflow (free)
197
+ You: "What's trending on X right now?"
198
+ Agent uses tweetclaw -> returns curated trending topics from 7 sources
114
199
  ```
115
200
 
116
201
  ## API Categories
@@ -136,9 +221,13 @@ Subscription ($20/month): write actions, search, media, extractions, draws, moni
136
221
 
137
222
  When a paid endpoint returns 402, TweetClaw provides a checkout URL.
138
223
 
139
- ## When NOT to Use
224
+ ## Tips
140
225
 
141
- - Reading tweets in a browser or basic browsing (use a browser skill instead)
142
- - X/Twitter analytics dashboards (TweetClaw returns raw data, not visualizations)
143
- - Scheduling tweets for future posting (Xquik posts immediately)
144
- - Managing X/Twitter ads or promoted content (not supported)
226
+ - Use `explore` first to discover endpoints before calling `tweetclaw` - saves tokens and avoids guessing
227
+ - Free endpoints (compose, styles, radar, drafts) work without a subscription - always try them first
228
+ - Never combine free and paid API calls in the same `Promise.all` - a 402 on one call kills all results
229
+ - For write actions (post, like, follow, DM), always pass the `account` parameter with the X username
230
+ - Follow/unfollow/DM require a numeric user ID - look up the user first via `/api/v1/x/users/:username`
231
+ - On 402 errors, call `POST /api/v1/subscribe` to get a checkout URL instead of giving up
232
+ - Use `/xstatus` to quickly check subscription and usage without invoking the AI agent
233
+ - The compose workflow (compose/refine/score) is free and helps draft high-engagement tweets
package/src/index.ts CHANGED
@@ -15,66 +15,64 @@ function isPollerEvent(value: unknown): value is PollerEvent {
15
15
  return typeof value === 'object' && value !== null;
16
16
  }
17
17
 
18
+ function isPluginConfig(value: unknown): value is PluginConfig {
19
+ return typeof value === 'object' && value !== null && 'apiKey' in value;
20
+ }
21
+
18
22
  const DEFAULT_POLLING_INTERVAL_SECONDS = 60;
19
23
 
24
+ interface ToolResult {
25
+ readonly content: ReadonlyArray<{ readonly text: string; readonly type: string }>;
26
+ readonly isError?: true;
27
+ }
28
+
20
29
  interface CommandContext {
21
30
  readonly args?: string;
31
+ readonly commandBody?: string;
32
+ readonly senderId?: string;
22
33
  }
23
34
 
24
35
  interface OpenClawApi {
25
- readonly config: {
26
- readonly plugins?: {
27
- readonly entries?: {
28
- readonly tweetclaw?: {
29
- readonly config?: PluginConfig;
30
- };
31
- };
32
- };
33
- };
34
36
  readonly logger: {
37
+ readonly debug?: (message: string) => void;
38
+ readonly error: (message: string) => void;
35
39
  readonly info: (message: string) => void;
36
40
  readonly warn: (message: string) => void;
37
41
  };
42
+ readonly pluginConfig?: Readonly<Record<string, unknown>>;
38
43
  readonly registerCommand: (options: {
39
- readonly acceptsArguments?: boolean;
44
+ readonly acceptsArgs?: boolean;
40
45
  readonly description: string;
41
46
  readonly handler: (context: CommandContext) => Promise<{ readonly text: string }>;
42
47
  readonly name: string;
43
48
  }) => void;
44
49
  readonly registerService: (options: {
45
50
  readonly id: string;
46
- readonly start: () => void;
47
- readonly stop: () => void;
51
+ readonly start: (context?: unknown) => void;
52
+ readonly stop?: (context?: unknown) => void;
48
53
  }) => void;
49
54
  readonly registerTool: (
50
- options: {
55
+ tool: {
51
56
  readonly description: string;
57
+ readonly execute: (toolCallId: string, params: { readonly code: string }) => Promise<ToolResult>;
52
58
  readonly name: string;
53
- readonly parameters: {
54
- readonly properties: Readonly<Record<string, { readonly description: string; readonly type: string }>>;
55
- readonly required: readonly string[];
56
- readonly type: string;
57
- };
59
+ readonly parameters: unknown;
58
60
  },
59
- handler: (params: { readonly code: string }) => Promise<{
60
- readonly content: ReadonlyArray<{ readonly text: string; readonly type: string }>;
61
- readonly isError?: true;
62
- }>,
61
+ options?: { readonly name?: string; readonly optional?: boolean },
63
62
  ) => void;
64
- readonly sendMessage: (text: string) => void;
65
63
  }
66
64
 
67
65
  const CODE_PARAMETER = {
68
66
  properties: {
69
67
  code: { description: 'Async arrow function to execute', type: 'string' },
70
68
  },
71
- required: ['code'] as const,
69
+ required: ['code'],
72
70
  type: 'object',
73
71
  };
74
72
 
75
73
  export default function register(api: OpenClawApi, fetchFunction?: FetchFunction): void {
76
- const config = api.config.plugins?.entries?.tweetclaw?.config;
77
- if (config?.apiKey === undefined) {
74
+ const config: unknown = api.pluginConfig;
75
+ if (!isPluginConfig(config)) {
78
76
  api.logger.warn(
79
77
  "TweetClaw: No API key configured. Run: openclaw config set plugins.entries.tweetclaw.config.apiKey 'xq_YOUR_KEY'",
80
78
  );
@@ -84,23 +82,25 @@ export default function register(api: OpenClawApi, fetchFunction?: FetchFunction
84
82
  const { apiKey, baseUrl = 'https://xquik.com' } = config;
85
83
  const request = createProxiedRequest(baseUrl, apiKey, fetchFunction);
86
84
 
87
- // --- Tools (2-tool approach) ---
85
+ // --- Tools (2-tool approach, execute inside tool object) ---
88
86
  api.registerTool(
89
87
  {
90
88
  description: SEARCH_DESCRIPTION,
89
+ execute: async (_toolCallId, { code }) => handleExplore(code),
91
90
  name: 'explore',
92
91
  parameters: CODE_PARAMETER,
93
92
  },
94
- async ({ code }) => handleExplore(code),
93
+ { name: 'explore' },
95
94
  );
96
95
 
97
96
  api.registerTool(
98
97
  {
99
98
  description: EXECUTE_DESCRIPTION,
99
+ execute: async (_toolCallId, { code }) => handleTweetclaw({ apiKey, baseUrl, code, fetchFunction }),
100
100
  name: 'tweetclaw',
101
101
  parameters: CODE_PARAMETER,
102
102
  },
103
- async ({ code }) => handleTweetclaw({ apiKey, baseUrl, code, fetchFunction }),
103
+ { name: 'tweetclaw', optional: true },
104
104
  );
105
105
 
106
106
  // --- Commands (instant, no LLM) ---
@@ -114,7 +114,7 @@ export default function register(api: OpenClawApi, fetchFunction?: FetchFunction
114
114
  });
115
115
 
116
116
  api.registerCommand({
117
- acceptsArguments: true,
117
+ acceptsArgs: true,
118
118
  description: 'Show trending topics on X',
119
119
  handler: async ({ args }) => {
120
120
  const text = await handleXTrends(request, args);
@@ -136,7 +136,7 @@ export default function register(api: OpenClawApi, fetchFunction?: FetchFunction
136
136
  const username: string = isPollerEvent(event) && typeof event.xUsername === 'string'
137
137
  ? event.xUsername
138
138
  : '';
139
- api.sendMessage(`[TweetClaw] ${eventType} from @${username}`);
139
+ api.logger.info(`[TweetClaw] ${eventType} from @${username}`);
140
140
  }
141
141
  },
142
142
  request,
@@ -4,7 +4,7 @@ import type { EndpointInfo, ToolResult } from '../types.js';
4
4
 
5
5
  const categories = [...new Set(API_SPEC.map((endpoint) => endpoint.category))].toSorted((a, b) => a.localeCompare(b)).join(', ');
6
6
 
7
- const SEARCH_DESCRIPTION = `Search the X (Twitter) API spec for endpoints: tweet search, user lookup, media download, monitoring, giveaways, composition, and more. No network calls - runs against an in-memory endpoint catalog.
7
+ const SEARCH_DESCRIPTION = `Search the X (Twitter) API spec for endpoints: post tweets, reply, like, retweet, follow, DM, update profile, upload media, search tweets, look up users, extract data, monitor accounts, run giveaways, compose tweets, and more. No network calls - runs against an in-memory endpoint catalog.
8
8
 
9
9
  Write an async arrow function. The sandbox provides:
10
10
 
@@ -2,7 +2,7 @@ import { createProxiedRequest } from '../request.js';
2
2
  import { AsyncFunction, errorResult, specEndpoints, successResult } from './sandbox.js';
3
3
  import type { FetchFunction, RequestFunction, ToolResult } from '../types.js';
4
4
 
5
- const EXECUTE_DESCRIPTION = `Execute X (Twitter) API calls: search tweets, look up users, download media, compose tweets, run giveaways, monitor accounts, and more. Write an async arrow function.
5
+ const EXECUTE_DESCRIPTION = `Execute X (Twitter) API calls: post tweets, reply, like, retweet, follow, DM, update profile, upload media, search tweets, look up users, extract data, run giveaways, monitor accounts, compose tweets, and more. Write an async arrow function.
6
6
 
7
7
  The sandbox provides:
8
8
  \`\`\`typescript
@@ -20,6 +20,13 @@ declare const spec: { endpoints: EndpointInfo[] };
20
20
  Auth is injected automatically - never pass API keys.
21
21
  First use "explore" to find endpoints, then write code here to call them.
22
22
 
23
+ ## Important rules
24
+ - TWEET ACTIONS: SENDING a tweet ("tweet this", "post this") uses POST /api/v1/x/tweets. DRAFTING a tweet ("help me write", "compose") uses the 3-step compose flow. Never use compose when the user has text and wants to send it.
25
+ - CALL ORDERING: NEVER combine free and paid endpoints in Promise.all. Call free endpoints first (radar, styles, compose), then paid ones separately. If a paid call fails with 402, still use free data already fetched.
26
+ - WRITE ACTIONS: All require the "account" parameter (X username, e.g. "@myaccount"). Follow/unfollow/DM use numeric user ID in path - look up the user first via GET /api/v1/x/users/:username.
27
+ - CURRENT EVENTS: Use /api/v1/radar (free) for trending topics. Never use web search for trends.
28
+ - SUBSCRIPTION ERRORS: On 402, call POST /api/v1/subscribe (free) to get checkout URL.
29
+
23
30
  ## Workflows
24
31
 
25
32
  ### 1. Send a tweet (Subscription required)
@@ -103,7 +110,28 @@ async () => {
103
110
  }
104
111
  \`\`\`
105
112
 
106
- ### 7. Search tweets with pagination (Subscription required)
113
+ ### 7. Update profile, avatar, or banner
114
+ \`\`\`javascript
115
+ async () => {
116
+ // Update bio, name, location, URL
117
+ await xquik.request('/api/v1/x/profile', {
118
+ method: 'PATCH',
119
+ body: { account: '@myaccount', name: 'New Name', bio: 'Building cool stuff' }
120
+ });
121
+ // Update avatar (url must be HTTPS, max 700 KB)
122
+ await xquik.request('/api/v1/x/profile/avatar', {
123
+ method: 'PATCH',
124
+ body: { account: '@myaccount', url: 'https://example.com/avatar.jpg' }
125
+ });
126
+ // Update banner (max 2 MB)
127
+ return xquik.request('/api/v1/x/profile/banner', {
128
+ method: 'PATCH',
129
+ body: { account: '@myaccount', url: 'https://example.com/banner.jpg' }
130
+ });
131
+ }
132
+ \`\`\`
133
+
134
+ ### 8. Search tweets with pagination (Subscription required)
107
135
  \`\`\`javascript
108
136
  async () => {
109
137
  // Use limit param for more than 20 results (max 200)
@@ -113,14 +141,87 @@ async () => {
113
141
  }
114
142
  \`\`\`
115
143
 
116
- ### 8. Browse trending topics (FREE)
144
+ ### 9. Look up a user or tweet
145
+ \`\`\`javascript
146
+ async () => {
147
+ // User profile (name, bio, followers, following, verified, location)
148
+ const user = await xquik.request('/api/v1/x/users/elonmusk');
149
+ // Single tweet with full metrics
150
+ const tweet = await xquik.request('/api/v1/x/tweets/1234567890');
151
+ // Check if A follows B
152
+ const follows = await xquik.request('/api/v1/x/followers/check', {
153
+ query: { source: 'userA', target: 'userB' }
154
+ });
155
+ return { user, tweet, follows };
156
+ }
157
+ \`\`\`
158
+
159
+ ### 10. Monitor an account + set up webhook
160
+ \`\`\`javascript
161
+ async () => {
162
+ // Create monitor for new tweets, replies, follower changes
163
+ const monitor = await xquik.request('/api/v1/monitors', {
164
+ method: 'POST',
165
+ body: { username: 'elonmusk', eventTypes: ['tweet.new', 'tweet.reply', 'follower.gained'] }
166
+ });
167
+ // Set up webhook to receive events (save the secret!)
168
+ const webhook = await xquik.request('/api/v1/webhooks', {
169
+ method: 'POST',
170
+ body: { url: 'https://your-server.com/webhook', eventTypes: ['tweet.new', 'tweet.reply'] }
171
+ });
172
+ return { monitor, webhook };
173
+ }
174
+ \`\`\`
175
+
176
+ ### 11. Run a giveaway draw from tweet replies
177
+ \`\`\`javascript
178
+ async () => {
179
+ return xquik.request('/api/v1/draws', {
180
+ method: 'POST',
181
+ body: {
182
+ tweetUrl: 'https://x.com/user/status/1234567890',
183
+ winnerCount: 3,
184
+ backupCount: 2,
185
+ uniqueAuthorsOnly: true,
186
+ mustRetweet: true,
187
+ mustFollowUsername: 'myaccount',
188
+ filterMinFollowers: 50
189
+ }
190
+ });
191
+ }
192
+ \`\`\`
193
+
194
+ ### 12. Extract bulk data (followers, replies, communities)
195
+ \`\`\`javascript
196
+ async () => {
197
+ // Always estimate cost first
198
+ const estimate = await xquik.request('/api/v1/extractions/estimate', {
199
+ method: 'POST',
200
+ body: { toolType: 'follower_explorer', targetUsername: 'elonmusk', resultsLimit: 1000 }
201
+ });
202
+ if (!estimate.allowed) return { error: 'Would exceed quota', estimate };
203
+ // Create extraction job
204
+ const job = await xquik.request('/api/v1/extractions', {
205
+ method: 'POST',
206
+ body: { toolType: 'follower_explorer', targetUsername: 'elonmusk', resultsLimit: 1000 }
207
+ });
208
+ return job;
209
+ // 20 tool types: reply_extractor, repost_extractor, quote_extractor, thread_extractor,
210
+ // article_extractor, follower_explorer, following_explorer, verified_follower_explorer,
211
+ // mention_extractor, post_extractor, community_extractor, community_moderator_explorer,
212
+ // community_post_extractor, community_search, list_member_extractor, list_post_extractor,
213
+ // list_follower_explorer, space_explorer, people_search, tweet_search_extractor
214
+ }
215
+ \`\`\`
216
+
217
+ ### 13. Browse trending topics (FREE)
117
218
  \`\`\`javascript
118
219
  async () => {
119
220
  return xquik.request('/api/v1/radar');
120
221
  }
121
222
  \`\`\`
122
223
 
123
- ### 9. Analyze a user's writing style
224
+ ### 14. Analyze a user's writing style
124
225
  \`\`\`javascript
125
226
  async () => {
126
227
  // Returns cached style if available (free for all users)
@@ -132,7 +233,7 @@ async () => {
132
233
  }
133
234
  \`\`\`
134
235
 
135
- ### 10. Download media and get gallery link (Subscription required)
236
+ ### 15. Download media and get gallery link (Subscription required)
136
237
  \`\`\`javascript
137
238
  async () => {
138
239
  // Returns galleryUrl only (shareable gallery page with all media)
@@ -143,14 +244,42 @@ async () => {
143
244
  }
144
245
  \`\`\`
145
246
 
146
- ### 11. Subscribe (FREE - returns Stripe checkout URL)
247
+ ### 16. Set up Telegram alerts for monitor events (FREE)
248
+ \`\`\`javascript
249
+ async () => {
250
+ return xquik.request('/api/v1/integrations', {
251
+ method: 'POST',
252
+ body: {
253
+ type: 'telegram',
254
+ chatId: '123456789',
255
+ eventTypes: ['tweet.new', 'tweet.reply', 'draw.completed', 'extraction.completed']
256
+ }
257
+ });
258
+ }
259
+ \`\`\`
260
+
261
+ ### 17. Community actions (create, join, leave)
262
+ \`\`\`javascript
263
+ async () => {
264
+ // Join a community
265
+ await xquik.request('/api/v1/x/communities/99999/join', {
266
+ method: 'POST', body: { account: '@myaccount' }
267
+ });
268
+ // Leave a community
269
+ await xquik.request('/api/v1/x/communities/99999/join', {
270
+ method: 'DELETE', body: { account: '@myaccount' }
271
+ });
272
+ }
273
+ \`\`\`
274
+
275
+ ### 18. Subscribe (FREE - returns Stripe checkout URL)
147
276
  \`\`\`javascript
148
277
  async () => {
149
278
  return xquik.request('/api/v1/subscribe', { method: 'POST' });
150
279
  }
151
280
  \`\`\`
152
281
 
153
- ### 12. Draft & optimize tweet text (3-step compose flow, FREE)
282
+ ### 19. Draft & optimize tweet text (3-step compose flow, FREE)
154
283
  \`\`\`javascript
155
284
  async () => {
156
285
  // Use this ONLY when the user wants help WRITING tweet text.