scavio 0.13.0 → 0.15.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.js CHANGED
@@ -44,12 +44,13 @@ var InsufficientCreditsError = class extends ScavioError {
44
44
  }
45
45
  };
46
46
  var BadRequestError = class extends ScavioError {
47
- statusCode = 400;
47
+ statusCode;
48
48
  responseBody;
49
- constructor(message = "Bad request", responseBody) {
49
+ constructor(message = "Bad request", responseBody, statusCode = 400) {
50
50
  super(message);
51
51
  this.name = "BadRequestError";
52
52
  this.responseBody = responseBody;
53
+ this.statusCode = statusCode;
53
54
  }
54
55
  };
55
56
  var NotFoundError = class extends ScavioError {
@@ -151,7 +152,9 @@ function handleError(statusCode, body) {
151
152
  }
152
153
  const msg = String(error);
153
154
  const responseBody = Object.keys(body).length > 0 ? body : void 0;
154
- if (statusCode === 400) throw new BadRequestError(msg, responseBody);
155
+ if (statusCode === 400 || statusCode === 422) {
156
+ throw new BadRequestError(msg, responseBody, statusCode);
157
+ }
155
158
  if (statusCode === 401) throw new InvalidAPIKeyError(msg, responseBody);
156
159
  if (statusCode === 402) throw new InsufficientCreditsError(msg, responseBody);
157
160
  if (statusCode === 404) throw new NotFoundError(msg, responseBody);
@@ -362,12 +365,17 @@ var RedditNamespace = class {
362
365
  this.client = client;
363
366
  }
364
367
  client;
368
+ /** Returns `data.results` plus `next_cursor` / `has_more` (not `data.posts`). */
365
369
  async search(options) {
366
370
  return this.client._post("/api/v1/reddit/search", options);
367
371
  }
368
372
  async searchSuggestions(options) {
369
373
  return this.client._post("/api/v1/reddit/search/suggestions", options);
370
374
  }
375
+ /**
376
+ * Returns a flat post object under `data` (post_id, title, text, url,
377
+ * subreddit, author, score, ...). Comments are a separate call.
378
+ */
371
379
  async post(options) {
372
380
  return this.client._post("/api/v1/reddit/post", options);
373
381
  }
@@ -599,12 +607,71 @@ var WalmartNamespace = class {
599
607
  this.client = client;
600
608
  }
601
609
  client;
610
+ /**
611
+ * Structured Walmart search results: `products[]`, `products_count` and the
612
+ * resolved `location`. Page through with `page` (1-indexed).
613
+ *
614
+ * Costs 1 credit for `domain` "com" or "ca", 2 credits for "com.mx".
615
+ */
602
616
  async search(options) {
603
617
  return this.client._post("/api/v1/walmart/search", options);
604
618
  }
619
+ /**
620
+ * Full product detail: price, rating, images, specifications, availability
621
+ * and seller.
622
+ *
623
+ * Costs 1 credit. Walmart.ca product pages are not fetchable, so this is
624
+ * walmart.com only.
625
+ */
605
626
  async product(options) {
606
627
  return this.client._post("/api/v1/walmart/product", options);
607
628
  }
629
+ /**
630
+ * Customer reviews with ratings, text, author, date and the rating
631
+ * breakdown. 10 reviews per page; advance with `page`.
632
+ *
633
+ * Costs 1 credit.
634
+ */
635
+ async reviews(options) {
636
+ return this.client._post("/api/v1/walmart/reviews", options);
637
+ }
638
+ /**
639
+ * Products within a category, in the same product shape as `search()`.
640
+ * Page through with `page`; `limit` only trims the response.
641
+ *
642
+ * Costs 1 credit for `domain` "com" or "ca", 2 credits for "com.mx".
643
+ */
644
+ async category(options) {
645
+ return this.client._post("/api/v1/walmart/category", options);
646
+ }
647
+ /**
648
+ * Seller offer for a product: price, seller, condition and buy-box flag.
649
+ * Returns the BUY-BOX SELLER ONLY, not the full offer list.
650
+ *
651
+ * Costs 1 credit.
652
+ */
653
+ async offers(options) {
654
+ return this.client._post("/api/v1/walmart/offers", options);
655
+ }
656
+ /**
657
+ * Marketplace seller storefront: name, rating, review count, Pro Seller
658
+ * badge and business details.
659
+ *
660
+ * Costs 1 credit. `seller_id` must be the numeric catalog seller id.
661
+ */
662
+ async seller(options) {
663
+ return this.client._post("/api/v1/walmart/seller", options);
664
+ }
665
+ /**
666
+ * A seller's catalog. Roughly the first 40 items are server-rendered and
667
+ * that is all this returns - there is no pagination. `total_count` reports
668
+ * the seller's real catalog size, which is usually far larger.
669
+ *
670
+ * Costs 1 credit. `seller_id` must be the numeric catalog seller id.
671
+ */
672
+ async sellerProducts(options) {
673
+ return this.client._post("/api/v1/walmart/seller-products", options);
674
+ }
608
675
  };
609
676
 
610
677
  // src/namespaces/youtube.ts
@@ -811,90 +878,1544 @@ var LinkedInNamespace = class {
811
878
  }
812
879
  };
813
880
 
814
- // src/client.ts
815
- var Scavio = class {
816
- google;
817
- amazon;
818
- walmart;
819
- youtube;
820
- reddit;
821
- tiktok;
822
- tiktokShop;
823
- instagram;
824
- x;
825
- linkedin;
826
- apiKey;
827
- baseUrl;
828
- timeout;
829
- maxRetries;
830
- rateLimiter;
831
- constructor(config) {
832
- this.apiKey = config?.apiKey ?? process.env.SCAVIO_API_KEY ?? "";
833
- if (!this.apiKey) {
834
- throw new MissingAPIKeyError();
835
- }
836
- this.baseUrl = (config?.baseUrl ?? BASE_URL).replace(/\/+$/, "");
837
- this.timeout = config?.timeout ?? DEFAULT_TIMEOUT;
838
- this.maxRetries = config?.maxRetries ?? DEFAULT_MAX_RETRIES;
839
- const rps = config?.maxRequestsPerSecond ?? 1;
840
- if (rps < 1 || rps > 10) {
841
- throw new ScavioError("maxRequestsPerSecond must be between 1 and 10");
842
- }
843
- this.rateLimiter = new RateLimiter(rps);
844
- this.google = new GoogleNamespace(this);
845
- this.amazon = new AmazonNamespace(this);
846
- this.walmart = new WalmartNamespace(this);
847
- this.youtube = new YouTubeNamespace(this);
848
- this.reddit = new RedditNamespace(this);
849
- this.tiktok = new TikTokNamespace(this);
850
- this.tiktokShop = new TikTokShopNamespace(this);
851
- this.instagram = new InstagramNamespace(this);
852
- this.x = new XNamespace(this);
853
- this.linkedin = new LinkedInNamespace(this);
881
+ // src/namespaces/threads.ts
882
+ var ThreadsNamespace = class {
883
+ constructor(client) {
884
+ this.client = client;
854
885
  }
855
- /** @internal */
856
- async _post(path, body) {
857
- return request({
858
- method: "POST",
859
- path,
860
- apiKey: this.apiKey,
861
- baseUrl: this.baseUrl,
862
- timeout: this.timeout,
863
- maxRetries: this.maxRetries,
864
- rateLimiter: this.rateLimiter,
865
- body
866
- });
886
+ client;
887
+ /**
888
+ * Profile details for a Threads user. Pass `user_id` or `username`;
889
+ * sending neither returns 422 and no match returns 404.
890
+ *
891
+ * Costs 2 credits by `user_id`, 4 credits by `username`.
892
+ */
893
+ async profile(options) {
894
+ return this.client._post("/api/v1/threads/profile", options);
867
895
  }
868
- /** @internal */
869
- async _get(path) {
870
- return request({
871
- method: "GET",
872
- path,
873
- apiKey: this.apiKey,
874
- baseUrl: this.baseUrl,
875
- timeout: this.timeout,
876
- maxRetries: this.maxRetries,
877
- rateLimiter: this.rateLimiter
878
- });
896
+ /**
897
+ * A user's Threads posts. Advance with the previous response's
898
+ * `next_cursor`. Pass `user_id` or `username`.
899
+ *
900
+ * Costs 2 credits by `user_id`, 4 credits by `username` - and that surcharge
901
+ * applies to every page, so resolve the id once before paging.
902
+ */
903
+ async userPosts(options) {
904
+ return this.client._post("/api/v1/threads/user/posts", options);
905
+ }
906
+ /**
907
+ * A user's replies. Advance with the previous response's `next_cursor`.
908
+ * Pass `user_id` or `username`.
909
+ *
910
+ * Costs 2 credits by `user_id`, 4 credits by `username` - and that surcharge
911
+ * applies to every page, so resolve the id once before paging.
912
+ */
913
+ async userReplies(options) {
914
+ return this.client._post("/api/v1/threads/user/replies", options);
915
+ }
916
+ /**
917
+ * A single post, addressed by `post_id` or by its threads.net `url`.
918
+ * Sending neither returns 422.
919
+ *
920
+ * Costs 2 credits.
921
+ */
922
+ async post(options) {
923
+ return this.client._post("/api/v1/threads/post", options);
924
+ }
925
+ /**
926
+ * Replies to a post. Advance with the previous response's `next_cursor`.
927
+ *
928
+ * Costs 2 credits - this endpoint is never username-keyed, so there is no
929
+ * handle surcharge.
930
+ */
931
+ async postComments(options) {
932
+ return this.client._post("/api/v1/threads/post/comments", options);
933
+ }
934
+ /**
935
+ * Threads profiles matching a name or handle. This is people search, and it
936
+ * is the only search Threads exposes - there is no content/post search.
937
+ * Use it to turn a handle into the `user_id` every other method prefers.
938
+ *
939
+ * Costs 2 credits. Single response, no pagination.
940
+ */
941
+ async searchUsers(options) {
942
+ return this.client._post("/api/v1/threads/search/users", options);
943
+ }
944
+ };
945
+
946
+ // src/namespaces/kuaishou.ts
947
+ var KuaishouNamespace = class {
948
+ constructor(client) {
949
+ this.client = client;
950
+ }
951
+ client;
952
+ /**
953
+ * Profile details for a Kuaishou user, addressed by numeric `user_id`.
954
+ *
955
+ * Costs 10 credits - the dearest single-object call on the platform. If you
956
+ * only have a share link, resolve it with `userResolve()` (1 credit) first.
957
+ */
958
+ async profile(options) {
959
+ return this.client._post("/api/v1/kuaishou/profile", options);
960
+ }
961
+ /**
962
+ * A user's top posts. Advance with the previous response's `next_cursor`.
963
+ *
964
+ * Costs 1 credit per page.
965
+ */
966
+ async userPosts(options) {
967
+ return this.client._post("/api/v1/kuaishou/user/posts", options);
968
+ }
969
+ /**
970
+ * A user's current live-stream status.
971
+ *
972
+ * Costs 1 credit.
973
+ */
974
+ async userLive(options) {
975
+ return this.client._post("/api/v1/kuaishou/user/live", options);
976
+ }
977
+ /**
978
+ * Turns a Kuaishou share link into a `user_id` you can feed to the other
979
+ * user endpoints. kuaishou.com and v.kuaishou.com links only - kwai.com is
980
+ * not supported.
981
+ *
982
+ * Costs 1 credit.
983
+ */
984
+ async userResolve(options) {
985
+ return this.client._post("/api/v1/kuaishou/user/resolve", options);
986
+ }
987
+ /**
988
+ * A single video, addressed by `photo_id` or by its Kuaishou `url`.
989
+ * Sending neither returns 422.
990
+ *
991
+ * Costs 2 credits.
992
+ */
993
+ async video(options) {
994
+ return this.client._post("/api/v1/kuaishou/video", options);
995
+ }
996
+ /**
997
+ * Comments on a video. Advance with the previous response's `next_cursor`.
998
+ *
999
+ * Costs 1 credit per page.
1000
+ */
1001
+ async videoComments(options) {
1002
+ return this.client._post("/api/v1/kuaishou/video/comments", options);
879
1003
  }
1004
+ /**
1005
+ * Replies under a root comment. Advance with the previous response's
1006
+ * `next_cursor`; `count` (1-50) sizes the page.
1007
+ *
1008
+ * Costs 1 credit per page.
1009
+ */
1010
+ async commentReplies(options) {
1011
+ return this.client._post("/api/v1/kuaishou/video/sub-comments", options);
1012
+ }
1013
+ /**
1014
+ * Several videos in one call, up to 20 photo ids (a hard cap - a longer
1015
+ * `photo_ids` array is rejected).
1016
+ *
1017
+ * Costs 40 credits per call, flat, whether you send 1 id or 20 - so batch
1018
+ * to the cap. For a single video `video()` costs 2.
1019
+ */
1020
+ async videosBatch(options) {
1021
+ return this.client._post("/api/v1/kuaishou/videos/batch", options);
1022
+ }
1023
+ /**
1024
+ * Mixed-result search across Kuaishou. Advance with the previous response's
1025
+ * `next_cursor`.
1026
+ *
1027
+ * Costs 10 credits per page.
1028
+ */
880
1029
  async search(options) {
881
- return this.google.search(options);
1030
+ return this.client._post("/api/v1/kuaishou/search", options);
1031
+ }
1032
+ /**
1033
+ * Video search results. Advance with the previous response's `next_cursor`.
1034
+ *
1035
+ * Costs 10 credits per page.
1036
+ */
1037
+ async searchVideos(options) {
1038
+ return this.client._post("/api/v1/kuaishou/search/videos", options);
1039
+ }
1040
+ /**
1041
+ * User search results. Advance with the previous response's `next_cursor`.
1042
+ *
1043
+ * Costs 10 credits per page.
1044
+ */
1045
+ async searchUsers(options) {
1046
+ return this.client._post("/api/v1/kuaishou/search/users", options);
1047
+ }
1048
+ /**
1049
+ * Live-stream search results. Advance with the previous response's
1050
+ * `next_cursor`.
1051
+ *
1052
+ * Costs 10 credits per page.
1053
+ */
1054
+ async searchLive(options) {
1055
+ return this.client._post("/api/v1/kuaishou/search/live", options);
1056
+ }
1057
+ /**
1058
+ * Posts under a hashtag. Advance with the previous response's `next_cursor`.
1059
+ *
1060
+ * Costs 1 credit per page - the cheap way to pull volume, versus 10 for
1061
+ * `search()`.
1062
+ */
1063
+ async tagFeed(options) {
1064
+ return this.client._post("/api/v1/kuaishou/tag/feed", options);
1065
+ }
1066
+ /**
1067
+ * Leaderboards: hot, live, shopping, brand or music. Defaults to "hot".
1068
+ *
1069
+ * Costs 1 credit.
1070
+ */
1071
+ async trending(options = {}) {
1072
+ return this.client._post("/api/v1/kuaishou/trending", options);
1073
+ }
1074
+ };
1075
+
1076
+ // src/namespaces/ebay.ts
1077
+ var EbayNamespace = class {
1078
+ constructor(client) {
1079
+ this.client = client;
1080
+ }
1081
+ client;
1082
+ /**
1083
+ * Structured eBay listing results: price, condition, bids, shipping, seller,
1084
+ * feedback, plus `count` and `total_results`.
1085
+ *
1086
+ * Either `query` or `seller` is required. Set `sold: true` to search
1087
+ * completed listings that actually sold - on that view `total_results` is
1088
+ * always null because eBay publishes no headline count for it.
1089
+ *
1090
+ * Paged with `page`; `per_page` accepts only 60, 120 or 240 and silently
1091
+ * falls back to 60 for any other value.
1092
+ *
1093
+ * Costs 1 credit.
1094
+ */
1095
+ async search(options) {
1096
+ return this.client._post("/api/v1/ebay/search", options);
1097
+ }
1098
+ /**
1099
+ * One eBay listing in full: price, condition, images, item specifics,
1100
+ * shipping, returns, auction state and seller.
1101
+ *
1102
+ * Costs 1 credit. Single response, no pagination.
1103
+ */
1104
+ async product(options) {
1105
+ return this.client._post("/api/v1/ebay/product", options);
1106
+ }
1107
+ /**
1108
+ * A seller's profile card: store name, feedback score and percentage, items
1109
+ * sold, followers, location and categories.
1110
+ *
1111
+ * PROFILE ONLY - it cannot list what the seller is selling. For inventory,
1112
+ * call search({ seller }) with no query and page through it.
1113
+ *
1114
+ * Costs 1 credit. Single response, no pagination.
1115
+ */
1116
+ async seller(options) {
1117
+ return this.client._post("/api/v1/ebay/seller", options);
1118
+ }
1119
+ };
1120
+
1121
+ // src/namespaces/target.ts
1122
+ var TargetNamespace = class {
1123
+ constructor(client) {
1124
+ this.client = client;
1125
+ }
1126
+ client;
1127
+ /**
1128
+ * Search Target.com: prices, ratings, badges and promotions.
1129
+ *
1130
+ * Paged with `page` + `count` (1-28, default 24). `seller_id` and
1131
+ * `seller_name` are null on first-party rows, which means "sold by Target".
1132
+ *
1133
+ * Costs 1 credit. Typically ~9s - it runs through a headless browser.
1134
+ */
1135
+ async search(options) {
1136
+ return this.client._post("/api/v1/target/search", options);
1137
+ }
1138
+ /**
1139
+ * Products in a Target category: the same shape as search() plus the
1140
+ * category breadcrumb.
1141
+ *
1142
+ * Paged with `page` + `count` (1-28, default 24).
1143
+ *
1144
+ * Costs 1 credit. The slowest endpoint here at ~37s - set a generous client
1145
+ * timeout before calling it.
1146
+ */
1147
+ async category(options) {
1148
+ return this.client._post("/api/v1/target/category", options);
1149
+ }
1150
+ /**
1151
+ * Target product details by TCIN: price, rating, images, specifications,
1152
+ * variants, return policy and fulfillment.
1153
+ *
1154
+ * `store_id` is a real request param here - the price and availability you
1155
+ * get back are the store you asked for.
1156
+ *
1157
+ * Costs 1 credit. Typically ~4s. Single response, no pagination.
1158
+ */
1159
+ async product(options) {
1160
+ return this.client._post("/api/v1/target/product", options);
1161
+ }
1162
+ /**
1163
+ * Target reviews with the rating breakdown, per-attribute averages and
1164
+ * guest photos.
1165
+ *
1166
+ * Returns 8 review BODIES MAXIMUM regardless of the product's review_count.
1167
+ * `limit` only trims that set; there is no page or offset param, so the
1168
+ * aggregate distribution is the full-population signal here, not the bodies.
1169
+ *
1170
+ * Costs 1 credit. Typically ~40s.
1171
+ */
1172
+ async reviews(options) {
1173
+ return this.client._post("/api/v1/target/reviews", options);
1174
+ }
1175
+ };
1176
+
1177
+ // src/namespaces/home-depot.ts
1178
+ var HomeDepotNamespace = class {
1179
+ constructor(client) {
1180
+ this.client = client;
1181
+ }
1182
+ client;
1183
+ /**
1184
+ * Search Home Depot: price and promotions, brand and model, ratings,
1185
+ * badges, and per-store pickup/delivery.
1186
+ *
1187
+ * Page size is FIXED at 12 products and cannot be raised - page through
1188
+ * with `page` to read further.
1189
+ *
1190
+ * Costs 2 credits.
1191
+ */
1192
+ async search(options) {
1193
+ return this.client._post("/api/v1/homedepot/search", options);
1194
+ }
1195
+ /**
1196
+ * Full item detail: pricing and promotions, images and videos, the spec
1197
+ * table, dimensions, bullets, documents and return policy.
1198
+ *
1199
+ * Carries only a 10-review PREVIEW - reviews() is the paginated surface.
1200
+ * An unknown item id comes back as 404.
1201
+ *
1202
+ * Costs 2 credits. Single response, no pagination.
1203
+ */
1204
+ async product(options) {
1205
+ return this.client._post("/api/v1/homedepot/product", options);
1206
+ }
1207
+ /**
1208
+ * One page of full review bodies with the rating distribution,
1209
+ * per-attribute ratings, photos and seller responses.
1210
+ *
1211
+ * 30 reviews per page. `total_pages` is the last page that exists; a page
1212
+ * beyond it is a 404, not an empty result.
1213
+ *
1214
+ * Costs 2 credits.
1215
+ */
1216
+ async reviews(options) {
1217
+ return this.client._post("/api/v1/homedepot/reviews", options);
1218
+ }
1219
+ };
1220
+
1221
+ // src/namespaces/zillow.ts
1222
+ var ZillowNamespace = class {
1223
+ constructor(client) {
1224
+ this.client = client;
1225
+ }
1226
+ client;
1227
+ /**
1228
+ * Listings in a region: price, beds, baths, living area, Zestimate,
1229
+ * coordinates, images and days on market.
1230
+ *
1231
+ * Paged with `page`. A bare ZIP works alone but not alongside a filter or a
1232
+ * sort - use the city name when filtering. On listing_status "for_rent",
1233
+ * min_price / max_price are MONTHLY RENT. A region Zillow cannot resolve is
1234
+ * a 404, not an empty list.
1235
+ *
1236
+ * Costs 1 credit.
1237
+ */
1238
+ async search(options) {
1239
+ return this.client._post("/api/v1/zillow/search", options);
1240
+ }
1241
+ /**
1242
+ * Full listing detail: price and price history, Zestimate, tax history,
1243
+ * description, RESO facts, rooms, schools, open houses, photos and
1244
+ * attribution. Rental buildings return floor plans, amenities and unit
1245
+ * counts instead.
1246
+ *
1247
+ * Costs 1 credit. Single response, no pagination.
1248
+ */
1249
+ async property(options) {
1250
+ return this.client._post("/api/v1/zillow/property", options);
1251
+ }
1252
+ /**
1253
+ * An AGENT's profile and reviews: rating, review count, bodies with
1254
+ * sub-ratings, specialties, languages, licenses, service areas and sales
1255
+ * counts.
1256
+ *
1257
+ * This addresses an agent by screen name, NOT a property. Zillow
1258
+ * server-renders the first five reviews only: `count` is what came back,
1259
+ * `total_review_count` is what the agent actually has, and there is no way
1260
+ * to page to the rest.
1261
+ *
1262
+ * Costs 1 credit.
1263
+ */
1264
+ async agentReviews(options) {
1265
+ return this.client._post("/api/v1/zillow/reviews", options);
1266
+ }
1267
+ };
1268
+
1269
+ // src/namespaces/redfin.ts
1270
+ var RedfinNamespace = class {
1271
+ constructor(client) {
1272
+ this.client = client;
1273
+ }
1274
+ client;
1275
+ /**
1276
+ * Redfin listings: price, price per sqft, beds, baths, living area, lot
1277
+ * size, year built, coordinates, listing remarks and full photo galleries.
1278
+ *
1279
+ * Pass `location` (a redfin.com region URL or a bare ZIP - city NAMES are
1280
+ * not accepted) or `region_id` AND `region_type` together. Paged with
1281
+ * `page` + `limit`, up to 350 listings per page.
1282
+ *
1283
+ * `days_on_market` comes back NULL on every row: Redfin's mainHouseInfo has
1284
+ * no `dom` key. Fractional numeric filters are rejected, not rounded.
1285
+ * `sold_within_days` requires `listing_status: "sold"`, and
1286
+ * `max_days_on_market` / `min_days_on_market` cannot be combined.
1287
+ *
1288
+ * Costs 1 credit.
1289
+ */
1290
+ async search(options) {
1291
+ return this.client._post("/api/v1/redfin/search", options);
1292
+ }
1293
+ /**
1294
+ * One Redfin listing in full: price, Redfin Estimate and rental estimate,
1295
+ * complete MLS fact sheet, price and tax history, listing agents, open
1296
+ * houses, schools, climate risk, walkability and location scores, sun
1297
+ * exposure, monthly weather, permits, zoning, comparable sales and photos.
1298
+ *
1299
+ * Reads the property PAGE, whose inlined request cache replaces the ~40
1300
+ * upstream calls that page made - which is why it is the same price as
1301
+ * search().
1302
+ *
1303
+ * Costs 1 credit. Single response, no pagination.
1304
+ */
1305
+ async property(options) {
1306
+ return this.client._post("/api/v1/redfin/property", options);
1307
+ }
1308
+ /**
1309
+ * Housing-market stats for a region: median list and sale price, price per
1310
+ * sqft, sale-to-list ratio, average offers and days on market, YoY
1311
+ * movement, Redfin's 0-100 compete score, live inventory by property type,
1312
+ * median price and active listings per bedroom count, plus Redfin agent
1313
+ * presence and aggregate rating.
1314
+ *
1315
+ * Pass `location` (city NAMES are not accepted) or `region_id` AND
1316
+ * `region_type` together.
1317
+ *
1318
+ * Costs 1 credit. Single response, no pagination.
1319
+ */
1320
+ async market(options) {
1321
+ return this.client._post("/api/v1/redfin/market", options);
1322
+ }
1323
+ };
1324
+
1325
+ // src/namespaces/booking.ts
1326
+ var BookingNamespace = class {
1327
+ constructor(client) {
1328
+ this.client = client;
1329
+ }
1330
+ client;
1331
+ /**
1332
+ * Search Booking.com properties for a destination and stay: live nightly
1333
+ * price, review score, star rating, location, room type and deal badges.
1334
+ *
1335
+ * Either `destination` or `dest_id` is required - without one the request
1336
+ * would land on Booking's homepage, so it is rejected instead of billed.
1337
+ * `dest_type` requires `dest_id`.
1338
+ *
1339
+ * Paged with `page`, 25 properties per page. `checkin` and `checkout` must
1340
+ * be sent together or Booking prices a range of its own choosing.
1341
+ *
1342
+ * Each row carries a `url` - chain it into hotel() rather than rebuilding a
1343
+ * slug, which risks a BILLED 404 on the wrong `country_code`.
1344
+ *
1345
+ * Costs 1 credit.
1346
+ */
1347
+ async search(options) {
1348
+ return this.client._post("/api/v1/booking/search", options);
1349
+ }
1350
+ /**
1351
+ * One Booking.com property in full: rooms and rate plans, facilities, house
1352
+ * rules, check-in windows, policies, images, location and review scores -
1353
+ * priced for the stay you ask for.
1354
+ *
1355
+ * Takes dates because Booking prices a STAY. Omit them and the response
1356
+ * carries prices for a two-night window Booking picked; the response echoes
1357
+ * whichever dates were used.
1358
+ *
1359
+ * Single response, no pagination.
1360
+ *
1361
+ * Costs 1 credit.
1362
+ */
1363
+ async hotel(options) {
1364
+ return this.client._post("/api/v1/booking/hotel", options);
1365
+ }
1366
+ /**
1367
+ * Booking.com guest reviews with the score breakdown by category and
1368
+ * Booking's own praise/complaint summary.
1369
+ *
1370
+ * NO PAGE PARAM - do not invent one. `total_count` is the property's whole
1371
+ * review history; `count` is what this response holds.
1372
+ *
1373
+ * Costs 1 credit.
1374
+ */
1375
+ async reviews(options) {
1376
+ return this.client._post("/api/v1/booking/reviews", options);
1377
+ }
1378
+ };
1379
+
1380
+ // src/namespaces/airbnb.ts
1381
+ var AirbnbNamespace = class {
1382
+ constructor(client) {
1383
+ this.client = client;
1384
+ }
1385
+ client;
1386
+ /**
1387
+ * Search Airbnb stays: stay-total and per-night price with the full
1388
+ * discount ledger, rating and review count, bedrooms/beds/baths,
1389
+ * coordinates, badges, images and `dates_are_defaulted`.
1390
+ *
1391
+ * This is the ONLY endpoint that carries a price - listing() has no nightly
1392
+ * rate field at all.
1393
+ *
1394
+ * Paged with `page` (18 listings per page) XOR `cursor`; `cursor` wins, so
1395
+ * sending both is rejected. `min_price` / `max_price` are WHOLE-STAY totals,
1396
+ * not per night.
1397
+ *
1398
+ * Pass `check_in` + `check_out` together whenever price matters: a dateless
1399
+ * search defaults to +30 days / 5 nights and A/Bs both the window and the
1400
+ * prices, which the response flags as `dates_are_defaulted`.
1401
+ *
1402
+ * Costs 1 credit.
1403
+ */
1404
+ async search(options) {
1405
+ return this.client._post("/api/v1/airbnb/search", options);
1406
+ }
1407
+ /**
1408
+ * One Airbnb listing in full: description, property and room type, capacity
1409
+ * and room counts, the complete grouped amenity list (including the
1410
+ * amenities the place does NOT have), host profile and stats, house rules
1411
+ * with parsed check-in/out times, cancellation policy, sleeping
1412
+ * arrangements, photo tour, every image, and the RATING BREAKDOWN - six
1413
+ * category ratings, the five-bucket star distribution and Airbnb's
1414
+ * AI-synthesised review tags.
1415
+ *
1416
+ * NO NIGHTLY PRICE. The room page carries no rate under any parameters,
1417
+ * with or without dates. Prices come from search() only.
1418
+ *
1419
+ * Single response, no pagination.
1420
+ *
1421
+ * Costs 1 credit.
1422
+ */
1423
+ async listing(options) {
1424
+ return this.client._post("/api/v1/airbnb/listing", options);
1425
+ }
1426
+ /**
1427
+ * Airbnb review BODIES with per-review rating, date, and reviewer name,
1428
+ * photo and location.
1429
+ *
1430
+ * Paged with `limit` (1-50, default 30) + `offset`. Send `limit`
1431
+ * explicitly - upstream returns a fixed 7 rows when none is given.
1432
+ *
1433
+ * `count` is the listing's TOTAL review count; `returned` is how many rows
1434
+ * this page holds. The rating breakdown is NOT here - it lives on
1435
+ * listing().
1436
+ *
1437
+ * Costs 1 credit.
1438
+ */
1439
+ async reviews(options) {
1440
+ return this.client._post("/api/v1/airbnb/reviews", options);
1441
+ }
1442
+ };
1443
+
1444
+ // src/namespaces/tripadvisor.ts
1445
+ var TripadvisorNamespace = class {
1446
+ constructor(client) {
1447
+ this.client = client;
1448
+ }
1449
+ client;
1450
+ /**
1451
+ * START HERE. Resolve a place or business NAME to the Tripadvisor
1452
+ * geo_id / location_id pairs every other endpoint needs.
1453
+ *
1454
+ * A GEO row answers `geo_id` for search(); a business row answers the
1455
+ * `geo_id` + `location_id` pair location() and reviews() take. Those ids
1456
+ * exist only inside Tripadvisor's own URLs, so this is the only entry point
1457
+ * from a name.
1458
+ *
1459
+ * `limit` (1-20, default 12) sizes the response; there is no pagination.
1460
+ *
1461
+ * Costs 2 credits.
1462
+ */
1463
+ async locations(options) {
1464
+ return this.client._post("/api/v1/tripadvisor/locations", options);
1465
+ }
1466
+ /**
1467
+ * Restaurants, hotels or attractions in a Tripadvisor geo, Tripadvisor-
1468
+ * ranked: rating, review count, price band, address, coordinates, phone,
1469
+ * hours and Travelers' Choice badge. Each row carries the location_id +
1470
+ * geo_id pair the detail endpoints take.
1471
+ *
1472
+ * `geo_id` or `url` is required - get `geo_id` from locations().
1473
+ *
1474
+ * Paged with `page`, 30 locations per page. A page beyond the last is a
1475
+ * 404, not an empty result.
1476
+ *
1477
+ * Costs 2 credits.
1478
+ */
1479
+ async search(options) {
1480
+ return this.client._post("/api/v1/tripadvisor/search", options);
1481
+ }
1482
+ /**
1483
+ * One Tripadvisor location in full: rating, review histogram and per-aspect
1484
+ * sub-ratings, city ranking, price band, cuisines, amenities, address,
1485
+ * coordinates, contact, photos, and the FIRST PAGE OF REVIEWS.
1486
+ *
1487
+ * `location_id` or `url` is required, and the transport additionally
1488
+ * requires a geo when a bare d-id is sent.
1489
+ *
1490
+ * Page 1 of the reviews is already here - call reviews() only to page PAST
1491
+ * it. An unknown location id is a 404 (upstream answers a billed city
1492
+ * listing that the transport restates).
1493
+ *
1494
+ * Costs 2 credits.
1495
+ */
1496
+ async location(options) {
1497
+ return this.client._post("/api/v1/tripadvisor/location", options);
1498
+ }
1499
+ /**
1500
+ * A page of Tripadvisor reviews: rating, trip date and type, reviewer home
1501
+ * town and contribution count, and any management response.
1502
+ *
1503
+ * `location_id` or `url` is required. Page size follows `category` - 15 per
1504
+ * page for restaurants, 10 for hotels and attractions - so keep it matched
1505
+ * to the location's own type on any page past the first.
1506
+ *
1507
+ * Consecutive pages can REPEAT one review at the boundary; de-duplicate on
1508
+ * review_id when concatenating.
1509
+ *
1510
+ * Costs 2 credits.
1511
+ */
1512
+ async reviews(options) {
1513
+ return this.client._post("/api/v1/tripadvisor/reviews", options);
1514
+ }
1515
+ };
1516
+
1517
+ // src/namespaces/yelp.ts
1518
+ var YelpNamespace = class {
1519
+ constructor(client) {
1520
+ this.client = client;
1521
+ }
1522
+ client;
1523
+ /**
1524
+ * Businesses in Yelp's ranked order: rating, review count, price band,
1525
+ * categories, address, contact rails, hours, photos and a review snippet.
1526
+ * Each row carries both business_id and alias, either of which addresses
1527
+ * business(). `count` is the 10-row page, `total_results` is Yelp's headline
1528
+ * count.
1529
+ *
1530
+ * `term` + `location` or `url` is required, and `location` is effectively
1531
+ * mandatory - Yelp geolocates a location-less search off the proxy exit.
1532
+ * Paged with `page`; the page size is fixed at 10.
1533
+ *
1534
+ * Costs 2 credits.
1535
+ */
1536
+ async search(options) {
1537
+ return this.client._post("/api/v1/yelp/search", options);
1538
+ }
1539
+ /**
1540
+ * One business in full: rating and per-star histogram, review count, price
1541
+ * band, categories, address and coordinates, phone, website and menu links,
1542
+ * hours and holidays, amenities, photos and videos, popular items, health
1543
+ * inspections, Q&A, licences and claim status - PLUS the first page of
1544
+ * reviews at no extra cost.
1545
+ *
1546
+ * Because those reviews ride along, calling reviews({ page: 1 }) after this
1547
+ * buys the same document twice. Yelp's recommendation software hides some
1548
+ * reviews entirely; those are never returned and are counted in
1549
+ * not_recommended_review_count here. popular_items rows can arrive as stub
1550
+ * shells with every field null but `identifier` - those are dropped and
1551
+ * popular_items_omitted flags it.
1552
+ *
1553
+ * `business_id` or `url` is required. Costs 2 credits. Single response, no
1554
+ * pagination.
1555
+ */
1556
+ async business(options) {
1557
+ return this.client._post("/api/v1/yelp/business", options);
1558
+ }
1559
+ /**
1560
+ * A page of reviews: rating, full text, language, author profile and
1561
+ * expertise counts, attached photos, reaction counts and owner response.
1562
+ *
1563
+ * START AT PAGE 2 - page 1 re-fetches the document business() already
1564
+ * returned and costs another 2 credits. 10 reviews per page, and a page past
1565
+ * the last review is a 404, not an empty result. `rating` changes
1566
+ * filtered_review_count, not review_count.
1567
+ *
1568
+ * `business_id` or `url` is required. Costs 2 credits.
1569
+ */
1570
+ async reviews(options) {
1571
+ return this.client._post("/api/v1/yelp/reviews", options);
1572
+ }
1573
+ };
1574
+
1575
+ // src/namespaces/indeed.ts
1576
+ var IndeedNamespace = class {
1577
+ constructor(client) {
1578
+ this.client = client;
1579
+ }
1580
+ client;
1581
+ /**
1582
+ * Search Indeed job postings: title, employer, rating, location, salary
1583
+ * range, job type, benefits, posting age and apply route.
1584
+ *
1585
+ * Either `query` or `location` is required; a location-only search is valid
1586
+ * and returns every posting in the metro.
1587
+ *
1588
+ * Paged with `page`, 10 postings per page. `radius` and `max_age_days` are
1589
+ * closed sets - Indeed silently ignores an off-list value and bills the
1590
+ * unfiltered search. `min_salary` filters on Indeed's own ESTIMATE for the
1591
+ * role, not a posted figure.
1592
+ *
1593
+ * Costs 2 credits.
1594
+ */
1595
+ async search(options) {
1596
+ return this.client._post("/api/v1/indeed/search", options);
1597
+ }
1598
+ /**
1599
+ * One Indeed posting in full: description text and HTML, structured salary,
1600
+ * employment types, benefits, geocoded address, employer rating, applicant
1601
+ * count and the original ATS link.
1602
+ *
1603
+ * Single response, no pagination. An unknown job key is a real 404 that
1604
+ * scrape.do BILLS - take `job_id` from a search row.
1605
+ *
1606
+ * Costs 2 credits.
1607
+ */
1608
+ async job(options) {
1609
+ return this.client._post("/api/v1/indeed/job", options);
1610
+ }
1611
+ /**
1612
+ * Indeed employer profile: description, industry, HQ, size, revenue, CEO
1613
+ * approval, overall and per-category ratings, reported salaries, open roles
1614
+ * and locations.
1615
+ *
1616
+ * Single response, no pagination. An unknown company slug is a real 404
1617
+ * that scrape.do BILLS.
1618
+ *
1619
+ * Costs 2 credits.
1620
+ */
1621
+ async company(options) {
1622
+ return this.client._post("/api/v1/indeed/company", options);
1623
+ }
1624
+ /**
1625
+ * Indeed employee reviews with per-category ratings, pros/cons, reviewer
1626
+ * job title and location, plus aggregated sentiment and topic / location /
1627
+ * job-title breakdowns.
1628
+ *
1629
+ * Paged with `page`, 20 reviews per page.
1630
+ *
1631
+ * Costs 2 credits.
1632
+ */
1633
+ async companyReviews(options) {
1634
+ return this.client._post("/api/v1/indeed/company/reviews", options);
1635
+ }
1636
+ };
1637
+
1638
+ // src/namespaces/glassdoor.ts
1639
+ var GlassdoorNamespace = class {
1640
+ constructor(client) {
1641
+ this.client = client;
1642
+ }
1643
+ client;
1644
+ /**
1645
+ * START HERE. Search Glassdoor for a company by NAME and resolve it to the
1646
+ * employer_id every other method needs, ranked by Glassdoor and
1647
+ * de-duplicated.
1648
+ *
1649
+ * company(), reviews() and salaries() all key off an employer_id that exists
1650
+ * only inside Glassdoor's /Overview/ URLs, so this lookup is the entry
1651
+ * point.
1652
+ *
1653
+ * Costs 1 credit. Single response, no pagination.
1654
+ */
1655
+ async companies(options) {
1656
+ return this.client._post("/api/v1/glassdoor/companies", options);
1657
+ }
1658
+ /**
1659
+ * Employer profile: description, mission, industry, sector, HQ, size band,
1660
+ * revenue band, stock symbol, year founded, overall and per-category
1661
+ * ratings, star distribution, CEO approval, awards, FAQ, the five
1662
+ * server-rendered reviews, AND reviews_url / salaries_url.
1663
+ *
1664
+ * THE CHAINING ENDPOINT: pass reviews_url / salaries_url back as `url` on
1665
+ * reviews() and salaries() to halve the upstream fetches. `employer_id` or
1666
+ * `url` is required - `company` is cosmetic and does not satisfy it.
1667
+ *
1668
+ * Costs 1 credit. Single response, no pagination. Typically ~3-47s.
1669
+ */
1670
+ async company(options) {
1671
+ return this.client._post("/api/v1/glassdoor/company", options);
1672
+ }
1673
+ /**
1674
+ * Full reviews with per-axis scores, pros, cons, advice, job title,
1675
+ * location, employment status and employer response - plus complete rating
1676
+ * statistics, star distribution, aggregate pro/con highlight terms and
1677
+ * per-job-title review counts.
1678
+ *
1679
+ * HARD CAP OF THREE REVIEW BODIES per response: that is Glassdoor's login
1680
+ * wall, not a limit option. There is deliberately NO `page` param. Move the
1681
+ * window with `category` and `employment_status` and read
1682
+ * filtered_review_count to see how many match; the aggregate statistics are
1683
+ * the full-population signal here, not the bodies.
1684
+ *
1685
+ * `employer_id` or `url` is required. Costs 1 credit. Typically ~75s.
1686
+ */
1687
+ async reviews(options) {
1688
+ return this.client._post("/api/v1/glassdoor/reviews", options);
1689
+ }
1690
+ /**
1691
+ * Salaries by job title: base-pay and total-pay percentiles P10-P90 with
1692
+ * medians called out, sample counts, currency, pay period and last-reported
1693
+ * date.
1694
+ *
1695
+ * These are Glassdoor's ESTIMATES for the title, not individual reported
1696
+ * salaries. Paged with `page` at 10 job titles per page; `page_count` on the
1697
+ * response is how many pages exist.
1698
+ *
1699
+ * `employer_id` or `url` is required. Costs 1 credit. Typically ~41s.
1700
+ */
1701
+ async salaries(options) {
1702
+ return this.client._post("/api/v1/glassdoor/salaries", options);
1703
+ }
1704
+ };
1705
+
1706
+ // src/namespaces/app-store.ts
1707
+ var AppStoreNamespace = class {
1708
+ constructor(client) {
1709
+ this.client = client;
1710
+ }
1711
+ client;
1712
+ /**
1713
+ * Up to 200 fully-shaped App Store apps - the same 43-field row as app() -
1714
+ * which makes this a bulk metadata fetch as well as a search, and a
1715
+ * publisher lookup when the term is a developer name.
1716
+ *
1717
+ * NO PAGINATION. `limit` (1-200, default 25) is the only lever on volume;
1718
+ * every offset spelling is silently ignored. Mac rows carry no iPad or Apple
1719
+ * TV screenshots, advisories, features, supported devices or Game Center
1720
+ * flag.
1721
+ *
1722
+ * Costs 1 credit.
1723
+ */
1724
+ async search(options) {
1725
+ return this.client._post("/api/v1/appstore/search", options);
1726
+ }
1727
+ /**
1728
+ * Full listing: title, description, developer and seller identity, price and
1729
+ * currency, all-time and current-version ratings, version and release notes,
1730
+ * genres, content rating and advisories, icons at three sizes, screenshots,
1731
+ * download size, minimum OS, languages, supported devices, Game Center and
1732
+ * VPP flags.
1733
+ *
1734
+ * Takes a numeric App Store id or a bundle id interchangeably. An id Apple
1735
+ * cannot resolve is a BILLED 404 - Apple charges for the empty result list.
1736
+ *
1737
+ * Costs 1 credit. Single response, no pagination.
1738
+ */
1739
+ async app(options) {
1740
+ return this.client._post("/api/v1/appstore/app", options);
1741
+ }
1742
+ /**
1743
+ * A page of reviews: star rating, title, full text, author, and the APP
1744
+ * VERSION the review was written against.
1745
+ *
1746
+ * NUMERIC APP IDS ONLY here. Paged 1-10 at 50 reviews each and hard-stopped
1747
+ * at page 10 - 500 reviews per storefront is Apple's anonymous ceiling, so
1748
+ * ask a different `country` to reach further. This endpoint CANNOT 404: an
1749
+ * unknown id and a real app with zero reviews return the same empty feed.
1750
+ * Under sort "most_recent" the vote fields are zeroes.
1751
+ *
1752
+ * Costs 1 credit.
1753
+ */
1754
+ async reviews(options) {
1755
+ return this.client._post("/api/v1/appstore/reviews", options);
1756
+ }
1757
+ };
1758
+
1759
+ // src/namespaces/google-play.ts
1760
+ var GooglePlayNamespace = class {
1761
+ constructor(client) {
1762
+ this.client = client;
1763
+ }
1764
+ client;
1765
+ /**
1766
+ * Ranked apps: package name, title, developer, rating, install count, price
1767
+ * and IAP range, content rating, icon and screenshots. A branded query
1768
+ * returns the hero card as result 1 projected to the same row shape, plus
1769
+ * Play's related-query rail.
1770
+ *
1771
+ * NO PAGINATION - one shelf of ~30 apps, with no page or cursor param.
1772
+ * `hl` moves the whole storefront, not just the language of the strings.
1773
+ *
1774
+ * Costs 2 credits.
1775
+ */
1776
+ async search(options) {
1777
+ return this.client._post("/api/v1/googleplay/search", options);
1778
+ }
1779
+ /**
1780
+ * Full store listing: installs including the REAL count Play publishes but
1781
+ * never renders, rating and star histogram, description, developer identity
1782
+ * and legal contact, price and IAPs, categories and gameplay tags,
1783
+ * screenshots and trailer, version and Android requirement, release and
1784
+ * update dates, changelog, full permission tree, Data safety table, the 20
1785
+ * server-rendered reviews, and the similar-apps and more-by-developer rails.
1786
+ *
1787
+ * Those 20 reviews ride along at no extra cost - use reviews() only to page
1788
+ * past them or to sort differently.
1789
+ *
1790
+ * Costs 2 credits. Single response, no pagination.
1791
+ */
1792
+ async app(options) {
1793
+ return this.client._post("/api/v1/googleplay/app", options);
1794
+ }
1795
+ /**
1796
+ * A page of reviews: star score, full text, author, thumbs-up count,
1797
+ * developer reply, and the APP VERSION the reviewer was running.
1798
+ *
1799
+ * Paged with `cursor` -> next_cursor. The cursor is opaque and SINGLE-USE
1800
+ * and encodes the sort as well as the position, so send it back with the
1801
+ * same `sort` it came from; a cursor past the last review is a 404, not an
1802
+ * empty page. `count` is capped at 200. An empty payload here is a BILLED
1803
+ * 404 - the premium price is paid to learn the package has no reviews or
1804
+ * does not exist.
1805
+ *
1806
+ * Costs 2 credits.
1807
+ */
1808
+ async reviews(options) {
1809
+ return this.client._post("/api/v1/googleplay/reviews", options);
1810
+ }
1811
+ };
1812
+
1813
+ // src/namespaces/g2.ts
1814
+ var G2Namespace = class {
1815
+ constructor(client) {
1816
+ this.client = client;
1817
+ }
1818
+ client;
1819
+ /**
1820
+ * Ranked B2B software products on G2: star rating, review count, vendor,
1821
+ * categories, seller description and logo. Every row carries `product_id`
1822
+ * and `slug` to feed product() and reviews().
1823
+ *
1824
+ * Paged with `page` and `limit` (1-100, default 20). `total_results` is
1825
+ * G2's Products-tab headline and is CAPPED AT 10000, so treat a 10000 as a
1826
+ * floor rather than a count; `total_by_type` breaks the same query across
1827
+ * products, sellers, categories and discussions.
1828
+ *
1829
+ * Pass `query` or `url`.
1830
+ *
1831
+ * Costs 5 credits.
1832
+ */
1833
+ async search(options) {
1834
+ return this.client._post("/api/v1/g2/search", options);
1835
+ }
1836
+ /**
1837
+ * A full G2 software profile: rating with per-star histogram, review count,
1838
+ * vendor, description and seller website, pricing editions with parsed
1839
+ * amounts, feature groups, categories and breadcrumbs, supported languages,
1840
+ * integrations, alternatives, head-to-head comparisons, media, community
1841
+ * discussions and G2's AI-derived pros and cons.
1842
+ *
1843
+ * CARRIES NO REVIEW TEXT. G2 loads review bodies in a separate frame, so
1844
+ * this endpoint returns none at all - call reviews() for text.
1845
+ *
1846
+ * Pass `product_id` (slug or numeric id as a string) or `url`.
1847
+ *
1848
+ * Costs 5 credits. Single response, no pagination.
1849
+ */
1850
+ async product(options) {
1851
+ return this.client._post("/api/v1/g2/product", options);
1852
+ }
1853
+ /**
1854
+ * A page of G2 reviews: rating, title, likes and dislikes, problems solved,
1855
+ * reviewer job title, industry and company size, validated and incentivized
1856
+ * flags - PLUS what the profile page has no form of: exact per-star counts,
1857
+ * pros and cons with per-theme counts, and company-size / role / industry /
1858
+ * region / category facets with counts.
1859
+ *
1860
+ * Fixed at 10 reviews per page; advance with `page`. This paginates well
1861
+ * past the 10 pages G2's own widget links to.
1862
+ *
1863
+ * `rating` buckets are HALF-STAR-INCLUSIVE (1 returns 0, 0.5 and 1-star).
1864
+ * Every filter is a closed enum because an unrecognised value matches
1865
+ * nothing upstream and comes back as an empty, plausible-looking result set.
1866
+ *
1867
+ * Pass `product_id` or `url`.
1868
+ *
1869
+ * Costs 5 credits.
1870
+ */
1871
+ async reviews(options) {
1872
+ return this.client._post("/api/v1/g2/reviews", options);
1873
+ }
1874
+ };
1875
+
1876
+ // src/namespaces/capterra.ts
1877
+ var CapterraNamespace = class {
1878
+ constructor(client) {
1879
+ this.client = client;
1880
+ }
1881
+ client;
1882
+ /**
1883
+ * 20 ranked Capterra software products: name, vendor description, rating,
1884
+ * review count, logo and the paid-placement flag. Every row carries
1885
+ * `product_id` and `slug` to feed product() and reviews().
1886
+ *
1887
+ * NO PAGINATION. Capterra fixes the result set at 20 and page 2 returns the
1888
+ * identical rows, so there is deliberately no page param - narrow the query
1889
+ * instead.
1890
+ *
1891
+ * Pass `query` or `url`.
1892
+ *
1893
+ * Costs 2 credits.
1894
+ */
1895
+ async search(options) {
1896
+ return this.client._post("/api/v1/capterra/search", options);
1897
+ }
1898
+ /**
1899
+ * A full Capterra profile: rating with per-star histogram and the four
1900
+ * scored criteria, likelihood to recommend, review sentiment and topics, the
1901
+ * complete pricing table with every plan and its features, every rated
1902
+ * feature, every integration, AI-derived pros and cons with the quoted
1903
+ * review, FAQs, screenshots, badges and awards, competitor comparisons and
1904
+ * alternatives, and the buyer profile by company size / industry / job
1905
+ * function - PLUS the 25 most recent reviews, which ride along at no extra
1906
+ * cost.
1907
+ *
1908
+ * `vendor` IS ALWAYS NULL here: Capterra does not publish it as structured
1909
+ * data on the product page. The reviews name the vendor per review.
1910
+ *
1911
+ * Pass `product_id` (a string) or `url`. `slug` is cosmetic on this
1912
+ * endpoint.
1913
+ *
1914
+ * Costs 2 credits. Single response, no pagination.
1915
+ */
1916
+ async product(options) {
1917
+ return this.client._post("/api/v1/capterra/product", options);
1918
+ }
1919
+ /**
1920
+ * A page of Capterra reviews: overall score plus five per-criterion scores,
1921
+ * title, pros, cons, advice, usage duration, incentivized flag, alternatives
1922
+ * considered and what the reviewer switched from, reviewer job title /
1923
+ * industry / company size, and the vendor response - plus a richer
1924
+ * competitor list than the profile carries, each alternative with its own
1925
+ * rating histogram and starting price.
1926
+ *
1927
+ * 25 reviews per page, CAPPED AT PAGE 100. Past it Capterra answers 200 with
1928
+ * PAGE ONE and the page quietly dropped from the canonical, so nothing
1929
+ * signals the cap but repeated rows. Page 1 is already inside product(), so
1930
+ * use this to page past it.
1931
+ *
1932
+ * Pass `product_id` or `url`. `slug` is load-bearing here and case-sensitive
1933
+ * upstream - a wrong one silently serves page one.
1934
+ *
1935
+ * Costs 2 credits.
1936
+ */
1937
+ async reviews(options) {
1938
+ return this.client._post("/api/v1/capterra/reviews", options);
1939
+ }
1940
+ };
1941
+
1942
+ // src/namespaces/sec.ts
1943
+ var SECNamespace = class {
1944
+ constructor(client) {
1945
+ this.client = client;
1946
+ }
1947
+ client;
1948
+ /**
1949
+ * START HERE. Resolves a company name or ticker to the CIK every other SEC
1950
+ * EDGAR endpoint is keyed by: matching filers with symbol, listing
1951
+ * exchange, and ready-made submissions / company-facts / EDGAR URLs, tiered
1952
+ * by match quality (each row carries its tier as `match`).
1953
+ *
1954
+ * `limit` sizes the response; there is no pagination. `exchange` is a
1955
+ * closed set matched case-insensitively, and filers listed with no exchange
1956
+ * are excluded by ANY value.
1957
+ *
1958
+ * Costs 1 credit.
1959
+ */
1960
+ async lookup(options) {
1961
+ return this.client._post("/api/v1/sec/lookup", options);
1962
+ }
1963
+ /**
1964
+ * Filer profile: legal and former names, SIC industry, filer category, EIN,
1965
+ * LEI, state of incorporation, fiscal year end, business and mailing
1966
+ * addresses, every ticker with its exchange, which forms it files and how
1967
+ * often, plus a preview of its 10 most recent filings.
1968
+ *
1969
+ * Either `cik` or `ticker` is required; `ticker` wins when both are given.
1970
+ *
1971
+ * Costs 1 credit. Single response, no pagination.
1972
+ */
1973
+ async company(options) {
1974
+ return this.client._post("/api/v1/sec/company", options);
1975
+ }
1976
+ /**
1977
+ * A page of one filer's filings: accession number, form and root form,
1978
+ * filing and period dates, 8-K item codes, and direct links to the primary
1979
+ * document, filing index and attachment directory.
1980
+ *
1981
+ * Either `cik` or `ticker` is required. Paged with `page` + `limit`.
1982
+ * `form` matches the form AND its root form, so "10-K" also returns 10-K/A.
1983
+ * EDGAR's "recent" block is not a fixed window - a decade for a quiet
1984
+ * filer, about a year for a prolific one; `include_history` reaches back
1985
+ * through up to 10 archived shards and sets `history_truncated` when the
1986
+ * filer had more.
1987
+ *
1988
+ * Costs 1 credit - including with `include_history`, which is the one call
1989
+ * that can buy more than one upstream fetch.
1990
+ */
1991
+ async filings(options) {
1992
+ return this.client._post("/api/v1/sec/filings", options);
1993
+ }
1994
+ /**
1995
+ * Every value a filer reported for one XBRL concept, newest period first,
1996
+ * with the form and filing each number came from. Restatements are KEPT,
1997
+ * not collapsed; `latest` disambiguates a quarter from its year-to-date
1998
+ * twin using the SEC's comparability flag.
1999
+ *
2000
+ * Either `cik` or `ticker` is required. The `concept` tag is CASE-SENSITIVE
2001
+ * - "netincomeloss" is a 404 upstream, not a match; call facts() to find
2002
+ * the real tag. `form` is an EXACT match here, so "10-K" excludes 10-K/A.
2003
+ * `limit` sizes the response; there is no pagination.
2004
+ *
2005
+ * Costs 1 credit.
2006
+ */
2007
+ async concept(options) {
2008
+ return this.client._post("/api/v1/sec/concept", options);
2009
+ }
2010
+ /**
2011
+ * The index of every XBRL concept a filer reports - tag, label,
2012
+ * description, units and most recent value - across us-gaap, dei and any
2013
+ * other taxonomy it uses. This is how you find what to ask concept() for.
2014
+ *
2015
+ * Either `cik` or `ticker` is required. `limit` sizes the response; there
2016
+ * is no pagination.
2017
+ *
2018
+ * Costs 1 credit.
2019
+ */
2020
+ async facts(options) {
2021
+ return this.client._post("/api/v1/sec/facts", options);
2022
+ }
2023
+ /**
2024
+ * EDGAR full-text search: each hit is the matching DOCUMENT with its URL,
2025
+ * form, filing date and filer identity, plus facets breaking the whole
2026
+ * result set down by company, form, industry and state.
2027
+ *
2028
+ * Coverage STARTS IN 2001 - nothing earlier is indexed. Accepts NO query at
2029
+ * all: a cik, ticker, form or date filter on its own is a valid search.
2030
+ * Paged with `page`, capped at 100 (100 documents per page) because the
2031
+ * index refuses a result window past 10,000.
2032
+ *
2033
+ * Costs 1 credit.
2034
+ */
2035
+ async search(options) {
2036
+ return this.client._post("/api/v1/sec/search", options);
2037
+ }
2038
+ };
2039
+
2040
+ // src/namespaces/companies-house.ts
2041
+ var CompaniesHouseNamespace = class {
2042
+ constructor(client) {
2043
+ this.client = client;
2044
+ }
2045
+ client;
2046
+ /**
2047
+ * START HERE. Searches the UK register by name and returns the
2048
+ * `company_number` every other endpoint is keyed by, plus name, status,
2049
+ * incorporation or dissolution date, registered office address and matched
2050
+ * former names.
2051
+ *
2052
+ * Matches CURRENT AND FORMER names. Paged with `page`, 20 results per page,
2053
+ * CAPPED AT PAGE 50 - the register serves a 1000-result window per term
2054
+ * whatever hit count it prints, and answers page 51 with HTTP 416.
2055
+ *
2056
+ * Costs 1 credit.
2057
+ */
2058
+ async search(options) {
2059
+ return this.client._post("/api/v1/companieshouse/search", options);
2060
+ }
2061
+ /**
2062
+ * Full register entry: status, type, incorporation and dissolution dates,
2063
+ * registered office, SIC codes, previous names, accounts and
2064
+ * confirmation-statement due dates with overdue flags, and whether it has
2065
+ * charges, insolvency history, officers or UK establishments. FC companies
2066
+ * return home registry / legal form / governing law, BR returns the parent,
2067
+ * CE returns the charity number.
2068
+ *
2069
+ * `company_number` is zero-padded and upper-cased for you, so a number off
2070
+ * a letterhead or out of a spreadsheet that ate its leading zeros still
2071
+ * resolves.
2072
+ *
2073
+ * Costs 1 credit. Single response, no pagination.
2074
+ */
2075
+ async company(options) {
2076
+ return this.client._post("/api/v1/companieshouse/company", options);
2077
+ }
2078
+ /**
2079
+ * Officers current and resigned: name, role, appointment and resignation
2080
+ * dates, correspondence address, nationality, country of residence,
2081
+ * month-and-year date of birth, and identity-verification status.
2082
+ *
2083
+ * Paged with `page`, 35 officers per page, NO upper bound - past the last
2084
+ * page the register answers an ordinary 200 with an empty list, identical
2085
+ * to a company with no officers.
2086
+ *
2087
+ * `officers_count` is EVERY appointment ever made and `resignations_count`
2088
+ * how many ended, so the active count is the difference. There is no
2089
+ * server-side active/resigned filter - filter on each officer's `status` in
2090
+ * the response.
2091
+ *
2092
+ * Costs 1 credit.
2093
+ */
2094
+ async officers(options) {
2095
+ return this.client._post("/api/v1/companieshouse/officers", options);
2096
+ }
2097
+ /**
2098
+ * Filings, most recent first: date, filing type code (AA, CS01, SH03),
2099
+ * description, register annotations and child documents, and a link to the
2100
+ * filed PDF with its page count.
2101
+ *
2102
+ * A filing the register has not finished processing carries a
2103
+ * `processing_note` instead of a document.
2104
+ *
2105
+ * Paged with `page`, NO upper bound - past the last page it is an ordinary
2106
+ * 200 with an empty list.
2107
+ *
2108
+ * Costs 1 credit.
2109
+ */
2110
+ async filingHistory(options) {
2111
+ return this.client._post("/api/v1/companieshouse/filing-history", options);
2112
+ }
2113
+ };
2114
+
2115
+ // src/namespaces/google-ads.ts
2116
+ var GoogleAdsNamespace = class {
2117
+ constructor(client) {
2118
+ this.client = client;
2119
+ }
2120
+ client;
2121
+ /**
2122
+ * START HERE. Resolves a brand name or a domain to the `advertiser_id` that
2123
+ * search() and creative() are keyed by.
2124
+ *
2125
+ * Returns two row kinds in one list: `advertiser` rows carry the id, the
2126
+ * verified name, the verification country and the total ad count AS A RANGE
2127
+ * (total_ads_min / total_ads_max - Google never publishes an exact figure);
2128
+ * `domain` rows carry a website. A name query returns both kinds, a
2129
+ * domain-shaped query returns domains only.
2130
+ *
2131
+ * NO PAGINATION - this is an autocomplete, roughly 20 rows per arm, and
2132
+ * `limit` caps each arm separately.
2133
+ *
2134
+ * Costs 1 credit.
2135
+ */
2136
+ async advertisers(options) {
2137
+ return this.client._post("/api/v1/googleads/advertisers", options);
2138
+ }
2139
+ /**
2140
+ * Every ad Google is running for one advertiser: the creative (archived
2141
+ * image, rich-media bundle, Google's renderer link, dimensions), advertiser
2142
+ * id and name, format, first and last seen dates, days actually run, plus
2143
+ * total_ads_min / total_ads_max.
2144
+ *
2145
+ * Cursor-paginated: read `next_cursor` off the response and send it back as
2146
+ * `cursor` WITH THE SAME FILTERS, up to 100 rows per page. `next_cursor` is
2147
+ * null once exhausted. A `limit` above 100 is not an error - Google answers
2148
+ * it with ZERO rows.
2149
+ *
2150
+ * The three `format` sets are disjoint, and `domain` is dropped from every
2151
+ * row when the query is by `advertiser_id`, so query by domain if you need
2152
+ * that field. The headline total is a RANGE, never an exact count.
2153
+ *
2154
+ * Pass `domain` or `advertiser_id`.
2155
+ *
2156
+ * Costs 1 credit per page.
2157
+ */
2158
+ async search(options) {
2159
+ return this.client._post("/api/v1/googleads/search", options);
2160
+ }
2161
+ /**
2162
+ * One creative in full, and the ONLY endpoint carrying its history: every
2163
+ * size variation of the asset, the impression bucket, the per-region
2164
+ * breakdown with first and last shown dates and a per-surface impression
2165
+ * split inside each region, the format, Google's category label, and the
2166
+ * funder disclosure on political ads.
2167
+ *
2168
+ * IMPRESSIONS AND REACH ARE EEA-ONLY: impressions_min, impressions_max and
2169
+ * first_shown are NULL on US creatives because Google publishes reach only
2170
+ * where the DSA compels it. A bucket row can carry a lower bound, an upper
2171
+ * bound, or one alone.
2172
+ *
2173
+ * Keyed by the `advertiser_id` + `creative_id` PAIR - a mismatched pair is a
2174
+ * 404, not an empty response.
2175
+ *
2176
+ * Costs 1 credit. Single response, no pagination.
2177
+ */
2178
+ async creative(options) {
2179
+ return this.client._post("/api/v1/googleads/creative", options);
2180
+ }
2181
+ };
2182
+
2183
+ // src/namespaces/meta-ads.ts
2184
+ var MetaAdsNamespace = class {
2185
+ constructor(client) {
2186
+ this.client = client;
2187
+ }
2188
+ client;
2189
+ /**
2190
+ * Search the Meta Ad Library. Page 1 returns 30 ads with the full creative:
2191
+ * page name, ad copy, headline, CTA, images and videos, the platforms each
2192
+ * ran on, and run dates - plus `total_results`, `total_is_capped`,
2193
+ * `has_next_page` and `next_cursor`.
2194
+ *
2195
+ * Cursor-paginated the whole way down: 30 ads on page 1, then 10 per page.
2196
+ * Walk `has_next_page` to pull an entire query. THE OTHER FILTERS ARE
2197
+ * IGNORED once `cursor` is set, because the cursor carries them itself.
2198
+ *
2199
+ * `total_results` CAPS AT 50000 with `total_is_capped: true` - Meta only
2200
+ * reports ">50,000", so never present it as an exact count. Spend, reach,
2201
+ * impressions and the paid-for-by disclosure are null unless
2202
+ * `ad_type` is "political_and_issue_ads".
2203
+ *
2204
+ * Costs 1 credit PER PAGE, so depth costs roughly 10 ads per credit past the
2205
+ * first 30.
2206
+ */
2207
+ async search(options) {
2208
+ return this.client._post("/api/v1/meta-ads/search", options);
2209
+ }
2210
+ /**
2211
+ * Every ad a Facebook Page is running, addressed by its numeric page id.
2212
+ * Page 1 returns 30 ads with the same creative detail as search(), then 10
2213
+ * per page off `next_cursor`; walk `has_next_page` to pull the advertiser's
2214
+ * whole library.
2215
+ *
2216
+ * The other filters are ignored once `cursor` is set. Spend, reach,
2217
+ * impressions and the paid-for-by disclosure are null on commercial ads -
2218
+ * only political/issue ads carry them.
2219
+ *
2220
+ * Costs 1 credit per page.
2221
+ */
2222
+ async advertiser(options) {
2223
+ return this.client._post("/api/v1/meta-ads/advertiser", options);
2224
+ }
2225
+ /**
2226
+ * One ad in full by archive id: creative, advertiser, run dates, platforms
2227
+ * and any political disclosure.
2228
+ *
2229
+ * Spend, reach and impressions are null unless the ad is a political/issue
2230
+ * ad.
2231
+ *
2232
+ * Costs 1 credit. Single response, no pagination.
2233
+ */
2234
+ async ad(options) {
2235
+ return this.client._post("/api/v1/meta-ads/ad", options);
2236
+ }
2237
+ };
2238
+
2239
+ // src/client.ts
2240
+ var Scavio = class {
2241
+ google;
2242
+ amazon;
2243
+ walmart;
2244
+ youtube;
2245
+ reddit;
2246
+ tiktok;
2247
+ tiktokShop;
2248
+ instagram;
2249
+ x;
2250
+ linkedin;
2251
+ threads;
2252
+ kuaishou;
2253
+ ebay;
2254
+ target;
2255
+ homeDepot;
2256
+ zillow;
2257
+ redfin;
2258
+ booking;
2259
+ airbnb;
2260
+ tripadvisor;
2261
+ yelp;
2262
+ indeed;
2263
+ glassdoor;
2264
+ appStore;
2265
+ googlePlay;
2266
+ g2;
2267
+ capterra;
2268
+ sec;
2269
+ companiesHouse;
2270
+ googleAds;
2271
+ metaAds;
2272
+ apiKey;
2273
+ baseUrl;
2274
+ timeout;
2275
+ maxRetries;
2276
+ rateLimiter;
2277
+ constructor(config) {
2278
+ this.apiKey = config?.apiKey ?? process.env.SCAVIO_API_KEY ?? "";
2279
+ if (!this.apiKey) {
2280
+ throw new MissingAPIKeyError();
2281
+ }
2282
+ this.baseUrl = (config?.baseUrl ?? BASE_URL).replace(/\/+$/, "");
2283
+ this.timeout = config?.timeout ?? DEFAULT_TIMEOUT;
2284
+ this.maxRetries = config?.maxRetries ?? DEFAULT_MAX_RETRIES;
2285
+ const rps = config?.maxRequestsPerSecond ?? 1;
2286
+ if (rps < 1 || rps > 10) {
2287
+ throw new ScavioError("maxRequestsPerSecond must be between 1 and 10");
2288
+ }
2289
+ this.rateLimiter = new RateLimiter(rps);
2290
+ this.google = new GoogleNamespace(this);
2291
+ this.amazon = new AmazonNamespace(this);
2292
+ this.walmart = new WalmartNamespace(this);
2293
+ this.youtube = new YouTubeNamespace(this);
2294
+ this.reddit = new RedditNamespace(this);
2295
+ this.tiktok = new TikTokNamespace(this);
2296
+ this.tiktokShop = new TikTokShopNamespace(this);
2297
+ this.instagram = new InstagramNamespace(this);
2298
+ this.x = new XNamespace(this);
2299
+ this.linkedin = new LinkedInNamespace(this);
2300
+ this.threads = new ThreadsNamespace(this);
2301
+ this.kuaishou = new KuaishouNamespace(this);
2302
+ this.ebay = new EbayNamespace(this);
2303
+ this.target = new TargetNamespace(this);
2304
+ this.homeDepot = new HomeDepotNamespace(this);
2305
+ this.zillow = new ZillowNamespace(this);
2306
+ this.redfin = new RedfinNamespace(this);
2307
+ this.booking = new BookingNamespace(this);
2308
+ this.airbnb = new AirbnbNamespace(this);
2309
+ this.tripadvisor = new TripadvisorNamespace(this);
2310
+ this.yelp = new YelpNamespace(this);
2311
+ this.indeed = new IndeedNamespace(this);
2312
+ this.glassdoor = new GlassdoorNamespace(this);
2313
+ this.appStore = new AppStoreNamespace(this);
2314
+ this.googlePlay = new GooglePlayNamespace(this);
2315
+ this.g2 = new G2Namespace(this);
2316
+ this.capterra = new CapterraNamespace(this);
2317
+ this.sec = new SECNamespace(this);
2318
+ this.companiesHouse = new CompaniesHouseNamespace(this);
2319
+ this.googleAds = new GoogleAdsNamespace(this);
2320
+ this.metaAds = new MetaAdsNamespace(this);
2321
+ }
2322
+ /** @internal */
2323
+ async _post(path, body) {
2324
+ return request({
2325
+ method: "POST",
2326
+ path,
2327
+ apiKey: this.apiKey,
2328
+ baseUrl: this.baseUrl,
2329
+ timeout: this.timeout,
2330
+ maxRetries: this.maxRetries,
2331
+ rateLimiter: this.rateLimiter,
2332
+ body
2333
+ });
2334
+ }
2335
+ /** @internal */
2336
+ async _get(path) {
2337
+ return request({
2338
+ method: "GET",
2339
+ path,
2340
+ apiKey: this.apiKey,
2341
+ baseUrl: this.baseUrl,
2342
+ timeout: this.timeout,
2343
+ maxRetries: this.maxRetries,
2344
+ rateLimiter: this.rateLimiter
2345
+ });
2346
+ }
2347
+ async search(options) {
2348
+ return this.google.search(options);
2349
+ }
2350
+ /**
2351
+ * Read ANY web page and get it back as readability Markdown (the default),
2352
+ * plain text, or raw HTML. Returns `{ url, format, mode, content,
2353
+ * content_length }`.
2354
+ *
2355
+ * This is a core endpoint, not a platform, so it lives on the client itself:
2356
+ * `scavio.extract({ url })`, never `scavio.extract.extract()`.
2357
+ *
2358
+ * Credits are a function of `mode`, not a flat per-call constant:
2359
+ * "normal" costs 1, "advanced" costs 1, "ultra" costs 2. Billing happens
2360
+ * only on a successful extraction - a dead link, bot wall or timeout costs
2361
+ * nothing.
2362
+ *
2363
+ * Start on "normal". Move to "advanced" when the page builds its content in
2364
+ * the browser, and to "ultra" only when a bot wall blocks the other two.
2365
+ *
2366
+ * @example
2367
+ * const page = await scavio.extract({ url: "https://example.com/pricing" });
2368
+ * console.log(page.content);
2369
+ */
2370
+ async extract(options) {
2371
+ return this._post("/api/v1/extract", options);
882
2372
  }
883
2373
  async getUsage() {
884
2374
  return this._get("/api/v1/usage");
885
2375
  }
886
2376
  };
887
2377
  export {
2378
+ AirbnbNamespace,
2379
+ AmazonNamespace,
2380
+ AppStoreNamespace,
888
2381
  BadRequestError,
2382
+ BookingNamespace,
2383
+ CapterraNamespace,
2384
+ CompaniesHouseNamespace,
2385
+ EbayNamespace,
2386
+ G2Namespace,
2387
+ GlassdoorNamespace,
2388
+ GoogleAdsNamespace,
2389
+ GoogleNamespace,
2390
+ GooglePlayNamespace,
2391
+ HomeDepotNamespace,
2392
+ IndeedNamespace,
2393
+ InstagramNamespace,
889
2394
  InsufficientCreditsError,
890
2395
  InvalidAPIKeyError,
2396
+ KuaishouNamespace,
2397
+ LinkedInNamespace,
2398
+ MetaAdsNamespace,
891
2399
  MissingAPIKeyError,
892
2400
  NotFoundError,
893
2401
  RateLimitError,
2402
+ RedditNamespace,
2403
+ RedfinNamespace,
2404
+ SECNamespace,
894
2405
  Scavio,
895
2406
  ScavioAPIError,
896
2407
  ScavioConnectionError,
897
2408
  ScavioError,
898
- ScavioTimeoutError
2409
+ ScavioTimeoutError,
2410
+ TargetNamespace,
2411
+ ThreadsNamespace,
2412
+ TikTokNamespace,
2413
+ TikTokShopNamespace,
2414
+ TripadvisorNamespace,
2415
+ WalmartNamespace,
2416
+ XNamespace,
2417
+ YelpNamespace,
2418
+ YouTubeNamespace,
2419
+ ZillowNamespace
899
2420
  };
900
2421
  //# sourceMappingURL=index.js.map