scraper-api-com 0.1.0
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/dist/scraper-api.js +3658 -0
- package/package.json +60 -0
|
@@ -0,0 +1,3658 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/cli.js
|
|
4
|
+
import { Command as Command2 } from "commander";
|
|
5
|
+
import chalk9 from "chalk";
|
|
6
|
+
|
|
7
|
+
// src/command-registry.js
|
|
8
|
+
import { Command } from "commander";
|
|
9
|
+
import chalk from "chalk";
|
|
10
|
+
import ora from "ora";
|
|
11
|
+
|
|
12
|
+
// ../../packages/api-client/src/endpoints.generated.js
|
|
13
|
+
var endpoints = [
|
|
14
|
+
{
|
|
15
|
+
"platform": "instagram",
|
|
16
|
+
"action": "profile",
|
|
17
|
+
"resource": "profile",
|
|
18
|
+
"version": "v1",
|
|
19
|
+
"method": "GET",
|
|
20
|
+
"path": "/v1/instagram/profile",
|
|
21
|
+
"toolName": "v1_instagram_profile",
|
|
22
|
+
"summary": "Get an Instagram user's full profile by handle (followers/bio need a backend session).",
|
|
23
|
+
"cost": 1,
|
|
24
|
+
"live": true,
|
|
25
|
+
"anyOf": [
|
|
26
|
+
[
|
|
27
|
+
"handle"
|
|
28
|
+
]
|
|
29
|
+
],
|
|
30
|
+
"params": [
|
|
31
|
+
{
|
|
32
|
+
"name": "handle",
|
|
33
|
+
"type": "string",
|
|
34
|
+
"required": false,
|
|
35
|
+
"anyOf": true
|
|
36
|
+
}
|
|
37
|
+
]
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
"platform": "instagram",
|
|
41
|
+
"action": "basic-profile",
|
|
42
|
+
"resource": "basic-profile",
|
|
43
|
+
"version": "v1",
|
|
44
|
+
"method": "GET",
|
|
45
|
+
"path": "/v1/instagram/basic-profile",
|
|
46
|
+
"toolName": "v1_instagram_basic_profile",
|
|
47
|
+
"summary": "Get an Instagram user's basic public profile (name, verified, private, picture) by handle.",
|
|
48
|
+
"cost": 1,
|
|
49
|
+
"live": true,
|
|
50
|
+
"anyOf": [
|
|
51
|
+
[
|
|
52
|
+
"handle"
|
|
53
|
+
]
|
|
54
|
+
],
|
|
55
|
+
"params": [
|
|
56
|
+
{
|
|
57
|
+
"name": "handle",
|
|
58
|
+
"type": "string",
|
|
59
|
+
"required": false,
|
|
60
|
+
"anyOf": true
|
|
61
|
+
}
|
|
62
|
+
]
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
"platform": "instagram",
|
|
66
|
+
"action": "user-posts",
|
|
67
|
+
"resource": "user/posts",
|
|
68
|
+
"version": "v2",
|
|
69
|
+
"method": "GET",
|
|
70
|
+
"path": "/v2/instagram/user/posts",
|
|
71
|
+
"toolName": "v2_instagram_user_posts",
|
|
72
|
+
"summary": "Get an Instagram user's posts (incl. reels) by handle; paginate via next_max_id.",
|
|
73
|
+
"cost": 1,
|
|
74
|
+
"live": true,
|
|
75
|
+
"anyOf": [
|
|
76
|
+
[
|
|
77
|
+
"handle"
|
|
78
|
+
]
|
|
79
|
+
],
|
|
80
|
+
"params": [
|
|
81
|
+
{
|
|
82
|
+
"name": "handle",
|
|
83
|
+
"type": "string",
|
|
84
|
+
"required": false,
|
|
85
|
+
"anyOf": true
|
|
86
|
+
}
|
|
87
|
+
]
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
"platform": "instagram",
|
|
91
|
+
"action": "post",
|
|
92
|
+
"resource": "post",
|
|
93
|
+
"version": "v1",
|
|
94
|
+
"method": "GET",
|
|
95
|
+
"path": "/v1/instagram/post",
|
|
96
|
+
"toolName": "v1_instagram_post",
|
|
97
|
+
"summary": "Get a single Instagram post/reel by URL.",
|
|
98
|
+
"cost": 1,
|
|
99
|
+
"live": true,
|
|
100
|
+
"anyOf": [],
|
|
101
|
+
"params": [
|
|
102
|
+
{
|
|
103
|
+
"name": "url",
|
|
104
|
+
"type": "string",
|
|
105
|
+
"required": true,
|
|
106
|
+
"anyOf": false
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
"name": "handle",
|
|
110
|
+
"type": "string",
|
|
111
|
+
"required": false,
|
|
112
|
+
"anyOf": false
|
|
113
|
+
}
|
|
114
|
+
]
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
"platform": "instagram",
|
|
118
|
+
"action": "user-reels",
|
|
119
|
+
"resource": "user/reels",
|
|
120
|
+
"version": "v1",
|
|
121
|
+
"method": "GET",
|
|
122
|
+
"path": "/v1/instagram/user/reels",
|
|
123
|
+
"toolName": "v1_instagram_user_reels",
|
|
124
|
+
"summary": "Get an Instagram user's reels by handle/user_id (paginated via max_id).",
|
|
125
|
+
"cost": 1,
|
|
126
|
+
"live": true,
|
|
127
|
+
"anyOf": [
|
|
128
|
+
[
|
|
129
|
+
"handle",
|
|
130
|
+
"user_id"
|
|
131
|
+
]
|
|
132
|
+
],
|
|
133
|
+
"params": [
|
|
134
|
+
{
|
|
135
|
+
"name": "handle",
|
|
136
|
+
"type": "string",
|
|
137
|
+
"required": false,
|
|
138
|
+
"anyOf": true
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
"name": "user_id",
|
|
142
|
+
"type": "string",
|
|
143
|
+
"required": false,
|
|
144
|
+
"anyOf": true
|
|
145
|
+
}
|
|
146
|
+
]
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
"platform": "instagram",
|
|
150
|
+
"action": "post-comments",
|
|
151
|
+
"resource": "post/comments",
|
|
152
|
+
"version": "v2",
|
|
153
|
+
"method": "GET",
|
|
154
|
+
"path": "/v2/instagram/post/comments",
|
|
155
|
+
"toolName": "v2_instagram_post_comments",
|
|
156
|
+
"summary": "Get comments on an Instagram post by URL (paginated via next_min_id).",
|
|
157
|
+
"cost": 1,
|
|
158
|
+
"live": true,
|
|
159
|
+
"anyOf": [],
|
|
160
|
+
"params": [
|
|
161
|
+
{
|
|
162
|
+
"name": "url",
|
|
163
|
+
"type": "string",
|
|
164
|
+
"required": true,
|
|
165
|
+
"anyOf": false
|
|
166
|
+
},
|
|
167
|
+
{
|
|
168
|
+
"name": "handle",
|
|
169
|
+
"type": "string",
|
|
170
|
+
"required": false,
|
|
171
|
+
"anyOf": false
|
|
172
|
+
}
|
|
173
|
+
]
|
|
174
|
+
},
|
|
175
|
+
{
|
|
176
|
+
"platform": "instagram",
|
|
177
|
+
"action": "media-transcript",
|
|
178
|
+
"resource": "media/transcript",
|
|
179
|
+
"version": "v2",
|
|
180
|
+
"method": "GET",
|
|
181
|
+
"path": "/v2/instagram/media/transcript",
|
|
182
|
+
"toolName": "v2_instagram_media_transcript",
|
|
183
|
+
"summary": "Get the transcript of an Instagram reel/video by URL.",
|
|
184
|
+
"cost": 1,
|
|
185
|
+
"live": true,
|
|
186
|
+
"anyOf": [],
|
|
187
|
+
"params": [
|
|
188
|
+
{
|
|
189
|
+
"name": "url",
|
|
190
|
+
"type": "string",
|
|
191
|
+
"required": true,
|
|
192
|
+
"anyOf": false
|
|
193
|
+
},
|
|
194
|
+
{
|
|
195
|
+
"name": "handle",
|
|
196
|
+
"type": "string",
|
|
197
|
+
"required": false,
|
|
198
|
+
"anyOf": false
|
|
199
|
+
}
|
|
200
|
+
]
|
|
201
|
+
},
|
|
202
|
+
{
|
|
203
|
+
"platform": "instagram",
|
|
204
|
+
"action": "search-hashtag",
|
|
205
|
+
"resource": "search/hashtag",
|
|
206
|
+
"version": "v1",
|
|
207
|
+
"method": "GET",
|
|
208
|
+
"path": "/v1/instagram/search/hashtag",
|
|
209
|
+
"toolName": "v1_instagram_search_hashtag",
|
|
210
|
+
"summary": "Search Instagram posts by hashtag.",
|
|
211
|
+
"cost": 1,
|
|
212
|
+
"live": true,
|
|
213
|
+
"anyOf": [],
|
|
214
|
+
"params": [
|
|
215
|
+
{
|
|
216
|
+
"name": "hashtag",
|
|
217
|
+
"type": "string",
|
|
218
|
+
"required": true,
|
|
219
|
+
"anyOf": false
|
|
220
|
+
},
|
|
221
|
+
{
|
|
222
|
+
"name": "handle",
|
|
223
|
+
"type": "string",
|
|
224
|
+
"required": false,
|
|
225
|
+
"anyOf": false
|
|
226
|
+
}
|
|
227
|
+
]
|
|
228
|
+
},
|
|
229
|
+
{
|
|
230
|
+
"platform": "instagram",
|
|
231
|
+
"action": "search-profiles",
|
|
232
|
+
"resource": "search/profiles",
|
|
233
|
+
"version": "v1",
|
|
234
|
+
"method": "GET",
|
|
235
|
+
"path": "/v1/instagram/search/profiles",
|
|
236
|
+
"toolName": "v1_instagram_search_profiles",
|
|
237
|
+
"summary": "Search Instagram profiles by query.",
|
|
238
|
+
"cost": 1,
|
|
239
|
+
"live": true,
|
|
240
|
+
"anyOf": [],
|
|
241
|
+
"params": [
|
|
242
|
+
{
|
|
243
|
+
"name": "query",
|
|
244
|
+
"type": "string",
|
|
245
|
+
"required": true,
|
|
246
|
+
"anyOf": false
|
|
247
|
+
},
|
|
248
|
+
{
|
|
249
|
+
"name": "handle",
|
|
250
|
+
"type": "string",
|
|
251
|
+
"required": false,
|
|
252
|
+
"anyOf": false
|
|
253
|
+
}
|
|
254
|
+
]
|
|
255
|
+
},
|
|
256
|
+
{
|
|
257
|
+
"platform": "instagram",
|
|
258
|
+
"action": "reels-search",
|
|
259
|
+
"resource": "reels/search",
|
|
260
|
+
"version": "v2",
|
|
261
|
+
"method": "GET",
|
|
262
|
+
"path": "/v2/instagram/reels/search",
|
|
263
|
+
"toolName": "v2_instagram_reels_search",
|
|
264
|
+
"summary": "Search Instagram reels by query.",
|
|
265
|
+
"cost": 1,
|
|
266
|
+
"live": true,
|
|
267
|
+
"anyOf": [],
|
|
268
|
+
"params": [
|
|
269
|
+
{
|
|
270
|
+
"name": "query",
|
|
271
|
+
"type": "string",
|
|
272
|
+
"required": true,
|
|
273
|
+
"anyOf": false
|
|
274
|
+
},
|
|
275
|
+
{
|
|
276
|
+
"name": "handle",
|
|
277
|
+
"type": "string",
|
|
278
|
+
"required": false,
|
|
279
|
+
"anyOf": false
|
|
280
|
+
}
|
|
281
|
+
]
|
|
282
|
+
},
|
|
283
|
+
{
|
|
284
|
+
"platform": "instagram",
|
|
285
|
+
"action": "audio-reels",
|
|
286
|
+
"resource": "audio/reels",
|
|
287
|
+
"version": "v1",
|
|
288
|
+
"method": "GET",
|
|
289
|
+
"path": "/v1/instagram/audio/reels",
|
|
290
|
+
"toolName": "v1_instagram_audio_reels",
|
|
291
|
+
"summary": "Get Instagram reels using a given audio/track (paginated via max_id).",
|
|
292
|
+
"cost": 1,
|
|
293
|
+
"live": true,
|
|
294
|
+
"anyOf": [],
|
|
295
|
+
"params": [
|
|
296
|
+
{
|
|
297
|
+
"name": "audio_id",
|
|
298
|
+
"type": "string",
|
|
299
|
+
"required": true,
|
|
300
|
+
"anyOf": false
|
|
301
|
+
},
|
|
302
|
+
{
|
|
303
|
+
"name": "handle",
|
|
304
|
+
"type": "string",
|
|
305
|
+
"required": false,
|
|
306
|
+
"anyOf": false
|
|
307
|
+
}
|
|
308
|
+
]
|
|
309
|
+
},
|
|
310
|
+
{
|
|
311
|
+
"platform": "instagram",
|
|
312
|
+
"action": "reels-trending",
|
|
313
|
+
"resource": "reels/trending",
|
|
314
|
+
"version": "v1",
|
|
315
|
+
"method": "GET",
|
|
316
|
+
"path": "/v1/instagram/reels/trending",
|
|
317
|
+
"toolName": "v1_instagram_reels_trending",
|
|
318
|
+
"summary": "Get currently trending Instagram reels (paginated via max_id).",
|
|
319
|
+
"cost": 1,
|
|
320
|
+
"live": true,
|
|
321
|
+
"anyOf": [],
|
|
322
|
+
"params": [
|
|
323
|
+
{
|
|
324
|
+
"name": "handle",
|
|
325
|
+
"type": "string",
|
|
326
|
+
"required": false,
|
|
327
|
+
"anyOf": false
|
|
328
|
+
}
|
|
329
|
+
]
|
|
330
|
+
},
|
|
331
|
+
{
|
|
332
|
+
"platform": "instagram",
|
|
333
|
+
"action": "user-highlights",
|
|
334
|
+
"resource": "user/highlights",
|
|
335
|
+
"version": "v1",
|
|
336
|
+
"method": "GET",
|
|
337
|
+
"path": "/v1/instagram/user/highlights",
|
|
338
|
+
"toolName": "v1_instagram_user_highlights",
|
|
339
|
+
"summary": "Get an Instagram user's story highlights by handle/user_id.",
|
|
340
|
+
"cost": 1,
|
|
341
|
+
"live": true,
|
|
342
|
+
"anyOf": [
|
|
343
|
+
[
|
|
344
|
+
"handle",
|
|
345
|
+
"user_id"
|
|
346
|
+
]
|
|
347
|
+
],
|
|
348
|
+
"params": [
|
|
349
|
+
{
|
|
350
|
+
"name": "handle",
|
|
351
|
+
"type": "string",
|
|
352
|
+
"required": false,
|
|
353
|
+
"anyOf": true
|
|
354
|
+
},
|
|
355
|
+
{
|
|
356
|
+
"name": "user_id",
|
|
357
|
+
"type": "string",
|
|
358
|
+
"required": false,
|
|
359
|
+
"anyOf": true
|
|
360
|
+
}
|
|
361
|
+
]
|
|
362
|
+
},
|
|
363
|
+
{
|
|
364
|
+
"platform": "instagram",
|
|
365
|
+
"action": "user-highlight-detail",
|
|
366
|
+
"resource": "user/highlight/detail",
|
|
367
|
+
"version": "v1",
|
|
368
|
+
"method": "GET",
|
|
369
|
+
"path": "/v1/instagram/user/highlight/detail",
|
|
370
|
+
"toolName": "v1_instagram_user_highlight_detail",
|
|
371
|
+
"summary": "Get the media items of a single Instagram highlight by highlight_id.",
|
|
372
|
+
"cost": 1,
|
|
373
|
+
"live": true,
|
|
374
|
+
"anyOf": [],
|
|
375
|
+
"params": [
|
|
376
|
+
{
|
|
377
|
+
"name": "highlight_id",
|
|
378
|
+
"type": "string",
|
|
379
|
+
"required": true,
|
|
380
|
+
"anyOf": false
|
|
381
|
+
},
|
|
382
|
+
{
|
|
383
|
+
"name": "handle",
|
|
384
|
+
"type": "string",
|
|
385
|
+
"required": false,
|
|
386
|
+
"anyOf": false
|
|
387
|
+
}
|
|
388
|
+
]
|
|
389
|
+
},
|
|
390
|
+
{
|
|
391
|
+
"platform": "instagram",
|
|
392
|
+
"action": "user-embed",
|
|
393
|
+
"resource": "user/embed",
|
|
394
|
+
"version": "v1",
|
|
395
|
+
"method": "GET",
|
|
396
|
+
"path": "/v1/instagram/user/embed",
|
|
397
|
+
"toolName": "v1_instagram_user_embed",
|
|
398
|
+
"summary": "Get an embeddable HTML representation of an Instagram profile by handle.",
|
|
399
|
+
"cost": 1,
|
|
400
|
+
"live": true,
|
|
401
|
+
"anyOf": [
|
|
402
|
+
[
|
|
403
|
+
"handle",
|
|
404
|
+
"url"
|
|
405
|
+
]
|
|
406
|
+
],
|
|
407
|
+
"params": [
|
|
408
|
+
{
|
|
409
|
+
"name": "handle",
|
|
410
|
+
"type": "string",
|
|
411
|
+
"required": false,
|
|
412
|
+
"anyOf": true
|
|
413
|
+
},
|
|
414
|
+
{
|
|
415
|
+
"name": "url",
|
|
416
|
+
"type": "string",
|
|
417
|
+
"required": false,
|
|
418
|
+
"anyOf": true
|
|
419
|
+
}
|
|
420
|
+
]
|
|
421
|
+
},
|
|
422
|
+
{
|
|
423
|
+
"platform": "youtube",
|
|
424
|
+
"action": "channel",
|
|
425
|
+
"resource": "channel",
|
|
426
|
+
"version": "v1",
|
|
427
|
+
"method": "GET",
|
|
428
|
+
"path": "/v1/youtube/channel",
|
|
429
|
+
"toolName": "v1_youtube_channel",
|
|
430
|
+
"summary": "Get a YouTube channel's details by channelId, handle or url.",
|
|
431
|
+
"cost": 1,
|
|
432
|
+
"live": true,
|
|
433
|
+
"anyOf": [
|
|
434
|
+
[
|
|
435
|
+
"handle",
|
|
436
|
+
"channelId",
|
|
437
|
+
"url"
|
|
438
|
+
]
|
|
439
|
+
],
|
|
440
|
+
"params": [
|
|
441
|
+
{
|
|
442
|
+
"name": "handle",
|
|
443
|
+
"type": "string",
|
|
444
|
+
"required": false,
|
|
445
|
+
"anyOf": true
|
|
446
|
+
},
|
|
447
|
+
{
|
|
448
|
+
"name": "channelId",
|
|
449
|
+
"type": "string",
|
|
450
|
+
"required": false,
|
|
451
|
+
"anyOf": true
|
|
452
|
+
},
|
|
453
|
+
{
|
|
454
|
+
"name": "url",
|
|
455
|
+
"type": "string",
|
|
456
|
+
"required": false,
|
|
457
|
+
"anyOf": true
|
|
458
|
+
}
|
|
459
|
+
]
|
|
460
|
+
},
|
|
461
|
+
{
|
|
462
|
+
"platform": "youtube",
|
|
463
|
+
"action": "channel-videos",
|
|
464
|
+
"resource": "channel-videos",
|
|
465
|
+
"version": "v1",
|
|
466
|
+
"method": "GET",
|
|
467
|
+
"path": "/v1/youtube/channel-videos",
|
|
468
|
+
"toolName": "v1_youtube_channel_videos",
|
|
469
|
+
"summary": "Get a YouTube channel's videos (paginated via continuationToken).",
|
|
470
|
+
"cost": 1,
|
|
471
|
+
"live": true,
|
|
472
|
+
"anyOf": [
|
|
473
|
+
[
|
|
474
|
+
"handle",
|
|
475
|
+
"channelId",
|
|
476
|
+
"url"
|
|
477
|
+
]
|
|
478
|
+
],
|
|
479
|
+
"params": [
|
|
480
|
+
{
|
|
481
|
+
"name": "handle",
|
|
482
|
+
"type": "string",
|
|
483
|
+
"required": false,
|
|
484
|
+
"anyOf": true
|
|
485
|
+
},
|
|
486
|
+
{
|
|
487
|
+
"name": "channelId",
|
|
488
|
+
"type": "string",
|
|
489
|
+
"required": false,
|
|
490
|
+
"anyOf": true
|
|
491
|
+
},
|
|
492
|
+
{
|
|
493
|
+
"name": "url",
|
|
494
|
+
"type": "string",
|
|
495
|
+
"required": false,
|
|
496
|
+
"anyOf": true
|
|
497
|
+
}
|
|
498
|
+
]
|
|
499
|
+
},
|
|
500
|
+
{
|
|
501
|
+
"platform": "youtube",
|
|
502
|
+
"action": "channel-playlists",
|
|
503
|
+
"resource": "channel/playlists",
|
|
504
|
+
"version": "v1",
|
|
505
|
+
"method": "GET",
|
|
506
|
+
"path": "/v1/youtube/channel/playlists",
|
|
507
|
+
"toolName": "v1_youtube_channel_playlists",
|
|
508
|
+
"summary": "Get a YouTube channel's playlists.",
|
|
509
|
+
"cost": 1,
|
|
510
|
+
"live": true,
|
|
511
|
+
"anyOf": [
|
|
512
|
+
[
|
|
513
|
+
"handle",
|
|
514
|
+
"channelId",
|
|
515
|
+
"url"
|
|
516
|
+
]
|
|
517
|
+
],
|
|
518
|
+
"params": [
|
|
519
|
+
{
|
|
520
|
+
"name": "handle",
|
|
521
|
+
"type": "string",
|
|
522
|
+
"required": false,
|
|
523
|
+
"anyOf": true
|
|
524
|
+
},
|
|
525
|
+
{
|
|
526
|
+
"name": "channelId",
|
|
527
|
+
"type": "string",
|
|
528
|
+
"required": false,
|
|
529
|
+
"anyOf": true
|
|
530
|
+
},
|
|
531
|
+
{
|
|
532
|
+
"name": "url",
|
|
533
|
+
"type": "string",
|
|
534
|
+
"required": false,
|
|
535
|
+
"anyOf": true
|
|
536
|
+
}
|
|
537
|
+
]
|
|
538
|
+
},
|
|
539
|
+
{
|
|
540
|
+
"platform": "youtube",
|
|
541
|
+
"action": "channel-lives",
|
|
542
|
+
"resource": "channel/lives",
|
|
543
|
+
"version": "v1",
|
|
544
|
+
"method": "GET",
|
|
545
|
+
"path": "/v1/youtube/channel/lives",
|
|
546
|
+
"toolName": "v1_youtube_channel_lives",
|
|
547
|
+
"summary": "Get a YouTube channel's live streams.",
|
|
548
|
+
"cost": 1,
|
|
549
|
+
"live": true,
|
|
550
|
+
"anyOf": [
|
|
551
|
+
[
|
|
552
|
+
"handle",
|
|
553
|
+
"channelId",
|
|
554
|
+
"url"
|
|
555
|
+
]
|
|
556
|
+
],
|
|
557
|
+
"params": [
|
|
558
|
+
{
|
|
559
|
+
"name": "handle",
|
|
560
|
+
"type": "string",
|
|
561
|
+
"required": false,
|
|
562
|
+
"anyOf": true
|
|
563
|
+
},
|
|
564
|
+
{
|
|
565
|
+
"name": "channelId",
|
|
566
|
+
"type": "string",
|
|
567
|
+
"required": false,
|
|
568
|
+
"anyOf": true
|
|
569
|
+
},
|
|
570
|
+
{
|
|
571
|
+
"name": "url",
|
|
572
|
+
"type": "string",
|
|
573
|
+
"required": false,
|
|
574
|
+
"anyOf": true
|
|
575
|
+
}
|
|
576
|
+
]
|
|
577
|
+
},
|
|
578
|
+
{
|
|
579
|
+
"platform": "youtube",
|
|
580
|
+
"action": "channel-community-posts",
|
|
581
|
+
"resource": "channel/community-posts",
|
|
582
|
+
"version": "v1",
|
|
583
|
+
"method": "GET",
|
|
584
|
+
"path": "/v1/youtube/channel/community-posts",
|
|
585
|
+
"toolName": "v1_youtube_channel_community_posts",
|
|
586
|
+
"summary": "Get a YouTube channel's community posts.",
|
|
587
|
+
"cost": 1,
|
|
588
|
+
"live": true,
|
|
589
|
+
"anyOf": [
|
|
590
|
+
[
|
|
591
|
+
"handle",
|
|
592
|
+
"channelId",
|
|
593
|
+
"url"
|
|
594
|
+
]
|
|
595
|
+
],
|
|
596
|
+
"params": [
|
|
597
|
+
{
|
|
598
|
+
"name": "handle",
|
|
599
|
+
"type": "string",
|
|
600
|
+
"required": false,
|
|
601
|
+
"anyOf": true
|
|
602
|
+
},
|
|
603
|
+
{
|
|
604
|
+
"name": "channelId",
|
|
605
|
+
"type": "string",
|
|
606
|
+
"required": false,
|
|
607
|
+
"anyOf": true
|
|
608
|
+
},
|
|
609
|
+
{
|
|
610
|
+
"name": "url",
|
|
611
|
+
"type": "string",
|
|
612
|
+
"required": false,
|
|
613
|
+
"anyOf": true
|
|
614
|
+
}
|
|
615
|
+
]
|
|
616
|
+
},
|
|
617
|
+
{
|
|
618
|
+
"platform": "youtube",
|
|
619
|
+
"action": "channel-shorts",
|
|
620
|
+
"resource": "channel/shorts",
|
|
621
|
+
"version": "v1",
|
|
622
|
+
"method": "GET",
|
|
623
|
+
"path": "/v1/youtube/channel/shorts",
|
|
624
|
+
"toolName": "v1_youtube_channel_shorts",
|
|
625
|
+
"summary": "Get a YouTube channel's shorts.",
|
|
626
|
+
"cost": 1,
|
|
627
|
+
"live": true,
|
|
628
|
+
"anyOf": [
|
|
629
|
+
[
|
|
630
|
+
"handle",
|
|
631
|
+
"channelId",
|
|
632
|
+
"url"
|
|
633
|
+
]
|
|
634
|
+
],
|
|
635
|
+
"params": [
|
|
636
|
+
{
|
|
637
|
+
"name": "handle",
|
|
638
|
+
"type": "string",
|
|
639
|
+
"required": false,
|
|
640
|
+
"anyOf": true
|
|
641
|
+
},
|
|
642
|
+
{
|
|
643
|
+
"name": "channelId",
|
|
644
|
+
"type": "string",
|
|
645
|
+
"required": false,
|
|
646
|
+
"anyOf": true
|
|
647
|
+
},
|
|
648
|
+
{
|
|
649
|
+
"name": "url",
|
|
650
|
+
"type": "string",
|
|
651
|
+
"required": false,
|
|
652
|
+
"anyOf": true
|
|
653
|
+
}
|
|
654
|
+
]
|
|
655
|
+
},
|
|
656
|
+
{
|
|
657
|
+
"platform": "youtube",
|
|
658
|
+
"action": "video",
|
|
659
|
+
"resource": "video",
|
|
660
|
+
"version": "v1",
|
|
661
|
+
"method": "GET",
|
|
662
|
+
"path": "/v1/youtube/video",
|
|
663
|
+
"toolName": "v1_youtube_video",
|
|
664
|
+
"summary": "Get details of a YouTube video or short.",
|
|
665
|
+
"cost": 1,
|
|
666
|
+
"live": true,
|
|
667
|
+
"anyOf": [],
|
|
668
|
+
"params": [
|
|
669
|
+
{
|
|
670
|
+
"name": "url",
|
|
671
|
+
"type": "string",
|
|
672
|
+
"required": true,
|
|
673
|
+
"anyOf": false
|
|
674
|
+
},
|
|
675
|
+
{
|
|
676
|
+
"name": "handle",
|
|
677
|
+
"type": "string",
|
|
678
|
+
"required": false,
|
|
679
|
+
"anyOf": false
|
|
680
|
+
},
|
|
681
|
+
{
|
|
682
|
+
"name": "channelId",
|
|
683
|
+
"type": "string",
|
|
684
|
+
"required": false,
|
|
685
|
+
"anyOf": false
|
|
686
|
+
}
|
|
687
|
+
]
|
|
688
|
+
},
|
|
689
|
+
{
|
|
690
|
+
"platform": "youtube",
|
|
691
|
+
"action": "video-transcript",
|
|
692
|
+
"resource": "video/transcript",
|
|
693
|
+
"version": "v1",
|
|
694
|
+
"method": "GET",
|
|
695
|
+
"path": "/v1/youtube/video/transcript",
|
|
696
|
+
"toolName": "v1_youtube_video_transcript",
|
|
697
|
+
"summary": "Get the transcript of a YouTube video or short.",
|
|
698
|
+
"cost": 1,
|
|
699
|
+
"live": true,
|
|
700
|
+
"anyOf": [],
|
|
701
|
+
"params": [
|
|
702
|
+
{
|
|
703
|
+
"name": "url",
|
|
704
|
+
"type": "string",
|
|
705
|
+
"required": true,
|
|
706
|
+
"anyOf": false
|
|
707
|
+
},
|
|
708
|
+
{
|
|
709
|
+
"name": "handle",
|
|
710
|
+
"type": "string",
|
|
711
|
+
"required": false,
|
|
712
|
+
"anyOf": false
|
|
713
|
+
},
|
|
714
|
+
{
|
|
715
|
+
"name": "channelId",
|
|
716
|
+
"type": "string",
|
|
717
|
+
"required": false,
|
|
718
|
+
"anyOf": false
|
|
719
|
+
}
|
|
720
|
+
]
|
|
721
|
+
},
|
|
722
|
+
{
|
|
723
|
+
"platform": "youtube",
|
|
724
|
+
"action": "video-sponsors",
|
|
725
|
+
"resource": "video/sponsors",
|
|
726
|
+
"version": "v1",
|
|
727
|
+
"method": "GET",
|
|
728
|
+
"path": "/v1/youtube/video/sponsors",
|
|
729
|
+
"toolName": "v1_youtube_video_sponsors",
|
|
730
|
+
"summary": "Detect suspected sponsors of a YouTube video.",
|
|
731
|
+
"cost": 1,
|
|
732
|
+
"live": true,
|
|
733
|
+
"anyOf": [],
|
|
734
|
+
"params": [
|
|
735
|
+
{
|
|
736
|
+
"name": "url",
|
|
737
|
+
"type": "string",
|
|
738
|
+
"required": true,
|
|
739
|
+
"anyOf": false
|
|
740
|
+
},
|
|
741
|
+
{
|
|
742
|
+
"name": "handle",
|
|
743
|
+
"type": "string",
|
|
744
|
+
"required": false,
|
|
745
|
+
"anyOf": false
|
|
746
|
+
},
|
|
747
|
+
{
|
|
748
|
+
"name": "channelId",
|
|
749
|
+
"type": "string",
|
|
750
|
+
"required": false,
|
|
751
|
+
"anyOf": false
|
|
752
|
+
}
|
|
753
|
+
]
|
|
754
|
+
},
|
|
755
|
+
{
|
|
756
|
+
"platform": "youtube",
|
|
757
|
+
"action": "search",
|
|
758
|
+
"resource": "search",
|
|
759
|
+
"version": "v1",
|
|
760
|
+
"method": "GET",
|
|
761
|
+
"path": "/v1/youtube/search",
|
|
762
|
+
"toolName": "v1_youtube_search",
|
|
763
|
+
"summary": "Search YouTube (videos, channels, playlists, shorts).",
|
|
764
|
+
"cost": 1,
|
|
765
|
+
"live": true,
|
|
766
|
+
"anyOf": [],
|
|
767
|
+
"params": [
|
|
768
|
+
{
|
|
769
|
+
"name": "query",
|
|
770
|
+
"type": "string",
|
|
771
|
+
"required": true,
|
|
772
|
+
"anyOf": false
|
|
773
|
+
},
|
|
774
|
+
{
|
|
775
|
+
"name": "handle",
|
|
776
|
+
"type": "string",
|
|
777
|
+
"required": false,
|
|
778
|
+
"anyOf": false
|
|
779
|
+
},
|
|
780
|
+
{
|
|
781
|
+
"name": "channelId",
|
|
782
|
+
"type": "string",
|
|
783
|
+
"required": false,
|
|
784
|
+
"anyOf": false
|
|
785
|
+
}
|
|
786
|
+
]
|
|
787
|
+
},
|
|
788
|
+
{
|
|
789
|
+
"platform": "youtube",
|
|
790
|
+
"action": "search-hashtag",
|
|
791
|
+
"resource": "search/hashtag",
|
|
792
|
+
"version": "v1",
|
|
793
|
+
"method": "GET",
|
|
794
|
+
"path": "/v1/youtube/search/hashtag",
|
|
795
|
+
"toolName": "v1_youtube_search_hashtag",
|
|
796
|
+
"summary": "Search YouTube by hashtag.",
|
|
797
|
+
"cost": 1,
|
|
798
|
+
"live": true,
|
|
799
|
+
"anyOf": [],
|
|
800
|
+
"params": [
|
|
801
|
+
{
|
|
802
|
+
"name": "hashtag",
|
|
803
|
+
"type": "string",
|
|
804
|
+
"required": true,
|
|
805
|
+
"anyOf": false
|
|
806
|
+
},
|
|
807
|
+
{
|
|
808
|
+
"name": "handle",
|
|
809
|
+
"type": "string",
|
|
810
|
+
"required": false,
|
|
811
|
+
"anyOf": false
|
|
812
|
+
},
|
|
813
|
+
{
|
|
814
|
+
"name": "channelId",
|
|
815
|
+
"type": "string",
|
|
816
|
+
"required": false,
|
|
817
|
+
"anyOf": false
|
|
818
|
+
}
|
|
819
|
+
]
|
|
820
|
+
},
|
|
821
|
+
{
|
|
822
|
+
"platform": "youtube",
|
|
823
|
+
"action": "video-comments",
|
|
824
|
+
"resource": "video/comments",
|
|
825
|
+
"version": "v1",
|
|
826
|
+
"method": "GET",
|
|
827
|
+
"path": "/v1/youtube/video/comments",
|
|
828
|
+
"toolName": "v1_youtube_video_comments",
|
|
829
|
+
"summary": "Get comments of a YouTube video.",
|
|
830
|
+
"cost": 1,
|
|
831
|
+
"live": true,
|
|
832
|
+
"anyOf": [],
|
|
833
|
+
"params": [
|
|
834
|
+
{
|
|
835
|
+
"name": "url",
|
|
836
|
+
"type": "string",
|
|
837
|
+
"required": true,
|
|
838
|
+
"anyOf": false
|
|
839
|
+
},
|
|
840
|
+
{
|
|
841
|
+
"name": "handle",
|
|
842
|
+
"type": "string",
|
|
843
|
+
"required": false,
|
|
844
|
+
"anyOf": false
|
|
845
|
+
},
|
|
846
|
+
{
|
|
847
|
+
"name": "channelId",
|
|
848
|
+
"type": "string",
|
|
849
|
+
"required": false,
|
|
850
|
+
"anyOf": false
|
|
851
|
+
}
|
|
852
|
+
]
|
|
853
|
+
},
|
|
854
|
+
{
|
|
855
|
+
"platform": "youtube",
|
|
856
|
+
"action": "video-comment-replies",
|
|
857
|
+
"resource": "video/comment/replies",
|
|
858
|
+
"version": "v1",
|
|
859
|
+
"method": "GET",
|
|
860
|
+
"path": "/v1/youtube/video/comment/replies",
|
|
861
|
+
"toolName": "v1_youtube_video_comment_replies",
|
|
862
|
+
"summary": "Get replies to a YouTube comment.",
|
|
863
|
+
"cost": 1,
|
|
864
|
+
"live": true,
|
|
865
|
+
"anyOf": [],
|
|
866
|
+
"params": [
|
|
867
|
+
{
|
|
868
|
+
"name": "continuationToken",
|
|
869
|
+
"type": "string",
|
|
870
|
+
"required": true,
|
|
871
|
+
"anyOf": false
|
|
872
|
+
},
|
|
873
|
+
{
|
|
874
|
+
"name": "handle",
|
|
875
|
+
"type": "string",
|
|
876
|
+
"required": false,
|
|
877
|
+
"anyOf": false
|
|
878
|
+
},
|
|
879
|
+
{
|
|
880
|
+
"name": "channelId",
|
|
881
|
+
"type": "string",
|
|
882
|
+
"required": false,
|
|
883
|
+
"anyOf": false
|
|
884
|
+
}
|
|
885
|
+
]
|
|
886
|
+
},
|
|
887
|
+
{
|
|
888
|
+
"platform": "youtube",
|
|
889
|
+
"action": "shorts-trending",
|
|
890
|
+
"resource": "shorts/trending",
|
|
891
|
+
"version": "v1",
|
|
892
|
+
"method": "GET",
|
|
893
|
+
"path": "/v1/youtube/shorts/trending",
|
|
894
|
+
"toolName": "v1_youtube_shorts_trending",
|
|
895
|
+
"summary": "Get trending YouTube shorts.",
|
|
896
|
+
"cost": 1,
|
|
897
|
+
"live": true,
|
|
898
|
+
"anyOf": [],
|
|
899
|
+
"params": [
|
|
900
|
+
{
|
|
901
|
+
"name": "handle",
|
|
902
|
+
"type": "string",
|
|
903
|
+
"required": false,
|
|
904
|
+
"anyOf": false
|
|
905
|
+
},
|
|
906
|
+
{
|
|
907
|
+
"name": "channelId",
|
|
908
|
+
"type": "string",
|
|
909
|
+
"required": false,
|
|
910
|
+
"anyOf": false
|
|
911
|
+
}
|
|
912
|
+
]
|
|
913
|
+
},
|
|
914
|
+
{
|
|
915
|
+
"platform": "youtube",
|
|
916
|
+
"action": "playlist",
|
|
917
|
+
"resource": "playlist",
|
|
918
|
+
"version": "v1",
|
|
919
|
+
"method": "GET",
|
|
920
|
+
"path": "/v1/youtube/playlist",
|
|
921
|
+
"toolName": "v1_youtube_playlist",
|
|
922
|
+
"summary": "Get the videos of a YouTube playlist.",
|
|
923
|
+
"cost": 1,
|
|
924
|
+
"live": true,
|
|
925
|
+
"anyOf": [],
|
|
926
|
+
"params": [
|
|
927
|
+
{
|
|
928
|
+
"name": "playlist_id",
|
|
929
|
+
"type": "string",
|
|
930
|
+
"required": true,
|
|
931
|
+
"anyOf": false
|
|
932
|
+
},
|
|
933
|
+
{
|
|
934
|
+
"name": "handle",
|
|
935
|
+
"type": "string",
|
|
936
|
+
"required": false,
|
|
937
|
+
"anyOf": false
|
|
938
|
+
},
|
|
939
|
+
{
|
|
940
|
+
"name": "channelId",
|
|
941
|
+
"type": "string",
|
|
942
|
+
"required": false,
|
|
943
|
+
"anyOf": false
|
|
944
|
+
}
|
|
945
|
+
]
|
|
946
|
+
},
|
|
947
|
+
{
|
|
948
|
+
"platform": "youtube",
|
|
949
|
+
"action": "community-post",
|
|
950
|
+
"resource": "community-post",
|
|
951
|
+
"version": "v1",
|
|
952
|
+
"method": "GET",
|
|
953
|
+
"path": "/v1/youtube/community-post",
|
|
954
|
+
"toolName": "v1_youtube_community_post",
|
|
955
|
+
"summary": "Get details of a YouTube community post.",
|
|
956
|
+
"cost": 1,
|
|
957
|
+
"live": true,
|
|
958
|
+
"anyOf": [],
|
|
959
|
+
"params": [
|
|
960
|
+
{
|
|
961
|
+
"name": "url",
|
|
962
|
+
"type": "string",
|
|
963
|
+
"required": true,
|
|
964
|
+
"anyOf": false
|
|
965
|
+
},
|
|
966
|
+
{
|
|
967
|
+
"name": "handle",
|
|
968
|
+
"type": "string",
|
|
969
|
+
"required": false,
|
|
970
|
+
"anyOf": false
|
|
971
|
+
},
|
|
972
|
+
{
|
|
973
|
+
"name": "channelId",
|
|
974
|
+
"type": "string",
|
|
975
|
+
"required": false,
|
|
976
|
+
"anyOf": false
|
|
977
|
+
}
|
|
978
|
+
]
|
|
979
|
+
},
|
|
980
|
+
{
|
|
981
|
+
"platform": "facebook",
|
|
982
|
+
"action": "profile",
|
|
983
|
+
"resource": "profile",
|
|
984
|
+
"version": "v1",
|
|
985
|
+
"method": "GET",
|
|
986
|
+
"path": "/v1/facebook/profile",
|
|
987
|
+
"toolName": "v1_facebook_profile",
|
|
988
|
+
"summary": "Get a Facebook page/profile by URL (name, category, photos, likes, followers).",
|
|
989
|
+
"cost": 1,
|
|
990
|
+
"live": true,
|
|
991
|
+
"anyOf": [
|
|
992
|
+
[
|
|
993
|
+
"url",
|
|
994
|
+
"pageId",
|
|
995
|
+
"handle"
|
|
996
|
+
]
|
|
997
|
+
],
|
|
998
|
+
"params": [
|
|
999
|
+
{
|
|
1000
|
+
"name": "url",
|
|
1001
|
+
"type": "string",
|
|
1002
|
+
"required": false,
|
|
1003
|
+
"anyOf": true
|
|
1004
|
+
},
|
|
1005
|
+
{
|
|
1006
|
+
"name": "pageId",
|
|
1007
|
+
"type": "string",
|
|
1008
|
+
"required": false,
|
|
1009
|
+
"anyOf": true
|
|
1010
|
+
},
|
|
1011
|
+
{
|
|
1012
|
+
"name": "handle",
|
|
1013
|
+
"type": "string",
|
|
1014
|
+
"required": false,
|
|
1015
|
+
"anyOf": true
|
|
1016
|
+
}
|
|
1017
|
+
]
|
|
1018
|
+
},
|
|
1019
|
+
{
|
|
1020
|
+
"platform": "facebook",
|
|
1021
|
+
"action": "profile-posts",
|
|
1022
|
+
"resource": "profile/posts",
|
|
1023
|
+
"version": "v1",
|
|
1024
|
+
"method": "GET",
|
|
1025
|
+
"path": "/v1/facebook/profile/posts",
|
|
1026
|
+
"toolName": "v1_facebook_profile_posts",
|
|
1027
|
+
"summary": "Get a Facebook page's posts (message, reactions, comments, shares); paginate via cursor.",
|
|
1028
|
+
"cost": 1,
|
|
1029
|
+
"live": true,
|
|
1030
|
+
"anyOf": [
|
|
1031
|
+
[
|
|
1032
|
+
"url",
|
|
1033
|
+
"pageId",
|
|
1034
|
+
"handle"
|
|
1035
|
+
]
|
|
1036
|
+
],
|
|
1037
|
+
"params": [
|
|
1038
|
+
{
|
|
1039
|
+
"name": "url",
|
|
1040
|
+
"type": "string",
|
|
1041
|
+
"required": false,
|
|
1042
|
+
"anyOf": true
|
|
1043
|
+
},
|
|
1044
|
+
{
|
|
1045
|
+
"name": "pageId",
|
|
1046
|
+
"type": "string",
|
|
1047
|
+
"required": false,
|
|
1048
|
+
"anyOf": true
|
|
1049
|
+
},
|
|
1050
|
+
{
|
|
1051
|
+
"name": "handle",
|
|
1052
|
+
"type": "string",
|
|
1053
|
+
"required": false,
|
|
1054
|
+
"anyOf": true
|
|
1055
|
+
}
|
|
1056
|
+
]
|
|
1057
|
+
},
|
|
1058
|
+
{
|
|
1059
|
+
"platform": "facebook",
|
|
1060
|
+
"action": "post",
|
|
1061
|
+
"resource": "post",
|
|
1062
|
+
"version": "v1",
|
|
1063
|
+
"method": "GET",
|
|
1064
|
+
"path": "/v1/facebook/post",
|
|
1065
|
+
"toolName": "v1_facebook_post",
|
|
1066
|
+
"summary": "Get a single Facebook post by URL (message, reactions, comments, shares, video).",
|
|
1067
|
+
"cost": 1,
|
|
1068
|
+
"live": true,
|
|
1069
|
+
"anyOf": [
|
|
1070
|
+
[
|
|
1071
|
+
"url"
|
|
1072
|
+
]
|
|
1073
|
+
],
|
|
1074
|
+
"params": [
|
|
1075
|
+
{
|
|
1076
|
+
"name": "url",
|
|
1077
|
+
"type": "string",
|
|
1078
|
+
"required": false,
|
|
1079
|
+
"anyOf": true
|
|
1080
|
+
}
|
|
1081
|
+
]
|
|
1082
|
+
},
|
|
1083
|
+
{
|
|
1084
|
+
"platform": "facebook",
|
|
1085
|
+
"action": "post-comments",
|
|
1086
|
+
"resource": "post/comments",
|
|
1087
|
+
"version": "v1",
|
|
1088
|
+
"method": "GET",
|
|
1089
|
+
"path": "/v1/facebook/post/comments",
|
|
1090
|
+
"toolName": "v1_facebook_post_comments",
|
|
1091
|
+
"summary": "Get the comments on a Facebook post by URL (embedded top comments; full list needs FB_SESSION).",
|
|
1092
|
+
"cost": 1,
|
|
1093
|
+
"live": true,
|
|
1094
|
+
"anyOf": [
|
|
1095
|
+
[
|
|
1096
|
+
"url"
|
|
1097
|
+
]
|
|
1098
|
+
],
|
|
1099
|
+
"params": [
|
|
1100
|
+
{
|
|
1101
|
+
"name": "url",
|
|
1102
|
+
"type": "string",
|
|
1103
|
+
"required": false,
|
|
1104
|
+
"anyOf": true
|
|
1105
|
+
}
|
|
1106
|
+
]
|
|
1107
|
+
},
|
|
1108
|
+
{
|
|
1109
|
+
"platform": "facebook",
|
|
1110
|
+
"action": "profile-reels",
|
|
1111
|
+
"resource": "profile/reels",
|
|
1112
|
+
"version": "v1",
|
|
1113
|
+
"method": "GET",
|
|
1114
|
+
"path": "/v1/facebook/profile/reels",
|
|
1115
|
+
"toolName": "v1_facebook_profile_reels",
|
|
1116
|
+
"summary": "Get a Facebook page's videos/reels (id, title, thumbnail, play count).",
|
|
1117
|
+
"cost": 1,
|
|
1118
|
+
"live": true,
|
|
1119
|
+
"anyOf": [
|
|
1120
|
+
[
|
|
1121
|
+
"url",
|
|
1122
|
+
"pageId",
|
|
1123
|
+
"handle"
|
|
1124
|
+
]
|
|
1125
|
+
],
|
|
1126
|
+
"params": [
|
|
1127
|
+
{
|
|
1128
|
+
"name": "url",
|
|
1129
|
+
"type": "string",
|
|
1130
|
+
"required": false,
|
|
1131
|
+
"anyOf": true
|
|
1132
|
+
},
|
|
1133
|
+
{
|
|
1134
|
+
"name": "pageId",
|
|
1135
|
+
"type": "string",
|
|
1136
|
+
"required": false,
|
|
1137
|
+
"anyOf": true
|
|
1138
|
+
},
|
|
1139
|
+
{
|
|
1140
|
+
"name": "handle",
|
|
1141
|
+
"type": "string",
|
|
1142
|
+
"required": false,
|
|
1143
|
+
"anyOf": true
|
|
1144
|
+
}
|
|
1145
|
+
]
|
|
1146
|
+
},
|
|
1147
|
+
{
|
|
1148
|
+
"platform": "facebook",
|
|
1149
|
+
"action": "profile-photos",
|
|
1150
|
+
"resource": "profile/photos",
|
|
1151
|
+
"version": "v1",
|
|
1152
|
+
"method": "GET",
|
|
1153
|
+
"path": "/v1/facebook/profile/photos",
|
|
1154
|
+
"toolName": "v1_facebook_profile_photos",
|
|
1155
|
+
"summary": "Get a Facebook page's photos (id, image url, link).",
|
|
1156
|
+
"cost": 1,
|
|
1157
|
+
"live": true,
|
|
1158
|
+
"anyOf": [
|
|
1159
|
+
[
|
|
1160
|
+
"url",
|
|
1161
|
+
"pageId",
|
|
1162
|
+
"handle"
|
|
1163
|
+
]
|
|
1164
|
+
],
|
|
1165
|
+
"params": [
|
|
1166
|
+
{
|
|
1167
|
+
"name": "url",
|
|
1168
|
+
"type": "string",
|
|
1169
|
+
"required": false,
|
|
1170
|
+
"anyOf": true
|
|
1171
|
+
},
|
|
1172
|
+
{
|
|
1173
|
+
"name": "pageId",
|
|
1174
|
+
"type": "string",
|
|
1175
|
+
"required": false,
|
|
1176
|
+
"anyOf": true
|
|
1177
|
+
},
|
|
1178
|
+
{
|
|
1179
|
+
"name": "handle",
|
|
1180
|
+
"type": "string",
|
|
1181
|
+
"required": false,
|
|
1182
|
+
"anyOf": true
|
|
1183
|
+
}
|
|
1184
|
+
]
|
|
1185
|
+
},
|
|
1186
|
+
{
|
|
1187
|
+
"platform": "facebook",
|
|
1188
|
+
"action": "profile-events",
|
|
1189
|
+
"resource": "profile/events",
|
|
1190
|
+
"version": "v1",
|
|
1191
|
+
"method": "GET",
|
|
1192
|
+
"path": "/v1/facebook/profile/events",
|
|
1193
|
+
"toolName": "v1_facebook_profile_events",
|
|
1194
|
+
"summary": "Get a Facebook page's events.",
|
|
1195
|
+
"cost": 1,
|
|
1196
|
+
"live": false,
|
|
1197
|
+
"anyOf": [
|
|
1198
|
+
[
|
|
1199
|
+
"url",
|
|
1200
|
+
"pageId"
|
|
1201
|
+
]
|
|
1202
|
+
],
|
|
1203
|
+
"params": [
|
|
1204
|
+
{
|
|
1205
|
+
"name": "url",
|
|
1206
|
+
"type": "string",
|
|
1207
|
+
"required": false,
|
|
1208
|
+
"anyOf": true
|
|
1209
|
+
},
|
|
1210
|
+
{
|
|
1211
|
+
"name": "pageId",
|
|
1212
|
+
"type": "string",
|
|
1213
|
+
"required": false,
|
|
1214
|
+
"anyOf": true
|
|
1215
|
+
}
|
|
1216
|
+
]
|
|
1217
|
+
},
|
|
1218
|
+
{
|
|
1219
|
+
"platform": "facebook",
|
|
1220
|
+
"action": "post-transcript",
|
|
1221
|
+
"resource": "post/transcript",
|
|
1222
|
+
"version": "v1",
|
|
1223
|
+
"method": "GET",
|
|
1224
|
+
"path": "/v1/facebook/post/transcript",
|
|
1225
|
+
"toolName": "v1_facebook_post_transcript",
|
|
1226
|
+
"summary": "Get the transcript of a Facebook video post by URL.",
|
|
1227
|
+
"cost": 1,
|
|
1228
|
+
"live": false,
|
|
1229
|
+
"anyOf": [],
|
|
1230
|
+
"params": [
|
|
1231
|
+
{
|
|
1232
|
+
"name": "url",
|
|
1233
|
+
"type": "string",
|
|
1234
|
+
"required": true,
|
|
1235
|
+
"anyOf": false
|
|
1236
|
+
}
|
|
1237
|
+
]
|
|
1238
|
+
},
|
|
1239
|
+
{
|
|
1240
|
+
"platform": "facebook",
|
|
1241
|
+
"action": "post-comment-replies",
|
|
1242
|
+
"resource": "post/comment/replies",
|
|
1243
|
+
"version": "v1",
|
|
1244
|
+
"method": "GET",
|
|
1245
|
+
"path": "/v1/facebook/post/comment/replies",
|
|
1246
|
+
"toolName": "v1_facebook_post_comment_replies",
|
|
1247
|
+
"summary": "Get replies to a Facebook comment (paginated).",
|
|
1248
|
+
"cost": 1,
|
|
1249
|
+
"live": false,
|
|
1250
|
+
"anyOf": [
|
|
1251
|
+
[
|
|
1252
|
+
"url",
|
|
1253
|
+
"commentId"
|
|
1254
|
+
]
|
|
1255
|
+
],
|
|
1256
|
+
"params": [
|
|
1257
|
+
{
|
|
1258
|
+
"name": "url",
|
|
1259
|
+
"type": "string",
|
|
1260
|
+
"required": false,
|
|
1261
|
+
"anyOf": true
|
|
1262
|
+
},
|
|
1263
|
+
{
|
|
1264
|
+
"name": "commentId",
|
|
1265
|
+
"type": "string",
|
|
1266
|
+
"required": false,
|
|
1267
|
+
"anyOf": true
|
|
1268
|
+
}
|
|
1269
|
+
]
|
|
1270
|
+
},
|
|
1271
|
+
{
|
|
1272
|
+
"platform": "facebook",
|
|
1273
|
+
"action": "group-posts",
|
|
1274
|
+
"resource": "group/posts",
|
|
1275
|
+
"version": "v1",
|
|
1276
|
+
"method": "GET",
|
|
1277
|
+
"path": "/v1/facebook/group/posts",
|
|
1278
|
+
"toolName": "v1_facebook_group_posts",
|
|
1279
|
+
"summary": "Get a public Facebook group's posts (paginated via cursor).",
|
|
1280
|
+
"cost": 1,
|
|
1281
|
+
"live": false,
|
|
1282
|
+
"anyOf": [
|
|
1283
|
+
[
|
|
1284
|
+
"url",
|
|
1285
|
+
"groupId"
|
|
1286
|
+
]
|
|
1287
|
+
],
|
|
1288
|
+
"params": [
|
|
1289
|
+
{
|
|
1290
|
+
"name": "url",
|
|
1291
|
+
"type": "string",
|
|
1292
|
+
"required": false,
|
|
1293
|
+
"anyOf": true
|
|
1294
|
+
},
|
|
1295
|
+
{
|
|
1296
|
+
"name": "groupId",
|
|
1297
|
+
"type": "string",
|
|
1298
|
+
"required": false,
|
|
1299
|
+
"anyOf": true
|
|
1300
|
+
}
|
|
1301
|
+
]
|
|
1302
|
+
},
|
|
1303
|
+
{
|
|
1304
|
+
"platform": "facebook",
|
|
1305
|
+
"action": "marketplace-location-search",
|
|
1306
|
+
"resource": "marketplace/location/search",
|
|
1307
|
+
"version": "v1",
|
|
1308
|
+
"method": "GET",
|
|
1309
|
+
"path": "/v1/facebook/marketplace/location/search",
|
|
1310
|
+
"toolName": "v1_facebook_marketplace_location_search",
|
|
1311
|
+
"summary": "Search Facebook Marketplace locations by query.",
|
|
1312
|
+
"cost": 1,
|
|
1313
|
+
"live": false,
|
|
1314
|
+
"anyOf": [],
|
|
1315
|
+
"params": [
|
|
1316
|
+
{
|
|
1317
|
+
"name": "query",
|
|
1318
|
+
"type": "string",
|
|
1319
|
+
"required": true,
|
|
1320
|
+
"anyOf": false
|
|
1321
|
+
},
|
|
1322
|
+
{
|
|
1323
|
+
"name": "url",
|
|
1324
|
+
"type": "string",
|
|
1325
|
+
"required": false,
|
|
1326
|
+
"anyOf": false
|
|
1327
|
+
}
|
|
1328
|
+
]
|
|
1329
|
+
},
|
|
1330
|
+
{
|
|
1331
|
+
"platform": "facebook",
|
|
1332
|
+
"action": "marketplace-search",
|
|
1333
|
+
"resource": "marketplace/search",
|
|
1334
|
+
"version": "v1",
|
|
1335
|
+
"method": "GET",
|
|
1336
|
+
"path": "/v1/facebook/marketplace/search",
|
|
1337
|
+
"toolName": "v1_facebook_marketplace_search",
|
|
1338
|
+
"summary": "Search Facebook Marketplace listings.",
|
|
1339
|
+
"cost": 1,
|
|
1340
|
+
"live": false,
|
|
1341
|
+
"anyOf": [],
|
|
1342
|
+
"params": [
|
|
1343
|
+
{
|
|
1344
|
+
"name": "query",
|
|
1345
|
+
"type": "string",
|
|
1346
|
+
"required": true,
|
|
1347
|
+
"anyOf": false
|
|
1348
|
+
},
|
|
1349
|
+
{
|
|
1350
|
+
"name": "url",
|
|
1351
|
+
"type": "string",
|
|
1352
|
+
"required": false,
|
|
1353
|
+
"anyOf": false
|
|
1354
|
+
}
|
|
1355
|
+
]
|
|
1356
|
+
},
|
|
1357
|
+
{
|
|
1358
|
+
"platform": "facebook",
|
|
1359
|
+
"action": "marketplace-item",
|
|
1360
|
+
"resource": "marketplace/item",
|
|
1361
|
+
"version": "v1",
|
|
1362
|
+
"method": "GET",
|
|
1363
|
+
"path": "/v1/facebook/marketplace/item",
|
|
1364
|
+
"toolName": "v1_facebook_marketplace_item",
|
|
1365
|
+
"summary": "Get a single Facebook Marketplace item by URL/id.",
|
|
1366
|
+
"cost": 1,
|
|
1367
|
+
"live": false,
|
|
1368
|
+
"anyOf": [
|
|
1369
|
+
[
|
|
1370
|
+
"url",
|
|
1371
|
+
"id"
|
|
1372
|
+
]
|
|
1373
|
+
],
|
|
1374
|
+
"params": [
|
|
1375
|
+
{
|
|
1376
|
+
"name": "url",
|
|
1377
|
+
"type": "string",
|
|
1378
|
+
"required": false,
|
|
1379
|
+
"anyOf": true
|
|
1380
|
+
},
|
|
1381
|
+
{
|
|
1382
|
+
"name": "id",
|
|
1383
|
+
"type": "string",
|
|
1384
|
+
"required": false,
|
|
1385
|
+
"anyOf": true
|
|
1386
|
+
}
|
|
1387
|
+
]
|
|
1388
|
+
},
|
|
1389
|
+
{
|
|
1390
|
+
"platform": "facebook",
|
|
1391
|
+
"action": "events-search",
|
|
1392
|
+
"resource": "events/search",
|
|
1393
|
+
"version": "v1",
|
|
1394
|
+
"method": "GET",
|
|
1395
|
+
"path": "/v1/facebook/events/search",
|
|
1396
|
+
"toolName": "v1_facebook_events_search",
|
|
1397
|
+
"summary": "Search Facebook events by query.",
|
|
1398
|
+
"cost": 1,
|
|
1399
|
+
"live": false,
|
|
1400
|
+
"anyOf": [],
|
|
1401
|
+
"params": [
|
|
1402
|
+
{
|
|
1403
|
+
"name": "query",
|
|
1404
|
+
"type": "string",
|
|
1405
|
+
"required": true,
|
|
1406
|
+
"anyOf": false
|
|
1407
|
+
},
|
|
1408
|
+
{
|
|
1409
|
+
"name": "url",
|
|
1410
|
+
"type": "string",
|
|
1411
|
+
"required": false,
|
|
1412
|
+
"anyOf": false
|
|
1413
|
+
}
|
|
1414
|
+
]
|
|
1415
|
+
},
|
|
1416
|
+
{
|
|
1417
|
+
"platform": "facebook",
|
|
1418
|
+
"action": "events",
|
|
1419
|
+
"resource": "events",
|
|
1420
|
+
"version": "v1",
|
|
1421
|
+
"method": "GET",
|
|
1422
|
+
"path": "/v1/facebook/events",
|
|
1423
|
+
"toolName": "v1_facebook_events",
|
|
1424
|
+
"summary": "Get Facebook events for a location/query.",
|
|
1425
|
+
"cost": 1,
|
|
1426
|
+
"live": false,
|
|
1427
|
+
"anyOf": [
|
|
1428
|
+
[
|
|
1429
|
+
"query",
|
|
1430
|
+
"location"
|
|
1431
|
+
]
|
|
1432
|
+
],
|
|
1433
|
+
"params": [
|
|
1434
|
+
{
|
|
1435
|
+
"name": "query",
|
|
1436
|
+
"type": "string",
|
|
1437
|
+
"required": false,
|
|
1438
|
+
"anyOf": true
|
|
1439
|
+
},
|
|
1440
|
+
{
|
|
1441
|
+
"name": "location",
|
|
1442
|
+
"type": "string",
|
|
1443
|
+
"required": false,
|
|
1444
|
+
"anyOf": true
|
|
1445
|
+
},
|
|
1446
|
+
{
|
|
1447
|
+
"name": "url",
|
|
1448
|
+
"type": "string",
|
|
1449
|
+
"required": false,
|
|
1450
|
+
"anyOf": false
|
|
1451
|
+
}
|
|
1452
|
+
]
|
|
1453
|
+
},
|
|
1454
|
+
{
|
|
1455
|
+
"platform": "facebook",
|
|
1456
|
+
"action": "event-details",
|
|
1457
|
+
"resource": "event/details",
|
|
1458
|
+
"version": "v1",
|
|
1459
|
+
"method": "GET",
|
|
1460
|
+
"path": "/v1/facebook/event/details",
|
|
1461
|
+
"toolName": "v1_facebook_event_details",
|
|
1462
|
+
"summary": "Get details of a single Facebook event by URL/id.",
|
|
1463
|
+
"cost": 1,
|
|
1464
|
+
"live": false,
|
|
1465
|
+
"anyOf": [
|
|
1466
|
+
[
|
|
1467
|
+
"url",
|
|
1468
|
+
"id"
|
|
1469
|
+
]
|
|
1470
|
+
],
|
|
1471
|
+
"params": [
|
|
1472
|
+
{
|
|
1473
|
+
"name": "url",
|
|
1474
|
+
"type": "string",
|
|
1475
|
+
"required": false,
|
|
1476
|
+
"anyOf": true
|
|
1477
|
+
},
|
|
1478
|
+
{
|
|
1479
|
+
"name": "id",
|
|
1480
|
+
"type": "string",
|
|
1481
|
+
"required": false,
|
|
1482
|
+
"anyOf": true
|
|
1483
|
+
}
|
|
1484
|
+
]
|
|
1485
|
+
},
|
|
1486
|
+
{
|
|
1487
|
+
"platform": "facebook",
|
|
1488
|
+
"action": "adLibrary-ad",
|
|
1489
|
+
"resource": "adLibrary/ad",
|
|
1490
|
+
"version": "v1",
|
|
1491
|
+
"method": "GET",
|
|
1492
|
+
"path": "/v1/facebook/adLibrary/ad",
|
|
1493
|
+
"toolName": "v1_facebook_adLibrary_ad",
|
|
1494
|
+
"summary": "Get details of a Facebook Ad Library ad by id/URL.",
|
|
1495
|
+
"cost": 1,
|
|
1496
|
+
"live": false,
|
|
1497
|
+
"anyOf": [
|
|
1498
|
+
[
|
|
1499
|
+
"url",
|
|
1500
|
+
"id"
|
|
1501
|
+
]
|
|
1502
|
+
],
|
|
1503
|
+
"params": [
|
|
1504
|
+
{
|
|
1505
|
+
"name": "url",
|
|
1506
|
+
"type": "string",
|
|
1507
|
+
"required": false,
|
|
1508
|
+
"anyOf": true
|
|
1509
|
+
},
|
|
1510
|
+
{
|
|
1511
|
+
"name": "id",
|
|
1512
|
+
"type": "string",
|
|
1513
|
+
"required": false,
|
|
1514
|
+
"anyOf": true
|
|
1515
|
+
}
|
|
1516
|
+
]
|
|
1517
|
+
},
|
|
1518
|
+
{
|
|
1519
|
+
"platform": "facebook",
|
|
1520
|
+
"action": "adLibrary-ad-transcript",
|
|
1521
|
+
"resource": "adLibrary/ad/transcript",
|
|
1522
|
+
"version": "v1",
|
|
1523
|
+
"method": "GET",
|
|
1524
|
+
"path": "/v1/facebook/adLibrary/ad/transcript",
|
|
1525
|
+
"toolName": "v1_facebook_adLibrary_ad_transcript",
|
|
1526
|
+
"summary": "Get the transcript of a Facebook Ad Library video ad.",
|
|
1527
|
+
"cost": 1,
|
|
1528
|
+
"live": false,
|
|
1529
|
+
"anyOf": [
|
|
1530
|
+
[
|
|
1531
|
+
"url",
|
|
1532
|
+
"id"
|
|
1533
|
+
]
|
|
1534
|
+
],
|
|
1535
|
+
"params": [
|
|
1536
|
+
{
|
|
1537
|
+
"name": "url",
|
|
1538
|
+
"type": "string",
|
|
1539
|
+
"required": false,
|
|
1540
|
+
"anyOf": true
|
|
1541
|
+
},
|
|
1542
|
+
{
|
|
1543
|
+
"name": "id",
|
|
1544
|
+
"type": "string",
|
|
1545
|
+
"required": false,
|
|
1546
|
+
"anyOf": true
|
|
1547
|
+
}
|
|
1548
|
+
]
|
|
1549
|
+
},
|
|
1550
|
+
{
|
|
1551
|
+
"platform": "facebook",
|
|
1552
|
+
"action": "adLibrary-search-ads",
|
|
1553
|
+
"resource": "adLibrary/search/ads",
|
|
1554
|
+
"version": "v1",
|
|
1555
|
+
"method": "GET",
|
|
1556
|
+
"path": "/v1/facebook/adLibrary/search/ads",
|
|
1557
|
+
"toolName": "v1_facebook_adLibrary_search_ads",
|
|
1558
|
+
"summary": "Search Facebook Ad Library ads.",
|
|
1559
|
+
"cost": 1,
|
|
1560
|
+
"live": false,
|
|
1561
|
+
"anyOf": [
|
|
1562
|
+
[
|
|
1563
|
+
"query",
|
|
1564
|
+
"pageId"
|
|
1565
|
+
]
|
|
1566
|
+
],
|
|
1567
|
+
"params": [
|
|
1568
|
+
{
|
|
1569
|
+
"name": "query",
|
|
1570
|
+
"type": "string",
|
|
1571
|
+
"required": false,
|
|
1572
|
+
"anyOf": true
|
|
1573
|
+
},
|
|
1574
|
+
{
|
|
1575
|
+
"name": "pageId",
|
|
1576
|
+
"type": "string",
|
|
1577
|
+
"required": false,
|
|
1578
|
+
"anyOf": true
|
|
1579
|
+
},
|
|
1580
|
+
{
|
|
1581
|
+
"name": "url",
|
|
1582
|
+
"type": "string",
|
|
1583
|
+
"required": false,
|
|
1584
|
+
"anyOf": false
|
|
1585
|
+
}
|
|
1586
|
+
]
|
|
1587
|
+
},
|
|
1588
|
+
{
|
|
1589
|
+
"platform": "facebook",
|
|
1590
|
+
"action": "adLibrary-company-ads",
|
|
1591
|
+
"resource": "adLibrary/company/ads",
|
|
1592
|
+
"version": "v1",
|
|
1593
|
+
"method": "GET",
|
|
1594
|
+
"path": "/v1/facebook/adLibrary/company/ads",
|
|
1595
|
+
"toolName": "v1_facebook_adLibrary_company_ads",
|
|
1596
|
+
"summary": "Get all ads a company is running in the Facebook Ad Library.",
|
|
1597
|
+
"cost": 1,
|
|
1598
|
+
"live": false,
|
|
1599
|
+
"anyOf": [
|
|
1600
|
+
[
|
|
1601
|
+
"pageId",
|
|
1602
|
+
"url"
|
|
1603
|
+
]
|
|
1604
|
+
],
|
|
1605
|
+
"params": [
|
|
1606
|
+
{
|
|
1607
|
+
"name": "pageId",
|
|
1608
|
+
"type": "string",
|
|
1609
|
+
"required": false,
|
|
1610
|
+
"anyOf": true
|
|
1611
|
+
},
|
|
1612
|
+
{
|
|
1613
|
+
"name": "url",
|
|
1614
|
+
"type": "string",
|
|
1615
|
+
"required": false,
|
|
1616
|
+
"anyOf": true
|
|
1617
|
+
}
|
|
1618
|
+
]
|
|
1619
|
+
},
|
|
1620
|
+
{
|
|
1621
|
+
"platform": "facebook",
|
|
1622
|
+
"action": "adLibrary-search-companies",
|
|
1623
|
+
"resource": "adLibrary/search/companies",
|
|
1624
|
+
"version": "v1",
|
|
1625
|
+
"method": "GET",
|
|
1626
|
+
"path": "/v1/facebook/adLibrary/search/companies",
|
|
1627
|
+
"toolName": "v1_facebook_adLibrary_search_companies",
|
|
1628
|
+
"summary": "Search companies in the Facebook Ad Library.",
|
|
1629
|
+
"cost": 1,
|
|
1630
|
+
"live": false,
|
|
1631
|
+
"anyOf": [],
|
|
1632
|
+
"params": [
|
|
1633
|
+
{
|
|
1634
|
+
"name": "query",
|
|
1635
|
+
"type": "string",
|
|
1636
|
+
"required": true,
|
|
1637
|
+
"anyOf": false
|
|
1638
|
+
},
|
|
1639
|
+
{
|
|
1640
|
+
"name": "url",
|
|
1641
|
+
"type": "string",
|
|
1642
|
+
"required": false,
|
|
1643
|
+
"anyOf": false
|
|
1644
|
+
}
|
|
1645
|
+
]
|
|
1646
|
+
},
|
|
1647
|
+
{
|
|
1648
|
+
"platform": "linkedin",
|
|
1649
|
+
"action": "profile",
|
|
1650
|
+
"resource": "profile",
|
|
1651
|
+
"version": "v1",
|
|
1652
|
+
"method": "GET",
|
|
1653
|
+
"path": "/v1/linkedin/profile",
|
|
1654
|
+
"toolName": "v1_linkedin_profile",
|
|
1655
|
+
"summary": "Get a LinkedIn member's public profile by URL.",
|
|
1656
|
+
"cost": 1,
|
|
1657
|
+
"live": true,
|
|
1658
|
+
"anyOf": [],
|
|
1659
|
+
"params": [
|
|
1660
|
+
{
|
|
1661
|
+
"name": "url",
|
|
1662
|
+
"type": "string",
|
|
1663
|
+
"required": true,
|
|
1664
|
+
"anyOf": false
|
|
1665
|
+
}
|
|
1666
|
+
]
|
|
1667
|
+
},
|
|
1668
|
+
{
|
|
1669
|
+
"platform": "linkedin",
|
|
1670
|
+
"action": "company",
|
|
1671
|
+
"resource": "company",
|
|
1672
|
+
"version": "v1",
|
|
1673
|
+
"method": "GET",
|
|
1674
|
+
"path": "/v1/linkedin/company",
|
|
1675
|
+
"toolName": "v1_linkedin_company",
|
|
1676
|
+
"summary": "Get a LinkedIn company page by URL.",
|
|
1677
|
+
"cost": 1,
|
|
1678
|
+
"live": true,
|
|
1679
|
+
"anyOf": [],
|
|
1680
|
+
"params": [
|
|
1681
|
+
{
|
|
1682
|
+
"name": "url",
|
|
1683
|
+
"type": "string",
|
|
1684
|
+
"required": true,
|
|
1685
|
+
"anyOf": false
|
|
1686
|
+
}
|
|
1687
|
+
]
|
|
1688
|
+
},
|
|
1689
|
+
{
|
|
1690
|
+
"platform": "linkedin",
|
|
1691
|
+
"action": "company-posts",
|
|
1692
|
+
"resource": "company/posts",
|
|
1693
|
+
"version": "v1",
|
|
1694
|
+
"method": "GET",
|
|
1695
|
+
"path": "/v1/linkedin/company/posts",
|
|
1696
|
+
"toolName": "v1_linkedin_company_posts",
|
|
1697
|
+
"summary": "Get a LinkedIn company's posts (page 1 via guest; deeper pages via Voyager).",
|
|
1698
|
+
"cost": 1,
|
|
1699
|
+
"live": true,
|
|
1700
|
+
"anyOf": [],
|
|
1701
|
+
"params": [
|
|
1702
|
+
{
|
|
1703
|
+
"name": "url",
|
|
1704
|
+
"type": "string",
|
|
1705
|
+
"required": true,
|
|
1706
|
+
"anyOf": false
|
|
1707
|
+
}
|
|
1708
|
+
]
|
|
1709
|
+
},
|
|
1710
|
+
{
|
|
1711
|
+
"platform": "linkedin",
|
|
1712
|
+
"action": "post",
|
|
1713
|
+
"resource": "post",
|
|
1714
|
+
"version": "v1",
|
|
1715
|
+
"method": "GET",
|
|
1716
|
+
"path": "/v1/linkedin/post",
|
|
1717
|
+
"toolName": "v1_linkedin_post",
|
|
1718
|
+
"summary": "Get a single LinkedIn post or article by URL.",
|
|
1719
|
+
"cost": 1,
|
|
1720
|
+
"live": true,
|
|
1721
|
+
"anyOf": [],
|
|
1722
|
+
"params": [
|
|
1723
|
+
{
|
|
1724
|
+
"name": "url",
|
|
1725
|
+
"type": "string",
|
|
1726
|
+
"required": true,
|
|
1727
|
+
"anyOf": false
|
|
1728
|
+
}
|
|
1729
|
+
]
|
|
1730
|
+
},
|
|
1731
|
+
{
|
|
1732
|
+
"platform": "linkedin",
|
|
1733
|
+
"action": "post-transcript",
|
|
1734
|
+
"resource": "post/transcript",
|
|
1735
|
+
"version": "v1",
|
|
1736
|
+
"method": "GET",
|
|
1737
|
+
"path": "/v1/linkedin/post/transcript",
|
|
1738
|
+
"toolName": "v1_linkedin_post_transcript",
|
|
1739
|
+
"summary": "Get the transcript of a LinkedIn video post by URL.",
|
|
1740
|
+
"cost": 1,
|
|
1741
|
+
"live": true,
|
|
1742
|
+
"anyOf": [],
|
|
1743
|
+
"params": [
|
|
1744
|
+
{
|
|
1745
|
+
"name": "url",
|
|
1746
|
+
"type": "string",
|
|
1747
|
+
"required": true,
|
|
1748
|
+
"anyOf": false
|
|
1749
|
+
}
|
|
1750
|
+
]
|
|
1751
|
+
},
|
|
1752
|
+
{
|
|
1753
|
+
"platform": "linkedin",
|
|
1754
|
+
"action": "search-posts",
|
|
1755
|
+
"resource": "search/posts",
|
|
1756
|
+
"version": "v1",
|
|
1757
|
+
"method": "GET",
|
|
1758
|
+
"path": "/v1/linkedin/search/posts",
|
|
1759
|
+
"toolName": "v1_linkedin_search_posts",
|
|
1760
|
+
"summary": "Search LinkedIn posts by keyword (authenticated Voyager API).",
|
|
1761
|
+
"cost": 1,
|
|
1762
|
+
"live": true,
|
|
1763
|
+
"anyOf": [],
|
|
1764
|
+
"params": [
|
|
1765
|
+
{
|
|
1766
|
+
"name": "query",
|
|
1767
|
+
"type": "string",
|
|
1768
|
+
"required": true,
|
|
1769
|
+
"anyOf": false
|
|
1770
|
+
},
|
|
1771
|
+
{
|
|
1772
|
+
"name": "url",
|
|
1773
|
+
"type": "string",
|
|
1774
|
+
"required": false,
|
|
1775
|
+
"anyOf": false
|
|
1776
|
+
}
|
|
1777
|
+
]
|
|
1778
|
+
},
|
|
1779
|
+
{
|
|
1780
|
+
"platform": "twitter",
|
|
1781
|
+
"action": "profile",
|
|
1782
|
+
"resource": "profile",
|
|
1783
|
+
"version": "v1",
|
|
1784
|
+
"method": "GET",
|
|
1785
|
+
"path": "/v1/twitter/profile",
|
|
1786
|
+
"toolName": "v1_twitter_profile",
|
|
1787
|
+
"summary": "Get an X/Twitter user's profile (stats, verification, metadata) by handle.",
|
|
1788
|
+
"cost": 1,
|
|
1789
|
+
"live": true,
|
|
1790
|
+
"anyOf": [
|
|
1791
|
+
[
|
|
1792
|
+
"handle"
|
|
1793
|
+
]
|
|
1794
|
+
],
|
|
1795
|
+
"params": [
|
|
1796
|
+
{
|
|
1797
|
+
"name": "handle",
|
|
1798
|
+
"type": "string",
|
|
1799
|
+
"required": false,
|
|
1800
|
+
"anyOf": true
|
|
1801
|
+
}
|
|
1802
|
+
]
|
|
1803
|
+
},
|
|
1804
|
+
{
|
|
1805
|
+
"platform": "twitter",
|
|
1806
|
+
"action": "user-tweets",
|
|
1807
|
+
"resource": "user-tweets",
|
|
1808
|
+
"version": "v1",
|
|
1809
|
+
"method": "GET",
|
|
1810
|
+
"path": "/v1/twitter/user-tweets",
|
|
1811
|
+
"toolName": "v1_twitter_user_tweets",
|
|
1812
|
+
"summary": "Get an X/Twitter user's tweets by handle. Guest access returns the ~100 most popular tweets.",
|
|
1813
|
+
"cost": 1,
|
|
1814
|
+
"live": true,
|
|
1815
|
+
"anyOf": [
|
|
1816
|
+
[
|
|
1817
|
+
"handle"
|
|
1818
|
+
]
|
|
1819
|
+
],
|
|
1820
|
+
"params": [
|
|
1821
|
+
{
|
|
1822
|
+
"name": "handle",
|
|
1823
|
+
"type": "string",
|
|
1824
|
+
"required": false,
|
|
1825
|
+
"anyOf": true
|
|
1826
|
+
}
|
|
1827
|
+
]
|
|
1828
|
+
},
|
|
1829
|
+
{
|
|
1830
|
+
"platform": "twitter",
|
|
1831
|
+
"action": "tweet",
|
|
1832
|
+
"resource": "tweet",
|
|
1833
|
+
"version": "v1",
|
|
1834
|
+
"method": "GET",
|
|
1835
|
+
"path": "/v1/twitter/tweet",
|
|
1836
|
+
"toolName": "v1_twitter_tweet",
|
|
1837
|
+
"summary": "Get a single X/Twitter tweet (content + engagement + author) by URL.",
|
|
1838
|
+
"cost": 1,
|
|
1839
|
+
"live": true,
|
|
1840
|
+
"anyOf": [],
|
|
1841
|
+
"params": [
|
|
1842
|
+
{
|
|
1843
|
+
"name": "url",
|
|
1844
|
+
"type": "string",
|
|
1845
|
+
"required": true,
|
|
1846
|
+
"anyOf": false
|
|
1847
|
+
},
|
|
1848
|
+
{
|
|
1849
|
+
"name": "handle",
|
|
1850
|
+
"type": "string",
|
|
1851
|
+
"required": false,
|
|
1852
|
+
"anyOf": false
|
|
1853
|
+
}
|
|
1854
|
+
]
|
|
1855
|
+
},
|
|
1856
|
+
{
|
|
1857
|
+
"platform": "twitter",
|
|
1858
|
+
"action": "tweet-transcript",
|
|
1859
|
+
"resource": "tweet/transcript",
|
|
1860
|
+
"version": "v1",
|
|
1861
|
+
"method": "GET",
|
|
1862
|
+
"path": "/v1/twitter/tweet/transcript",
|
|
1863
|
+
"toolName": "v1_twitter_tweet_transcript",
|
|
1864
|
+
"summary": "Get the transcript of a video tweet by URL.",
|
|
1865
|
+
"cost": 1,
|
|
1866
|
+
"live": false,
|
|
1867
|
+
"anyOf": [],
|
|
1868
|
+
"params": [
|
|
1869
|
+
{
|
|
1870
|
+
"name": "url",
|
|
1871
|
+
"type": "string",
|
|
1872
|
+
"required": true,
|
|
1873
|
+
"anyOf": false
|
|
1874
|
+
},
|
|
1875
|
+
{
|
|
1876
|
+
"name": "handle",
|
|
1877
|
+
"type": "string",
|
|
1878
|
+
"required": false,
|
|
1879
|
+
"anyOf": false
|
|
1880
|
+
}
|
|
1881
|
+
]
|
|
1882
|
+
},
|
|
1883
|
+
{
|
|
1884
|
+
"platform": "twitter",
|
|
1885
|
+
"action": "community",
|
|
1886
|
+
"resource": "community",
|
|
1887
|
+
"version": "v1",
|
|
1888
|
+
"method": "GET",
|
|
1889
|
+
"path": "/v1/twitter/community",
|
|
1890
|
+
"toolName": "v1_twitter_community",
|
|
1891
|
+
"summary": "Get an X/Twitter Community by id or URL.",
|
|
1892
|
+
"cost": 1,
|
|
1893
|
+
"live": false,
|
|
1894
|
+
"anyOf": [
|
|
1895
|
+
[
|
|
1896
|
+
"id",
|
|
1897
|
+
"url"
|
|
1898
|
+
]
|
|
1899
|
+
],
|
|
1900
|
+
"params": [
|
|
1901
|
+
{
|
|
1902
|
+
"name": "id",
|
|
1903
|
+
"type": "string",
|
|
1904
|
+
"required": false,
|
|
1905
|
+
"anyOf": true
|
|
1906
|
+
},
|
|
1907
|
+
{
|
|
1908
|
+
"name": "url",
|
|
1909
|
+
"type": "string",
|
|
1910
|
+
"required": false,
|
|
1911
|
+
"anyOf": true
|
|
1912
|
+
},
|
|
1913
|
+
{
|
|
1914
|
+
"name": "handle",
|
|
1915
|
+
"type": "string",
|
|
1916
|
+
"required": false,
|
|
1917
|
+
"anyOf": false
|
|
1918
|
+
}
|
|
1919
|
+
]
|
|
1920
|
+
},
|
|
1921
|
+
{
|
|
1922
|
+
"platform": "twitter",
|
|
1923
|
+
"action": "community-tweets",
|
|
1924
|
+
"resource": "community/tweets",
|
|
1925
|
+
"version": "v1",
|
|
1926
|
+
"method": "GET",
|
|
1927
|
+
"path": "/v1/twitter/community/tweets",
|
|
1928
|
+
"toolName": "v1_twitter_community_tweets",
|
|
1929
|
+
"summary": "Get the tweets of an X/Twitter Community (paginated via cursor).",
|
|
1930
|
+
"cost": 1,
|
|
1931
|
+
"live": false,
|
|
1932
|
+
"anyOf": [
|
|
1933
|
+
[
|
|
1934
|
+
"id",
|
|
1935
|
+
"url"
|
|
1936
|
+
]
|
|
1937
|
+
],
|
|
1938
|
+
"params": [
|
|
1939
|
+
{
|
|
1940
|
+
"name": "id",
|
|
1941
|
+
"type": "string",
|
|
1942
|
+
"required": false,
|
|
1943
|
+
"anyOf": true
|
|
1944
|
+
},
|
|
1945
|
+
{
|
|
1946
|
+
"name": "url",
|
|
1947
|
+
"type": "string",
|
|
1948
|
+
"required": false,
|
|
1949
|
+
"anyOf": true
|
|
1950
|
+
},
|
|
1951
|
+
{
|
|
1952
|
+
"name": "handle",
|
|
1953
|
+
"type": "string",
|
|
1954
|
+
"required": false,
|
|
1955
|
+
"anyOf": false
|
|
1956
|
+
}
|
|
1957
|
+
]
|
|
1958
|
+
},
|
|
1959
|
+
{
|
|
1960
|
+
"platform": "spotify",
|
|
1961
|
+
"action": "artist",
|
|
1962
|
+
"resource": "artist",
|
|
1963
|
+
"version": "v1",
|
|
1964
|
+
"method": "GET",
|
|
1965
|
+
"path": "/v1/spotify/artist",
|
|
1966
|
+
"toolName": "v1_spotify_artist",
|
|
1967
|
+
"summary": "Get a Spotify artist (profile, stats, discography) by URL or id.",
|
|
1968
|
+
"cost": 1,
|
|
1969
|
+
"live": true,
|
|
1970
|
+
"anyOf": [
|
|
1971
|
+
[
|
|
1972
|
+
"url",
|
|
1973
|
+
"id"
|
|
1974
|
+
]
|
|
1975
|
+
],
|
|
1976
|
+
"params": [
|
|
1977
|
+
{
|
|
1978
|
+
"name": "url",
|
|
1979
|
+
"type": "string",
|
|
1980
|
+
"required": false,
|
|
1981
|
+
"anyOf": true
|
|
1982
|
+
},
|
|
1983
|
+
{
|
|
1984
|
+
"name": "id",
|
|
1985
|
+
"type": "string",
|
|
1986
|
+
"required": false,
|
|
1987
|
+
"anyOf": true
|
|
1988
|
+
}
|
|
1989
|
+
]
|
|
1990
|
+
},
|
|
1991
|
+
{
|
|
1992
|
+
"platform": "spotify",
|
|
1993
|
+
"action": "track",
|
|
1994
|
+
"resource": "track",
|
|
1995
|
+
"version": "v1",
|
|
1996
|
+
"method": "GET",
|
|
1997
|
+
"path": "/v1/spotify/track",
|
|
1998
|
+
"toolName": "v1_spotify_track",
|
|
1999
|
+
"summary": "Get a single Spotify track by URL or id.",
|
|
2000
|
+
"cost": 1,
|
|
2001
|
+
"live": true,
|
|
2002
|
+
"anyOf": [
|
|
2003
|
+
[
|
|
2004
|
+
"url",
|
|
2005
|
+
"id"
|
|
2006
|
+
]
|
|
2007
|
+
],
|
|
2008
|
+
"params": [
|
|
2009
|
+
{
|
|
2010
|
+
"name": "url",
|
|
2011
|
+
"type": "string",
|
|
2012
|
+
"required": false,
|
|
2013
|
+
"anyOf": true
|
|
2014
|
+
},
|
|
2015
|
+
{
|
|
2016
|
+
"name": "id",
|
|
2017
|
+
"type": "string",
|
|
2018
|
+
"required": false,
|
|
2019
|
+
"anyOf": true
|
|
2020
|
+
}
|
|
2021
|
+
]
|
|
2022
|
+
},
|
|
2023
|
+
{
|
|
2024
|
+
"platform": "spotify",
|
|
2025
|
+
"action": "album",
|
|
2026
|
+
"resource": "album",
|
|
2027
|
+
"version": "v1",
|
|
2028
|
+
"method": "GET",
|
|
2029
|
+
"path": "/v1/spotify/album",
|
|
2030
|
+
"toolName": "v1_spotify_album",
|
|
2031
|
+
"summary": "Get a Spotify album (with tracks) by URL or id.",
|
|
2032
|
+
"cost": 1,
|
|
2033
|
+
"live": true,
|
|
2034
|
+
"anyOf": [
|
|
2035
|
+
[
|
|
2036
|
+
"url",
|
|
2037
|
+
"id"
|
|
2038
|
+
]
|
|
2039
|
+
],
|
|
2040
|
+
"params": [
|
|
2041
|
+
{
|
|
2042
|
+
"name": "url",
|
|
2043
|
+
"type": "string",
|
|
2044
|
+
"required": false,
|
|
2045
|
+
"anyOf": true
|
|
2046
|
+
},
|
|
2047
|
+
{
|
|
2048
|
+
"name": "id",
|
|
2049
|
+
"type": "string",
|
|
2050
|
+
"required": false,
|
|
2051
|
+
"anyOf": true
|
|
2052
|
+
}
|
|
2053
|
+
]
|
|
2054
|
+
},
|
|
2055
|
+
{
|
|
2056
|
+
"platform": "spotify",
|
|
2057
|
+
"action": "search",
|
|
2058
|
+
"resource": "search",
|
|
2059
|
+
"version": "v1",
|
|
2060
|
+
"method": "GET",
|
|
2061
|
+
"path": "/v1/spotify/search",
|
|
2062
|
+
"toolName": "v1_spotify_search",
|
|
2063
|
+
"summary": "Search Spotify across artists, albums, tracks, playlists, podcasts and episodes.",
|
|
2064
|
+
"cost": 1,
|
|
2065
|
+
"live": true,
|
|
2066
|
+
"anyOf": [],
|
|
2067
|
+
"params": [
|
|
2068
|
+
{
|
|
2069
|
+
"name": "query",
|
|
2070
|
+
"type": "string",
|
|
2071
|
+
"required": true,
|
|
2072
|
+
"anyOf": false
|
|
2073
|
+
},
|
|
2074
|
+
{
|
|
2075
|
+
"name": "url",
|
|
2076
|
+
"type": "string",
|
|
2077
|
+
"required": false,
|
|
2078
|
+
"anyOf": false
|
|
2079
|
+
}
|
|
2080
|
+
]
|
|
2081
|
+
},
|
|
2082
|
+
{
|
|
2083
|
+
"platform": "spotify",
|
|
2084
|
+
"action": "podcast",
|
|
2085
|
+
"resource": "podcast",
|
|
2086
|
+
"version": "v1",
|
|
2087
|
+
"method": "GET",
|
|
2088
|
+
"path": "/v1/spotify/podcast",
|
|
2089
|
+
"toolName": "v1_spotify_podcast",
|
|
2090
|
+
"summary": "Get a Spotify podcast/show's metadata by URL or id.",
|
|
2091
|
+
"cost": 1,
|
|
2092
|
+
"live": true,
|
|
2093
|
+
"anyOf": [
|
|
2094
|
+
[
|
|
2095
|
+
"url",
|
|
2096
|
+
"id"
|
|
2097
|
+
]
|
|
2098
|
+
],
|
|
2099
|
+
"params": [
|
|
2100
|
+
{
|
|
2101
|
+
"name": "url",
|
|
2102
|
+
"type": "string",
|
|
2103
|
+
"required": false,
|
|
2104
|
+
"anyOf": true
|
|
2105
|
+
},
|
|
2106
|
+
{
|
|
2107
|
+
"name": "id",
|
|
2108
|
+
"type": "string",
|
|
2109
|
+
"required": false,
|
|
2110
|
+
"anyOf": true
|
|
2111
|
+
}
|
|
2112
|
+
]
|
|
2113
|
+
},
|
|
2114
|
+
{
|
|
2115
|
+
"platform": "spotify",
|
|
2116
|
+
"action": "podcast-episodes",
|
|
2117
|
+
"resource": "podcast/episodes",
|
|
2118
|
+
"version": "v1",
|
|
2119
|
+
"method": "GET",
|
|
2120
|
+
"path": "/v1/spotify/podcast/episodes",
|
|
2121
|
+
"toolName": "v1_spotify_podcast_episodes",
|
|
2122
|
+
"summary": "Get a Spotify podcast's episodes by URL or id (paginate via ?cursor=).",
|
|
2123
|
+
"cost": 1,
|
|
2124
|
+
"live": true,
|
|
2125
|
+
"anyOf": [
|
|
2126
|
+
[
|
|
2127
|
+
"url",
|
|
2128
|
+
"id"
|
|
2129
|
+
]
|
|
2130
|
+
],
|
|
2131
|
+
"params": [
|
|
2132
|
+
{
|
|
2133
|
+
"name": "url",
|
|
2134
|
+
"type": "string",
|
|
2135
|
+
"required": false,
|
|
2136
|
+
"anyOf": true
|
|
2137
|
+
},
|
|
2138
|
+
{
|
|
2139
|
+
"name": "id",
|
|
2140
|
+
"type": "string",
|
|
2141
|
+
"required": false,
|
|
2142
|
+
"anyOf": true
|
|
2143
|
+
}
|
|
2144
|
+
]
|
|
2145
|
+
},
|
|
2146
|
+
{
|
|
2147
|
+
"platform": "applemusic",
|
|
2148
|
+
"action": "artist",
|
|
2149
|
+
"resource": "artist",
|
|
2150
|
+
"version": "v1",
|
|
2151
|
+
"method": "GET",
|
|
2152
|
+
"path": "/v1/applemusic/artist",
|
|
2153
|
+
"toolName": "v1_applemusic_artist",
|
|
2154
|
+
"summary": "Get an Apple Music artist (profile, top songs, discography) by URL or id.",
|
|
2155
|
+
"cost": 1,
|
|
2156
|
+
"live": true,
|
|
2157
|
+
"anyOf": [
|
|
2158
|
+
[
|
|
2159
|
+
"url",
|
|
2160
|
+
"id"
|
|
2161
|
+
]
|
|
2162
|
+
],
|
|
2163
|
+
"params": [
|
|
2164
|
+
{
|
|
2165
|
+
"name": "url",
|
|
2166
|
+
"type": "string",
|
|
2167
|
+
"required": false,
|
|
2168
|
+
"anyOf": true
|
|
2169
|
+
},
|
|
2170
|
+
{
|
|
2171
|
+
"name": "id",
|
|
2172
|
+
"type": "string",
|
|
2173
|
+
"required": false,
|
|
2174
|
+
"anyOf": true
|
|
2175
|
+
}
|
|
2176
|
+
]
|
|
2177
|
+
},
|
|
2178
|
+
{
|
|
2179
|
+
"platform": "applemusic",
|
|
2180
|
+
"action": "album",
|
|
2181
|
+
"resource": "album",
|
|
2182
|
+
"version": "v1",
|
|
2183
|
+
"method": "GET",
|
|
2184
|
+
"path": "/v1/applemusic/album",
|
|
2185
|
+
"toolName": "v1_applemusic_album",
|
|
2186
|
+
"summary": "Get an Apple Music album (metadata + full tracklist) by URL or id.",
|
|
2187
|
+
"cost": 1,
|
|
2188
|
+
"live": true,
|
|
2189
|
+
"anyOf": [
|
|
2190
|
+
[
|
|
2191
|
+
"url",
|
|
2192
|
+
"id"
|
|
2193
|
+
]
|
|
2194
|
+
],
|
|
2195
|
+
"params": [
|
|
2196
|
+
{
|
|
2197
|
+
"name": "url",
|
|
2198
|
+
"type": "string",
|
|
2199
|
+
"required": false,
|
|
2200
|
+
"anyOf": true
|
|
2201
|
+
},
|
|
2202
|
+
{
|
|
2203
|
+
"name": "id",
|
|
2204
|
+
"type": "string",
|
|
2205
|
+
"required": false,
|
|
2206
|
+
"anyOf": true
|
|
2207
|
+
}
|
|
2208
|
+
]
|
|
2209
|
+
},
|
|
2210
|
+
{
|
|
2211
|
+
"platform": "applemusic",
|
|
2212
|
+
"action": "track",
|
|
2213
|
+
"resource": "track",
|
|
2214
|
+
"version": "v1",
|
|
2215
|
+
"method": "GET",
|
|
2216
|
+
"path": "/v1/applemusic/track",
|
|
2217
|
+
"toolName": "v1_applemusic_track",
|
|
2218
|
+
"summary": "Get a single Apple Music song by URL or id.",
|
|
2219
|
+
"cost": 1,
|
|
2220
|
+
"live": true,
|
|
2221
|
+
"anyOf": [
|
|
2222
|
+
[
|
|
2223
|
+
"url",
|
|
2224
|
+
"id"
|
|
2225
|
+
]
|
|
2226
|
+
],
|
|
2227
|
+
"params": [
|
|
2228
|
+
{
|
|
2229
|
+
"name": "url",
|
|
2230
|
+
"type": "string",
|
|
2231
|
+
"required": false,
|
|
2232
|
+
"anyOf": true
|
|
2233
|
+
},
|
|
2234
|
+
{
|
|
2235
|
+
"name": "id",
|
|
2236
|
+
"type": "string",
|
|
2237
|
+
"required": false,
|
|
2238
|
+
"anyOf": true
|
|
2239
|
+
}
|
|
2240
|
+
]
|
|
2241
|
+
},
|
|
2242
|
+
{
|
|
2243
|
+
"platform": "applemusic",
|
|
2244
|
+
"action": "search",
|
|
2245
|
+
"resource": "search",
|
|
2246
|
+
"version": "v1",
|
|
2247
|
+
"method": "GET",
|
|
2248
|
+
"path": "/v1/applemusic/search",
|
|
2249
|
+
"toolName": "v1_applemusic_search",
|
|
2250
|
+
"summary": "Search the Apple Music catalog (songs/albums/artists) by query.",
|
|
2251
|
+
"cost": 1,
|
|
2252
|
+
"live": true,
|
|
2253
|
+
"anyOf": [],
|
|
2254
|
+
"params": [
|
|
2255
|
+
{
|
|
2256
|
+
"name": "query",
|
|
2257
|
+
"type": "string",
|
|
2258
|
+
"required": true,
|
|
2259
|
+
"anyOf": false
|
|
2260
|
+
},
|
|
2261
|
+
{
|
|
2262
|
+
"name": "url",
|
|
2263
|
+
"type": "string",
|
|
2264
|
+
"required": false,
|
|
2265
|
+
"anyOf": false
|
|
2266
|
+
},
|
|
2267
|
+
{
|
|
2268
|
+
"name": "id",
|
|
2269
|
+
"type": "string",
|
|
2270
|
+
"required": false,
|
|
2271
|
+
"anyOf": false
|
|
2272
|
+
}
|
|
2273
|
+
]
|
|
2274
|
+
},
|
|
2275
|
+
{
|
|
2276
|
+
"platform": "kleinanzeigen",
|
|
2277
|
+
"action": "search",
|
|
2278
|
+
"resource": "search",
|
|
2279
|
+
"version": "v1",
|
|
2280
|
+
"method": "GET",
|
|
2281
|
+
"path": "/v1/kleinanzeigen/search",
|
|
2282
|
+
"toolName": "v1_kleinanzeigen_search",
|
|
2283
|
+
"summary": "Search Kleinanzeigen listings by keyword and/or category+location, with filters (price, ad/poster type, sort, distance) and pagination. Provide a `query`, a `categoryId`, or a `locationId` (any combination).",
|
|
2284
|
+
"cost": 1,
|
|
2285
|
+
"live": true,
|
|
2286
|
+
"anyOf": [
|
|
2287
|
+
[
|
|
2288
|
+
"query",
|
|
2289
|
+
"categoryId",
|
|
2290
|
+
"locationId"
|
|
2291
|
+
]
|
|
2292
|
+
],
|
|
2293
|
+
"params": [
|
|
2294
|
+
{
|
|
2295
|
+
"name": "query",
|
|
2296
|
+
"type": "string",
|
|
2297
|
+
"required": false,
|
|
2298
|
+
"anyOf": true,
|
|
2299
|
+
"description": "Free-text keyword. Optional when a categoryId/locationId is given.",
|
|
2300
|
+
"example": "fahrrad"
|
|
2301
|
+
},
|
|
2302
|
+
{
|
|
2303
|
+
"name": "categoryId",
|
|
2304
|
+
"type": "string",
|
|
2305
|
+
"required": false,
|
|
2306
|
+
"anyOf": true,
|
|
2307
|
+
"description": "Kleinanzeigen category id (e.g. 203 = Mietwohnungen). Browse without a keyword.",
|
|
2308
|
+
"example": "203"
|
|
2309
|
+
},
|
|
2310
|
+
{
|
|
2311
|
+
"name": "locationId",
|
|
2312
|
+
"type": "string",
|
|
2313
|
+
"required": false,
|
|
2314
|
+
"anyOf": true,
|
|
2315
|
+
"description": "Location id from the /locations endpoint (city or ZIP). Anchors the search + `distance`.",
|
|
2316
|
+
"example": "996"
|
|
2317
|
+
},
|
|
2318
|
+
{
|
|
2319
|
+
"name": "minPrice",
|
|
2320
|
+
"type": "string",
|
|
2321
|
+
"required": false,
|
|
2322
|
+
"anyOf": false,
|
|
2323
|
+
"description": "Minimum price in EUR.",
|
|
2324
|
+
"example": "50"
|
|
2325
|
+
},
|
|
2326
|
+
{
|
|
2327
|
+
"name": "maxPrice",
|
|
2328
|
+
"type": "string",
|
|
2329
|
+
"required": false,
|
|
2330
|
+
"anyOf": false,
|
|
2331
|
+
"description": "Maximum price in EUR.",
|
|
2332
|
+
"example": "1500"
|
|
2333
|
+
},
|
|
2334
|
+
{
|
|
2335
|
+
"name": "adType",
|
|
2336
|
+
"type": "string",
|
|
2337
|
+
"required": false,
|
|
2338
|
+
"anyOf": false,
|
|
2339
|
+
"description": "Listing type.",
|
|
2340
|
+
"enum": [
|
|
2341
|
+
"OFFERED",
|
|
2342
|
+
"WANTED"
|
|
2343
|
+
]
|
|
2344
|
+
},
|
|
2345
|
+
{
|
|
2346
|
+
"name": "posterType",
|
|
2347
|
+
"type": "string",
|
|
2348
|
+
"required": false,
|
|
2349
|
+
"anyOf": false,
|
|
2350
|
+
"description": "Seller type.",
|
|
2351
|
+
"enum": [
|
|
2352
|
+
"PRIVATE",
|
|
2353
|
+
"COMMERCIAL"
|
|
2354
|
+
]
|
|
2355
|
+
},
|
|
2356
|
+
{
|
|
2357
|
+
"name": "sortType",
|
|
2358
|
+
"type": "string",
|
|
2359
|
+
"required": false,
|
|
2360
|
+
"anyOf": false,
|
|
2361
|
+
"description": "Result ordering (default: newest first).",
|
|
2362
|
+
"enum": [
|
|
2363
|
+
"PRICE_ASCENDING",
|
|
2364
|
+
"PRICE_DESCENDING",
|
|
2365
|
+
"DATE_DESCENDING",
|
|
2366
|
+
"DISTANCE"
|
|
2367
|
+
]
|
|
2368
|
+
},
|
|
2369
|
+
{
|
|
2370
|
+
"name": "distance",
|
|
2371
|
+
"type": "string",
|
|
2372
|
+
"required": false,
|
|
2373
|
+
"anyOf": false,
|
|
2374
|
+
"description": "Search radius in km around locationId.",
|
|
2375
|
+
"example": "20"
|
|
2376
|
+
},
|
|
2377
|
+
{
|
|
2378
|
+
"name": "pictureRequired",
|
|
2379
|
+
"type": "string",
|
|
2380
|
+
"required": false,
|
|
2381
|
+
"anyOf": false,
|
|
2382
|
+
"description": "Only listings with at least one photo.",
|
|
2383
|
+
"enum": [
|
|
2384
|
+
"true",
|
|
2385
|
+
"false"
|
|
2386
|
+
]
|
|
2387
|
+
},
|
|
2388
|
+
{
|
|
2389
|
+
"name": "page",
|
|
2390
|
+
"type": "string",
|
|
2391
|
+
"required": false,
|
|
2392
|
+
"anyOf": false,
|
|
2393
|
+
"description": "0-based page index for pagination.",
|
|
2394
|
+
"example": "0"
|
|
2395
|
+
},
|
|
2396
|
+
{
|
|
2397
|
+
"name": "size",
|
|
2398
|
+
"type": "string",
|
|
2399
|
+
"required": false,
|
|
2400
|
+
"anyOf": false,
|
|
2401
|
+
"description": "Results per page (1\u201341, default 25).",
|
|
2402
|
+
"example": "25"
|
|
2403
|
+
}
|
|
2404
|
+
]
|
|
2405
|
+
},
|
|
2406
|
+
{
|
|
2407
|
+
"platform": "kleinanzeigen",
|
|
2408
|
+
"action": "ad",
|
|
2409
|
+
"resource": "ad",
|
|
2410
|
+
"version": "v1",
|
|
2411
|
+
"method": "GET",
|
|
2412
|
+
"path": "/v1/kleinanzeigen/ad",
|
|
2413
|
+
"toolName": "v1_kleinanzeigen_ad",
|
|
2414
|
+
"summary": "Get a single Kleinanzeigen listing (full detail: price, attributes, images, seller) by id or URL.",
|
|
2415
|
+
"cost": 1,
|
|
2416
|
+
"live": true,
|
|
2417
|
+
"anyOf": [
|
|
2418
|
+
[
|
|
2419
|
+
"id",
|
|
2420
|
+
"url"
|
|
2421
|
+
]
|
|
2422
|
+
],
|
|
2423
|
+
"params": [
|
|
2424
|
+
{
|
|
2425
|
+
"name": "id",
|
|
2426
|
+
"type": "string",
|
|
2427
|
+
"required": false,
|
|
2428
|
+
"anyOf": true,
|
|
2429
|
+
"description": "Numeric ad id.",
|
|
2430
|
+
"example": "3460253912"
|
|
2431
|
+
},
|
|
2432
|
+
{
|
|
2433
|
+
"name": "url",
|
|
2434
|
+
"type": "string",
|
|
2435
|
+
"required": false,
|
|
2436
|
+
"anyOf": true,
|
|
2437
|
+
"description": "Full listing URL (web or API) \u2014 the ad id is extracted from it.",
|
|
2438
|
+
"example": "https://www.kleinanzeigen.de/s-anzeige/\u2026/3460253912-203-996"
|
|
2439
|
+
}
|
|
2440
|
+
]
|
|
2441
|
+
},
|
|
2442
|
+
{
|
|
2443
|
+
"platform": "kleinanzeigen",
|
|
2444
|
+
"action": "locations",
|
|
2445
|
+
"resource": "locations",
|
|
2446
|
+
"version": "v1",
|
|
2447
|
+
"method": "GET",
|
|
2448
|
+
"path": "/v1/kleinanzeigen/locations",
|
|
2449
|
+
"toolName": "v1_kleinanzeigen_locations",
|
|
2450
|
+
"summary": "Resolve a place name (city / ZIP) to Kleinanzeigen locationId(s) for the search `locationId` filter.",
|
|
2451
|
+
"cost": 1,
|
|
2452
|
+
"live": true,
|
|
2453
|
+
"anyOf": [],
|
|
2454
|
+
"params": [
|
|
2455
|
+
{
|
|
2456
|
+
"name": "query",
|
|
2457
|
+
"type": "string",
|
|
2458
|
+
"required": true,
|
|
2459
|
+
"anyOf": false,
|
|
2460
|
+
"description": "City name or ZIP code to resolve.",
|
|
2461
|
+
"example": "51063"
|
|
2462
|
+
},
|
|
2463
|
+
{
|
|
2464
|
+
"name": "depth",
|
|
2465
|
+
"type": "string",
|
|
2466
|
+
"required": false,
|
|
2467
|
+
"anyOf": false,
|
|
2468
|
+
"description": "How many sub-location levels to include (0 = the matched locations only).",
|
|
2469
|
+
"example": "0"
|
|
2470
|
+
}
|
|
2471
|
+
]
|
|
2472
|
+
},
|
|
2473
|
+
{
|
|
2474
|
+
"platform": "11880",
|
|
2475
|
+
"action": "search",
|
|
2476
|
+
"resource": "search",
|
|
2477
|
+
"version": "v1",
|
|
2478
|
+
"method": "GET",
|
|
2479
|
+
"path": "/v1/11880/search",
|
|
2480
|
+
"toolName": "v1_11880_search",
|
|
2481
|
+
"summary": "Search 11880.com business listings for a term in a location (paginated).",
|
|
2482
|
+
"cost": 1,
|
|
2483
|
+
"live": true,
|
|
2484
|
+
"anyOf": [],
|
|
2485
|
+
"params": [
|
|
2486
|
+
{
|
|
2487
|
+
"name": "query",
|
|
2488
|
+
"type": "string",
|
|
2489
|
+
"required": true,
|
|
2490
|
+
"anyOf": false
|
|
2491
|
+
},
|
|
2492
|
+
{
|
|
2493
|
+
"name": "location",
|
|
2494
|
+
"type": "string",
|
|
2495
|
+
"required": false,
|
|
2496
|
+
"anyOf": false
|
|
2497
|
+
},
|
|
2498
|
+
{
|
|
2499
|
+
"name": "page",
|
|
2500
|
+
"type": "string",
|
|
2501
|
+
"required": false,
|
|
2502
|
+
"anyOf": false
|
|
2503
|
+
},
|
|
2504
|
+
{
|
|
2505
|
+
"name": "sort",
|
|
2506
|
+
"type": "string",
|
|
2507
|
+
"required": false,
|
|
2508
|
+
"anyOf": false
|
|
2509
|
+
},
|
|
2510
|
+
{
|
|
2511
|
+
"name": "url",
|
|
2512
|
+
"type": "string",
|
|
2513
|
+
"required": false,
|
|
2514
|
+
"anyOf": false
|
|
2515
|
+
}
|
|
2516
|
+
]
|
|
2517
|
+
},
|
|
2518
|
+
{
|
|
2519
|
+
"platform": "11880",
|
|
2520
|
+
"action": "detail",
|
|
2521
|
+
"resource": "detail",
|
|
2522
|
+
"version": "v1",
|
|
2523
|
+
"method": "GET",
|
|
2524
|
+
"path": "/v1/11880/detail",
|
|
2525
|
+
"toolName": "v1_11880_detail",
|
|
2526
|
+
"summary": "Fetch a single 11880.com business detail page by its URL.",
|
|
2527
|
+
"cost": 1,
|
|
2528
|
+
"live": true,
|
|
2529
|
+
"anyOf": [],
|
|
2530
|
+
"params": [
|
|
2531
|
+
{
|
|
2532
|
+
"name": "url",
|
|
2533
|
+
"type": "string",
|
|
2534
|
+
"required": true,
|
|
2535
|
+
"anyOf": false
|
|
2536
|
+
},
|
|
2537
|
+
{
|
|
2538
|
+
"name": "query",
|
|
2539
|
+
"type": "string",
|
|
2540
|
+
"required": false,
|
|
2541
|
+
"anyOf": false
|
|
2542
|
+
},
|
|
2543
|
+
{
|
|
2544
|
+
"name": "location",
|
|
2545
|
+
"type": "string",
|
|
2546
|
+
"required": false,
|
|
2547
|
+
"anyOf": false
|
|
2548
|
+
},
|
|
2549
|
+
{
|
|
2550
|
+
"name": "page",
|
|
2551
|
+
"type": "string",
|
|
2552
|
+
"required": false,
|
|
2553
|
+
"anyOf": false
|
|
2554
|
+
},
|
|
2555
|
+
{
|
|
2556
|
+
"name": "sort",
|
|
2557
|
+
"type": "string",
|
|
2558
|
+
"required": false,
|
|
2559
|
+
"anyOf": false
|
|
2560
|
+
}
|
|
2561
|
+
]
|
|
2562
|
+
},
|
|
2563
|
+
{
|
|
2564
|
+
"platform": "gelbeseiten",
|
|
2565
|
+
"action": "search",
|
|
2566
|
+
"resource": "search",
|
|
2567
|
+
"version": "v1",
|
|
2568
|
+
"method": "GET",
|
|
2569
|
+
"path": "/v1/gelbeseiten/search",
|
|
2570
|
+
"toolName": "v1_gelbeseiten_search",
|
|
2571
|
+
"summary": "Search Gelbe Seiten businesses by keyword (query) and place (location), with radius / sort / open-now filters and page-based pagination.",
|
|
2572
|
+
"cost": 1,
|
|
2573
|
+
"live": true,
|
|
2574
|
+
"anyOf": [],
|
|
2575
|
+
"params": [
|
|
2576
|
+
{
|
|
2577
|
+
"name": "query",
|
|
2578
|
+
"type": "string",
|
|
2579
|
+
"required": true,
|
|
2580
|
+
"anyOf": false
|
|
2581
|
+
},
|
|
2582
|
+
{
|
|
2583
|
+
"name": "location",
|
|
2584
|
+
"type": "string",
|
|
2585
|
+
"required": false,
|
|
2586
|
+
"anyOf": false
|
|
2587
|
+
},
|
|
2588
|
+
{
|
|
2589
|
+
"name": "radius",
|
|
2590
|
+
"type": "string",
|
|
2591
|
+
"required": false,
|
|
2592
|
+
"anyOf": false
|
|
2593
|
+
},
|
|
2594
|
+
{
|
|
2595
|
+
"name": "sort",
|
|
2596
|
+
"type": "string",
|
|
2597
|
+
"required": false,
|
|
2598
|
+
"anyOf": false
|
|
2599
|
+
},
|
|
2600
|
+
{
|
|
2601
|
+
"name": "open_now",
|
|
2602
|
+
"type": "string",
|
|
2603
|
+
"required": false,
|
|
2604
|
+
"anyOf": false
|
|
2605
|
+
},
|
|
2606
|
+
{
|
|
2607
|
+
"name": "page",
|
|
2608
|
+
"type": "string",
|
|
2609
|
+
"required": false,
|
|
2610
|
+
"anyOf": false
|
|
2611
|
+
},
|
|
2612
|
+
{
|
|
2613
|
+
"name": "id",
|
|
2614
|
+
"type": "string",
|
|
2615
|
+
"required": false,
|
|
2616
|
+
"anyOf": false
|
|
2617
|
+
},
|
|
2618
|
+
{
|
|
2619
|
+
"name": "url",
|
|
2620
|
+
"type": "string",
|
|
2621
|
+
"required": false,
|
|
2622
|
+
"anyOf": false
|
|
2623
|
+
}
|
|
2624
|
+
]
|
|
2625
|
+
},
|
|
2626
|
+
{
|
|
2627
|
+
"platform": "gelbeseiten",
|
|
2628
|
+
"action": "listing",
|
|
2629
|
+
"resource": "listing",
|
|
2630
|
+
"version": "v1",
|
|
2631
|
+
"method": "GET",
|
|
2632
|
+
"path": "/v1/gelbeseiten/listing",
|
|
2633
|
+
"toolName": "v1_gelbeseiten_listing",
|
|
2634
|
+
"summary": "Get one Gelbe Seiten business listing (full detail: address, phone, website, rating, opening hours) by numeric id or URL.",
|
|
2635
|
+
"cost": 1,
|
|
2636
|
+
"live": true,
|
|
2637
|
+
"anyOf": [
|
|
2638
|
+
[
|
|
2639
|
+
"id",
|
|
2640
|
+
"url"
|
|
2641
|
+
]
|
|
2642
|
+
],
|
|
2643
|
+
"params": [
|
|
2644
|
+
{
|
|
2645
|
+
"name": "id",
|
|
2646
|
+
"type": "string",
|
|
2647
|
+
"required": false,
|
|
2648
|
+
"anyOf": true
|
|
2649
|
+
},
|
|
2650
|
+
{
|
|
2651
|
+
"name": "url",
|
|
2652
|
+
"type": "string",
|
|
2653
|
+
"required": false,
|
|
2654
|
+
"anyOf": true
|
|
2655
|
+
},
|
|
2656
|
+
{
|
|
2657
|
+
"name": "query",
|
|
2658
|
+
"type": "string",
|
|
2659
|
+
"required": false,
|
|
2660
|
+
"anyOf": false
|
|
2661
|
+
},
|
|
2662
|
+
{
|
|
2663
|
+
"name": "location",
|
|
2664
|
+
"type": "string",
|
|
2665
|
+
"required": false,
|
|
2666
|
+
"anyOf": false
|
|
2667
|
+
},
|
|
2668
|
+
{
|
|
2669
|
+
"name": "radius",
|
|
2670
|
+
"type": "string",
|
|
2671
|
+
"required": false,
|
|
2672
|
+
"anyOf": false
|
|
2673
|
+
},
|
|
2674
|
+
{
|
|
2675
|
+
"name": "sort",
|
|
2676
|
+
"type": "string",
|
|
2677
|
+
"required": false,
|
|
2678
|
+
"anyOf": false
|
|
2679
|
+
},
|
|
2680
|
+
{
|
|
2681
|
+
"name": "open_now",
|
|
2682
|
+
"type": "string",
|
|
2683
|
+
"required": false,
|
|
2684
|
+
"anyOf": false
|
|
2685
|
+
},
|
|
2686
|
+
{
|
|
2687
|
+
"name": "page",
|
|
2688
|
+
"type": "string",
|
|
2689
|
+
"required": false,
|
|
2690
|
+
"anyOf": false
|
|
2691
|
+
}
|
|
2692
|
+
]
|
|
2693
|
+
},
|
|
2694
|
+
{
|
|
2695
|
+
"platform": "immobilienscout24",
|
|
2696
|
+
"action": "search",
|
|
2697
|
+
"resource": "search",
|
|
2698
|
+
"version": "v1",
|
|
2699
|
+
"method": "GET",
|
|
2700
|
+
"path": "/v1/immobilienscout24/search",
|
|
2701
|
+
"toolName": "v1_immobilienscout24_search",
|
|
2702
|
+
"summary": "Search ImmobilienScout24 real-estate listings by location (place name, region path, or lat/lon radius) with filters (type, price, rooms, living space, courtage-free, new-build, full-text) and pagination.",
|
|
2703
|
+
"cost": 1,
|
|
2704
|
+
"live": true,
|
|
2705
|
+
"anyOf": [
|
|
2706
|
+
[
|
|
2707
|
+
"location",
|
|
2708
|
+
"geocodes",
|
|
2709
|
+
"geocoordinates"
|
|
2710
|
+
]
|
|
2711
|
+
],
|
|
2712
|
+
"params": [
|
|
2713
|
+
{
|
|
2714
|
+
"name": "location",
|
|
2715
|
+
"type": "string",
|
|
2716
|
+
"required": false,
|
|
2717
|
+
"anyOf": true
|
|
2718
|
+
},
|
|
2719
|
+
{
|
|
2720
|
+
"name": "geocodes",
|
|
2721
|
+
"type": "string",
|
|
2722
|
+
"required": false,
|
|
2723
|
+
"anyOf": true
|
|
2724
|
+
},
|
|
2725
|
+
{
|
|
2726
|
+
"name": "geocoordinates",
|
|
2727
|
+
"type": "string",
|
|
2728
|
+
"required": false,
|
|
2729
|
+
"anyOf": true
|
|
2730
|
+
},
|
|
2731
|
+
{
|
|
2732
|
+
"name": "real_estate_type",
|
|
2733
|
+
"type": "string",
|
|
2734
|
+
"required": false,
|
|
2735
|
+
"anyOf": false
|
|
2736
|
+
},
|
|
2737
|
+
{
|
|
2738
|
+
"name": "price_min",
|
|
2739
|
+
"type": "string",
|
|
2740
|
+
"required": false,
|
|
2741
|
+
"anyOf": false
|
|
2742
|
+
},
|
|
2743
|
+
{
|
|
2744
|
+
"name": "price_max",
|
|
2745
|
+
"type": "string",
|
|
2746
|
+
"required": false,
|
|
2747
|
+
"anyOf": false
|
|
2748
|
+
},
|
|
2749
|
+
{
|
|
2750
|
+
"name": "rooms_min",
|
|
2751
|
+
"type": "string",
|
|
2752
|
+
"required": false,
|
|
2753
|
+
"anyOf": false
|
|
2754
|
+
},
|
|
2755
|
+
{
|
|
2756
|
+
"name": "rooms_max",
|
|
2757
|
+
"type": "string",
|
|
2758
|
+
"required": false,
|
|
2759
|
+
"anyOf": false
|
|
2760
|
+
},
|
|
2761
|
+
{
|
|
2762
|
+
"name": "living_space_min",
|
|
2763
|
+
"type": "string",
|
|
2764
|
+
"required": false,
|
|
2765
|
+
"anyOf": false
|
|
2766
|
+
},
|
|
2767
|
+
{
|
|
2768
|
+
"name": "living_space_max",
|
|
2769
|
+
"type": "string",
|
|
2770
|
+
"required": false,
|
|
2771
|
+
"anyOf": false
|
|
2772
|
+
},
|
|
2773
|
+
{
|
|
2774
|
+
"name": "free_of_courtage",
|
|
2775
|
+
"type": "string",
|
|
2776
|
+
"required": false,
|
|
2777
|
+
"anyOf": false
|
|
2778
|
+
},
|
|
2779
|
+
{
|
|
2780
|
+
"name": "newbuilding",
|
|
2781
|
+
"type": "string",
|
|
2782
|
+
"required": false,
|
|
2783
|
+
"anyOf": false
|
|
2784
|
+
},
|
|
2785
|
+
{
|
|
2786
|
+
"name": "fulltext",
|
|
2787
|
+
"type": "string",
|
|
2788
|
+
"required": false,
|
|
2789
|
+
"anyOf": false
|
|
2790
|
+
},
|
|
2791
|
+
{
|
|
2792
|
+
"name": "sort",
|
|
2793
|
+
"type": "string",
|
|
2794
|
+
"required": false,
|
|
2795
|
+
"anyOf": false
|
|
2796
|
+
},
|
|
2797
|
+
{
|
|
2798
|
+
"name": "page",
|
|
2799
|
+
"type": "string",
|
|
2800
|
+
"required": false,
|
|
2801
|
+
"anyOf": false
|
|
2802
|
+
},
|
|
2803
|
+
{
|
|
2804
|
+
"name": "page_size",
|
|
2805
|
+
"type": "string",
|
|
2806
|
+
"required": false,
|
|
2807
|
+
"anyOf": false
|
|
2808
|
+
}
|
|
2809
|
+
]
|
|
2810
|
+
},
|
|
2811
|
+
{
|
|
2812
|
+
"platform": "immobilienscout24",
|
|
2813
|
+
"action": "expose",
|
|
2814
|
+
"resource": "expose",
|
|
2815
|
+
"version": "v1",
|
|
2816
|
+
"method": "GET",
|
|
2817
|
+
"path": "/v1/immobilienscout24/expose",
|
|
2818
|
+
"toolName": "v1_immobilienscout24_expose",
|
|
2819
|
+
"summary": "Get a single ImmobilienScout24 listing (full detail: price, criteria, images, agent, texts) by id or URL.",
|
|
2820
|
+
"cost": 1,
|
|
2821
|
+
"live": true,
|
|
2822
|
+
"anyOf": [
|
|
2823
|
+
[
|
|
2824
|
+
"id",
|
|
2825
|
+
"url"
|
|
2826
|
+
]
|
|
2827
|
+
],
|
|
2828
|
+
"params": [
|
|
2829
|
+
{
|
|
2830
|
+
"name": "id",
|
|
2831
|
+
"type": "string",
|
|
2832
|
+
"required": false,
|
|
2833
|
+
"anyOf": true
|
|
2834
|
+
},
|
|
2835
|
+
{
|
|
2836
|
+
"name": "url",
|
|
2837
|
+
"type": "string",
|
|
2838
|
+
"required": false,
|
|
2839
|
+
"anyOf": true
|
|
2840
|
+
}
|
|
2841
|
+
]
|
|
2842
|
+
}
|
|
2843
|
+
];
|
|
2844
|
+
|
|
2845
|
+
// ../../packages/api-client/src/endpoints.js
|
|
2846
|
+
var platforms = [...new Set(endpoints.map((e) => e.platform))];
|
|
2847
|
+
function endpointsForPlatform(platform) {
|
|
2848
|
+
return endpoints.filter((e) => e.platform === platform);
|
|
2849
|
+
}
|
|
2850
|
+
|
|
2851
|
+
// src/config.js
|
|
2852
|
+
import os from "node:os";
|
|
2853
|
+
import path from "node:path";
|
|
2854
|
+
import fs from "node:fs";
|
|
2855
|
+
import Conf from "conf";
|
|
2856
|
+
var CONFIG_DIR = path.join(os.homedir(), ".config", "scraper-api");
|
|
2857
|
+
var instance = null;
|
|
2858
|
+
function harden(store) {
|
|
2859
|
+
try {
|
|
2860
|
+
fs.chmodSync(CONFIG_DIR, 448);
|
|
2861
|
+
} catch {
|
|
2862
|
+
}
|
|
2863
|
+
try {
|
|
2864
|
+
fs.chmodSync(store.path, 384);
|
|
2865
|
+
} catch {
|
|
2866
|
+
}
|
|
2867
|
+
}
|
|
2868
|
+
function getConfig() {
|
|
2869
|
+
if (instance) return instance;
|
|
2870
|
+
fs.mkdirSync(CONFIG_DIR, { recursive: true, mode: 448 });
|
|
2871
|
+
const store = new Conf({ projectName: "scraper-api", configName: "config", cwd: CONFIG_DIR });
|
|
2872
|
+
harden(store);
|
|
2873
|
+
instance = store;
|
|
2874
|
+
return store;
|
|
2875
|
+
}
|
|
2876
|
+
function configSet(key, value) {
|
|
2877
|
+
const store = getConfig();
|
|
2878
|
+
store.set(key, value);
|
|
2879
|
+
harden(store);
|
|
2880
|
+
}
|
|
2881
|
+
function configGet(key) {
|
|
2882
|
+
return getConfig().get(key);
|
|
2883
|
+
}
|
|
2884
|
+
function configDelete(key) {
|
|
2885
|
+
const store = getConfig();
|
|
2886
|
+
store.delete(key);
|
|
2887
|
+
harden(store);
|
|
2888
|
+
}
|
|
2889
|
+
function configPath() {
|
|
2890
|
+
return getConfig().path;
|
|
2891
|
+
}
|
|
2892
|
+
var KEYS = {
|
|
2893
|
+
apiKey: "api-key",
|
|
2894
|
+
email: "email",
|
|
2895
|
+
authDomain: "auth-domain",
|
|
2896
|
+
clientId: "client-id",
|
|
2897
|
+
audience: "audience"
|
|
2898
|
+
};
|
|
2899
|
+
|
|
2900
|
+
// src/auth.js
|
|
2901
|
+
function resolveApiKey(flagKey) {
|
|
2902
|
+
if (flagKey) return flagKey;
|
|
2903
|
+
const stored = configGet(KEYS.apiKey);
|
|
2904
|
+
if (stored) return stored;
|
|
2905
|
+
if (process.env.SCRAPER_API_KEY) return process.env.SCRAPER_API_KEY;
|
|
2906
|
+
return null;
|
|
2907
|
+
}
|
|
2908
|
+
function requireApiKey(flagKey) {
|
|
2909
|
+
const key = resolveApiKey(flagKey);
|
|
2910
|
+
if (!key) {
|
|
2911
|
+
throw new Error(
|
|
2912
|
+
"No API key found. Run `scraper-api login` (OAuth) or `scraper-api auth login --api-key <key>`, or set the SCRAPER_API_KEY environment variable."
|
|
2913
|
+
);
|
|
2914
|
+
}
|
|
2915
|
+
return key;
|
|
2916
|
+
}
|
|
2917
|
+
var DEFAULT_AUTH_DOMAIN = "auth.scraper-api.com";
|
|
2918
|
+
var DEFAULT_CLIENT_ID = "jf81Z8XIF5SUDKJPMLJzCEa3vG1vzzgo";
|
|
2919
|
+
function resolveAuthSettings() {
|
|
2920
|
+
const authDomain = configGet(KEYS.authDomain) || process.env.SCRAPER_API_AUTH_DOMAIN || process.env.AUTH0_DOMAIN || DEFAULT_AUTH_DOMAIN;
|
|
2921
|
+
const clientId = configGet(KEYS.clientId) || process.env.SCRAPER_API_CLIENT_ID || process.env.AUTH0_CLIENT_ID || DEFAULT_CLIENT_ID;
|
|
2922
|
+
const audience = configGet(KEYS.audience) || process.env.SCRAPER_API_AUDIENCE || process.env.AUTH0_AUDIENCE || "https://api.scraper-api.com";
|
|
2923
|
+
return { authDomain, clientId, audience };
|
|
2924
|
+
}
|
|
2925
|
+
|
|
2926
|
+
// src/api-client.js
|
|
2927
|
+
var DEFAULT_BASE = "https://api.scraper-api.com";
|
|
2928
|
+
var TIMEOUT_MS = 6e4;
|
|
2929
|
+
function apiBase() {
|
|
2930
|
+
return (process.env.SCRAPER_API_BASE || DEFAULT_BASE).replace(/\/$/, "");
|
|
2931
|
+
}
|
|
2932
|
+
function buildError(status, body) {
|
|
2933
|
+
const detail = typeof body === "string" ? body : body && (body.message || body.error) || JSON.stringify(body);
|
|
2934
|
+
const err = new Error(`API ${status}: ${detail}`);
|
|
2935
|
+
err.status = status;
|
|
2936
|
+
err.body = body;
|
|
2937
|
+
return err;
|
|
2938
|
+
}
|
|
2939
|
+
async function parse(res) {
|
|
2940
|
+
const text2 = await res.text();
|
|
2941
|
+
if (!text2) return null;
|
|
2942
|
+
try {
|
|
2943
|
+
return JSON.parse(text2);
|
|
2944
|
+
} catch {
|
|
2945
|
+
return text2;
|
|
2946
|
+
}
|
|
2947
|
+
}
|
|
2948
|
+
async function withTimeout(run2) {
|
|
2949
|
+
const controller = new AbortController();
|
|
2950
|
+
const timer = setTimeout(() => controller.abort(), TIMEOUT_MS);
|
|
2951
|
+
try {
|
|
2952
|
+
return await run2(controller.signal);
|
|
2953
|
+
} catch (err) {
|
|
2954
|
+
if (err?.name === "AbortError") throw new Error(`Request timed out after ${TIMEOUT_MS / 1e3}s`);
|
|
2955
|
+
throw err;
|
|
2956
|
+
} finally {
|
|
2957
|
+
clearTimeout(timer);
|
|
2958
|
+
}
|
|
2959
|
+
}
|
|
2960
|
+
function buildUrl(path3, params = {}) {
|
|
2961
|
+
const url = new URL(apiBase() + (path3.startsWith("/") ? path3 : `/${path3}`));
|
|
2962
|
+
for (const [key, value] of Object.entries(params)) {
|
|
2963
|
+
if (value === void 0 || value === null || value === "") continue;
|
|
2964
|
+
url.searchParams.set(key, String(value));
|
|
2965
|
+
}
|
|
2966
|
+
return url.toString();
|
|
2967
|
+
}
|
|
2968
|
+
async function apiGet(path3, params, apiKey) {
|
|
2969
|
+
return withTimeout(async (signal) => {
|
|
2970
|
+
const res = await fetch(buildUrl(path3, params), {
|
|
2971
|
+
method: "GET",
|
|
2972
|
+
headers: { "x-api-key": apiKey, accept: "application/json" },
|
|
2973
|
+
signal
|
|
2974
|
+
});
|
|
2975
|
+
const body = await parse(res);
|
|
2976
|
+
if (!res.ok) throw buildError(res.status, body);
|
|
2977
|
+
return body;
|
|
2978
|
+
});
|
|
2979
|
+
}
|
|
2980
|
+
async function bearerPost(path3, accessToken, payload) {
|
|
2981
|
+
return withTimeout(async (signal) => {
|
|
2982
|
+
const res = await fetch(buildUrl(path3), {
|
|
2983
|
+
method: "POST",
|
|
2984
|
+
headers: {
|
|
2985
|
+
authorization: `Bearer ${accessToken}`,
|
|
2986
|
+
accept: "application/json",
|
|
2987
|
+
"content-type": "application/json"
|
|
2988
|
+
},
|
|
2989
|
+
body: JSON.stringify(payload ?? {}),
|
|
2990
|
+
signal
|
|
2991
|
+
});
|
|
2992
|
+
const body = await parse(res);
|
|
2993
|
+
if (!res.ok) throw buildError(res.status, body);
|
|
2994
|
+
return body;
|
|
2995
|
+
});
|
|
2996
|
+
}
|
|
2997
|
+
|
|
2998
|
+
// src/output.js
|
|
2999
|
+
import fs2 from "node:fs";
|
|
3000
|
+
import Table from "cli-table3";
|
|
3001
|
+
function toRows(data) {
|
|
3002
|
+
if (Array.isArray(data)) return data;
|
|
3003
|
+
if (data && typeof data === "object") {
|
|
3004
|
+
const arrayField = Object.values(data).find((v) => Array.isArray(v));
|
|
3005
|
+
if (arrayField) return arrayField;
|
|
3006
|
+
return [data];
|
|
3007
|
+
}
|
|
3008
|
+
return [{ value: data }];
|
|
3009
|
+
}
|
|
3010
|
+
function columns(rows) {
|
|
3011
|
+
const set = /* @__PURE__ */ new Set();
|
|
3012
|
+
for (const row of rows) {
|
|
3013
|
+
if (row && typeof row === "object" && !Array.isArray(row)) {
|
|
3014
|
+
for (const key of Object.keys(row)) set.add(key);
|
|
3015
|
+
} else {
|
|
3016
|
+
set.add("value");
|
|
3017
|
+
}
|
|
3018
|
+
}
|
|
3019
|
+
return [...set];
|
|
3020
|
+
}
|
|
3021
|
+
function cell(value) {
|
|
3022
|
+
if (value === null || value === void 0) return "";
|
|
3023
|
+
if (typeof value === "object") return JSON.stringify(value);
|
|
3024
|
+
return String(value);
|
|
3025
|
+
}
|
|
3026
|
+
function asTable(rows) {
|
|
3027
|
+
const cols = columns(rows);
|
|
3028
|
+
const table = new Table({ head: cols });
|
|
3029
|
+
for (const row of rows) {
|
|
3030
|
+
if (row && typeof row === "object" && !Array.isArray(row)) {
|
|
3031
|
+
table.push(cols.map((c) => cell(row[c])));
|
|
3032
|
+
} else {
|
|
3033
|
+
table.push([cell(row)]);
|
|
3034
|
+
}
|
|
3035
|
+
}
|
|
3036
|
+
return table.toString();
|
|
3037
|
+
}
|
|
3038
|
+
function asCsv(rows) {
|
|
3039
|
+
const cols = columns(rows);
|
|
3040
|
+
const escape = (v) => {
|
|
3041
|
+
const s = cell(v);
|
|
3042
|
+
return /[",\n]/.test(s) ? `"${s.replace(/"/g, '""')}"` : s;
|
|
3043
|
+
};
|
|
3044
|
+
const lines = [cols.join(",")];
|
|
3045
|
+
for (const row of rows) {
|
|
3046
|
+
if (row && typeof row === "object" && !Array.isArray(row)) {
|
|
3047
|
+
lines.push(cols.map((c) => escape(row[c])).join(","));
|
|
3048
|
+
} else {
|
|
3049
|
+
lines.push(escape(row));
|
|
3050
|
+
}
|
|
3051
|
+
}
|
|
3052
|
+
return lines.join("\n");
|
|
3053
|
+
}
|
|
3054
|
+
function asMarkdown(rows) {
|
|
3055
|
+
const cols = columns(rows);
|
|
3056
|
+
const escape = (v) => cell(v).replace(/\|/g, "\\|").replace(/\n/g, " ");
|
|
3057
|
+
const header = `| ${cols.join(" | ")} |`;
|
|
3058
|
+
const sep = `| ${cols.map(() => "---").join(" | ")} |`;
|
|
3059
|
+
const body = rows.map((row) => {
|
|
3060
|
+
if (row && typeof row === "object" && !Array.isArray(row)) {
|
|
3061
|
+
return `| ${cols.map((c) => escape(row[c])).join(" | ")} |`;
|
|
3062
|
+
}
|
|
3063
|
+
return `| ${escape(row)} |`;
|
|
3064
|
+
});
|
|
3065
|
+
return [header, sep, ...body].join("\n");
|
|
3066
|
+
}
|
|
3067
|
+
function format(data, { format: fmt = "json", pretty = false } = {}) {
|
|
3068
|
+
switch (fmt) {
|
|
3069
|
+
case "table":
|
|
3070
|
+
return asTable(toRows(data));
|
|
3071
|
+
case "csv":
|
|
3072
|
+
return asCsv(toRows(data));
|
|
3073
|
+
case "markdown":
|
|
3074
|
+
return asMarkdown(toRows(data));
|
|
3075
|
+
case "json":
|
|
3076
|
+
default:
|
|
3077
|
+
return JSON.stringify(data, null, pretty ? 2 : 0);
|
|
3078
|
+
}
|
|
3079
|
+
}
|
|
3080
|
+
function emit(data, opts = {}) {
|
|
3081
|
+
const text2 = format(data, opts);
|
|
3082
|
+
if (opts.output) {
|
|
3083
|
+
fs2.writeFileSync(opts.output, text2);
|
|
3084
|
+
process.stderr.write(`Saved to ${opts.output}
|
|
3085
|
+
`);
|
|
3086
|
+
return;
|
|
3087
|
+
}
|
|
3088
|
+
process.stdout.write(text2 + "\n");
|
|
3089
|
+
}
|
|
3090
|
+
|
|
3091
|
+
// src/command-registry.js
|
|
3092
|
+
function paramFlag(param) {
|
|
3093
|
+
const bits = [];
|
|
3094
|
+
if (param.required) bits.push(chalk.yellow("required"));
|
|
3095
|
+
else if (param.anyOf) bits.push("any-of");
|
|
3096
|
+
if (param.enum) bits.push(`one of: ${param.enum.join(", ")}`);
|
|
3097
|
+
const suffix = bits.length ? ` (${bits.join("; ")})` : "";
|
|
3098
|
+
return { flag: `--${param.name} <value>`, description: `${param.description ?? param.name}${suffix}` };
|
|
3099
|
+
}
|
|
3100
|
+
function collectParams(endpoint, opts) {
|
|
3101
|
+
const params = {};
|
|
3102
|
+
for (const param of endpoint.params) {
|
|
3103
|
+
const value = opts[param.name];
|
|
3104
|
+
if (value !== void 0 && value !== null && value !== "") params[param.name] = value;
|
|
3105
|
+
}
|
|
3106
|
+
return params;
|
|
3107
|
+
}
|
|
3108
|
+
function validate(endpoint, params) {
|
|
3109
|
+
const problems = [];
|
|
3110
|
+
for (const param of endpoint.params) {
|
|
3111
|
+
if (param.required && params[param.name] === void 0) problems.push(`--${param.name} is required`);
|
|
3112
|
+
}
|
|
3113
|
+
for (const group of endpoint.anyOf ?? []) {
|
|
3114
|
+
if (!group.some((name) => params[name] !== void 0)) {
|
|
3115
|
+
problems.push(`one of ${group.map((n) => `--${n}`).join(", ")} is required`);
|
|
3116
|
+
}
|
|
3117
|
+
}
|
|
3118
|
+
return problems;
|
|
3119
|
+
}
|
|
3120
|
+
function formatOpts(global) {
|
|
3121
|
+
return {
|
|
3122
|
+
format: global.json ? "json" : global.format,
|
|
3123
|
+
pretty: global.pretty,
|
|
3124
|
+
output: global.output
|
|
3125
|
+
};
|
|
3126
|
+
}
|
|
3127
|
+
async function runEndpoint(endpoint, opts, command) {
|
|
3128
|
+
const global = command.optsWithGlobals();
|
|
3129
|
+
const apiKey = requireApiKey(global.apiKey);
|
|
3130
|
+
const params = collectParams(endpoint, opts);
|
|
3131
|
+
const problems = validate(endpoint, params);
|
|
3132
|
+
if (problems.length) throw new Error(`Invalid parameters:
|
|
3133
|
+
- ${problems.join("\n - ")}`);
|
|
3134
|
+
if (endpoint.cost > 1) {
|
|
3135
|
+
process.stderr.write(chalk.yellow(`\u26A0 This endpoint costs ${endpoint.cost} credits per call.
|
|
3136
|
+
`));
|
|
3137
|
+
}
|
|
3138
|
+
if (!endpoint.live) {
|
|
3139
|
+
process.stderr.write(chalk.gray("\u2139 This endpoint is a stub (mock data) \u2014 not yet live.\n"));
|
|
3140
|
+
}
|
|
3141
|
+
const useSpinner = !global.json && !global.output && global.verbose !== false;
|
|
3142
|
+
const spinner2 = useSpinner ? ora({ stream: process.stderr, text: `${endpoint.platform} ${endpoint.action}\u2026` }).start() : null;
|
|
3143
|
+
try {
|
|
3144
|
+
const data = await apiGet(endpoint.path, params, apiKey);
|
|
3145
|
+
spinner2?.stop();
|
|
3146
|
+
if (global.verbose) process.stderr.write(chalk.gray(`GET ${endpoint.path}
|
|
3147
|
+
`));
|
|
3148
|
+
emit(data, formatOpts(global));
|
|
3149
|
+
} catch (err) {
|
|
3150
|
+
spinner2?.stop();
|
|
3151
|
+
throw err;
|
|
3152
|
+
}
|
|
3153
|
+
}
|
|
3154
|
+
function registerEndpointCommands(program) {
|
|
3155
|
+
for (const platform of platforms) {
|
|
3156
|
+
const group = new Command(platform).description(`${platform} endpoints`);
|
|
3157
|
+
for (const endpoint of endpointsForPlatform(platform)) {
|
|
3158
|
+
const sub = new Command(endpoint.action).description(
|
|
3159
|
+
`${endpoint.summary}${endpoint.cost > 1 ? ` [${endpoint.cost} credits]` : ""}${endpoint.live ? "" : " [stub]"}`
|
|
3160
|
+
);
|
|
3161
|
+
for (const param of endpoint.params) {
|
|
3162
|
+
const { flag, description } = paramFlag(param);
|
|
3163
|
+
sub.option(flag, description);
|
|
3164
|
+
}
|
|
3165
|
+
sub.action((opts, cmd) => runEndpoint(endpoint, opts, cmd));
|
|
3166
|
+
group.addCommand(sub);
|
|
3167
|
+
}
|
|
3168
|
+
program.addCommand(group);
|
|
3169
|
+
}
|
|
3170
|
+
return program;
|
|
3171
|
+
}
|
|
3172
|
+
|
|
3173
|
+
// src/commands/login.js
|
|
3174
|
+
import http from "node:http";
|
|
3175
|
+
import crypto from "node:crypto";
|
|
3176
|
+
import os2 from "node:os";
|
|
3177
|
+
import chalk2 from "chalk";
|
|
3178
|
+
import ora2 from "ora";
|
|
3179
|
+
import open from "open";
|
|
3180
|
+
var CALLBACK_TIMEOUT_MS = 18e4;
|
|
3181
|
+
function base64url(buffer) {
|
|
3182
|
+
return buffer.toString("base64").replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
3183
|
+
}
|
|
3184
|
+
function pkcePair() {
|
|
3185
|
+
const verifier = base64url(crypto.randomBytes(32));
|
|
3186
|
+
const challenge = base64url(crypto.createHash("sha256").update(verifier).digest());
|
|
3187
|
+
return { verifier, challenge };
|
|
3188
|
+
}
|
|
3189
|
+
var successPage = `<!doctype html><meta charset="utf-8"><title>scraper-api.com</title>
|
|
3190
|
+
<body style="font-family:system-ui;background:#0b0b0f;color:#e6e6e6;display:grid;place-items:center;height:100vh;margin:0">
|
|
3191
|
+
<div style="text-align:center"><h1>\u2713 Signed in</h1><p>You can close this tab and return to the terminal.</p></div>`;
|
|
3192
|
+
var failurePage = `<!doctype html><meta charset="utf-8"><title>scraper-api.com</title>
|
|
3193
|
+
<body style="font-family:system-ui;background:#0b0b0f;color:#e6e6e6;display:grid;place-items:center;height:100vh;margin:0">
|
|
3194
|
+
<div style="text-align:center"><h1>Sign-in failed</h1><p>Return to the terminal for details.</p></div>`;
|
|
3195
|
+
function startCallbackServer(expectedState) {
|
|
3196
|
+
return new Promise((resolvePort, rejectPort) => {
|
|
3197
|
+
let onCode;
|
|
3198
|
+
let onError;
|
|
3199
|
+
const waitForCode = new Promise((res, rej) => {
|
|
3200
|
+
onCode = res;
|
|
3201
|
+
onError = rej;
|
|
3202
|
+
});
|
|
3203
|
+
const server = http.createServer((req, res) => {
|
|
3204
|
+
const url = new URL(req.url, "http://127.0.0.1");
|
|
3205
|
+
if (url.pathname !== "/callback") {
|
|
3206
|
+
res.writeHead(404).end();
|
|
3207
|
+
return;
|
|
3208
|
+
}
|
|
3209
|
+
const error = url.searchParams.get("error");
|
|
3210
|
+
const code = url.searchParams.get("code");
|
|
3211
|
+
const state = url.searchParams.get("state");
|
|
3212
|
+
const finish = (ok, settle) => {
|
|
3213
|
+
res.writeHead(ok ? 200 : 400, { "content-type": "text/html; charset=utf-8" });
|
|
3214
|
+
res.end(ok ? successPage : failurePage);
|
|
3215
|
+
server.close();
|
|
3216
|
+
settle();
|
|
3217
|
+
};
|
|
3218
|
+
if (error) return finish(false, () => onError(new Error(`Authorization failed: ${error}`)));
|
|
3219
|
+
if (state !== expectedState) return finish(false, () => onError(new Error("State mismatch \u2014 aborting for safety.")));
|
|
3220
|
+
if (!code) return finish(false, () => onError(new Error("No authorization code returned.")));
|
|
3221
|
+
finish(true, () => onCode(code));
|
|
3222
|
+
});
|
|
3223
|
+
const timer = setTimeout(() => {
|
|
3224
|
+
server.close();
|
|
3225
|
+
onError(new Error("Timed out waiting for the browser sign-in (3 min)."));
|
|
3226
|
+
}, CALLBACK_TIMEOUT_MS);
|
|
3227
|
+
timer.unref?.();
|
|
3228
|
+
server.once("close", () => clearTimeout(timer));
|
|
3229
|
+
server.on("error", (err) => {
|
|
3230
|
+
const wrapped = err.code === "EADDRINUSE" ? new Error("Could not bind a local port for the OAuth callback.") : err;
|
|
3231
|
+
rejectPort(wrapped);
|
|
3232
|
+
onError(wrapped);
|
|
3233
|
+
});
|
|
3234
|
+
const port = Number(process.env.SCRAPER_API_LOGIN_PORT) || 8976;
|
|
3235
|
+
server.listen(port, "127.0.0.1", () => {
|
|
3236
|
+
resolvePort({ port: server.address().port, waitForCode });
|
|
3237
|
+
});
|
|
3238
|
+
});
|
|
3239
|
+
}
|
|
3240
|
+
async function exchangeCode({ authDomain, clientId, code, redirectUri, verifier }) {
|
|
3241
|
+
const res = await fetch(`https://${authDomain}/oauth/token`, {
|
|
3242
|
+
method: "POST",
|
|
3243
|
+
headers: { "content-type": "application/x-www-form-urlencoded" },
|
|
3244
|
+
body: new URLSearchParams({
|
|
3245
|
+
grant_type: "authorization_code",
|
|
3246
|
+
client_id: clientId,
|
|
3247
|
+
code,
|
|
3248
|
+
redirect_uri: redirectUri,
|
|
3249
|
+
code_verifier: verifier
|
|
3250
|
+
})
|
|
3251
|
+
});
|
|
3252
|
+
const body = await res.json().catch(() => ({}));
|
|
3253
|
+
if (!res.ok) throw new Error(`Token exchange failed (${res.status}): ${body.error_description || body.error || "unknown"}`);
|
|
3254
|
+
return body.access_token;
|
|
3255
|
+
}
|
|
3256
|
+
async function loginCommand() {
|
|
3257
|
+
const { authDomain, clientId, audience } = resolveAuthSettings();
|
|
3258
|
+
if (!authDomain || !clientId) {
|
|
3259
|
+
throw new Error(
|
|
3260
|
+
"OAuth is not configured. Set the issuer first:\n scraper-api config set auth-domain <your-tenant>.auth0.com\n scraper-api config set client-id <client-id>\n(or export SCRAPER_API_AUTH_DOMAIN / SCRAPER_API_CLIENT_ID)\nAlternatively, skip OAuth: scraper-api auth login --api-key <key>"
|
|
3261
|
+
);
|
|
3262
|
+
}
|
|
3263
|
+
const { verifier, challenge } = pkcePair();
|
|
3264
|
+
const state = base64url(crypto.randomBytes(16));
|
|
3265
|
+
const { port, waitForCode } = await startCallbackServer(state);
|
|
3266
|
+
const redirectUri = `http://127.0.0.1:${port}/callback`;
|
|
3267
|
+
const authorizeUrl = `https://${authDomain}/authorize?` + new URLSearchParams({
|
|
3268
|
+
response_type: "code",
|
|
3269
|
+
client_id: clientId,
|
|
3270
|
+
redirect_uri: redirectUri,
|
|
3271
|
+
scope: "openid profile email offline_access",
|
|
3272
|
+
audience,
|
|
3273
|
+
code_challenge: challenge,
|
|
3274
|
+
code_challenge_method: "S256",
|
|
3275
|
+
state
|
|
3276
|
+
}).toString();
|
|
3277
|
+
process.stderr.write(chalk2.gray("Opening your browser to sign in\u2026\n"));
|
|
3278
|
+
process.stderr.write(chalk2.gray(`If it does not open, visit:
|
|
3279
|
+
${authorizeUrl}
|
|
3280
|
+
`));
|
|
3281
|
+
try {
|
|
3282
|
+
await open(authorizeUrl);
|
|
3283
|
+
} catch {
|
|
3284
|
+
}
|
|
3285
|
+
const spinner2 = ora2({ stream: process.stderr, text: "Waiting for browser sign-in\u2026" }).start();
|
|
3286
|
+
let code;
|
|
3287
|
+
try {
|
|
3288
|
+
code = await waitForCode;
|
|
3289
|
+
} catch (err) {
|
|
3290
|
+
spinner2.fail("Sign-in failed.");
|
|
3291
|
+
throw err;
|
|
3292
|
+
}
|
|
3293
|
+
spinner2.text = "Exchanging authorization code\u2026";
|
|
3294
|
+
const accessToken = await exchangeCode({ authDomain, clientId, code, redirectUri, verifier });
|
|
3295
|
+
spinner2.text = "Minting your API key\u2026";
|
|
3296
|
+
const label = `CLI ${os2.hostname()}`;
|
|
3297
|
+
const minted = await bearerPost("/v1/account/keys", accessToken, { label });
|
|
3298
|
+
if (!minted?.key) throw new Error("Key minting returned no key.");
|
|
3299
|
+
configSet(KEYS.apiKey, minted.key);
|
|
3300
|
+
spinner2.text = "Fetching account\u2026";
|
|
3301
|
+
let me = null;
|
|
3302
|
+
try {
|
|
3303
|
+
me = await apiGet("/v1/me", {}, minted.key);
|
|
3304
|
+
if (me?.email) configSet(KEYS.email, me.email);
|
|
3305
|
+
} catch {
|
|
3306
|
+
}
|
|
3307
|
+
spinner2.succeed("Signed in.");
|
|
3308
|
+
process.stderr.write(
|
|
3309
|
+
chalk2.green(`\u2713 Logged in${me?.email ? ` as ${chalk2.bold(me.email)}` : ""}. API key saved.
|
|
3310
|
+
`) + (me ? chalk2.gray(` Credits: ${me.credits}${me.plan ? ` (plan: ${me.plan})` : ""}
|
|
3311
|
+
`) : "") + chalk2.gray(` Base: ${apiBase()}
|
|
3312
|
+
`)
|
|
3313
|
+
);
|
|
3314
|
+
}
|
|
3315
|
+
|
|
3316
|
+
// src/commands/session.js
|
|
3317
|
+
import chalk3 from "chalk";
|
|
3318
|
+
async function whoamiCommand(opts = {}, command) {
|
|
3319
|
+
const global = command?.optsWithGlobals?.() ?? {};
|
|
3320
|
+
const apiKey = requireApiKey(global.apiKey);
|
|
3321
|
+
const me = await apiGet("/v1/me", {}, apiKey);
|
|
3322
|
+
if (global.json) {
|
|
3323
|
+
process.stdout.write(JSON.stringify(me, null, global.pretty ? 2 : 0) + "\n");
|
|
3324
|
+
return;
|
|
3325
|
+
}
|
|
3326
|
+
process.stdout.write(
|
|
3327
|
+
`${chalk3.bold("Email:")} ${me?.email ?? chalk3.gray("unknown")}
|
|
3328
|
+
${chalk3.bold("Plan:")} ${me?.plan ?? chalk3.gray("unknown")}
|
|
3329
|
+
${chalk3.bold("Credits:")} ${me?.credits}
|
|
3330
|
+
`
|
|
3331
|
+
);
|
|
3332
|
+
}
|
|
3333
|
+
function logoutCommand() {
|
|
3334
|
+
configDelete(KEYS.apiKey);
|
|
3335
|
+
configDelete(KEYS.email);
|
|
3336
|
+
configDelete("access-token");
|
|
3337
|
+
process.stderr.write(chalk3.green("\u2713 Logged out \u2014 stored key and identity removed.\n"));
|
|
3338
|
+
}
|
|
3339
|
+
|
|
3340
|
+
// src/commands/balance.js
|
|
3341
|
+
import chalk4 from "chalk";
|
|
3342
|
+
async function balanceCommand(opts = {}, command) {
|
|
3343
|
+
const global = command?.optsWithGlobals?.() ?? {};
|
|
3344
|
+
const apiKey = requireApiKey(global.apiKey);
|
|
3345
|
+
const me = await apiGet("/v1/me", {}, apiKey);
|
|
3346
|
+
if (global.json) {
|
|
3347
|
+
process.stdout.write(JSON.stringify(me, null, global.pretty ? 2 : 0) + "\n");
|
|
3348
|
+
return;
|
|
3349
|
+
}
|
|
3350
|
+
const credits = me?.credits;
|
|
3351
|
+
process.stdout.write(
|
|
3352
|
+
`${chalk4.bold("Credits:")} ${chalk4.green(credits === "unlimited" ? "unlimited" : credits)}` + (me?.plan ? chalk4.gray(` (plan: ${me.plan})`) : "") + "\n"
|
|
3353
|
+
);
|
|
3354
|
+
}
|
|
3355
|
+
|
|
3356
|
+
// src/commands/list.js
|
|
3357
|
+
import chalk5 from "chalk";
|
|
3358
|
+
function listCommand(platform, opts = {}, command) {
|
|
3359
|
+
const global = command?.optsWithGlobals?.() ?? {};
|
|
3360
|
+
if (global.json || opts.json) {
|
|
3361
|
+
const data = platform ? endpointsForPlatform(platform).map(pick) : endpoints.map(pick);
|
|
3362
|
+
process.stdout.write(JSON.stringify(data, null, global.pretty ? 2 : 0) + "\n");
|
|
3363
|
+
return;
|
|
3364
|
+
}
|
|
3365
|
+
if (platform) {
|
|
3366
|
+
const list = endpointsForPlatform(platform);
|
|
3367
|
+
if (!list.length) {
|
|
3368
|
+
process.stderr.write(chalk5.red(`Unknown platform "${platform}". Known: ${platforms.join(", ")}
|
|
3369
|
+
`));
|
|
3370
|
+
process.exitCode = 1;
|
|
3371
|
+
return;
|
|
3372
|
+
}
|
|
3373
|
+
process.stdout.write(chalk5.bold(`${platform} \u2014 ${list.length} endpoints
|
|
3374
|
+
`));
|
|
3375
|
+
for (const e of list) {
|
|
3376
|
+
const tags = [e.cost > 1 ? chalk5.yellow(`${e.cost} credits`) : null, e.live ? null : chalk5.gray("stub")].filter(Boolean).join(" ");
|
|
3377
|
+
process.stdout.write(` ${chalk5.cyan(`${platform} ${e.action}`)} ${e.summary}${tags ? ` ${tags}` : ""}
|
|
3378
|
+
`);
|
|
3379
|
+
}
|
|
3380
|
+
return;
|
|
3381
|
+
}
|
|
3382
|
+
process.stdout.write(chalk5.bold(`${endpoints.length} endpoints across ${platforms.length} platforms
|
|
3383
|
+
`));
|
|
3384
|
+
for (const p2 of platforms) {
|
|
3385
|
+
const count = endpointsForPlatform(p2).length;
|
|
3386
|
+
process.stdout.write(` ${chalk5.cyan(p2.padEnd(18))} ${count} endpoints
|
|
3387
|
+
`);
|
|
3388
|
+
}
|
|
3389
|
+
process.stdout.write(chalk5.gray("\nRun `scraper-api list <platform>` to see a platform's commands.\n"));
|
|
3390
|
+
}
|
|
3391
|
+
function pick(e) {
|
|
3392
|
+
return {
|
|
3393
|
+
command: `${e.platform} ${e.action}`,
|
|
3394
|
+
platform: e.platform,
|
|
3395
|
+
action: e.action,
|
|
3396
|
+
path: e.path,
|
|
3397
|
+
tool: e.toolName,
|
|
3398
|
+
cost: e.cost,
|
|
3399
|
+
live: e.live,
|
|
3400
|
+
summary: e.summary,
|
|
3401
|
+
params: e.params.map((p2) => ({ name: p2.name, required: p2.required, anyOf: p2.anyOf }))
|
|
3402
|
+
};
|
|
3403
|
+
}
|
|
3404
|
+
|
|
3405
|
+
// src/commands/auth-cmd.js
|
|
3406
|
+
import chalk6 from "chalk";
|
|
3407
|
+
function authLoginCommand(opts = {}) {
|
|
3408
|
+
if (!opts.apiKey) {
|
|
3409
|
+
throw new Error("Provide the key: scraper-api auth login --api-key <key>");
|
|
3410
|
+
}
|
|
3411
|
+
configSet(KEYS.apiKey, opts.apiKey);
|
|
3412
|
+
process.stderr.write(chalk6.green("\u2713 API key stored.\n"));
|
|
3413
|
+
}
|
|
3414
|
+
function authStatusCommand(opts = {}, command) {
|
|
3415
|
+
const global = command?.optsWithGlobals?.() ?? {};
|
|
3416
|
+
let source = null;
|
|
3417
|
+
if (global.apiKey) source = "--api-key flag";
|
|
3418
|
+
else if (configGet(KEYS.apiKey)) source = "config file";
|
|
3419
|
+
else if (process.env.SCRAPER_API_KEY) source = "SCRAPER_API_KEY env";
|
|
3420
|
+
const key = resolveApiKey(global.apiKey);
|
|
3421
|
+
if (!key) {
|
|
3422
|
+
process.stdout.write(chalk6.yellow("Not authenticated. Run `scraper-api login`.\n"));
|
|
3423
|
+
return;
|
|
3424
|
+
}
|
|
3425
|
+
const masked = key.length > 8 ? `${key.slice(0, 4)}\u2026${key.slice(-4)}` : "set";
|
|
3426
|
+
process.stdout.write(`${chalk6.green("Authenticated")} \u2014 key ${masked} (source: ${source})
|
|
3427
|
+
`);
|
|
3428
|
+
}
|
|
3429
|
+
|
|
3430
|
+
// src/commands/config-cmd.js
|
|
3431
|
+
import chalk7 from "chalk";
|
|
3432
|
+
var SECRET_KEYS = /* @__PURE__ */ new Set(["api-key"]);
|
|
3433
|
+
function mask(key, value) {
|
|
3434
|
+
if (value === void 0) return chalk7.gray("(unset)");
|
|
3435
|
+
if (SECRET_KEYS.has(key) && typeof value === "string" && value.length > 8) {
|
|
3436
|
+
return `${value.slice(0, 4)}\u2026${value.slice(-4)}`;
|
|
3437
|
+
}
|
|
3438
|
+
return String(value);
|
|
3439
|
+
}
|
|
3440
|
+
function configSetCommand(key, value) {
|
|
3441
|
+
configSet(key, value);
|
|
3442
|
+
process.stderr.write(chalk7.green(`\u2713 set ${key}
|
|
3443
|
+
`));
|
|
3444
|
+
}
|
|
3445
|
+
function configGetCommand(key) {
|
|
3446
|
+
const value = getConfig().get(key);
|
|
3447
|
+
process.stdout.write(`${mask(key, value)}
|
|
3448
|
+
`);
|
|
3449
|
+
}
|
|
3450
|
+
function configDeleteCommand(key) {
|
|
3451
|
+
configDelete(key);
|
|
3452
|
+
process.stderr.write(chalk7.green(`\u2713 deleted ${key}
|
|
3453
|
+
`));
|
|
3454
|
+
}
|
|
3455
|
+
function configListCommand(opts = {}, command) {
|
|
3456
|
+
const global = command?.optsWithGlobals?.() ?? {};
|
|
3457
|
+
const store = getConfig().store;
|
|
3458
|
+
if (global.json) {
|
|
3459
|
+
const safe = { ...store };
|
|
3460
|
+
if (safe["api-key"]) safe["api-key"] = mask("api-key", safe["api-key"]);
|
|
3461
|
+
process.stdout.write(JSON.stringify(safe, null, global.pretty ? 2 : 0) + "\n");
|
|
3462
|
+
return;
|
|
3463
|
+
}
|
|
3464
|
+
process.stderr.write(chalk7.gray(`# ${configPath()}
|
|
3465
|
+
`));
|
|
3466
|
+
const keys = Object.keys(store);
|
|
3467
|
+
if (!keys.length) {
|
|
3468
|
+
process.stdout.write(chalk7.gray("(empty)\n"));
|
|
3469
|
+
return;
|
|
3470
|
+
}
|
|
3471
|
+
for (const key of keys) {
|
|
3472
|
+
process.stdout.write(`${chalk7.cyan(key)} = ${mask(key, store[key])}
|
|
3473
|
+
`);
|
|
3474
|
+
}
|
|
3475
|
+
}
|
|
3476
|
+
|
|
3477
|
+
// src/commands/agent-cmd.js
|
|
3478
|
+
import fs3 from "node:fs";
|
|
3479
|
+
import path2 from "node:path";
|
|
3480
|
+
import os3 from "node:os";
|
|
3481
|
+
import chalk8 from "chalk";
|
|
3482
|
+
var SERVER_NAME = "scraper-api";
|
|
3483
|
+
function jsonConfigPath(agent) {
|
|
3484
|
+
const home = os3.homedir();
|
|
3485
|
+
if (agent === "cursor") return path2.join(home, ".cursor", "mcp.json");
|
|
3486
|
+
if (agent === "claude") {
|
|
3487
|
+
if (process.platform === "darwin") {
|
|
3488
|
+
return path2.join(home, "Library", "Application Support", "Claude", "claude_desktop_config.json");
|
|
3489
|
+
}
|
|
3490
|
+
if (process.platform === "win32") {
|
|
3491
|
+
return path2.join(process.env.APPDATA || path2.join(home, "AppData", "Roaming"), "Claude", "claude_desktop_config.json");
|
|
3492
|
+
}
|
|
3493
|
+
return path2.join(home, ".config", "Claude", "claude_desktop_config.json");
|
|
3494
|
+
}
|
|
3495
|
+
return null;
|
|
3496
|
+
}
|
|
3497
|
+
function assertNotSymlink(filePath) {
|
|
3498
|
+
try {
|
|
3499
|
+
const stat = fs3.lstatSync(filePath);
|
|
3500
|
+
if (stat.isSymbolicLink()) {
|
|
3501
|
+
throw new Error(`Refusing to write through a symlink: ${filePath}`);
|
|
3502
|
+
}
|
|
3503
|
+
} catch (err) {
|
|
3504
|
+
if (err.code !== "ENOENT") throw err;
|
|
3505
|
+
}
|
|
3506
|
+
}
|
|
3507
|
+
function writeSecure(filePath, contents) {
|
|
3508
|
+
fs3.mkdirSync(path2.dirname(filePath), { recursive: true });
|
|
3509
|
+
assertNotSymlink(filePath);
|
|
3510
|
+
fs3.writeFileSync(filePath, contents, { mode: 384 });
|
|
3511
|
+
try {
|
|
3512
|
+
fs3.chmodSync(filePath, 384);
|
|
3513
|
+
} catch {
|
|
3514
|
+
}
|
|
3515
|
+
}
|
|
3516
|
+
function serverEnv(apiKey) {
|
|
3517
|
+
const env = { SCRAPER_API_KEY: apiKey || "${SCRAPER_API_KEY}" };
|
|
3518
|
+
if (process.env.SCRAPER_API_BASE) env.SCRAPER_API_BASE = process.env.SCRAPER_API_BASE;
|
|
3519
|
+
return env;
|
|
3520
|
+
}
|
|
3521
|
+
function addToJsonAgent(filePath, apiKey) {
|
|
3522
|
+
assertNotSymlink(filePath);
|
|
3523
|
+
let config = {};
|
|
3524
|
+
if (fs3.existsSync(filePath)) {
|
|
3525
|
+
try {
|
|
3526
|
+
config = JSON.parse(fs3.readFileSync(filePath, "utf8"));
|
|
3527
|
+
} catch {
|
|
3528
|
+
throw new Error(`Existing config is not valid JSON: ${filePath}`);
|
|
3529
|
+
}
|
|
3530
|
+
}
|
|
3531
|
+
config.mcpServers = config.mcpServers || {};
|
|
3532
|
+
config.mcpServers[SERVER_NAME] = {
|
|
3533
|
+
command: "npx",
|
|
3534
|
+
args: ["-y", "@scraper-api/mcp"],
|
|
3535
|
+
env: serverEnv(apiKey)
|
|
3536
|
+
};
|
|
3537
|
+
writeSecure(filePath, JSON.stringify(config, null, 2) + "\n");
|
|
3538
|
+
return filePath;
|
|
3539
|
+
}
|
|
3540
|
+
function addToCodex(apiKey) {
|
|
3541
|
+
const filePath = path2.join(os3.homedir(), ".codex", "config.toml");
|
|
3542
|
+
assertNotSymlink(filePath);
|
|
3543
|
+
const existing = fs3.existsSync(filePath) ? fs3.readFileSync(filePath, "utf8") : "";
|
|
3544
|
+
const envKey = apiKey || "${SCRAPER_API_KEY}";
|
|
3545
|
+
const block = `[mcp_servers.${SERVER_NAME}]
|
|
3546
|
+
command = "npx"
|
|
3547
|
+
args = ["-y", "@scraper-api/mcp"]
|
|
3548
|
+
env = { SCRAPER_API_KEY = "${envKey}"${process.env.SCRAPER_API_BASE ? `, SCRAPER_API_BASE = "${process.env.SCRAPER_API_BASE}"` : ""} }
|
|
3549
|
+
`;
|
|
3550
|
+
const sectionRe = new RegExp(`(^|\\n)\\[mcp_servers\\.${SERVER_NAME}\\][\\s\\S]*?(?=\\n\\[|$)`);
|
|
3551
|
+
let next;
|
|
3552
|
+
if (sectionRe.test(existing)) {
|
|
3553
|
+
next = existing.replace(sectionRe, (m, lead) => `${lead}${block.trimEnd()}`);
|
|
3554
|
+
} else {
|
|
3555
|
+
next = existing.trimEnd() ? `${existing.trimEnd()}
|
|
3556
|
+
|
|
3557
|
+
${block}` : block;
|
|
3558
|
+
}
|
|
3559
|
+
writeSecure(filePath, next.endsWith("\n") ? next : next + "\n");
|
|
3560
|
+
return filePath;
|
|
3561
|
+
}
|
|
3562
|
+
function agentAddCommand(agent, opts = {}, command) {
|
|
3563
|
+
const global = command?.optsWithGlobals?.() ?? {};
|
|
3564
|
+
const target = String(agent || "").toLowerCase();
|
|
3565
|
+
if (!["cursor", "claude", "codex"].includes(target)) {
|
|
3566
|
+
throw new Error(`Unknown agent "${agent}". Supported: cursor, claude, codex.`);
|
|
3567
|
+
}
|
|
3568
|
+
const apiKey = resolveApiKey(global.apiKey);
|
|
3569
|
+
if (!apiKey) {
|
|
3570
|
+
process.stderr.write(
|
|
3571
|
+
chalk8.yellow("\u26A0 No API key found \u2014 writing a ${SCRAPER_API_KEY} placeholder. Run `scraper-api login` first for a baked-in key.\n")
|
|
3572
|
+
);
|
|
3573
|
+
}
|
|
3574
|
+
const written = target === "codex" ? addToCodex(apiKey) : addToJsonAgent(jsonConfigPath(target), apiKey);
|
|
3575
|
+
process.stderr.write(chalk8.green(`\u2713 Added the scraper-api MCP server to ${target}.
|
|
3576
|
+
`));
|
|
3577
|
+
process.stderr.write(chalk8.gray(` ${written}
|
|
3578
|
+
`));
|
|
3579
|
+
process.stderr.write(chalk8.gray(" Restart the agent to load the new tools.\n"));
|
|
3580
|
+
}
|
|
3581
|
+
|
|
3582
|
+
// src/commands/interactive.js
|
|
3583
|
+
import * as p from "@clack/prompts";
|
|
3584
|
+
async function interactiveCommand(opts = {}, command) {
|
|
3585
|
+
const global = command?.optsWithGlobals?.() ?? {};
|
|
3586
|
+
const apiKey = requireApiKey(global.apiKey);
|
|
3587
|
+
p.intro("scraper-api");
|
|
3588
|
+
const platform = await p.select({
|
|
3589
|
+
message: "Platform",
|
|
3590
|
+
options: platforms.map((value) => ({ value, label: value }))
|
|
3591
|
+
});
|
|
3592
|
+
if (p.isCancel(platform)) return void p.cancel("Cancelled.");
|
|
3593
|
+
const list = endpointsForPlatform(platform);
|
|
3594
|
+
const action = await p.select({
|
|
3595
|
+
message: "Endpoint",
|
|
3596
|
+
options: list.map((e) => ({ value: e.action, label: `${e.action} \u2014 ${e.summary}` }))
|
|
3597
|
+
});
|
|
3598
|
+
if (p.isCancel(action)) return void p.cancel("Cancelled.");
|
|
3599
|
+
const endpoint = list.find((e) => e.action === action);
|
|
3600
|
+
const params = {};
|
|
3601
|
+
for (const param of endpoint.params) {
|
|
3602
|
+
const anyOfHint = param.anyOf ? " (any-of group)" : "";
|
|
3603
|
+
const value = await p.text({
|
|
3604
|
+
message: `${param.name}${param.required ? " *" : ""}${anyOfHint}`,
|
|
3605
|
+
placeholder: param.enum ? param.enum.join(" | ") : param.description || ""
|
|
3606
|
+
});
|
|
3607
|
+
if (p.isCancel(value)) return void p.cancel("Cancelled.");
|
|
3608
|
+
if (value) params[param.name] = value;
|
|
3609
|
+
}
|
|
3610
|
+
const spin = p.spinner();
|
|
3611
|
+
spin.start(`GET ${endpoint.path}`);
|
|
3612
|
+
try {
|
|
3613
|
+
const data = await apiGet(endpoint.path, params, apiKey);
|
|
3614
|
+
spin.stop("Done.");
|
|
3615
|
+
p.outro("Response:");
|
|
3616
|
+
emit(data, { format: global.json ? "json" : global.format, pretty: true, output: global.output });
|
|
3617
|
+
} catch (err) {
|
|
3618
|
+
spin.stop("Failed.");
|
|
3619
|
+
p.cancel(err.message);
|
|
3620
|
+
}
|
|
3621
|
+
}
|
|
3622
|
+
|
|
3623
|
+
// src/cli.js
|
|
3624
|
+
function buildProgram() {
|
|
3625
|
+
const program = new Command2();
|
|
3626
|
+
program.name("scraper-api").description("Command-line client for the scraper-api.com scraping API").version("0.1.0").option("--api-key <key>", "API key (overrides config and env)").option("-f, --format <format>", "output format: json | table | csv | markdown", "json").option("--json", "shortcut for --format json").option("--pretty", "pretty-print JSON output").option("-o, --output <file>", "write output to a file instead of stdout").option("--no-color", "disable colored output").option("--verbose", "print request diagnostics to stderr").showHelpAfterError();
|
|
3627
|
+
program.hook("preAction", (thisCommand) => {
|
|
3628
|
+
if (thisCommand.opts().color === false) chalk9.level = 0;
|
|
3629
|
+
});
|
|
3630
|
+
program.command("login").description("Sign in via your browser (OAuth PKCE) and mint an API key").action(loginCommand);
|
|
3631
|
+
program.command("logout").description("Remove the stored API key and identity").action(logoutCommand);
|
|
3632
|
+
program.command("whoami").description("Show the account the active API key belongs to").action((opts, cmd) => whoamiCommand(opts, cmd));
|
|
3633
|
+
const auth = program.command("auth").description("Manual API-key authentication");
|
|
3634
|
+
auth.command("login").description("Store an API key you minted in the dashboard").requiredOption("--api-key <key>", "the API key to store").action(authLoginCommand);
|
|
3635
|
+
auth.command("status").description("Show the active key and its source").action((opts, cmd) => authStatusCommand(opts, cmd));
|
|
3636
|
+
program.command("balance").description("Show remaining credits for the active API key").action((opts, cmd) => balanceCommand(opts, cmd));
|
|
3637
|
+
program.command("list").argument("[platform]", "restrict to one platform").description("List available platforms and endpoint commands").action((platform, opts, cmd) => listCommand(platform, opts, cmd));
|
|
3638
|
+
const config = program.command("config").description("Read and edit persisted CLI settings");
|
|
3639
|
+
config.command("set <key> <value>").description("Set a config value").action(configSetCommand);
|
|
3640
|
+
config.command("get <key>").description("Read a config value").action(configGetCommand);
|
|
3641
|
+
config.command("delete <key>").description("Delete a config value").action(configDeleteCommand);
|
|
3642
|
+
config.command("list").description("List all config values").action((opts, cmd) => configListCommand(opts, cmd));
|
|
3643
|
+
const agent = program.command("agent").description("Wire the scraper-api MCP server into an AI agent");
|
|
3644
|
+
agent.command("add <agent>").description("Add the MCP server to cursor | claude | codex").action((target, opts, cmd) => agentAddCommand(target, opts, cmd));
|
|
3645
|
+
program.command("interactive").description("Guided endpoint picker").action((opts, cmd) => interactiveCommand(opts, cmd));
|
|
3646
|
+
registerEndpointCommands(program);
|
|
3647
|
+
return program;
|
|
3648
|
+
}
|
|
3649
|
+
async function run(argv) {
|
|
3650
|
+
const program = buildProgram();
|
|
3651
|
+
await program.parseAsync(argv);
|
|
3652
|
+
}
|
|
3653
|
+
|
|
3654
|
+
// bin/scraper-api.js
|
|
3655
|
+
run(process.argv).catch((err) => {
|
|
3656
|
+
console.error(err?.message ?? err);
|
|
3657
|
+
process.exit(1);
|
|
3658
|
+
});
|