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.
@@ -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