scavio 0.8.0 → 0.10.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/index.d.ts CHANGED
@@ -624,6 +624,169 @@ declare class TikTokNamespace {
624
624
  userFollowings(options: TikTokUserFollowingsOptions): Promise<Record<string, unknown>>;
625
625
  }
626
626
 
627
+ /** Marketplace regions served by suggestions, product, reviews, and shop products. */
628
+ type TikTokShopRegion = "US" | "GB" | "SG" | "MY" | "PH" | "TH" | "VN" | "ID";
629
+ /** Marketplace regions served by category listings. */
630
+ type TikTokShopListingRegion = "US" | "GB";
631
+ /** Review ordering: 'relevant' is text-complete and image-heavy, 'recent' is fresher but text-sparse. */
632
+ type TikTokShopReviewSort = "relevant" | "recent";
633
+ interface TikTokShopSearchOptions {
634
+ /** Search query (1-200 characters). US catalog only. */
635
+ search: string;
636
+ /** Opaque cursor from a prior response's next_cursor. */
637
+ cursor?: string;
638
+ [key: string]: unknown;
639
+ }
640
+ interface TikTokShopSuggestionsOptions {
641
+ /** Partial query to expand (1-100 characters). */
642
+ search: string;
643
+ /** Marketplace region (default 'US'). */
644
+ region?: TikTokShopRegion;
645
+ [key: string]: unknown;
646
+ }
647
+ interface TikTokShopProductOptions {
648
+ /** TikTok Shop product id (6-25 digits). */
649
+ product_id: string;
650
+ /** Marketplace region (default 'US'). */
651
+ region?: TikTokShopRegion;
652
+ [key: string]: unknown;
653
+ }
654
+ interface TikTokShopProductReviewsOptions {
655
+ /** TikTok Shop product id (6-25 digits). */
656
+ product_id: string;
657
+ /** 1-based page number (1-500, default 1). */
658
+ page?: number;
659
+ /** Reviews per page (1-200, default 20). */
660
+ page_size?: number;
661
+ /** 'relevant' (default) is text-complete and image-heavy; 'recent' is fresher but far more text-sparse. */
662
+ sort?: TikTokShopReviewSort;
663
+ /** Only reviews with this star rating (1-5). */
664
+ rating?: number;
665
+ /** Only reviews with a photo or video (default false). */
666
+ has_media?: boolean;
667
+ /** Only verified purchases (default false). */
668
+ verified_only?: boolean;
669
+ /** Marketplace region (default 'US'). */
670
+ region?: TikTokShopRegion;
671
+ [key: string]: unknown;
672
+ }
673
+ interface TikTokShopCategoryProductsOptions {
674
+ /** Category id from tiktokShop.categories(); level 1 or 2 both work. */
675
+ category_id: string;
676
+ /** Opaque cursor from a prior response's next_cursor. */
677
+ cursor?: string;
678
+ /** Marketplace region, 'US' or 'GB' only (default 'US'). */
679
+ region?: TikTokShopListingRegion;
680
+ [key: string]: unknown;
681
+ }
682
+ interface TikTokShopShopProductsOptions {
683
+ /** TikTok Shop seller id (also called seller_id elsewhere on TikTok). */
684
+ shop_id: string;
685
+ /** Opaque cursor from a prior response's next_cursor. */
686
+ cursor?: string;
687
+ /** Marketplace region (default 'US'). */
688
+ region?: TikTokShopRegion;
689
+ [key: string]: unknown;
690
+ }
691
+ interface TikTokShopResolveOptions {
692
+ /** A TikTok Shop product or store URL, affiliate share link, or vt.tiktok.com short link. */
693
+ url: string;
694
+ [key: string]: unknown;
695
+ }
696
+ declare class TikTokShopNamespace {
697
+ private client;
698
+ constructor(client: Scavio);
699
+ /**
700
+ * Search TikTok Shop products by keyword (US catalog), up to 30 per page with
701
+ * exact prices, ratings, and shop details. Paginate with next_cursor and dedupe
702
+ * by product_id across pages.
703
+ *
704
+ * This is one of the three endpoints that return exact prices; tiktokShop.product()
705
+ * does not return a price. A product_id returned here is not guaranteed to resolve
706
+ * on tiktokShop.product() - only about 44% do.
707
+ */
708
+ search(options: TikTokShopSearchOptions): Promise<Record<string, unknown>>;
709
+ /**
710
+ * Keyword autocomplete and expansion for a partial query, across 8 marketplace
711
+ * regions. Suggestions are not guaranteed prefix matches: a misspelling returns
712
+ * typo corrections, and results can include brand and shop names.
713
+ */
714
+ searchSuggestions(options: TikTokShopSuggestionsOptions): Promise<Record<string, unknown>>;
715
+ /**
716
+ * Full product detail: description, images, variants with stock, shipping, shop
717
+ * profile, category path, and top reviews.
718
+ *
719
+ * Two limits worth knowing before you build on this:
720
+ *
721
+ * 1. It resolves only about 44% of the product ids returned by tiktokShop.search().
722
+ * Upstream has no detail data for the rest, so an HTTP 404 is a normal outcome,
723
+ * not an error. Skip the item rather than retrying - retries do not help and no
724
+ * other region carries it. Search to product is not a reliable pipeline.
725
+ *
726
+ * This method throws `NotFoundError` on that 404 (there is no `data` field in
727
+ * the response body to test), so a loop over search ids must catch it or it
728
+ * dies on the first miss:
729
+ *
730
+ * ```ts
731
+ * import { NotFoundError } from "scavio";
732
+ *
733
+ * for (const productId of productIds) {
734
+ * try {
735
+ * const detail = await client.tiktokShop.product({ product_id: productId });
736
+ * } catch (e) {
737
+ * if (e instanceof NotFoundError) continue; // no detail upstream; skip
738
+ * throw e;
739
+ * }
740
+ * }
741
+ * ```
742
+ *
743
+ * tiktokShop.productReviews() often works for ids product() cannot resolve: of
744
+ * 8 such ids tested, 8 returned HTTP 200 and 7 carried at least one review, so
745
+ * it is a useful fallback source of product detail.
746
+ * 2. It does NOT return a price. Upstream masks the price on the product page.
747
+ * Exact prices come from tiktokShop.search(), tiktokShop.shopProducts(), and
748
+ * tiktokShop.categoryProducts().
749
+ */
750
+ product(options: TikTokShopProductOptions): Promise<Record<string, unknown>>;
751
+ /**
752
+ * Paginated product reviews with text, images, star histogram, and
753
+ * verified-purchase flags, up to 200 per call. total_reviews drifts between calls
754
+ * and must not be used to compute a page count; page with has_more instead.
755
+ */
756
+ productReviews(options: TikTokShopProductReviewsOptions): Promise<Record<string, unknown>>;
757
+ /**
758
+ * The global TikTok Shop category tree: 28 top-level categories, 240 nodes, two
759
+ * levels deep. Category ids are identical in every region and names are always
760
+ * English.
761
+ */
762
+ categories(): Promise<Record<string, unknown>>;
763
+ /**
764
+ * Products listed under a category id from tiktokShop.categories(), with exact
765
+ * prices. Page size is inconsistent upstream (15 to 20 per page), so always
766
+ * paginate with next_cursor rather than assuming a fixed page size. Category
767
+ * listings are shallow: after a few pages the source stops returning new products
768
+ * and has_more turns false, which is the end of the listing rather than an error.
769
+ */
770
+ categoryProducts(options: TikTokShopCategoryProductsOptions): Promise<Record<string, unknown>>;
771
+ /**
772
+ * A shop's product catalog, 30 per page, with exact prices. Shop follower count,
773
+ * location, and shop-level rating are not available here; call
774
+ * tiktokShop.product() for the full shop profile.
775
+ */
776
+ shopProducts(options: TikTokShopShopProductsOptions): Promise<Record<string, unknown>>;
777
+ /**
778
+ * Resolve any TikTok Shop URL or share link to a product_id or shop_id, ready to
779
+ * pass to the other methods. Accepts canonical product and store pages,
780
+ * tiktok.com/view links, affiliate share links, and vt.tiktok.com short links.
781
+ */
782
+ resolve(options: TikTokShopResolveOptions): Promise<Record<string, unknown>>;
783
+ }
784
+
785
+ /**
786
+ * Instagram endpoints (/api/v1/instagram). Credit cost varies by endpoint:
787
+ * `userPosts` costs 2 credits, every other endpoint costs 8.
788
+ * See https://scavio.dev/docs/instagram-api.
789
+ */
627
790
  interface InstagramProfileOptions {
628
791
  /** Instagram username (without the @). */
629
792
  username?: string;
@@ -987,150 +1150,125 @@ declare class XNamespace {
987
1150
  trending(options?: XTrendingOptions): Promise<Record<string, unknown>>;
988
1151
  }
989
1152
 
1153
+ /** A member reference: a vanity handle, or a full profile URL. */
990
1154
  interface LinkedInPersonOptions {
991
- /** Public identifier (vanity handle). */
992
- username: string;
993
- /** Include the experiences section (default true server-side). */
994
- include_experiences?: boolean;
995
- /** Include the educations section (default true server-side). */
996
- include_educations?: boolean;
997
- /** Include the skills section (default true server-side). */
998
- include_skills?: boolean;
999
- /** Include the certifications section (default true server-side). */
1000
- include_certifications?: boolean;
1001
- /** Include follower and connection counts (default true server-side). */
1002
- include_follower_and_connection?: boolean;
1003
- [key: string]: unknown;
1004
- }
1005
- interface LinkedInPersonRefOptions {
1006
- /** Member urn. */
1007
- urn?: string;
1008
- /** Public identifier; resolved to a urn if urn is omitted. */
1155
+ /** Public identifier (vanity handle), e.g. "williamhgates". */
1009
1156
  username?: string;
1157
+ /** Full LinkedIn profile URL, as an alternative to username. */
1158
+ url?: string;
1010
1159
  [key: string]: unknown;
1011
1160
  }
1012
- interface LinkedInPersonPostsOptions {
1013
- /** Member urn. */
1014
- urn?: string;
1015
- /** Public identifier; resolved to a urn if urn is omitted. */
1016
- username?: string;
1017
- /** Pagination cursor from a prior response. */
1018
- cursor?: string;
1161
+ /** A company reference: a universal name (slug), or a full company URL. */
1162
+ interface LinkedInCompanyOptions {
1163
+ /** Company universal name (slug), e.g. "microsoft". */
1164
+ company?: string;
1165
+ /** Full LinkedIn company URL, as an alternative to company. */
1166
+ url?: string;
1019
1167
  [key: string]: unknown;
1020
1168
  }
1021
- interface LinkedInPersonContactOptions {
1022
- /** Public identifier (vanity handle). */
1023
- username: string;
1169
+ /** @deprecated Use {@link LinkedInPersonOptions}. */
1170
+ type LinkedInPersonRefOptions = LinkedInPersonOptions;
1171
+ /** @deprecated Use {@link LinkedInPersonOptions}. */
1172
+ type LinkedInPersonPostsOptions = LinkedInPersonOptions;
1173
+ /** @deprecated Use {@link LinkedInCompanyOptions}. */
1174
+ type LinkedInCompanyPostsOptions = LinkedInCompanyOptions;
1175
+ interface LinkedInSearchJobsOptions {
1176
+ /** Search keyword. */
1177
+ search: string;
1178
+ /** Geographic filter; omit to search everywhere. */
1179
+ location?: string;
1024
1180
  [key: string]: unknown;
1025
1181
  }
1026
- interface LinkedInCompanyOptions {
1027
- /** Company universal name (slug) or LinkedIn company URL. */
1028
- company: string;
1182
+ interface LinkedInJobOptions {
1183
+ /** Job listing id. */
1184
+ job_id?: string;
1185
+ /** Full LinkedIn job URL, as an alternative to job_id. */
1186
+ url?: string;
1029
1187
  [key: string]: unknown;
1030
1188
  }
1031
- interface LinkedInCompanyPostsOptions {
1032
- /** Company universal name (slug) or LinkedIn company URL. */
1033
- company: string;
1034
- /** Pagination cursor from a prior response. */
1035
- cursor?: string;
1036
- /** Results per page (1-100). */
1037
- count?: number;
1189
+ interface LinkedInPostOptions {
1190
+ /** Post id or activity urn. */
1191
+ post_id?: string;
1192
+ /** Full LinkedIn post URL, as an alternative to post_id. */
1193
+ url?: string;
1194
+ [key: string]: unknown;
1195
+ }
1196
+ interface LinkedInPostCommentsOptions extends LinkedInPostOptions {
1197
+ /** 1-based page number, 10 comments per page. */
1198
+ page?: number;
1199
+ }
1200
+ /** @deprecated Retired upstream; always returns HTTP 410. */
1201
+ interface LinkedInPersonContactOptions {
1202
+ username?: string;
1038
1203
  [key: string]: unknown;
1039
1204
  }
1205
+ /** @deprecated Retired upstream; always returns HTTP 410. */
1040
1206
  interface LinkedInCompanyRefOptions {
1041
- /** Numeric company id. */
1042
1207
  company_id?: string;
1043
- /** Company slug/url; resolved to a company_id if company_id is omitted. */
1044
1208
  company?: string;
1045
- /** Pagination cursor from a prior response. */
1046
- cursor?: string;
1047
1209
  [key: string]: unknown;
1048
1210
  }
1211
+ /** @deprecated Retired upstream; always returns HTTP 410. */
1049
1212
  interface LinkedInSearchPeopleOptions {
1050
- /** Name to search for. */
1051
1213
  search?: string;
1052
- /** Job title filter. */
1053
1214
  title?: string;
1054
- /** Company filter. */
1055
1215
  company?: string;
1056
- /** School filter. */
1057
1216
  school?: string;
1058
- /** A geo name or id to filter by. */
1059
1217
  location?: string;
1060
- /** Page cursor (page number). */
1061
- cursor?: string;
1062
- [key: string]: unknown;
1063
- }
1064
- interface LinkedInSearchJobsOptions {
1065
- /** Search query (1-500 characters). */
1066
- search: string;
1067
- /** Page cursor (page number). */
1068
- cursor?: string;
1069
- /** Date-posted filter. */
1070
- date_posted?: string;
1071
- /** Geo code to filter by. */
1072
- geocode?: string;
1073
- /** Experience level filter. */
1074
- experience_level?: string;
1075
- /** Remote filter. */
1076
- remote?: string;
1077
- /** Job type filter. */
1078
- job_type?: string;
1079
1218
  [key: string]: unknown;
1080
1219
  }
1220
+ /** @deprecated Retired upstream; always returns HTTP 410. */
1081
1221
  interface LinkedInSearchPostsOptions {
1082
- /** Search query (1-500 characters). */
1083
- search: string;
1084
- /** Page cursor (page number). */
1085
- cursor?: string;
1086
- /** Date-posted filter. */
1087
- date_posted?: string;
1088
- /** Sort order. */
1089
- sort_by?: string;
1090
- /** Content type filter. */
1091
- content_type?: string;
1092
- [key: string]: unknown;
1093
- }
1094
- interface LinkedInJobOptions {
1095
- /** Job listing id. */
1096
- job_id: string;
1097
- /** Include the required-skills section. */
1098
- include_skills?: boolean;
1099
- [key: string]: unknown;
1100
- }
1101
- interface LinkedInPostOptions {
1102
- /** Post id or activity urn. */
1103
- post_id: string;
1104
- [key: string]: unknown;
1105
- }
1106
- interface LinkedInPostCommentsOptions {
1107
- /** Post id or activity urn. */
1108
- post_id: string;
1109
- /** Pagination cursor from a prior response. */
1110
- cursor?: string;
1111
- /** Comment sort order. */
1112
- sort_order?: "relevance" | "recent";
1113
- /** Post type. */
1114
- post_type?: "activity" | "ugc";
1222
+ search?: string;
1115
1223
  [key: string]: unknown;
1116
1224
  }
1117
1225
  declare class LinkedInNamespace {
1118
1226
  private client;
1119
1227
  constructor(client: Scavio);
1228
+ /** Full profile: about text, experience, education, honours and links. */
1120
1229
  person(options: LinkedInPersonOptions): Promise<Record<string, unknown>>;
1121
- personAbout(options: LinkedInPersonRefOptions): Promise<Record<string, unknown>>;
1122
- personPosts(options: LinkedInPersonPostsOptions): Promise<Record<string, unknown>>;
1123
- personContact(options: LinkedInPersonContactOptions): Promise<Record<string, unknown>>;
1230
+ /** The about-only slice of the profile payload. */
1231
+ personAbout(options: LinkedInPersonOptions): Promise<Record<string, unknown>>;
1232
+ /** Recent posts, up to 50. Upstream exposes no further pages. */
1233
+ personPosts(options: LinkedInPersonOptions): Promise<Record<string, unknown>>;
1234
+ /** Company profile, including locations and featured employees. */
1124
1235
  company(options: LinkedInCompanyOptions): Promise<Record<string, unknown>>;
1125
- companyPosts(options: LinkedInCompanyPostsOptions): Promise<Record<string, unknown>>;
1126
- companyPeople(options: LinkedInCompanyRefOptions): Promise<Record<string, unknown>>;
1127
- companyJobs(options: LinkedInCompanyRefOptions): Promise<Record<string, unknown>>;
1128
- searchPeople(options: LinkedInSearchPeopleOptions): Promise<Record<string, unknown>>;
1236
+ /** Recent company posts, up to 50. Upstream exposes no further pages. */
1237
+ companyPosts(options: LinkedInCompanyOptions): Promise<Record<string, unknown>>;
1238
+ /** Job search. Upstream rotates its result set, so repeat calls differ. */
1129
1239
  searchJobs(options: LinkedInSearchJobsOptions): Promise<Record<string, unknown>>;
1130
- searchPosts(options: LinkedInSearchPostsOptions): Promise<Record<string, unknown>>;
1240
+ /** Full detail for one job listing, including the hiring company. */
1131
1241
  job(options: LinkedInJobOptions): Promise<Record<string, unknown>>;
1242
+ /** Full detail for one post, including its top visible comments. */
1132
1243
  post(options: LinkedInPostOptions): Promise<Record<string, unknown>>;
1244
+ /** Comments with their replies, 10 per page. */
1133
1245
  postComments(options: LinkedInPostCommentsOptions): Promise<Record<string, unknown>>;
1246
+ /**
1247
+ * @deprecated Retired by the upstream provider. Always returns HTTP 410 and is
1248
+ * never billed.
1249
+ */
1250
+ personContact(options: LinkedInPersonContactOptions): Promise<Record<string, unknown>>;
1251
+ /**
1252
+ * @deprecated Retired by the upstream provider. Always returns HTTP 410 and is
1253
+ * never billed. `company()` returns `featured_employees`, a small sample of
1254
+ * staff profiles.
1255
+ */
1256
+ companyPeople(options: LinkedInCompanyRefOptions): Promise<Record<string, unknown>>;
1257
+ /**
1258
+ * @deprecated Retired by the upstream provider. Always returns HTTP 410 and is
1259
+ * never billed. Use `searchJobs()` with the company name as the search term.
1260
+ */
1261
+ companyJobs(options: LinkedInCompanyRefOptions): Promise<Record<string, unknown>>;
1262
+ /**
1263
+ * @deprecated Retired by the upstream provider. Always returns HTTP 410 and is
1264
+ * never billed.
1265
+ */
1266
+ searchPeople(options: LinkedInSearchPeopleOptions): Promise<Record<string, unknown>>;
1267
+ /**
1268
+ * @deprecated Retired by the upstream provider. Always returns HTTP 410 and is
1269
+ * never billed.
1270
+ */
1271
+ searchPosts(options: LinkedInSearchPostsOptions): Promise<Record<string, unknown>>;
1134
1272
  }
1135
1273
 
1136
1274
  interface ScavioConfig {
@@ -1152,6 +1290,7 @@ declare class Scavio {
1152
1290
  readonly youtube: YouTubeNamespace;
1153
1291
  readonly reddit: RedditNamespace;
1154
1292
  readonly tiktok: TikTokNamespace;
1293
+ readonly tiktokShop: TikTokShopNamespace;
1155
1294
  readonly instagram: InstagramNamespace;
1156
1295
  readonly x: XNamespace;
1157
1296
  readonly linkedin: LinkedInNamespace;
@@ -1214,4 +1353,4 @@ declare class ScavioAPIError extends ScavioError {
1214
1353
  constructor(statusCode: number, message: string, responseBody?: Record<string, unknown>);
1215
1354
  }
1216
1355
 
1217
- export { type AmazonProductOptions, type AmazonSearchOptions, BadRequestError, type GoogleAiModeOptions, type GoogleFlightsOptions, type GoogleHotelsDetailOptions, type GoogleHotelsOptions, type GoogleMapsPlaceOptions, type GoogleMapsReviewsOptions, type GoogleMapsSearchOptions, type GoogleNewsOptions, type GoogleSearchOptions, type GoogleShoppingOptions, type GoogleShoppingProductOptions, type GoogleShoppingStoresOptions, type GoogleTrendingOptions, type GoogleTrendsOptions, type InstagramCommentRepliesOptions, type InstagramFollowOptions, type InstagramPostCommentsOptions, type InstagramPostOptions, type InstagramProfileOptions, type InstagramSearchOptions, type InstagramStoriesOptions, type InstagramUserFeedOptions, InsufficientCreditsError, InvalidAPIKeyError, type LinkedInCompanyOptions, type LinkedInCompanyPostsOptions, type LinkedInCompanyRefOptions, type LinkedInJobOptions, type LinkedInPersonContactOptions, type LinkedInPersonOptions, type LinkedInPersonPostsOptions, type LinkedInPersonRefOptions, type LinkedInPostCommentsOptions, type LinkedInPostOptions, type LinkedInSearchJobsOptions, type LinkedInSearchPeopleOptions, type LinkedInSearchPostsOptions, MissingAPIKeyError, NotFoundError, RateLimitError, type RedditCommentRepliesOptions, type RedditFeedSort, type RedditPopularOptions, type RedditPostCommentsOptions, type RedditPostOptions, type RedditSearchOptions, type RedditSearchSuggestionsOptions, type RedditSort, type RedditSubredditOptions, type RedditSubredditPostsOptions, type RedditUserFeedOptions, type RedditUserOptions, Scavio, ScavioAPIError, type ScavioConfig, ScavioConnectionError, ScavioError, ScavioTimeoutError, type TikTokCommentRepliesOptions, type TikTokHashtagOptions, type TikTokHashtagVideosOptions, type TikTokProfileOptions, type TikTokSearchUsersOptions, type TikTokSearchVideosOptions, type TikTokUserFollowersOptions, type TikTokUserFollowingsOptions, type TikTokUserPostsOptions, type TikTokVideoCommentsOptions, type TikTokVideoOptions, type WalmartProductOptions, type WalmartSearchOptions, type XSearchOptions, type XTrendingOptions, type XTweetCommentsOptions, type XTweetOptions, type XTweetRetweetersOptions, type XUserFeedOptions, type XUserOptions, type YouTubeChannelCommunityOptions, type YouTubeChannelOptions, type YouTubeChannelResolveOptions, type YouTubeChannelSearchOptions, type YouTubeChannelShortsOptions, type YouTubeChannelVideosOptions, type YouTubeCommentRepliesOptions, type YouTubeCommentsOptions, type YouTubeMetadataOptions, type YouTubeRelatedOptions, type YouTubeSearchOptions, type YouTubeShortsOptions, type YouTubeStreamsOptions, type YouTubeSuggestionsOptions, type YouTubeTranscriptOptions, type YouTubeVideoOptions };
1356
+ export { type AmazonProductOptions, type AmazonSearchOptions, BadRequestError, type GoogleAiModeOptions, type GoogleFlightsOptions, type GoogleHotelsDetailOptions, type GoogleHotelsOptions, type GoogleMapsPlaceOptions, type GoogleMapsReviewsOptions, type GoogleMapsSearchOptions, type GoogleNewsOptions, type GoogleSearchOptions, type GoogleShoppingOptions, type GoogleShoppingProductOptions, type GoogleShoppingStoresOptions, type GoogleTrendingOptions, type GoogleTrendsOptions, type InstagramCommentRepliesOptions, type InstagramFollowOptions, type InstagramPostCommentsOptions, type InstagramPostOptions, type InstagramProfileOptions, type InstagramSearchOptions, type InstagramStoriesOptions, type InstagramUserFeedOptions, InsufficientCreditsError, InvalidAPIKeyError, type LinkedInCompanyOptions, type LinkedInCompanyPostsOptions, type LinkedInCompanyRefOptions, type LinkedInJobOptions, type LinkedInPersonContactOptions, type LinkedInPersonOptions, type LinkedInPersonPostsOptions, type LinkedInPersonRefOptions, type LinkedInPostCommentsOptions, type LinkedInPostOptions, type LinkedInSearchJobsOptions, type LinkedInSearchPeopleOptions, type LinkedInSearchPostsOptions, MissingAPIKeyError, NotFoundError, RateLimitError, type RedditCommentRepliesOptions, type RedditFeedSort, type RedditPopularOptions, type RedditPostCommentsOptions, type RedditPostOptions, type RedditSearchOptions, type RedditSearchSuggestionsOptions, type RedditSort, type RedditSubredditOptions, type RedditSubredditPostsOptions, type RedditUserFeedOptions, type RedditUserOptions, Scavio, ScavioAPIError, type ScavioConfig, ScavioConnectionError, ScavioError, ScavioTimeoutError, type TikTokCommentRepliesOptions, type TikTokHashtagOptions, type TikTokHashtagVideosOptions, type TikTokProfileOptions, type TikTokSearchUsersOptions, type TikTokSearchVideosOptions, type TikTokShopCategoryProductsOptions, type TikTokShopListingRegion, type TikTokShopProductOptions, type TikTokShopProductReviewsOptions, type TikTokShopRegion, type TikTokShopResolveOptions, type TikTokShopReviewSort, type TikTokShopSearchOptions, type TikTokShopShopProductsOptions, type TikTokShopSuggestionsOptions, type TikTokUserFollowersOptions, type TikTokUserFollowingsOptions, type TikTokUserPostsOptions, type TikTokVideoCommentsOptions, type TikTokVideoOptions, type WalmartProductOptions, type WalmartSearchOptions, type XSearchOptions, type XTrendingOptions, type XTweetCommentsOptions, type XTweetOptions, type XTweetRetweetersOptions, type XUserFeedOptions, type XUserOptions, type YouTubeChannelCommunityOptions, type YouTubeChannelOptions, type YouTubeChannelResolveOptions, type YouTubeChannelSearchOptions, type YouTubeChannelShortsOptions, type YouTubeChannelVideosOptions, type YouTubeCommentRepliesOptions, type YouTubeCommentsOptions, type YouTubeMetadataOptions, type YouTubeRelatedOptions, type YouTubeSearchOptions, type YouTubeShortsOptions, type YouTubeStreamsOptions, type YouTubeSuggestionsOptions, type YouTubeTranscriptOptions, type YouTubeVideoOptions };
package/dist/index.js CHANGED
@@ -430,6 +430,114 @@ var TikTokNamespace = class {
430
430
  }
431
431
  };
432
432
 
433
+ // src/namespaces/tiktok-shop.ts
434
+ var TikTokShopNamespace = class {
435
+ constructor(client) {
436
+ this.client = client;
437
+ }
438
+ client;
439
+ /**
440
+ * Search TikTok Shop products by keyword (US catalog), up to 30 per page with
441
+ * exact prices, ratings, and shop details. Paginate with next_cursor and dedupe
442
+ * by product_id across pages.
443
+ *
444
+ * This is one of the three endpoints that return exact prices; tiktokShop.product()
445
+ * does not return a price. A product_id returned here is not guaranteed to resolve
446
+ * on tiktokShop.product() - only about 44% do.
447
+ */
448
+ async search(options) {
449
+ return this.client._post("/api/v1/tiktok-shop/search", options);
450
+ }
451
+ /**
452
+ * Keyword autocomplete and expansion for a partial query, across 8 marketplace
453
+ * regions. Suggestions are not guaranteed prefix matches: a misspelling returns
454
+ * typo corrections, and results can include brand and shop names.
455
+ */
456
+ async searchSuggestions(options) {
457
+ return this.client._post("/api/v1/tiktok-shop/search/suggestions", options);
458
+ }
459
+ /**
460
+ * Full product detail: description, images, variants with stock, shipping, shop
461
+ * profile, category path, and top reviews.
462
+ *
463
+ * Two limits worth knowing before you build on this:
464
+ *
465
+ * 1. It resolves only about 44% of the product ids returned by tiktokShop.search().
466
+ * Upstream has no detail data for the rest, so an HTTP 404 is a normal outcome,
467
+ * not an error. Skip the item rather than retrying - retries do not help and no
468
+ * other region carries it. Search to product is not a reliable pipeline.
469
+ *
470
+ * This method throws `NotFoundError` on that 404 (there is no `data` field in
471
+ * the response body to test), so a loop over search ids must catch it or it
472
+ * dies on the first miss:
473
+ *
474
+ * ```ts
475
+ * import { NotFoundError } from "scavio";
476
+ *
477
+ * for (const productId of productIds) {
478
+ * try {
479
+ * const detail = await client.tiktokShop.product({ product_id: productId });
480
+ * } catch (e) {
481
+ * if (e instanceof NotFoundError) continue; // no detail upstream; skip
482
+ * throw e;
483
+ * }
484
+ * }
485
+ * ```
486
+ *
487
+ * tiktokShop.productReviews() often works for ids product() cannot resolve: of
488
+ * 8 such ids tested, 8 returned HTTP 200 and 7 carried at least one review, so
489
+ * it is a useful fallback source of product detail.
490
+ * 2. It does NOT return a price. Upstream masks the price on the product page.
491
+ * Exact prices come from tiktokShop.search(), tiktokShop.shopProducts(), and
492
+ * tiktokShop.categoryProducts().
493
+ */
494
+ async product(options) {
495
+ return this.client._post("/api/v1/tiktok-shop/product", options);
496
+ }
497
+ /**
498
+ * Paginated product reviews with text, images, star histogram, and
499
+ * verified-purchase flags, up to 200 per call. total_reviews drifts between calls
500
+ * and must not be used to compute a page count; page with has_more instead.
501
+ */
502
+ async productReviews(options) {
503
+ return this.client._post("/api/v1/tiktok-shop/product/reviews", options);
504
+ }
505
+ /**
506
+ * The global TikTok Shop category tree: 28 top-level categories, 240 nodes, two
507
+ * levels deep. Category ids are identical in every region and names are always
508
+ * English.
509
+ */
510
+ async categories() {
511
+ return this.client._post("/api/v1/tiktok-shop/categories", {});
512
+ }
513
+ /**
514
+ * Products listed under a category id from tiktokShop.categories(), with exact
515
+ * prices. Page size is inconsistent upstream (15 to 20 per page), so always
516
+ * paginate with next_cursor rather than assuming a fixed page size. Category
517
+ * listings are shallow: after a few pages the source stops returning new products
518
+ * and has_more turns false, which is the end of the listing rather than an error.
519
+ */
520
+ async categoryProducts(options) {
521
+ return this.client._post("/api/v1/tiktok-shop/category/products", options);
522
+ }
523
+ /**
524
+ * A shop's product catalog, 30 per page, with exact prices. Shop follower count,
525
+ * location, and shop-level rating are not available here; call
526
+ * tiktokShop.product() for the full shop profile.
527
+ */
528
+ async shopProducts(options) {
529
+ return this.client._post("/api/v1/tiktok-shop/shop/products", options);
530
+ }
531
+ /**
532
+ * Resolve any TikTok Shop URL or share link to a product_id or shop_id, ready to
533
+ * pass to the other methods. Accepts canonical product and store pages,
534
+ * tiktok.com/view links, affiliate share links, and vt.tiktok.com short links.
535
+ */
536
+ async resolve(options) {
537
+ return this.client._post("/api/v1/tiktok-shop/resolve", options);
538
+ }
539
+ };
540
+
433
541
  // src/namespaces/instagram.ts
434
542
  var InstagramNamespace = class {
435
543
  constructor(client) {
@@ -612,48 +720,78 @@ var LinkedInNamespace = class {
612
720
  this.client = client;
613
721
  }
614
722
  client;
723
+ /** Full profile: about text, experience, education, honours and links. */
615
724
  async person(options) {
616
725
  return this.client._post("/api/v1/linkedin/person", options);
617
726
  }
727
+ /** The about-only slice of the profile payload. */
618
728
  async personAbout(options) {
619
729
  return this.client._post("/api/v1/linkedin/person/about", options);
620
730
  }
731
+ /** Recent posts, up to 50. Upstream exposes no further pages. */
621
732
  async personPosts(options) {
622
733
  return this.client._post("/api/v1/linkedin/person/posts", options);
623
734
  }
624
- async personContact(options) {
625
- return this.client._post("/api/v1/linkedin/person/contact", options);
626
- }
735
+ /** Company profile, including locations and featured employees. */
627
736
  async company(options) {
628
737
  return this.client._post("/api/v1/linkedin/company", options);
629
738
  }
739
+ /** Recent company posts, up to 50. Upstream exposes no further pages. */
630
740
  async companyPosts(options) {
631
741
  return this.client._post("/api/v1/linkedin/company/posts", options);
632
742
  }
633
- async companyPeople(options) {
634
- return this.client._post("/api/v1/linkedin/company/people", options);
635
- }
636
- async companyJobs(options) {
637
- return this.client._post("/api/v1/linkedin/company/jobs", options);
638
- }
639
- async searchPeople(options) {
640
- return this.client._post("/api/v1/linkedin/search/people", options);
641
- }
743
+ /** Job search. Upstream rotates its result set, so repeat calls differ. */
642
744
  async searchJobs(options) {
643
745
  return this.client._post("/api/v1/linkedin/search/jobs", options);
644
746
  }
645
- async searchPosts(options) {
646
- return this.client._post("/api/v1/linkedin/search/posts", options);
647
- }
747
+ /** Full detail for one job listing, including the hiring company. */
648
748
  async job(options) {
649
749
  return this.client._post("/api/v1/linkedin/job", options);
650
750
  }
751
+ /** Full detail for one post, including its top visible comments. */
651
752
  async post(options) {
652
753
  return this.client._post("/api/v1/linkedin/post", options);
653
754
  }
755
+ /** Comments with their replies, 10 per page. */
654
756
  async postComments(options) {
655
757
  return this.client._post("/api/v1/linkedin/post/comments", options);
656
758
  }
759
+ /**
760
+ * @deprecated Retired by the upstream provider. Always returns HTTP 410 and is
761
+ * never billed.
762
+ */
763
+ async personContact(options) {
764
+ return this.client._post("/api/v1/linkedin/person/contact", options);
765
+ }
766
+ /**
767
+ * @deprecated Retired by the upstream provider. Always returns HTTP 410 and is
768
+ * never billed. `company()` returns `featured_employees`, a small sample of
769
+ * staff profiles.
770
+ */
771
+ async companyPeople(options) {
772
+ return this.client._post("/api/v1/linkedin/company/people", options);
773
+ }
774
+ /**
775
+ * @deprecated Retired by the upstream provider. Always returns HTTP 410 and is
776
+ * never billed. Use `searchJobs()` with the company name as the search term.
777
+ */
778
+ async companyJobs(options) {
779
+ return this.client._post("/api/v1/linkedin/company/jobs", options);
780
+ }
781
+ /**
782
+ * @deprecated Retired by the upstream provider. Always returns HTTP 410 and is
783
+ * never billed.
784
+ */
785
+ async searchPeople(options) {
786
+ return this.client._post("/api/v1/linkedin/search/people", options);
787
+ }
788
+ /**
789
+ * @deprecated Retired by the upstream provider. Always returns HTTP 410 and is
790
+ * never billed.
791
+ */
792
+ async searchPosts(options) {
793
+ return this.client._post("/api/v1/linkedin/search/posts", options);
794
+ }
657
795
  };
658
796
 
659
797
  // src/client.ts
@@ -664,6 +802,7 @@ var Scavio = class {
664
802
  youtube;
665
803
  reddit;
666
804
  tiktok;
805
+ tiktokShop;
667
806
  instagram;
668
807
  x;
669
808
  linkedin;
@@ -691,6 +830,7 @@ var Scavio = class {
691
830
  this.youtube = new YouTubeNamespace(this);
692
831
  this.reddit = new RedditNamespace(this);
693
832
  this.tiktok = new TikTokNamespace(this);
833
+ this.tiktokShop = new TikTokShopNamespace(this);
694
834
  this.instagram = new InstagramNamespace(this);
695
835
  this.x = new XNamespace(this);
696
836
  this.linkedin = new LinkedInNamespace(this);