xapi-to 0.1.18 → 0.1.19
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/LICENSE +21 -0
- package/README.md +51 -10
- package/dist/index.js +384 -46
- package/package.json +9 -2
- package/skills/xapi/SKILL.md +485 -0
- package/skills/xapi/guides/ai.md +200 -0
- package/skills/xapi/guides/ai_gateway.md +263 -0
- package/skills/xapi/guides/crypto.md +197 -0
- package/skills/xapi/guides/douyin.md +297 -0
- package/skills/xapi/guides/google_search.md +194 -0
- package/skills/xapi/guides/linkedin.md +198 -0
- package/skills/xapi/guides/reddit.md +312 -0
- package/skills/xapi/guides/sms.md +186 -0
- package/skills/xapi/guides/tiktok.md +322 -0
- package/skills/xapi/guides/twitter.md +276 -0
- package/skills/xapi/guides/weibo.md +301 -0
- package/skills/xapi/guides/ws_gateway.md +206 -0
- package/skills/xapi/guides/xiaohongshu.md +315 -0
- package/skills/xapi/scripts/download_tweet_videos.sh +125 -0
|
@@ -0,0 +1,322 @@
|
|
|
1
|
+
# TikTok Guide
|
|
2
|
+
|
|
3
|
+
Complete guide for TikTok operations via xAPI — user profiles, videos, comments, search, hashtags, music, live rooms, and recommended feed.
|
|
4
|
+
|
|
5
|
+
> **Dynamic catalog:** These are database-registered third-party APIs under the `tiktok` service. Exact action IDs, HTTP methods, parameters, and response fields can change. Run `search` and `get` before calling; the current schema wins. Examples below reflect one known GET-based version and keep `"method":"GET"` in the input for compatibility.
|
|
6
|
+
|
|
7
|
+
## Contents
|
|
8
|
+
|
|
9
|
+
- [User data](#user-data)
|
|
10
|
+
- [Video data](#video-data)
|
|
11
|
+
- [Search](#search)
|
|
12
|
+
- [Hashtags](#hashtags)
|
|
13
|
+
- [Music](#music)
|
|
14
|
+
- [Live](#live)
|
|
15
|
+
- [Feed](#feed)
|
|
16
|
+
- [Common workflows](#common-workflows)
|
|
17
|
+
- [Pagination](#pagination-patterns)
|
|
18
|
+
- [API reference](#api-reference)
|
|
19
|
+
- [Error handling](#error-handling)
|
|
20
|
+
|
|
21
|
+
## User Data
|
|
22
|
+
|
|
23
|
+
### Get user profile
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
npx xapi-to call tiktok.api_v1_tiktok_app_v3_handler__user__profile \
|
|
27
|
+
--input '{"method":"GET","params":{"unique_id":"tiktok"}}'
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Look up a user by `unique_id` (username), `user_id` (numeric), or `sec_user_id`. At least one must be provided.
|
|
31
|
+
|
|
32
|
+
Returns `data.data.user` with fields: `uid`, `unique_id`, `nickname`, `signature`, `follower_count`, `following_count`, `total_favorited`, `aweme_count`, `avatar_thumb`, `avatar_medium`, `sec_uid`.
|
|
33
|
+
|
|
34
|
+
**Important:** The user profile returns `sec_uid`, but other TikTok APIs expect the parameter name `sec_user_id`. Pass the value of `sec_uid` as `sec_user_id` when calling other endpoints.
|
|
35
|
+
|
|
36
|
+
### Get user_id and sec_user_id by username
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
npx xapi-to call tiktok.api_v1_tiktok_app_v3_get__user__id__and__sec__user__id__by__username \
|
|
40
|
+
--input '{"method":"GET","params":{"username":"tiktok"}}'
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
**Important:** Many TikTok actions require `sec_user_id` instead of the username. Use this endpoint or `handler_user_profile` to get it first.
|
|
44
|
+
|
|
45
|
+
### Get user's videos
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
npx xapi-to call tiktok.api_v1_tiktok_app_v3_fetch__user__post__videos \
|
|
49
|
+
--input '{"method":"GET","params":{"unique_id":"tiktok","count":10}}'
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Can also pass `sec_user_id` instead of `unique_id`. Paginate with `max_cursor` from previous response.
|
|
53
|
+
|
|
54
|
+
Optional parameters:
|
|
55
|
+
- `count` — items per page
|
|
56
|
+
- `sort_type` — sort type
|
|
57
|
+
- `max_cursor` — pagination cursor
|
|
58
|
+
|
|
59
|
+
For faster response with simplified data, use the V3 endpoint: `tiktok.api_v1_tiktok_app_v3_fetch__user__post__videos__v3`.
|
|
60
|
+
|
|
61
|
+
### Get user's liked videos
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
npx xapi-to call tiktok.api_v1_tiktok_app_v3_fetch__user__like__videos \
|
|
65
|
+
--input '{"method":"GET","params":{"sec_user_id":"<sec_user_id>","counts":10}}'
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Requires `sec_user_id`. Paginate with `max_cursor`. Note: the parameter is `counts` (with 's'), not `count`.
|
|
69
|
+
|
|
70
|
+
### Get followers / following
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
# Followers
|
|
74
|
+
npx xapi-to call tiktok.api_v1_tiktok_app_v3_fetch__user__follower__list \
|
|
75
|
+
--input '{"method":"GET","params":{"user_id":"107955","count":20}}'
|
|
76
|
+
|
|
77
|
+
# Following
|
|
78
|
+
npx xapi-to call tiktok.api_v1_tiktok_app_v3_fetch__user__following__list \
|
|
79
|
+
--input '{"method":"GET","params":{"user_id":"107955","count":20}}'
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Pass either `user_id` or `sec_user_id`. Paginate with `min_time` and `page_token` from previous response.
|
|
83
|
+
|
|
84
|
+
### Get similar user recommendations
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
npx xapi-to call tiktok.api_v1_tiktok_app_v3_fetch__similar__user__recommendations \
|
|
88
|
+
--input '{"method":"GET","params":{"user_id":"107955"}}'
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## Video Data
|
|
92
|
+
|
|
93
|
+
### Get video by ID
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
npx xapi-to call tiktok.api_v1_tiktok_app_v3_fetch__one__video__v2 \
|
|
97
|
+
--input '{"method":"GET","params":{"aweme_id":"<video_id>"}}'
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
The `aweme_id` is the numeric video ID. Returns full video data including `desc`, `statistics`, `author`, `music`, `video` (with play URLs).
|
|
101
|
+
|
|
102
|
+
### Get video by share URL
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
npx xapi-to call tiktok.api_v1_tiktok_app_v3_fetch__one__video__by__share__url__v2 \
|
|
106
|
+
--input '{"method":"GET","params":{"share_url":"https://www.tiktok.com/@user/video/1234567890"}}'
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### Batch get videos
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
npx xapi-to call tiktok.api_v1_tiktok_app_v3_fetch__multi__video__v2 \
|
|
113
|
+
--input '{"method":"GET","params":{"aweme_ids":"id1,id2,id3"}}'
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### Get video comments
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
npx xapi-to call tiktok.api_v1_tiktok_app_v3_fetch__video__comments \
|
|
120
|
+
--input '{"method":"GET","params":{"aweme_id":"<video_id>","count":20,"cursor":0}}'
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
Paginate with `cursor`.
|
|
124
|
+
|
|
125
|
+
### Get comment replies
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
npx xapi-to call tiktok.api_v1_tiktok_app_v3_fetch__video__comment__replies \
|
|
129
|
+
--input '{"method":"GET","params":{"item_id":"<video_id>","comment_id":"<comment_id>","count":20,"cursor":0}}'
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
## Search
|
|
133
|
+
|
|
134
|
+
### General search (comprehensive)
|
|
135
|
+
|
|
136
|
+
```bash
|
|
137
|
+
npx xapi-to call tiktok.api_v1_tiktok_app_v3_fetch__general__search__result \
|
|
138
|
+
--input '{"method":"GET","params":{"keyword":"cat","count":10}}'
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
Returns mixed results (videos, users, hashtags). Paginate with `offset`.
|
|
142
|
+
|
|
143
|
+
Optional parameters:
|
|
144
|
+
- `sort_type` — sort type
|
|
145
|
+
- `publish_time` — publish time filter
|
|
146
|
+
|
|
147
|
+
### Video search
|
|
148
|
+
|
|
149
|
+
```bash
|
|
150
|
+
npx xapi-to call tiktok.api_v1_tiktok_app_v3_fetch__video__search__result \
|
|
151
|
+
--input '{"method":"GET","params":{"keyword":"cooking","count":10}}'
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
Optional: `region`, `sort_type`, `publish_time`. Paginate with `offset`.
|
|
155
|
+
|
|
156
|
+
### User search
|
|
157
|
+
|
|
158
|
+
```bash
|
|
159
|
+
npx xapi-to call tiktok.api_v1_tiktok_app_v3_fetch__user__search__result \
|
|
160
|
+
--input '{"method":"GET","params":{"keyword":"chef","count":10}}'
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
Optional filters: `user_search_follower_count`, `user_search_profile_type`. Paginate with `offset`.
|
|
164
|
+
|
|
165
|
+
### Music search
|
|
166
|
+
|
|
167
|
+
```bash
|
|
168
|
+
npx xapi-to call tiktok.api_v1_tiktok_app_v3_fetch__music__search__result \
|
|
169
|
+
--input '{"method":"GET","params":{"keyword":"pop","count":10}}'
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
Optional: `region`, `filter_by`, `sort_type`. Paginate with `offset`.
|
|
173
|
+
|
|
174
|
+
### Hashtag search
|
|
175
|
+
|
|
176
|
+
```bash
|
|
177
|
+
npx xapi-to call tiktok.api_v1_tiktok_app_v3_fetch__hashtag__search__result \
|
|
178
|
+
--input '{"method":"GET","params":{"keyword":"dance","count":10}}'
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
Paginate with `offset`.
|
|
182
|
+
|
|
183
|
+
## Hashtags
|
|
184
|
+
|
|
185
|
+
### Get hashtag details
|
|
186
|
+
|
|
187
|
+
```bash
|
|
188
|
+
npx xapi-to call tiktok.api_v1_tiktok_app_v3_fetch__hashtag__detail \
|
|
189
|
+
--input '{"method":"GET","params":{"ch_id":"<hashtag_id>"}}'
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
### Get hashtag video list
|
|
193
|
+
|
|
194
|
+
```bash
|
|
195
|
+
npx xapi-to call tiktok.api_v1_tiktok_app_v3_fetch__hashtag__video__list \
|
|
196
|
+
--input '{"method":"GET","params":{"ch_id":"<hashtag_id>","count":20,"cursor":0}}'
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
Paginate with `cursor`.
|
|
200
|
+
|
|
201
|
+
## Music
|
|
202
|
+
|
|
203
|
+
### Get music details
|
|
204
|
+
|
|
205
|
+
```bash
|
|
206
|
+
npx xapi-to call tiktok.api_v1_tiktok_app_v3_fetch__music__detail \
|
|
207
|
+
--input '{"method":"GET","params":{"music_id":"<music_id>"}}'
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
### Get videos using a music
|
|
211
|
+
|
|
212
|
+
```bash
|
|
213
|
+
npx xapi-to call tiktok.api_v1_tiktok_app_v3_fetch__music__video__list \
|
|
214
|
+
--input '{"method":"GET","params":{"music_id":"<music_id>","count":20,"cursor":0}}'
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
Paginate with `cursor`.
|
|
218
|
+
|
|
219
|
+
## Live
|
|
220
|
+
|
|
221
|
+
### Get live room info
|
|
222
|
+
|
|
223
|
+
```bash
|
|
224
|
+
npx xapi-to call tiktok.api_v1_tiktok_app_v3_fetch__live__room__info \
|
|
225
|
+
--input '{"method":"GET","params":{"room_id":"<room_id>"}}'
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
### Check if live room is online
|
|
229
|
+
|
|
230
|
+
```bash
|
|
231
|
+
npx xapi-to call tiktok.api_v1_tiktok_app_v3_check__live__room__online \
|
|
232
|
+
--input '{"method":"GET","params":{"room_id":"<room_id>"}}'
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
### Batch check live rooms online
|
|
236
|
+
|
|
237
|
+
```bash
|
|
238
|
+
npx xapi-to call tiktok.api_v1_tiktok_app_v3_check__live__room__online__batch \
|
|
239
|
+
--input '{"method":"GET","params":{"room_ids":"id1,id2,id3"}}'
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
### Get live search results
|
|
243
|
+
|
|
244
|
+
```bash
|
|
245
|
+
npx xapi-to call tiktok.api_v1_tiktok_app_v3_fetch__live__search__result \
|
|
246
|
+
--input '{"method":"GET","params":{"keyword":"gaming"}}'
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
## Feed
|
|
250
|
+
|
|
251
|
+
### Get home feed (recommended videos)
|
|
252
|
+
|
|
253
|
+
```bash
|
|
254
|
+
npx xapi-to call tiktok.api_v1_tiktok_app_v3_fetch__home__feed \
|
|
255
|
+
--input '{"method":"GET","params":{}}'
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
Returns recommended "For You" page videos. **Note:** This endpoint may return empty results depending on account/region configuration.
|
|
259
|
+
|
|
260
|
+
## Common Workflows
|
|
261
|
+
|
|
262
|
+
### Research a TikTok creator
|
|
263
|
+
|
|
264
|
+
1. Look up user: `tiktok...handler__user__profile` with `unique_id` → get `uid`, `sec_user_id`, follower stats
|
|
265
|
+
2. Get videos: `tiktok...fetch__user__post__videos` → browse recent content
|
|
266
|
+
3. Check engagement: view `statistics` in each video (play count, likes, comments, shares)
|
|
267
|
+
|
|
268
|
+
### Analyze a TikTok video
|
|
269
|
+
|
|
270
|
+
1. Get video: `tiktok...fetch__one__video__v2` with `aweme_id` → full video data
|
|
271
|
+
2. Read comments: `tiktok...fetch__video__comments` → top comments
|
|
272
|
+
3. Get replies: `tiktok...fetch__video__comment__replies` → comment threads
|
|
273
|
+
|
|
274
|
+
### Discover content by hashtag
|
|
275
|
+
|
|
276
|
+
1. Search hashtags: `tiktok...fetch__hashtag__search__result` with `keyword` → find hashtag IDs
|
|
277
|
+
2. Get details: `tiktok...fetch__hashtag__detail` with `ch_id` → view count, video count
|
|
278
|
+
3. Browse videos: `tiktok...fetch__hashtag__video__list` → videos using this hashtag
|
|
279
|
+
|
|
280
|
+
## Pagination Patterns
|
|
281
|
+
|
|
282
|
+
| Pattern | Endpoints | How to use |
|
|
283
|
+
|---------|-----------|------------|
|
|
284
|
+
| `max_cursor` | user videos, liked videos | Pass `max_cursor` from previous response |
|
|
285
|
+
| `cursor` | comments, hashtag videos, music videos | Pass `cursor` from previous response |
|
|
286
|
+
| `offset` | all search endpoints | Increment by `count` each page |
|
|
287
|
+
| `min_time` + `page_token` | follower/following lists | Pass both from previous response |
|
|
288
|
+
|
|
289
|
+
## API Reference
|
|
290
|
+
|
|
291
|
+
| API (prefix: `tiktok.api_v1_tiktok_app_v3_`) | Description | Key Params |
|
|
292
|
+
|---|---|---|
|
|
293
|
+
| `handler__user__profile` | Get user profile | `unique_id` or `user_id` or `sec_user_id` |
|
|
294
|
+
| `get__user__id__and__sec__user__id__by__username` | Get IDs by username | `username` |
|
|
295
|
+
| `fetch__user__post__videos` | User's videos | `unique_id` or `sec_user_id`, `count`, `max_cursor` |
|
|
296
|
+
| `fetch__user__post__videos__v3` | User's videos (simplified) | `unique_id` or `sec_user_id`, `count`, `max_cursor` |
|
|
297
|
+
| `fetch__user__like__videos` | User's liked videos | `sec_user_id`, `counts`, `max_cursor` |
|
|
298
|
+
| `fetch__user__follower__list` | User's followers | `user_id` or `sec_user_id`, `count` |
|
|
299
|
+
| `fetch__user__following__list` | User's following | `user_id` or `sec_user_id`, `count` |
|
|
300
|
+
| `fetch__one__video__v2` | Single video | `aweme_id` |
|
|
301
|
+
| `fetch__one__video__by__share__url__v2` | Video by share URL | `share_url` |
|
|
302
|
+
| `fetch__multi__video__v2` | Batch get videos | `aweme_ids` |
|
|
303
|
+
| `fetch__video__comments` | Video comments | `aweme_id`, `count`, `cursor` |
|
|
304
|
+
| `fetch__video__comment__replies` | Comment replies | `item_id`, `comment_id`, `count`, `cursor` |
|
|
305
|
+
| `fetch__general__search__result` | General search | `keyword`, `count`, `offset` |
|
|
306
|
+
| `fetch__video__search__result` | Video search | `keyword`, `count`, `offset` |
|
|
307
|
+
| `fetch__user__search__result` | User search | `keyword`, `count`, `offset` |
|
|
308
|
+
| `fetch__music__search__result` | Music search | `keyword`, `count`, `offset` |
|
|
309
|
+
| `fetch__hashtag__search__result` | Hashtag search | `keyword`, `count`, `offset` |
|
|
310
|
+
| `fetch__hashtag__detail` | Hashtag details | `ch_id` |
|
|
311
|
+
| `fetch__hashtag__video__list` | Hashtag videos | `ch_id`, `count`, `cursor` |
|
|
312
|
+
| `fetch__music__detail` | Music details | `music_id` |
|
|
313
|
+
| `fetch__music__video__list` | Music videos | `music_id`, `count`, `cursor` |
|
|
314
|
+
| `fetch__live__room__info` | Live room info | `room_id` |
|
|
315
|
+
| `check__live__room__online` | Check live online | `room_id` |
|
|
316
|
+
| `fetch__home__feed` | Home feed | — |
|
|
317
|
+
|
|
318
|
+
## Error Handling
|
|
319
|
+
|
|
320
|
+
- **Missing sec_user_id** → Use `handler_user_profile` or `get_user_id_and_sec_user_id_by_username` to get it first
|
|
321
|
+
- **Empty results** → Check that `aweme_id`, `ch_id`, or `music_id` is valid
|
|
322
|
+
- **Pagination exhausted** → When `has_more` is `0` or `false`, no more pages available
|
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
# Twitter / X Guide
|
|
2
|
+
|
|
3
|
+
Complete guide for Twitter operations via xAPI — reading data, downloading tweet videos, posting tweets, replying, and OAuth setup.
|
|
4
|
+
|
|
5
|
+
> **Upstream provider:** All `twitter.*` capabilities accept an optional `provider` — `"x"` (fapi.uk, the default) or `"twitter"` (legacy upstream). The response is normalized to an identical structure regardless of provider, so you normally omit it. Pass `"provider":"twitter"` only to force the legacy upstream, e.g. `--input '{"screen_name":"elonmusk","provider":"twitter"}'`.
|
|
6
|
+
|
|
7
|
+
## Contents
|
|
8
|
+
|
|
9
|
+
- [Read Twitter data](#reading-twitter-data-no-oauth-needed)
|
|
10
|
+
- [Download a tweet video](#download-a-tweet-video)
|
|
11
|
+
- [Post and mutate with OAuth](#posting-tweets-oauth-required)
|
|
12
|
+
- [Common workflows](#common-workflows)
|
|
13
|
+
- [Pagination reference](#pagination-reference)
|
|
14
|
+
- [API reference](#api-reference)
|
|
15
|
+
- [Error handling](#error-handling)
|
|
16
|
+
|
|
17
|
+
## Reading Twitter Data (no OAuth needed)
|
|
18
|
+
|
|
19
|
+
### Look up a user by @handle
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
npx xapi-to call twitter.user_by_screen_name --input '{"screen_name":"elonmusk"}'
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Returns `rest_id` (numeric user ID), `name`, `screen_name`, `followers_count`, `statuses_count`, etc.
|
|
26
|
+
|
|
27
|
+
**Important:** Most Twitter actions require the numeric `user_id` (called `rest_id` in the response), not the @handle. Always look up the user first to get the ID.
|
|
28
|
+
|
|
29
|
+
### Get a user's recent tweets
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
npx xapi-to call twitter.user_tweets --input '{"user_id":"44196397"}'
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Each tweet includes: `id`, `full_text`, `created_at`, `favorite_count`, `retweet_count`, `reply_count`, `views_count`, `media`, `author`, and `quoted_tweet` if applicable.
|
|
36
|
+
|
|
37
|
+
Paginate with the previous response's `data.cursors.bottom`:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
npx xapi-to call twitter.user_tweets \
|
|
41
|
+
--input '{"user_id":"44196397","cursor":"<cursors.bottom>"}'
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### Get a user's tweets and replies
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
npx xapi-to call twitter.user_tweets_and_replies --input '{"user_id":"44196397"}'
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Similar to `twitter.user_tweets`, but the timeline also includes the user's replies to other tweets and conversation threads they participate in. Each item includes the same fields: `id`, `full_text`, `created_at`, `favorite_count`, `retweet_count`, `reply_count`, `views_count`, `media`, `author`, and `quoted_tweet` if applicable.
|
|
51
|
+
|
|
52
|
+
**When to choose which:**
|
|
53
|
+
|
|
54
|
+
- `twitter.user_tweets` — only the user's own posts. Use for content/timeline of original tweets.
|
|
55
|
+
- `twitter.user_tweets_and_replies` — posts plus replies and conversation participants. Use to monitor a user's reply activity or full timeline.
|
|
56
|
+
|
|
57
|
+
**Filter tip:** because conversation entries can contain tweets from other authors, filter by `author.id === user_id` if you only want the monitored user's content.
|
|
58
|
+
|
|
59
|
+
Pagination uses the same `cursor` → `data.cursors.bottom` pattern as `twitter.user_tweets`.
|
|
60
|
+
|
|
61
|
+
For `twitter.user_tweets` and `twitter.user_tweets_and_replies`, set `"cache":true` to use the fast cache when available and skip the normal upstream call. Cached results can be less fresh; keep the default `false` when freshness matters.
|
|
62
|
+
|
|
63
|
+
### Get a specific tweet and its replies
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
npx xapi-to call twitter.tweet_detail --input '{"tweet_id":"2035526376468394305"}'
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
To load more replies, pass the previous response's `data.cursors.bottom` as `cursor`:
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
npx xapi-to call twitter.tweet_detail \
|
|
73
|
+
--input '{"tweet_id":"2035526376468394305","cursor":"<cursors.bottom>"}'
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Paginated pages commonly contain more `replies` but no main tweet, so `data.tweet` may be `null` when `cursor` is present.
|
|
77
|
+
|
|
78
|
+
### Download a tweet video
|
|
79
|
+
|
|
80
|
+
Use the bundled downloader with either a complete status URL or its numeric tweet ID. Resolve `<xapi-skill-directory>` to the directory containing this guide's parent `SKILL.md`:
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
bash <xapi-skill-directory>/scripts/download_tweet_videos.sh \
|
|
84
|
+
'https://x.com/NousResearch/status/2084325600643445095'
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Pass an optional existing output directory as the second argument; otherwise files are written to the current directory. A single video is named `tweet-<tweet-id>.mp4`; multiple videos are numbered `tweet-<tweet-id>-1.mp4`, `-2.mp4`, and so on. The script includes videos in the main, quoted, and retweeted tweets, deduplicates identical media URLs, and refuses to overwrite any existing output.
|
|
88
|
+
|
|
89
|
+
The script verifies that the deployed `twitter.tweet_detail` schema exposes `video_url` before making the paid call. It omits `provider` to retain automatic failover from the default `x` upstream to the legacy `twitter` upstream on transient failures. The response's `data.provider` identifies the upstream that served it; explicitly setting `provider` would pin that upstream and disable failover.
|
|
90
|
+
|
|
91
|
+
Each download is written to a same-directory temporary file, required to have MIME type `video/mp4`, optionally checked with `ffprobe`, and only renamed to its final path after every media file passes. Failures clean up temporary files, so a partial transfer is never published as the final MP4.
|
|
92
|
+
|
|
93
|
+
`data.tweet.media[].url` and `preview_url` are preview images; do not download them as MP4. The optional `video_info.variants` retains the original MP4 and HLS variants when a specific rendition is needed. `call --output` is not appropriate because the xAPI action returns JSON metadata rather than video bytes; the bundled script downloads each resolved `video_url` with `curl`.
|
|
94
|
+
|
|
95
|
+
### Read an X Article (long-form post)
|
|
96
|
+
|
|
97
|
+
Some tweets are long-form **X Articles**. `twitter.tweet_detail` detects them and returns the full normalized article directly in `data.tweet.article`; no raw GraphQL call or `fieldToggles` parameter is needed.
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
npx xapi-to call twitter.tweet_detail --input '{"tweet_id":"<tweet_id>"}'
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
The normalized `article` object contains:
|
|
104
|
+
|
|
105
|
+
- `id`, `title`, and `preview_text`
|
|
106
|
+
- `text` — full plain text
|
|
107
|
+
- `markdown` — full text with headings, lists, quotes, code blocks, and inline links preserved
|
|
108
|
+
- `cover_image` — URL and optional dimensions
|
|
109
|
+
- `links` — deduplicated external links in appearance order
|
|
110
|
+
- `first_published_at` and `modified_at` — ISO 8601 timestamps when available
|
|
111
|
+
|
|
112
|
+
Use the **tweet ID** from the share URL (`x.com/<user>/status/<tweet_id>` or `x.com/<user>/article/<tweet_id>`), not an internal article ID.
|
|
113
|
+
|
|
114
|
+
### Search tweets
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
npx xapi-to call twitter.search --input '{"raw_query":"AI agents","count":20}'
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
For `provider: "x"` (the default), structured advanced-search filters are also available:
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
npx xapi-to call twitter.search --input '{
|
|
124
|
+
"raw_query":"AI",
|
|
125
|
+
"from":"OpenAI",
|
|
126
|
+
"mentioning":"AnthropicAI",
|
|
127
|
+
"phrase":"AI agents",
|
|
128
|
+
"since":"2026-08-01",
|
|
129
|
+
"until":"2026-08-05",
|
|
130
|
+
"min_likes":100,
|
|
131
|
+
"min_replies":10,
|
|
132
|
+
"min_retweets":20,
|
|
133
|
+
"count":20
|
|
134
|
+
}'
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
Supported structured filters: `from`, `to`, `mentioning`, `phrase`, `any`, `none`, `tag`, `since`, `until`, `min_replies`, `min_likes`, `min_retweets`, and `count`. `sort_by` accepts `Top`, `Latest` (default), `People`, `Photos`, or `Videos`; the default `x` provider maps both media-specific values to its combined Media search. Dates use `YYYY-MM-DD`; `until` is exclusive. Paginate with `cursor` from `data.cursor_bottom`.
|
|
138
|
+
|
|
139
|
+
### Get user's media posts
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
npx xapi-to call twitter.user_media --input '{"user_id":"44196397"}'
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
Paginate with `cursor` from the previous response's `data.cursor_bottom`. Both the default `x` provider and legacy `twitter` provider are supported.
|
|
146
|
+
|
|
147
|
+
### Get followers / following
|
|
148
|
+
|
|
149
|
+
```bash
|
|
150
|
+
npx xapi-to call twitter.followers --input '{"user_id":"44196397"}'
|
|
151
|
+
npx xapi-to call twitter.following --input '{"user_id":"44196397"}'
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### Get retweeters
|
|
155
|
+
|
|
156
|
+
```bash
|
|
157
|
+
npx xapi-to call twitter.retweeters --input '{"tweet_id":"1234567890"}'
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
## Posting Tweets (OAuth required)
|
|
161
|
+
|
|
162
|
+
Posting, replying, quoting, liking, retweeting, and deleting require OAuth. A saved binding provides technical authorization, not standing user consent: confirm the current content and target before a write, and obtain explicit confirmation before destructive or bulk actions.
|
|
163
|
+
|
|
164
|
+
### Step 1: Bind Twitter OAuth
|
|
165
|
+
|
|
166
|
+
```bash
|
|
167
|
+
npx xapi-to oauth bind --provider twitter
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
This opens a browser for the user to authorize. After authorization, the binding is saved to the API key.
|
|
171
|
+
|
|
172
|
+
Verify:
|
|
173
|
+
|
|
174
|
+
```bash
|
|
175
|
+
npx xapi-to oauth status
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
Should show `tweet.write` in scopes.
|
|
179
|
+
|
|
180
|
+
### Step 2: Post a tweet
|
|
181
|
+
|
|
182
|
+
```bash
|
|
183
|
+
npx xapi-to call x-official.2_tweets --method POST \
|
|
184
|
+
--input '{"body":{"text":"Hello from my AI agent!"}}'
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
**Character limit:** 280 characters (140 CJK characters). Each CJK character counts as 2.
|
|
188
|
+
|
|
189
|
+
### Reply to a tweet
|
|
190
|
+
|
|
191
|
+
```bash
|
|
192
|
+
npx xapi-to call x-official.2_tweets --method POST \
|
|
193
|
+
--input '{"body":{"text":"Great point!","reply":{"in_reply_to_tweet_id":"2035526376468394305"}}}'
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
### Quote tweet
|
|
197
|
+
|
|
198
|
+
```bash
|
|
199
|
+
npx xapi-to call x-official.2_tweets --method POST \
|
|
200
|
+
--input '{"body":{"text":"Worth reading 👇","quote_tweet_id":"2035526376468394305"}}'
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
### Delete a tweet
|
|
204
|
+
|
|
205
|
+
```bash
|
|
206
|
+
npx xapi-to call x-official.2_tweets_id --method DELETE \
|
|
207
|
+
--input '{"pathParams":{"id":"2036012345678901234"}}'
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
### Like a tweet
|
|
211
|
+
|
|
212
|
+
```bash
|
|
213
|
+
npx xapi-to call x-official.2_users_id_likes --method POST \
|
|
214
|
+
--input '{"pathParams":{"id":"<your_user_id>"},"body":{"tweet_id":"2035526376468394305"}}'
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
### Retweet
|
|
218
|
+
|
|
219
|
+
```bash
|
|
220
|
+
npx xapi-to call x-official.2_users_id_retweets --method POST \
|
|
221
|
+
--input '{"pathParams":{"id":"<your_user_id>"},"body":{"tweet_id":"2035526376468394305"}}'
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
## Common Workflows
|
|
225
|
+
|
|
226
|
+
### Research and tweet
|
|
227
|
+
|
|
228
|
+
1. Search the web: `web.search.realtime` → get latest news
|
|
229
|
+
2. Summarize: `ai.text.summarize` → create a concise summary
|
|
230
|
+
3. Post: `x-official.2_tweets` POST → tweet the summary
|
|
231
|
+
|
|
232
|
+
### Monitor and reply
|
|
233
|
+
|
|
234
|
+
1. Get user activity: `twitter.user_tweets` (originals only) or `twitter.user_tweets_and_replies` (includes replies) → check latest posts
|
|
235
|
+
2. Get tweet detail: `twitter.tweet_detail` → read the thread
|
|
236
|
+
3. Reply: `x-official.2_tweets` POST with `reply` → respond
|
|
237
|
+
|
|
238
|
+
## Pagination Reference
|
|
239
|
+
|
|
240
|
+
| Capability | Next cursor field | Next request input |
|
|
241
|
+
|---|---|---|
|
|
242
|
+
| `twitter.user_tweets` | `data.cursors.bottom` | `cursor` |
|
|
243
|
+
| `twitter.user_tweets_and_replies` | `data.cursors.bottom` | `cursor` |
|
|
244
|
+
| `twitter.tweet_detail` replies | `data.cursors.bottom` | `cursor` |
|
|
245
|
+
| `twitter.user_media` | `data.cursor_bottom` | `cursor` |
|
|
246
|
+
| `twitter.search` | `data.cursor_bottom` | `cursor` |
|
|
247
|
+
| `twitter.followers` | `data.cursor_bottom` | `cursor` |
|
|
248
|
+
| `twitter.following` | `data.cursor_bottom` | `cursor` |
|
|
249
|
+
| `twitter.retweeters` | `data.cursor_bottom` | `cursor` |
|
|
250
|
+
|
|
251
|
+
Omit `cursor` for the first page. Stop when the relevant bottom cursor is absent or empty.
|
|
252
|
+
|
|
253
|
+
## API Reference
|
|
254
|
+
|
|
255
|
+
| API | Method | Description |
|
|
256
|
+
|-----------|--------|-------------|
|
|
257
|
+
| `twitter.user_by_screen_name` | — | Look up user by @handle |
|
|
258
|
+
| `twitter.user_tweets` | — | Get and paginate user's recent tweets |
|
|
259
|
+
| `twitter.user_tweets_and_replies` | — | Get and paginate user's tweets and replies |
|
|
260
|
+
| `twitter.user_media` | — | Get and paginate user's media posts |
|
|
261
|
+
| `twitter.tweet_detail` | — | Get tweet, full X Article content, and paginated replies |
|
|
262
|
+
| `twitter.search` | — | Search tweets with cursor and advanced filters |
|
|
263
|
+
| `twitter.followers` | — | Get user's followers |
|
|
264
|
+
| `twitter.following` | — | Get user's following |
|
|
265
|
+
| `twitter.retweeters` | — | Get tweet retweeters |
|
|
266
|
+
| `x-official.2_tweets` | POST | Post a tweet |
|
|
267
|
+
| `x-official.2_tweets_id` | DELETE | Delete a tweet |
|
|
268
|
+
| `x-official.2_users_id_likes` | POST | Like a tweet |
|
|
269
|
+
| `x-official.2_users_id_retweets` | POST | Retweet |
|
|
270
|
+
|
|
271
|
+
## Error Handling
|
|
272
|
+
|
|
273
|
+
- **OAuth Required** → Run `npx xapi-to oauth bind --provider twitter`
|
|
274
|
+
- **403 Forbidden** → Twitter account may have restrictions; check account status
|
|
275
|
+
- **Tweet too long** → Shorten to 280 chars (140 CJK)
|
|
276
|
+
- **User not found** → Check the screen_name spelling
|