xapi-to 0.1.18 → 0.1.20
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 +258 -10
- package/dist/chunk-TYY6JR6O.js +870 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1256 -590
- package/dist/openai-sandbox-client.d.ts +85 -0
- package/dist/openai-sandbox-client.js +285 -0
- package/examples/openai-agents-sandbox-local.ts +131 -0
- package/examples/sandbox-api-cli-openai.mjs +450 -0
- package/package.json +33 -4
- package/scripts/openai-sandbox-agent-e2e.ts +219 -0
- package/scripts/sandbox-playground-e2e.mjs +463 -0
- package/skills/xapi/SKILL.md +498 -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 +253 -0
- package/skills/xapi/guides/reddit.md +312 -0
- package/skills/xapi/guides/sandbox.md +466 -0
- package/skills/xapi/guides/serper.md +124 -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
- package/src/client.ts +664 -0
- package/src/config.ts +160 -0
- package/src/openai-sandbox-client.ts +349 -0
- package/src/sandbox-client.ts +289 -0
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
# LinkedIn Guide
|
|
2
|
+
|
|
3
|
+
Complete guide for LinkedIn operations via xAPI — person profiles with career history, company pages, posts and comments, and job search.
|
|
4
|
+
|
|
5
|
+
> **Dynamic catalog:** These are database-registered third-party APIs under the `linkedin` service. Exact action IDs, HTTP methods, parameters, response fields, charging, and retry behavior can change. Run `search` and `get` before calling; the current schema and live response win. Examples below reflect the `linkedin_web v2` version and keep `"method":"GET"` in the input for compatibility.
|
|
6
|
+
|
|
7
|
+
## Contents
|
|
8
|
+
|
|
9
|
+
- [Key concept: everything is addressed by URL](#key-concept-everything-is-addressed-by-url)
|
|
10
|
+
- [Person data](#person-data)
|
|
11
|
+
- [When `experience` and `education` come back `null`](#when-experience-and-education-come-back-null)
|
|
12
|
+
- [Company data](#company-data)
|
|
13
|
+
- [Posts and comments](#posts-and-comments)
|
|
14
|
+
- [Jobs](#jobs)
|
|
15
|
+
- [Common workflows](#common-workflows)
|
|
16
|
+
- [Pagination](#pagination)
|
|
17
|
+
- [API reference](#api-reference)
|
|
18
|
+
- [Error handling](#error-handling)
|
|
19
|
+
|
|
20
|
+
## Key Concept: everything is addressed by URL
|
|
21
|
+
|
|
22
|
+
Every `linkedin_web v2` endpoint except job search is addressed by an ordinary public LinkedIn page URL passed as `url`. There is no separate ID-resolution step: paste the URL you would open in a browser. The one extra parameter is `urn` on [post comments](#get-comments-on-a-post), and it is derived from the post URL.
|
|
23
|
+
|
|
24
|
+
| Resource | URL shape |
|
|
25
|
+
|----------|-----------|
|
|
26
|
+
| Person | `https://www.linkedin.com/in/<vanity>/` |
|
|
27
|
+
| Company | `https://www.linkedin.com/company/<slug>/` |
|
|
28
|
+
| Post | `https://www.linkedin.com/feed/update/urn:li:activity:<id>/` or `https://www.linkedin.com/posts/<slug>-activity-<id>-<hash>` |
|
|
29
|
+
| Job | `https://www.linkedin.com/jobs/view/<job_id>` |
|
|
30
|
+
|
|
31
|
+
Discover the current endpoint set before relying on any list here:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
npx xapi-to search "linkedin" --source api
|
|
35
|
+
npx xapi-to get linkedin.api_v1_linkedin_web__v2_get__user__profile
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Person Data
|
|
39
|
+
|
|
40
|
+
### Get a profile
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
npx xapi-to call linkedin.api_v1_linkedin_web__v2_get__user__profile \
|
|
44
|
+
--input '{"method":"GET","params":{"url":"https://www.linkedin.com/in/williamhgates/"}}'
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
One call returns the whole profile — no follow-up requests for individual sections. `data.data` contains:
|
|
48
|
+
|
|
49
|
+
- Identity: `name`, `first_name`, `last_name`, `id` (vanity), `linkedin_id`, `linkedin_num_id`, `url`, `avatar`, `banner_image`, `influencer`
|
|
50
|
+
- Headline & summary: `position`, `about`, `unformatted_about`, `bio_links`
|
|
51
|
+
- Location: `city`, `location`, `country_code`
|
|
52
|
+
- Career: `experience[]`, `current_company`, `current_company_name`, `current_company_company_id`
|
|
53
|
+
- Education: `education[]`, `educations_details`
|
|
54
|
+
- Recognition: `honors_and_awards[]`
|
|
55
|
+
- Social proof: `followers`, `connections`, `activity[]`, `posts[]`
|
|
56
|
+
- Discovery: `people_also_viewed[]`, `similar_profiles[]`
|
|
57
|
+
|
|
58
|
+
There are no separate `get__user__experience` / `educations` / `skills` / `honors` / `publications` endpoints in v2 — that was the older `username` → `urn` two-step API. If you were using those IDs, they now return `Action not found`.
|
|
59
|
+
|
|
60
|
+
### When `experience` and `education` come back `null`
|
|
61
|
+
|
|
62
|
+
`get__user__profile` reads the **logged-out** public page. LinkedIn renders the full career and school sections there only for creator/open profiles; on an ordinary member's page it serves a trimmed topcard. The call still succeeds with `code: 200`, so the failure is silent — you get identity, `current_company`, `educations_details`, `followers`, and `people_also_viewed`, but:
|
|
63
|
+
|
|
64
|
+
```json
|
|
65
|
+
{ "position": null, "experience": null, "education": null, "about": "Don't use LinkedIn that much…" }
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
`null` here means **not rendered to logged-out visitors**, not "this person has no jobs listed". A truncated `about` ending in `…` is the same signal. Never summarize a person's background from a response in this state, and never report the profile as private or empty — fall back:
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
npx xapi-to call icypeas-email.api_scrape_profile \
|
|
72
|
+
--input '{"method":"GET","params":{"url":"https://www.linkedin.com/in/ricky-wang-74b3a0194/"}}'
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
This returns a differently-shaped payload under `data.result`:
|
|
76
|
+
|
|
77
|
+
| Field | Contents |
|
|
78
|
+
|---|---|
|
|
79
|
+
| `worksFor[]` | Current positions — `jobTitle`, `startDate`, `description`, nested `company` (industry, size, website, HQ) |
|
|
80
|
+
| `alumniOf[]` | Past positions — same shape plus `endDate` |
|
|
81
|
+
| `educations[]` | `name`, `degree`, `fieldsOfStudy[]`, `description` |
|
|
82
|
+
| `headline`, `description` | Headline and the full untruncated About text |
|
|
83
|
+
| `firstname`, `lastname`, `address`, `numOfConnections`, `skills[]`, `languages[]` | Identity and profile detail |
|
|
84
|
+
|
|
85
|
+
Check `data.status` before reading `data.result`: `FOUND` means real data, `NOT_FOUND` means `result` is `null` and this source has nothing for that URL either. Two caveats worth carrying into any summary: the snapshot is cached, so `headline` can lag the person's current role, and `startDate`/`endDate` are year-granular (often stamped to January), so treat them as approximate. `jobTitle` also reflects whatever the member typed, which can disagree with a company's own announcement — prefer cross-checking a role against `web.search` before asserting a title.
|
|
86
|
+
|
|
87
|
+
Do not reach for `contactout-api.v1_linkedin_enrich` as a fallback. Without a separate ContactOut contract it returns a fully-populated **sample profile** (`"Example Person"` at `"Legros, Smitham and Kessler"`) with `status_code: 200`, which is easy to mistake for real data, and it is the most expensive LinkedIn-adjacent action in the catalog.
|
|
88
|
+
|
|
89
|
+
### Person profile decision path
|
|
90
|
+
|
|
91
|
+
```
|
|
92
|
+
get__user__profile
|
|
93
|
+
├─ experience[] present → done, use it
|
|
94
|
+
└─ experience/education == null → icypeas-email.api_scrape_profile
|
|
95
|
+
├─ status == FOUND → read worksFor / alumniOf / educations
|
|
96
|
+
└─ status == NOT_FOUND → say the career history is unavailable;
|
|
97
|
+
fall back to web.search for public
|
|
98
|
+
bios, or twitter.user_by_screen_name
|
|
99
|
+
when the person came from an X handle
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### Get a person's posts
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
npx xapi-to call linkedin.api_v1_linkedin_web__v2_get__user__posts \
|
|
106
|
+
--input '{"method":"GET","params":{"url":"https://www.linkedin.com/in/williamhgates/","page":1}}'
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
Returns `data.data.data[]` plus `data.data.paging`. Each item carries `urn`, `post_url`, `text`, `time`/`posted`, `poster`, `images[]`, and a reaction breakdown (`num_likes`, `num_comments`, `num_reposts`, `num_reactions`, `num_empathy`, `num_praises`, …).
|
|
110
|
+
|
|
111
|
+
Keep `urn` from here — it is the numeric activity ID that [post comments](#get-comments-on-a-post) additionally requires.
|
|
112
|
+
|
|
113
|
+
## Company Data
|
|
114
|
+
|
|
115
|
+
### Get a company page
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
npx xapi-to call linkedin.api_v1_linkedin_web__v2_get__company__profile \
|
|
119
|
+
--input '{"method":"GET","params":{"url":"https://www.linkedin.com/company/anthropicresearch/"}}'
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
Returns `data.data` with `name`, `company_id`, `about`, `description`, `slogan`, `website`, `industries`, `company_size`, `organization_type`, `followers`, `employees_in_linkedin`, `employees[]`, `locations[]`, `logo`, `image`, `similar[]`, `affiliated[]`, `alumni` / `alumni_information`, `updates[]`.
|
|
123
|
+
|
|
124
|
+
### Get a company's posts
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
npx xapi-to call linkedin.api_v1_linkedin_web__v2_get__company__posts \
|
|
128
|
+
--input '{"method":"GET","params":{"url":"https://www.linkedin.com/company/anthropicresearch/","page":1}}'
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
Same envelope as person posts: `data.data.data[]` + `data.data.paging`.
|
|
132
|
+
|
|
133
|
+
## Posts and Comments
|
|
134
|
+
|
|
135
|
+
### Get post detail
|
|
136
|
+
|
|
137
|
+
```bash
|
|
138
|
+
npx xapi-to call linkedin.api_v1_linkedin_web__v2_get__post__detail \
|
|
139
|
+
--input '{"method":"GET","params":{"url":"https://www.linkedin.com/feed/update/urn:li:activity:7490874650621612032/"}}'
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
Returns the full post: `post_text`, `post_text_html`, `title`, `headline`, `date_posted`, `hashtags[]`, `embedded_links[]`, `images[]`, `videos[]`, `num_likes`, `num_comments`, `top_visible_comments[]`, `repost`, `tagged_people[]`, `tagged_companies[]`, `external_link_data`, plus author context (`user_name`, `user_title`, `user_followers`, `author_profile_pic`).
|
|
143
|
+
|
|
144
|
+
### Get comments on a post
|
|
145
|
+
|
|
146
|
+
**This endpoint requires two parameters, not one** — `url` *and* `urn`, the bare numeric activity ID. Both are marked required in the schema, and `urn` is pattern-validated as `^[0-9]+$`.
|
|
147
|
+
|
|
148
|
+
```bash
|
|
149
|
+
npx xapi-to call linkedin.api_v1_linkedin_web__v2_get__post__comments \
|
|
150
|
+
--input '{"method":"GET","params":{"url":"https://www.linkedin.com/feed/update/urn:li:activity:7490874650621612032/","urn":"7490874650621612032","page":1}}'
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
Extract `urn` from the post URL — the digits after `activity:` (feed form) or after `-activity-` (posts form). Passing the prefixed `urn:li:activity:7490874650621612032` form is rejected by the pattern check before the call is billed.
|
|
154
|
+
|
|
155
|
+
Returns `data.data.data[]` with `text`, `commenter`, `created_at`, `created_datetime`, `permalink`, `pinned`, `replies`, `thread_urn`, plus `data.data.total` and `data.data.pagination_token`.
|
|
156
|
+
|
|
157
|
+
## Jobs
|
|
158
|
+
|
|
159
|
+
### Search jobs
|
|
160
|
+
|
|
161
|
+
The one endpoint that is not URL-addressed:
|
|
162
|
+
|
|
163
|
+
```bash
|
|
164
|
+
npx xapi-to call linkedin.api_v1_linkedin_web__v2_search__jobs \
|
|
165
|
+
--input '{"method":"GET","params":{"keywords":"machine learning engineer","location":"United States","page":1}}'
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
`keywords` is required; `location` and `page` are optional. Returns `data.data.data[]` (`job_title`, `job_url`, `job_urn`, `company`, `company_linkedin_url`, `company_logo`, `location`, `remote`, `salary`, `posted_time`) plus `data.data.total`.
|
|
169
|
+
|
|
170
|
+
### Get job detail
|
|
171
|
+
|
|
172
|
+
```bash
|
|
173
|
+
npx xapi-to call linkedin.api_v1_linkedin_web__v2_get__job__detail \
|
|
174
|
+
--input '{"method":"GET","params":{"url":"https://www.linkedin.com/jobs/view/4442605025"}}'
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
Returns `data.data.data` with the full JD (`job_description`), `job_title`, `job_type`, `experience_level`, `job_functions[]`, `skills[]`, `salary_details`, `salary_display`, `benefits[]`, `remote_allow`, `applies`, `views`, `posted`, `closed`/`expired`, `hiring_team[]`, and company context (`company_name`, `company_id`, `company_description`, `employee_count`, `industries[]`, `hq_*` address fields).
|
|
178
|
+
|
|
179
|
+
This is the most expensive LinkedIn endpoint — search first, then fetch detail only for the postings you actually care about.
|
|
180
|
+
|
|
181
|
+
## Common Workflows
|
|
182
|
+
|
|
183
|
+
### Profile → recent activity
|
|
184
|
+
|
|
185
|
+
```bash
|
|
186
|
+
# 1. Whole profile in one call
|
|
187
|
+
npx xapi-to call linkedin.api_v1_linkedin_web__v2_get__user__profile \
|
|
188
|
+
--input '{"method":"GET","params":{"url":"https://www.linkedin.com/in/williamhgates/"}}'
|
|
189
|
+
|
|
190
|
+
# 1b. Only if experience/education came back null — career history from the fallback
|
|
191
|
+
npx xapi-to call icypeas-email.api_scrape_profile \
|
|
192
|
+
--input '{"method":"GET","params":{"url":"https://www.linkedin.com/in/williamhgates/"}}'
|
|
193
|
+
|
|
194
|
+
# 2. Their posts (take `urn` from each item for step 3)
|
|
195
|
+
npx xapi-to call linkedin.api_v1_linkedin_web__v2_get__user__posts \
|
|
196
|
+
--input '{"method":"GET","params":{"url":"https://www.linkedin.com/in/williamhgates/","page":1}}'
|
|
197
|
+
|
|
198
|
+
# 3. Comments on one post — url AND numeric urn
|
|
199
|
+
npx xapi-to call linkedin.api_v1_linkedin_web__v2_get__post__comments \
|
|
200
|
+
--input '{"method":"GET","params":{"url":"<post_url>","urn":"<urn>","page":1}}'
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
### Job hunt
|
|
204
|
+
|
|
205
|
+
```bash
|
|
206
|
+
# 1. Search (cheap, paginated)
|
|
207
|
+
npx xapi-to call linkedin.api_v1_linkedin_web__v2_search__jobs \
|
|
208
|
+
--input '{"method":"GET","params":{"keywords":"rust engineer","location":"Berlin","page":1}}'
|
|
209
|
+
|
|
210
|
+
# 2. Detail only for shortlisted job_url values
|
|
211
|
+
npx xapi-to call linkedin.api_v1_linkedin_web__v2_get__job__detail \
|
|
212
|
+
--input '{"method":"GET","params":{"url":"<job_url>"}}'
|
|
213
|
+
|
|
214
|
+
# 3. Company context
|
|
215
|
+
npx xapi-to call linkedin.api_v1_linkedin_web__v2_get__company__profile \
|
|
216
|
+
--input '{"method":"GET","params":{"url":"<company_linkedin_url>"}}'
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
## Pagination
|
|
220
|
+
|
|
221
|
+
`get__user__posts`, `get__company__posts`, `get__post__comments`, and `search__jobs` take a 1-based `page` integer. Posts responses carry `data.data.paging`; comments carry `total` and `pagination_token`; job search carries `total`. Increment `page` until a response comes back exhausted — note that past the last page the upstream returns `code: 200` with `data: null` (not an empty array), so test for falsy rather than for `length === 0`. The other four endpoints return a complete resource and take no pagination parameter.
|
|
222
|
+
|
|
223
|
+
## API Reference
|
|
224
|
+
|
|
225
|
+
| Action ID (`linkedin.api_v1_linkedin_web__v2_…`) | Purpose | Required params | Optional |
|
|
226
|
+
|---|---|---|---|
|
|
227
|
+
| `get__user__profile` | Full person profile + experience/education/honors | `url` | — |
|
|
228
|
+
| `get__user__posts` | A person's posts | `url` | `page` |
|
|
229
|
+
| `get__company__profile` | Company page | `url` | — |
|
|
230
|
+
| `get__company__posts` | A company's posts | `url` | `page` |
|
|
231
|
+
| `get__post__detail` | Single post, full text and media | `url` | — |
|
|
232
|
+
| `get__post__comments` | Comments on a post | `url` **and** `urn` (digits only) | `page` |
|
|
233
|
+
| `search__jobs` | Job search | `keywords` | `location`, `page` |
|
|
234
|
+
| `get__job__detail` | Full job posting | `url` | — |
|
|
235
|
+
|
|
236
|
+
One non-`linkedin` action belongs in this workflow:
|
|
237
|
+
|
|
238
|
+
| Action ID | Purpose | Required params | Notes |
|
|
239
|
+
|---|---|---|---|
|
|
240
|
+
| `icypeas-email.api_scrape_profile` | Career history for profiles the logged-out page hides | `url` | Fallback when `get__user__profile` returns `experience: null`. Check `data.status == "FOUND"`. |
|
|
241
|
+
|
|
242
|
+
Detail-style endpoints (`get__*__profile`, `get__post__detail`) are the cheapest; list-style endpoints (posts, comments, job search) cost more per call, and `get__job__detail` is the most expensive. Run `npx xapi-to get <action-id>` for the current `meta.pricing` rather than assuming these ratios hold.
|
|
243
|
+
|
|
244
|
+
## Error Handling
|
|
245
|
+
|
|
246
|
+
- **`Action not found: linkedin.api_v1_linkedin_web_…`** — you used a pre-v2 action ID. The `username` → `urn` two-step endpoints (`get__user__experience`, `get__user__educations`, `get__user__skills`, `get__user__contact`, `search__people`, `get__company__jobs`, …) are gone; everything is now `…_linkedin_web__v2_…` and URL-addressed. Re-discover with `npx xapi-to search "linkedin" --source api`.
|
|
247
|
+
- **`Input validation failed … must have required property 'url'`** — the gateway rejected the call before it reached LinkedIn. Check the `params` object, not `pathParams`.
|
|
248
|
+
- **`must have required property 'urn'`** — `get__post__comments` needs the numeric `urn` alongside `url`. See [Get comments on a post](#get-comments-on-a-post).
|
|
249
|
+
- **`must match pattern "^[0-9]+$"` on `/params/urn`** — you passed the prefixed `urn:li:activity:<id>` form. Send the digits only.
|
|
250
|
+
- **`API Token lacks required permissions`** (upstream `403`) — the account's upstream provider token has no LinkedIn scope. This is an account entitlement, not a parameter problem; enable it in the provider dashboard.
|
|
251
|
+
- **`experience: null` / `education: null` / `about` ending in `…` on `get__user__profile`** — not an error and not a private profile: the logged-out page LinkedIn serves for ordinary members omits those sections. Fall back to `icypeas-email.api_scrape_profile`. See [When `experience` and `education` come back `null`](#when-experience-and-education-come-back-null).
|
|
252
|
+
- **A ContactOut response naming `Example Person` at `Legros, Smitham and Kessler`** — `contactout-api.*` returned its sample payload because the account has no ContactOut entitlement. It carries `status_code: 200` and a `message` pointing at a sales call. Discard it; never summarize from it.
|
|
253
|
+
- **Empty `data[]` on a valid URL** — either the page is private/deleted, or you paginated past the end. LinkedIn also rate-limits aggressively; retry with backoff rather than in a tight loop.
|
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
# Reddit Guide
|
|
2
|
+
|
|
3
|
+
Complete guide for Reddit operations via xAPI — user profiles, posts, comments, subreddit feeds, popular/news/games feeds, trending, and search suggestions.
|
|
4
|
+
|
|
5
|
+
> **Dynamic catalog:** These are database-registered third-party APIs under the `reddit` 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
|
+
**Tip:** Most endpoints accept `need_format` (boolean). Set it to `true` for cleaner, pre-processed responses; omit or set `false` for raw Reddit data.
|
|
8
|
+
|
|
9
|
+
## Contents
|
|
10
|
+
|
|
11
|
+
- [User data](#user-data)
|
|
12
|
+
- [Post data](#post-data)
|
|
13
|
+
- [Subreddit data](#subreddit-data)
|
|
14
|
+
- [Feeds](#feeds)
|
|
15
|
+
- [Search and trending](#search--trending)
|
|
16
|
+
- [Common workflows](#common-workflows)
|
|
17
|
+
- [Pagination](#pagination)
|
|
18
|
+
- [Reddit ID prefixes](#reddit-id-prefixes)
|
|
19
|
+
- [API reference](#api-reference)
|
|
20
|
+
- [Error handling](#error-handling)
|
|
21
|
+
|
|
22
|
+
## User Data
|
|
23
|
+
|
|
24
|
+
### Get user profile
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
npx xapi-to call reddit.api_v1_reddit_app_fetch__user__profile \
|
|
28
|
+
--input '{"method":"GET","params":{"username":"spez","need_format":true}}'
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Returns `data.data.redditorInfoByName` with fields: `id` (e.g. `t2_1w72`), `name`, `prefixedName`, `isEmployee`, `isVerified`, `accountType`, `karma` (total, fromPosts, fromComments), `profile` (createdAt, subscribersCount, publicDescriptionText, styles).
|
|
32
|
+
|
|
33
|
+
### Get user's posts
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
npx xapi-to call reddit.api_v1_reddit_app_fetch__user__posts \
|
|
37
|
+
--input '{"method":"GET","params":{"username":"spez","sort":"TOP","need_format":true}}'
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Optional parameters:
|
|
41
|
+
- `sort` — `NEW`, `TOP`, `HOT`, `CONTROVERSIAL`
|
|
42
|
+
- `after` — pagination cursor from previous response
|
|
43
|
+
|
|
44
|
+
### Get user's comments
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
npx xapi-to call reddit.api_v1_reddit_app_fetch__user__comments \
|
|
48
|
+
--input '{"method":"GET","params":{"username":"spez","sort":"TOP","need_format":true}}'
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Optional parameters:
|
|
52
|
+
- `sort` — `NEW`, `TOP`, `HOT`, `CONTROVERSIAL`
|
|
53
|
+
- `after` — pagination cursor
|
|
54
|
+
- `page_size` — items per page (default: 25)
|
|
55
|
+
|
|
56
|
+
### Get user's active subreddits
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
npx xapi-to call reddit.api_v1_reddit_app_fetch__user__active__subreddits \
|
|
60
|
+
--input '{"method":"GET","params":{"username":"spez","need_format":true}}'
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### Get user's trophies
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
npx xapi-to call reddit.api_v1_reddit_app_fetch__user__trophies \
|
|
67
|
+
--input '{"method":"GET","params":{"username":"spez","need_format":true}}'
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Post Data
|
|
71
|
+
|
|
72
|
+
### Get single post details
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
npx xapi-to call reddit.api_v1_reddit_app_fetch__post__details \
|
|
76
|
+
--input '{"method":"GET","params":{"post_id":"t3_1ojnh50","need_format":true}}'
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
The `post_id` must include the `t3_` prefix. To jump to a specific comment within the post, set `include_comment_id` to `true` and pass the `comment_id`.
|
|
80
|
+
|
|
81
|
+
### Batch get post details
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
npx xapi-to call reddit.api_v1_reddit_app_fetch__post__details__batch \
|
|
85
|
+
--input '{"method":"GET","params":{"post_ids":"t3_1ojnh50,t3_1abc123","need_format":true}}'
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Comma-separated, up to 5 post IDs per request.
|
|
89
|
+
|
|
90
|
+
### Get post comments
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
npx xapi-to call reddit.api_v1_reddit_app_fetch__post__comments \
|
|
94
|
+
--input '{"method":"GET","params":{"post_id":"t3_1ojnh50","sort_type":"TOP","need_format":true}}'
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Optional parameters:
|
|
98
|
+
- `sort_type` — `CONFIDENCE`, `NEW`, `TOP`, `HOT`, `CONTROVERSIAL`, `OLD`, `RANDOM`
|
|
99
|
+
- `after` — pagination cursor
|
|
100
|
+
|
|
101
|
+
### Get comment replies
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
npx xapi-to call reddit.api_v1_reddit_app_fetch__comment__replies \
|
|
105
|
+
--input '{"method":"GET","params":{"post_id":"t3_1qmup73","cursor":"commenttree:ex:(RjiJd)","need_format":true}}'
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
Both `post_id` and `cursor` are required. The `cursor` value comes from the `more.cursor` field in comment responses.
|
|
109
|
+
|
|
110
|
+
Optional: `sort_type` — same options as post comments.
|
|
111
|
+
|
|
112
|
+
## Subreddit Data
|
|
113
|
+
|
|
114
|
+
### Get subreddit info
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
npx xapi-to call reddit.api_v1_reddit_app_fetch__subreddit__info \
|
|
118
|
+
--input '{"method":"GET","params":{"subreddit_name":"bitcoin","need_format":true}}'
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
Returns `data.data.subredditInfoByName` with: `id`, `name`, `prefixedName`, `title`, `description`, `publicDescriptionText`, `subscribersCount`, `styles`.
|
|
122
|
+
|
|
123
|
+
### Get subreddit feed
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
npx xapi-to call reddit.api_v1_reddit_app_fetch__subreddit__feed \
|
|
127
|
+
--input '{"method":"GET","params":{"subreddit_name":"programming","sort":"HOT","need_format":true}}'
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
Optional parameters:
|
|
131
|
+
- `sort` — `BEST`, `HOT`, `NEW`, `TOP`, `CONTROVERSIAL`, `RISING`
|
|
132
|
+
- `after` — pagination cursor
|
|
133
|
+
- `filter_posts` — array of post IDs to exclude
|
|
134
|
+
|
|
135
|
+
### Get subreddit style
|
|
136
|
+
|
|
137
|
+
```bash
|
|
138
|
+
npx xapi-to call reddit.api_v1_reddit_app_fetch__subreddit__style \
|
|
139
|
+
--input '{"method":"GET","params":{"subreddit_name":"bitcoin","need_format":true}}'
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
Returns the subreddit's visual theme info (banner, icon, colors).
|
|
143
|
+
|
|
144
|
+
### Get subreddit post channels
|
|
145
|
+
|
|
146
|
+
```bash
|
|
147
|
+
npx xapi-to call reddit.api_v1_reddit_app_fetch__subreddit__post__channels \
|
|
148
|
+
--input '{"method":"GET","params":{"subreddit_name":"bitcoin","sort":"HOT","need_format":true}}'
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
Optional parameters:
|
|
152
|
+
- `sort` — `HOT`, `NEW`, `TOP`, `CONTROVERSIAL`, `RISING`
|
|
153
|
+
- `range` — `HOUR`, `DAY`, `WEEK`, `MONTH`, `YEAR`, `ALL`
|
|
154
|
+
|
|
155
|
+
### Check if subreddit is muted
|
|
156
|
+
|
|
157
|
+
```bash
|
|
158
|
+
npx xapi-to call reddit.api_v1_reddit_app_check__subreddit__muted \
|
|
159
|
+
--input '{"method":"GET","params":{"subreddit_id":"t5_2s3qj","need_format":true}}'
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
Requires the subreddit ID with `t5_` prefix (get it from subreddit info).
|
|
163
|
+
|
|
164
|
+
### Get community highlights
|
|
165
|
+
|
|
166
|
+
```bash
|
|
167
|
+
npx xapi-to call reddit.api_v1_reddit_app_fetch__community__highlights \
|
|
168
|
+
--input '{"method":"GET","params":{"subreddit_id":"t5_2s3qj","need_format":true}}'
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
Requires `subreddit_id` with `t5_` prefix.
|
|
172
|
+
|
|
173
|
+
## Feeds
|
|
174
|
+
|
|
175
|
+
### Get popular feed
|
|
176
|
+
|
|
177
|
+
```bash
|
|
178
|
+
npx xapi-to call reddit.api_v1_reddit_app_fetch__popular__feed \
|
|
179
|
+
--input '{"method":"GET","params":{"sort":"HOT","need_format":true}}'
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
Returns `data.data.posts[]` with post objects and `after` for pagination.
|
|
183
|
+
|
|
184
|
+
Each post includes: `id`, `postTitle`, `url`, `score`, `commentCount`, `subreddit`, `authorInfo`, `permalink`, `postHint`, `upvoteRatio`, `createdAt`, `isNsfw`, `isSpoiler`, `media`, `thumbnail`.
|
|
185
|
+
|
|
186
|
+
Optional parameters:
|
|
187
|
+
- `sort` — `BEST`, `HOT`, `NEW`, `TOP`, `CONTROVERSIAL`, `RISING`
|
|
188
|
+
- `time` — `ALL`, `HOUR`, `DAY`, `WEEK`, `MONTH`, `YEAR`
|
|
189
|
+
- `after` — pagination cursor
|
|
190
|
+
- `filter_posts` — array of post IDs to exclude
|
|
191
|
+
|
|
192
|
+
### Get news feed
|
|
193
|
+
|
|
194
|
+
```bash
|
|
195
|
+
npx xapi-to call reddit.api_v1_reddit_app_fetch__news__feed \
|
|
196
|
+
--input '{"method":"GET","params":{"need_format":true}}'
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
Optional parameters:
|
|
200
|
+
- `after` — pagination cursor
|
|
201
|
+
- `subtopic_ids` — array of subtopic IDs to filter
|
|
202
|
+
|
|
203
|
+
### Get games feed
|
|
204
|
+
|
|
205
|
+
```bash
|
|
206
|
+
npx xapi-to call reddit.api_v1_reddit_app_fetch__games__feed \
|
|
207
|
+
--input '{"method":"GET","params":{"sort":"HOT","need_format":true}}'
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
Optional: `sort`, `time`, `after`.
|
|
211
|
+
|
|
212
|
+
## Search & Trending
|
|
213
|
+
|
|
214
|
+
### Get trending searches
|
|
215
|
+
|
|
216
|
+
```bash
|
|
217
|
+
npx xapi-to call reddit.api_v1_reddit_app_fetch__trending__searches \
|
|
218
|
+
--input '{"method":"GET","params":{"need_format":true}}'
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
Returns current trending search queries on Reddit.
|
|
222
|
+
|
|
223
|
+
### Search typeahead (suggestions)
|
|
224
|
+
|
|
225
|
+
```bash
|
|
226
|
+
npx xapi-to call reddit.api_v1_reddit_app_fetch__search__typeahead \
|
|
227
|
+
--input '{"method":"GET","params":{"query":"bitcoin","need_format":true}}'
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
Returns search suggestions including query completions and matching subreddits.
|
|
231
|
+
|
|
232
|
+
Optional parameters:
|
|
233
|
+
- `allow_nsfw` — `"0"` or `"1"`
|
|
234
|
+
- `safe_search` — `"unset"` or `"strict"`
|
|
235
|
+
|
|
236
|
+
## Common Workflows
|
|
237
|
+
|
|
238
|
+
### Research a Reddit user
|
|
239
|
+
|
|
240
|
+
1. Get profile: `reddit...fetch__user__profile` → karma, account age, description
|
|
241
|
+
2. Get posts: `reddit...fetch__user__posts` with `sort=TOP` → most popular posts
|
|
242
|
+
3. Get comments: `reddit...fetch__user__comments` → user's comment activity
|
|
243
|
+
4. Active subreddits: `reddit...fetch__user__active__subreddits` → community participation
|
|
244
|
+
|
|
245
|
+
### Monitor a subreddit
|
|
246
|
+
|
|
247
|
+
1. Get info: `reddit...fetch__subreddit__info` → subscriber count, description
|
|
248
|
+
2. Get feed: `reddit...fetch__subreddit__feed` with `sort=HOT` → trending posts
|
|
249
|
+
3. Read post: `reddit...fetch__post__details` → full post content
|
|
250
|
+
4. Read comments: `reddit...fetch__post__comments` with `sort_type=TOP` → top comments
|
|
251
|
+
|
|
252
|
+
### Track what's trending
|
|
253
|
+
|
|
254
|
+
1. Trending: `reddit...fetch__trending__searches` → current trending topics
|
|
255
|
+
2. Popular feed: `reddit...fetch__popular__feed` with `sort=HOT` → top posts across Reddit
|
|
256
|
+
3. News feed: `reddit...fetch__news__feed` → latest news posts
|
|
257
|
+
|
|
258
|
+
### Deep-dive a post thread
|
|
259
|
+
|
|
260
|
+
1. Get post: `reddit...fetch__post__details` with `post_id` → post content
|
|
261
|
+
2. Get comments: `reddit...fetch__post__comments` with `sort_type=TOP` → top-level comments
|
|
262
|
+
3. Get replies: `reddit...fetch__comment__replies` with `cursor` → expand comment threads
|
|
263
|
+
|
|
264
|
+
## Pagination
|
|
265
|
+
|
|
266
|
+
All paginated endpoints use the `after` cursor pattern (except comment replies which use `cursor`):
|
|
267
|
+
|
|
268
|
+
1. Make the initial request without `after`
|
|
269
|
+
2. Extract `after` from the response (e.g. `data.data.after` or from `pageInfo.endCursor`)
|
|
270
|
+
3. Pass `after` in the next request to get the next page
|
|
271
|
+
4. When `after` is `null` or response has no more data, pagination is exhausted
|
|
272
|
+
|
|
273
|
+
## Reddit ID Prefixes
|
|
274
|
+
|
|
275
|
+
| Prefix | Type | Example |
|
|
276
|
+
|--------|------|---------|
|
|
277
|
+
| `t1_` | Comment | `t1_abc123` |
|
|
278
|
+
| `t2_` | User | `t2_1w72` |
|
|
279
|
+
| `t3_` | Post/Link | `t3_1ojnh50` |
|
|
280
|
+
| `t5_` | Subreddit | `t5_2s3qj` |
|
|
281
|
+
|
|
282
|
+
## API Reference
|
|
283
|
+
|
|
284
|
+
| API (prefix: `reddit.api_v1_reddit_app_`) | Description | Key Params |
|
|
285
|
+
|---|---|---|
|
|
286
|
+
| `fetch__user__profile` | User profile | `username`* |
|
|
287
|
+
| `fetch__user__posts` | User's posts | `username`*, `sort`, `after` |
|
|
288
|
+
| `fetch__user__comments` | User's comments | `username`*, `sort`, `after`, `page_size` |
|
|
289
|
+
| `fetch__user__active__subreddits` | User's active subreddits | `username`* |
|
|
290
|
+
| `fetch__user__trophies` | User's trophies | `username`* |
|
|
291
|
+
| `fetch__post__details` | Single post details | `post_id`* |
|
|
292
|
+
| `fetch__post__details__batch` | Batch post details (up to 5) | `post_ids`* |
|
|
293
|
+
| `fetch__post__comments` | Post comments | `post_id`*, `sort_type`, `after` |
|
|
294
|
+
| `fetch__comment__replies` | Comment replies | `post_id`*, `cursor`*, `sort_type` |
|
|
295
|
+
| `fetch__subreddit__info` | Subreddit info | `subreddit_name` |
|
|
296
|
+
| `fetch__subreddit__feed` | Subreddit feed | `subreddit_name`*, `sort`, `after` |
|
|
297
|
+
| `fetch__subreddit__style` | Subreddit style/theme | `subreddit_name` |
|
|
298
|
+
| `fetch__subreddit__post__channels` | Subreddit post channels | `subreddit_name`, `sort`, `range` |
|
|
299
|
+
| `check__subreddit__muted` | Check subreddit muted | `subreddit_id`* |
|
|
300
|
+
| `fetch__community__highlights` | Community highlights | `subreddit_id`* |
|
|
301
|
+
| `fetch__popular__feed` | Popular feed | `sort`, `time`, `after` |
|
|
302
|
+
| `fetch__news__feed` | News feed | `after`, `subtopic_ids` |
|
|
303
|
+
| `fetch__games__feed` | Games feed | `sort`, `time`, `after` |
|
|
304
|
+
| `fetch__trending__searches` | Trending searches | — |
|
|
305
|
+
| `fetch__search__typeahead` | Search suggestions | `query`* |
|
|
306
|
+
|
|
307
|
+
## Error Handling
|
|
308
|
+
|
|
309
|
+
- **Missing t3_ prefix** → Post IDs must include the `t3_` prefix (e.g. `t3_1ojnh50`, not just `1ojnh50`)
|
|
310
|
+
- **Empty results** → Verify the username or subreddit_name exists
|
|
311
|
+
- **Pagination exhausted** → `after` is `null` or missing in the response
|
|
312
|
+
- **Comment replies require cursor** → Get the `cursor` value from the `more` field in comment responses
|