diff --git a/CHANGELOG.md b/CHANGELOG.md index 382a31d..f7eebea 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Changelog +## v1.26.0-sdk.1 + +- Regenerated from the public API contract (832 to 837 operations). Adds Google Play ratings, Instagram user dataset search/item/facets, and Reddit trending dataset search. +- Reddit post and comments operations now expose `include_metrics`. The default feed mode costs 1 credit; metrics mode makes one anonymous HTML request and costs 3 credits. + ## v1.25.0-sdk.1 - Regenerated from the public API contract (836 to 832 operations). Adds Apple Podcasts chart rankings, new releases, and related shows; App Store editorial collections; and the Apple Podcasts shows dataset family. Removes the TCDB endpoints, which no longer exist upstream. diff --git a/crawlora/client.py b/crawlora/client.py index 6049311..23645c4 100644 --- a/crawlora/client.py +++ b/crawlora/client.py @@ -20,7 +20,7 @@ from .operations import GROUPS, OPERATIONS DEFAULT_BASE_URL = "https://api.crawlora.net/api/v1" -VERSION = "1.25.0-sdk.1" +VERSION = "1.26.0-sdk.1" DEFAULT_USER_AGENT = f"crawlora-python-sdk/{VERSION}" DEFAULT_MAX_RETRY_DELAY = 30.0 DEFAULT_RETRY_STATUSES = (408, 409, 425, 429) diff --git a/crawlora/client.pyi b/crawlora/client.pyi index 4678584..16731a1 100644 --- a/crawlora/client.pyi +++ b/crawlora/client.pyi @@ -3696,6 +3696,21 @@ ModelDatasetsHousingSearchResponse = TypedDict('ModelDatasetsHousingSearchRespon 'total': NotRequired[int], }, total=False) +ModelDatasetsInstagramUserFacetResponse = TypedDict('ModelDatasetsInstagramUserFacetResponse', { + 'dataset': NotRequired[str], + 'facet': NotRequired[str], + 'items': NotRequired[list[ModelEsInstagramUserDatasetFacetItem]], +}, total=False) + +ModelDatasetsInstagramUserSearchResponse = TypedDict('ModelDatasetsInstagramUserSearchResponse', { + 'dataset': NotRequired[str], + 'items': NotRequired[list[ModelEsInstagramUserDatasetItem]], + 'page': NotRequired[int], + 'page_size': NotRequired[int], + 'sort': NotRequired[str], + 'total': NotRequired[int], +}, total=False) + ModelDatasetsJobCompaniesResponse = TypedDict('ModelDatasetsJobCompaniesResponse', { 'companies': NotRequired[list[dict[str, Any]]], 'page': NotRequired[int], @@ -3890,6 +3905,16 @@ ModelDatasetsProductHuntTrendsSearchResponse = TypedDict('ModelDatasetsProductHu 'total': NotRequired[int], }, total=False) +ModelDatasetsRedditTrendingSearchResponse = TypedDict('ModelDatasetsRedditTrendingSearchResponse', { + 'dataset': NotRequired[str], + 'items': NotRequired[list[ModelEsRedditTrendingEntry]], + 'page': NotRequired[int], + 'page_size': NotRequired[int], + 'snapshot_date': NotRequired[str], + 'sort': NotRequired[str], + 'total': NotRequired[int], +}, total=False) + ModelDatasetsReviewsSearchResponse = TypedDict('ModelDatasetsReviewsSearchResponse', { 'dataset': NotRequired[str], 'items': NotRequired[list[ModelEsAppReview]], @@ -4269,6 +4294,24 @@ ModelDatasetsHousingMarketsSearchResponseDoc = TypedDict('ModelDatasetsHousingMa 'msg': NotRequired[str], }, total=False) +ModelDatasetsInstagramUserResponseDoc = TypedDict('ModelDatasetsInstagramUserResponseDoc', { + 'code': NotRequired[int], + 'data': NotRequired[ModelEsInstagramUserRecord], + 'msg': NotRequired[str], +}, total=False) + +ModelDatasetsInstagramUsersFacetResponseDoc = TypedDict('ModelDatasetsInstagramUsersFacetResponseDoc', { + 'code': NotRequired[int], + 'data': NotRequired[ModelDatasetsInstagramUserFacetResponse], + 'msg': NotRequired[str], +}, total=False) + +ModelDatasetsInstagramUsersSearchResponseDoc = TypedDict('ModelDatasetsInstagramUsersSearchResponseDoc', { + 'code': NotRequired[int], + 'data': NotRequired[ModelDatasetsInstagramUserSearchResponse], + 'msg': NotRequired[str], +}, total=False) + ModelDatasetsJobsCompaniesResponseDoc = TypedDict('ModelDatasetsJobsCompaniesResponseDoc', { 'code': NotRequired[int], 'data': NotRequired[ModelDatasetsJobCompaniesResponse], @@ -4503,6 +4546,12 @@ ModelDatasetsProducthuntTrendsSearchResponseDoc = TypedDict('ModelDatasetsProduc 'msg': NotRequired[str], }, total=False) +ModelDatasetsRedditTrendingSearchResponseDoc = TypedDict('ModelDatasetsRedditTrendingSearchResponseDoc', { + 'code': NotRequired[int], + 'data': NotRequired[ModelDatasetsRedditTrendingSearchResponse], + 'msg': NotRequired[str], +}, total=False) + ModelDatasetsReviewsSearchResponseDoc = TypedDict('ModelDatasetsReviewsSearchResponseDoc', { 'code': NotRequired[int], 'data': NotRequired[ModelDatasetsReviewsSearchResponse], @@ -5212,6 +5261,7 @@ ModelEsAppRecord = TypedDict('ModelEsAppRecord', { 'currency': NotRequired[str], 'developer': NotRequired[str], 'developer_id': NotRequired[str], + 'discovery_sources': NotRequired[list[str]], 'first_seen': NotRequired[str], 'free': NotRequired[bool], 'icon_url': NotRequired[str], @@ -5443,6 +5493,7 @@ ModelEsChromeExtensionRecord = TypedDict('ModelEsChromeExtensionRecord', { 'description': NotRequired[str], 'developer': NotRequired[str], 'developer_email': NotRequired[str], + 'discovery_sources': NotRequired[list[str]], 'first_seen': NotRequired[str], 'has_broad_host_access': NotRequired[bool], 'host_permissions': NotRequired[list[str]], @@ -5820,6 +5871,55 @@ ModelEsHousingMarketRecord = TypedDict('ModelEsHousingMarketRecord', { 'zip_code': NotRequired[str], }, total=False) +ModelEsInstagramUserDatasetFacetItem = TypedDict('ModelEsInstagramUserDatasetFacetItem', { + 'count': NotRequired[int], + 'value': NotRequired[str], +}, total=False) + +ModelEsInstagramUserDatasetItem = TypedDict('ModelEsInstagramUserDatasetItem', { + 'avatar_url': NotRequired[str], + 'biography': NotRequired[str], + 'category_name': NotRequired[str], + 'crawled_at': NotRequired[str], + 'created_at': NotRequired[str], + 'external_url': NotRequired[str], + 'follower_following_ratio': NotRequired[float], + 'followers': NotRequired[int], + 'following': NotRequired[int], + 'full_name': NotRequired[str], + 'has_bio': NotRequired[bool], + 'has_external_url': NotRequired[bool], + 'id': NotRequired[str], + 'is_business_account': NotRequired[bool], + 'is_verified': NotRequired[bool], + 'posts': NotRequired[int], + 'schema_version': NotRequired[int], + 'source_tier': NotRequired[str], + 'username': NotRequired[str], +}, total=False) + +ModelEsInstagramUserRecord = TypedDict('ModelEsInstagramUserRecord', { + 'avatar_url': NotRequired[str], + 'biography': NotRequired[str], + 'category_name': NotRequired[str], + 'crawled_at': NotRequired[str], + 'created_at': NotRequired[str], + 'external_url': NotRequired[str], + 'follower_following_ratio': NotRequired[float], + 'followers': NotRequired[int], + 'following': NotRequired[int], + 'full_name': NotRequired[str], + 'has_bio': NotRequired[bool], + 'has_external_url': NotRequired[bool], + 'id': NotRequired[str], + 'is_business_account': NotRequired[bool], + 'is_verified': NotRequired[bool], + 'posts': NotRequired[int], + 'schema_version': NotRequired[int], + 'source_tier': NotRequired[str], + 'username': NotRequired[str], +}, total=False) + ModelEsJobPostingFacets = TypedDict('ModelEsJobPostingFacets', { 'by_department': NotRequired[list[ModelEsFacetItem]], 'by_employment_type': NotRequired[list[ModelEsFacetItem]], @@ -6190,6 +6290,21 @@ ModelEsProductHuntTrendsFacetItem = TypedDict('ModelEsProductHuntTrendsFacetItem 'value': NotRequired[str], }, total=False) +ModelEsRedditTrendingEntry = TypedDict('ModelEsRedditTrendingEntry', { + 'author': NotRequired[str], + 'crawled_at': NotRequired[str], + 'created_utc': NotRequired[int], + 'domain': NotRequired[str], + 'permalink': NotRequired[str], + 'post_id': NotRequired[str], + 'post_uid': NotRequired[str], + 'rank': NotRequired[int], + 'snapshot_date': NotRequired[str], + 'subreddit': NotRequired[str], + 'title': NotRequired[str], + 'url': NotRequired[str], +}, total=False) + ModelEsSecCompanyFacetItem = TypedDict('ModelEsSecCompanyFacetItem', { 'count': NotRequired[int], 'value': NotRequired[str], @@ -7898,6 +8013,7 @@ ModelGoogleplayApp = TypedDict('ModelGoogleplayApp', { 'is_available_in_play_pass': NotRequired[bool], 'max_installs': NotRequired[int], 'min_installs': NotRequired[int], + 'more_by_developer': NotRequired[list[ModelGoogleplayListApp]], 'offers_iap': NotRequired[bool], 'original_price': NotRequired[float], 'preregister': NotRequired[bool], @@ -7912,6 +8028,7 @@ ModelGoogleplayApp = TypedDict('ModelGoogleplayApp', { 'score': NotRequired[float], 'score_text': NotRequired[str], 'screenshots': NotRequired[list[str]], + 'similar_apps': NotRequired[list[ModelGoogleplayListApp]], 'summary': NotRequired[str], 'title': NotRequired[str], 'updated': NotRequired[int], @@ -7946,11 +8063,36 @@ ModelGoogleplayDataSafetyResult = TypedDict('ModelGoogleplayDataSafetyResult', { 'shared_data': NotRequired[list[ModelGoogleplayDataSafetyEntry]], }, total=False) +ModelGoogleplayDeviceRating = TypedDict('ModelGoogleplayDeviceRating', { + 'device': NotRequired[str], + 'histogram': NotRequired[dict[str, Any]], + 'ratings': NotRequired[int], + 'reviews': NotRequired[int], + 'score': NotRequired[float], + 'score_text': NotRequired[str], +}, total=False) + ModelGoogleplayFeature = TypedDict('ModelGoogleplayFeature', { 'description': NotRequired[str], 'title': NotRequired[str], }, total=False) +ModelGoogleplayListApp = TypedDict('ModelGoogleplayListApp', { + 'app_id': NotRequired[str], + 'currency': NotRequired[str], + 'developer': NotRequired[str], + 'developer_id': NotRequired[str], + 'free': NotRequired[bool], + 'icon': NotRequired[str], + 'price': NotRequired[float], + 'price_text': NotRequired[str], + 'score': NotRequired[float], + 'score_text': NotRequired[str], + 'summary': NotRequired[str], + 'title': NotRequired[str], + 'url': NotRequired[str], +}, total=False) + ModelGoogleplayReview = TypedDict('ModelGoogleplayReview', { 'criterias': NotRequired[list[ModelGoogleplayReviewCriteria]], 'date': NotRequired[str], @@ -8017,6 +8159,12 @@ ModelGoogleplayPermissionsResultsResponseDoc = TypedDict('ModelGoogleplayPermiss 'msg': NotRequired[str], }, total=False) +ModelGoogleplayRatingsResponseDoc = TypedDict('ModelGoogleplayRatingsResponseDoc', { + 'code': NotRequired[int], + 'data': NotRequired[list[ModelGoogleplayDeviceRating]], + 'msg': NotRequired[str], +}, total=False) + ModelGoogleplayReviewsResponseDoc = TypedDict('ModelGoogleplayReviewsResponseDoc', { 'code': NotRequired[int], 'data': NotRequired[ModelGoogleplayReviewsResult], @@ -12611,6 +12759,7 @@ ModelRedditAuthor = TypedDict('ModelRedditAuthor', { ModelRedditComment = TypedDict('ModelRedditComment', { 'author': NotRequired[ModelRedditAuthor], + 'award_count': NotRequired[int], 'body': NotRequired[str], 'created': NotRequired[str], 'created_utc': NotRequired[int], @@ -12625,6 +12774,7 @@ ModelRedditComment = TypedDict('ModelRedditComment', { ModelRedditCommentsResponse = TypedDict('ModelRedditCommentsResponse', { 'comments': NotRequired[list[ModelRedditComment]], + 'metrics_source': NotRequired[ModelRedditSourceDetail], 'post': NotRequired[ModelRedditPost], 'source': NotRequired[ModelRedditSourceDetail], }, total=False) @@ -12654,10 +12804,13 @@ ModelRedditPagination = TypedDict('ModelRedditPagination', { ModelRedditPost = TypedDict('ModelRedditPost', { 'author': NotRequired[ModelRedditAuthor], + 'award_count': NotRequired[int], 'comment_count': NotRequired[int], 'created': NotRequired[str], 'created_utc': NotRequired[int], 'domain': NotRequired[str], + 'estimated_downvotes': NotRequired[int], + 'estimated_upvotes': NotRequired[int], 'flair': NotRequired[str], 'id': NotRequired[str], 'is_self': NotRequired[bool], @@ -12675,9 +12828,11 @@ ModelRedditPost = TypedDict('ModelRedditPost', { 'title': NotRequired[str], 'upvote_ratio': NotRequired[float], 'url': NotRequired[str], + 'vote_counts_estimated': NotRequired[bool], }, total=False) ModelRedditPostResponse = TypedDict('ModelRedditPostResponse', { + 'metrics_source': NotRequired[ModelRedditSourceDetail], 'post': NotRequired[ModelRedditPost], 'source': NotRequired[ModelRedditSourceDetail], }, total=False) @@ -21273,6 +21428,67 @@ DatasetsHousingMarketsSearchParams = TypedDict('DatasetsHousingMarketsSearchPara 'page_size': NotRequired[int], }, total=False) +DatasetsInstagramUsersFacetsResponse = ModelDatasetsInstagramUsersFacetResponseDoc +DatasetsInstagramUsersFacetsParams = TypedDict('DatasetsInstagramUsersFacetsParams', { + '_response_type': NotRequired[ResponseType], + '_timeout': NotRequired[float], + '_headers': NotRequired[Mapping[str, str]], + 'facet': Required[Literal['is_verified', 'is_business_account', 'has_bio', 'has_external_url', 'category_name', 'source_tier']], + 'q': NotRequired[str], + 'username': NotRequired[str], + 'category_name': NotRequired[str], + 'source_tier': NotRequired[str], + 'is_verified': NotRequired[bool], + 'is_business_account': NotRequired[bool], + 'has_bio': NotRequired[bool], + 'has_external_url': NotRequired[bool], + 'min_followers': NotRequired[int], + 'max_followers': NotRequired[int], + 'min_ratio': NotRequired[float], + 'max_ratio': NotRequired[float], + 'created_after': NotRequired[str], + 'created_before': NotRequired[str], + 'crawled_after': NotRequired[str], + 'crawled_before': NotRequired[str], + 'sort': NotRequired[Literal['relevance', 'followers_desc', 'followers_asc', 'crawled_at_desc', 'crawled_at_asc', 'created_at_desc', 'created_at_asc']], + 'page': NotRequired[int], + 'page_size': NotRequired[int], +}, total=False) + +DatasetsInstagramUsersItemResponse = ModelDatasetsInstagramUserResponseDoc +DatasetsInstagramUsersItemParams = TypedDict('DatasetsInstagramUsersItemParams', { + '_response_type': NotRequired[ResponseType], + '_timeout': NotRequired[float], + '_headers': NotRequired[Mapping[str, str]], + 'username': Required[str], +}, total=False) + +DatasetsInstagramUsersSearchResponse = ModelDatasetsInstagramUsersSearchResponseDoc +DatasetsInstagramUsersSearchParams = TypedDict('DatasetsInstagramUsersSearchParams', { + '_response_type': NotRequired[ResponseType], + '_timeout': NotRequired[float], + '_headers': NotRequired[Mapping[str, str]], + 'q': NotRequired[str], + 'username': NotRequired[str], + 'category_name': NotRequired[str], + 'source_tier': NotRequired[str], + 'is_verified': NotRequired[bool], + 'is_business_account': NotRequired[bool], + 'has_bio': NotRequired[bool], + 'has_external_url': NotRequired[bool], + 'min_followers': NotRequired[int], + 'max_followers': NotRequired[int], + 'min_ratio': NotRequired[float], + 'max_ratio': NotRequired[float], + 'created_after': NotRequired[str], + 'created_before': NotRequired[str], + 'crawled_after': NotRequired[str], + 'crawled_before': NotRequired[str], + 'sort': NotRequired[Literal['relevance', 'followers_desc', 'followers_asc', 'crawled_at_desc', 'crawled_at_asc', 'created_at_desc', 'created_at_asc']], + 'page': NotRequired[int], + 'page_size': NotRequired[int], +}, total=False) + DatasetsJobsCompaniesResponse = ModelDatasetsJobsCompaniesResponseDoc DatasetsJobsCompaniesParams = TypedDict('DatasetsJobsCompaniesParams', { '_response_type': NotRequired[ResponseType], @@ -21857,6 +22073,19 @@ DatasetsProducthuntTrendsSearchParams = TypedDict('DatasetsProducthuntTrendsSear 'page_size': NotRequired[int], }, total=False) +DatasetsRedditTrendingSearchResponse = ModelDatasetsRedditTrendingSearchResponseDoc +DatasetsRedditTrendingSearchParams = TypedDict('DatasetsRedditTrendingSearchParams', { + '_response_type': NotRequired[ResponseType], + '_timeout': NotRequired[float], + '_headers': NotRequired[Mapping[str, str]], + 'q': NotRequired[str], + 'subreddit': NotRequired[str], + 'date': NotRequired[str], + 'sort': NotRequired[Literal['rank', 'date_desc']], + 'page': NotRequired[int], + 'page_size': NotRequired[int], +}, total=False) + DatasetsSecCompaniesFacetsResponse = ModelDatasetsSecCompaniesFacetResponseDoc DatasetsSecCompaniesFacetsParams = TypedDict('DatasetsSecCompaniesFacetsParams', { '_response_type': NotRequired[ResponseType], @@ -23220,6 +23449,7 @@ GooglePlayListParams = TypedDict('GooglePlayListParams', { '_headers': NotRequired[Mapping[str, str]], 'collection': NotRequired[Literal['TOP_FREE', 'TOP_PAID', 'GROSSING', 'NEW_FREE', 'NEW_PAID']], 'category': NotRequired[str], + 'device': NotRequired[Literal['phone', 'tablet', 'tv', 'chromebook', 'watch', 'xr', 'car']], 'age': NotRequired[str], 'num': NotRequired[int], 'country': NotRequired[str], @@ -23238,6 +23468,16 @@ GooglePlayPermissionsParams = TypedDict('GooglePlayPermissionsParams', { 'short': NotRequired[bool], }, total=False) +GooglePlayRatingsResponse = ModelGoogleplayRatingsResponseDoc +GooglePlayRatingsParams = TypedDict('GooglePlayRatingsParams', { + '_response_type': NotRequired[ResponseType], + '_timeout': NotRequired[float], + '_headers': NotRequired[Mapping[str, str]], + 'app_id': Required[str], + 'country': NotRequired[str], + 'lang': NotRequired[str], +}, total=False) + GooglePlayReviewsResponse = ModelGoogleplayReviewsResponseDoc GooglePlayReviewsParams = TypedDict('GooglePlayReviewsParams', { '_response_type': NotRequired[ResponseType], @@ -25509,6 +25749,7 @@ RedditCommentsParams = TypedDict('RedditCommentsParams', { 'sort': NotRequired[Literal['confidence', 'top', 'new', 'controversial', 'old', 'qa']], 'limit': NotRequired[int], 'depth': NotRequired[int], + 'include_metrics': NotRequired[bool], }, total=False) RedditDomainPostsResponse = ModelRedditDomainPostsResponseDoc @@ -25529,6 +25770,7 @@ RedditPostParams = TypedDict('RedditPostParams', { '_timeout': NotRequired[float], '_headers': NotRequired[Mapping[str, str]], 'id': Required[str], + 'include_metrics': NotRequired[bool], }, total=False) RedditSearchResponse = ModelRedditSearchResponseDoc @@ -28365,6 +28607,9 @@ class DatasetsGroup: def housing_markets_facets(self, **params: Unpack[DatasetsHousingMarketsFacetsParams]) -> DatasetsHousingMarketsFacetsResponse: ... def housing_markets_item(self, **params: Unpack[DatasetsHousingMarketsItemParams]) -> DatasetsHousingMarketsItemResponse: ... def housing_markets_search(self, **params: Unpack[DatasetsHousingMarketsSearchParams]) -> DatasetsHousingMarketsSearchResponse: ... + def instagram_users_facets(self, **params: Unpack[DatasetsInstagramUsersFacetsParams]) -> DatasetsInstagramUsersFacetsResponse: ... + def instagram_users_item(self, **params: Unpack[DatasetsInstagramUsersItemParams]) -> DatasetsInstagramUsersItemResponse: ... + def instagram_users_search(self, **params: Unpack[DatasetsInstagramUsersSearchParams]) -> DatasetsInstagramUsersSearchResponse: ... def jobs_companies(self, **params: Unpack[DatasetsJobsCompaniesParams]) -> DatasetsJobsCompaniesResponse: ... def jobs_company_item(self, **params: Unpack[DatasetsJobsCompanyItemParams]) -> DatasetsJobsCompanyItemResponse: ... def jobs_facets(self, **params: Unpack[DatasetsJobsFacetsParams]) -> DatasetsJobsFacetsResponse: ... @@ -28405,6 +28650,7 @@ class DatasetsGroup: def producthunt_products_search(self, **params: Unpack[DatasetsProducthuntProductsSearchParams]) -> DatasetsProducthuntProductsSearchResponse: ... def producthunt_trends_facets(self, **params: Unpack[DatasetsProducthuntTrendsFacetsParams]) -> DatasetsProducthuntTrendsFacetsResponse: ... def producthunt_trends_search(self, **params: Unpack[DatasetsProducthuntTrendsSearchParams]) -> DatasetsProducthuntTrendsSearchResponse: ... + def reddit_trending_search(self, **params: Unpack[DatasetsRedditTrendingSearchParams]) -> DatasetsRedditTrendingSearchResponse: ... def sec_companies_facets(self, **params: Unpack[DatasetsSecCompaniesFacetsParams]) -> DatasetsSecCompaniesFacetsResponse: ... def sec_companies_financials(self, **params: Unpack[DatasetsSecCompaniesFinancialsParams]) -> DatasetsSecCompaniesFinancialsResponse: ... def sec_companies_insider(self, **params: Unpack[DatasetsSecCompaniesInsiderParams]) -> DatasetsSecCompaniesInsiderResponse: ... @@ -28545,6 +28791,7 @@ class GooglePlayGroup: def developer(self, **params: Unpack[GooglePlayDeveloperParams]) -> GooglePlayDeveloperResponse: ... def list(self, **params: Unpack[GooglePlayListParams]) -> GooglePlayListResponse: ... def permissions(self, **params: Unpack[GooglePlayPermissionsParams]) -> GooglePlayPermissionsResponse: ... + def ratings(self, **params: Unpack[GooglePlayRatingsParams]) -> GooglePlayRatingsResponse: ... def reviews(self, **params: Unpack[GooglePlayReviewsParams]) -> GooglePlayReviewsResponse: ... def search(self, **params: Unpack[GooglePlaySearchParams]) -> GooglePlaySearchResponse: ... def similar(self, **params: Unpack[GooglePlaySimilarParams]) -> GooglePlaySimilarResponse: ... @@ -29295,6 +29542,9 @@ OperationId = Literal[ 'datasets-housing-markets-facets', 'datasets-housing-markets-item', 'datasets-housing-markets-search', + 'datasets-instagram-users-facets', + 'datasets-instagram-users-item', + 'datasets-instagram-users-search', 'datasets-jobs-companies', 'datasets-jobs-company-item', 'datasets-jobs-facets', @@ -29335,6 +29585,7 @@ OperationId = Literal[ 'datasets-producthunt-products-search', 'datasets-producthunt-trends-facets', 'datasets-producthunt-trends-search', + 'datasets-reddit-trending-search', 'datasets-sec-companies-facets', 'datasets-sec-companies-financials', 'datasets-sec-companies-insider', @@ -29461,6 +29712,7 @@ OperationId = Literal[ 'googleplay-developer', 'googleplay-list', 'googleplay-permissions', + 'googleplay-ratings', 'googleplay-reviews', 'googleplay-search', 'googleplay-similar', @@ -32114,6 +32366,42 @@ class CrawloraClient: retry_predicate: Callable[[int, BaseException | None], bool] | None = ..., ) -> DatasetsHousingMarketsSearchResponse: ... @overload + def operation( + self, + operation_id: Literal['datasets-instagram-users-facets'], + params: DatasetsInstagramUsersFacetsParams, + *, + response_type: ResponseType = ..., + timeout: float | None = ..., + headers: Mapping[str, str] | None = ..., + retries: int | None = ..., + retry_predicate: Callable[[int, BaseException | None], bool] | None = ..., + ) -> DatasetsInstagramUsersFacetsResponse: ... + @overload + def operation( + self, + operation_id: Literal['datasets-instagram-users-item'], + params: DatasetsInstagramUsersItemParams, + *, + response_type: ResponseType = ..., + timeout: float | None = ..., + headers: Mapping[str, str] | None = ..., + retries: int | None = ..., + retry_predicate: Callable[[int, BaseException | None], bool] | None = ..., + ) -> DatasetsInstagramUsersItemResponse: ... + @overload + def operation( + self, + operation_id: Literal['datasets-instagram-users-search'], + params: DatasetsInstagramUsersSearchParams = ..., + *, + response_type: ResponseType = ..., + timeout: float | None = ..., + headers: Mapping[str, str] | None = ..., + retries: int | None = ..., + retry_predicate: Callable[[int, BaseException | None], bool] | None = ..., + ) -> DatasetsInstagramUsersSearchResponse: ... + @overload def operation( self, operation_id: Literal['datasets-jobs-companies'], @@ -32594,6 +32882,18 @@ class CrawloraClient: retry_predicate: Callable[[int, BaseException | None], bool] | None = ..., ) -> DatasetsProducthuntTrendsSearchResponse: ... @overload + def operation( + self, + operation_id: Literal['datasets-reddit-trending-search'], + params: DatasetsRedditTrendingSearchParams = ..., + *, + response_type: ResponseType = ..., + timeout: float | None = ..., + headers: Mapping[str, str] | None = ..., + retries: int | None = ..., + retry_predicate: Callable[[int, BaseException | None], bool] | None = ..., + ) -> DatasetsRedditTrendingSearchResponse: ... + @overload def operation( self, operation_id: Literal['datasets-sec-companies-facets'], @@ -34106,6 +34406,18 @@ class CrawloraClient: retry_predicate: Callable[[int, BaseException | None], bool] | None = ..., ) -> GooglePlayPermissionsResponse: ... @overload + def operation( + self, + operation_id: Literal['googleplay-ratings'], + params: GooglePlayRatingsParams, + *, + response_type: ResponseType = ..., + timeout: float | None = ..., + headers: Mapping[str, str] | None = ..., + retries: int | None = ..., + retry_predicate: Callable[[int, BaseException | None], bool] | None = ..., + ) -> GooglePlayRatingsResponse: ... + @overload def operation( self, operation_id: Literal['googleplay-reviews'], @@ -42110,6 +42422,42 @@ class CrawloraClient: retry_predicate: Callable[[int, BaseException | None], bool] | None = ..., ) -> DatasetsHousingMarketsSearchResponse: ... @overload + def request( + self, + operation_id: Literal['datasets-instagram-users-facets'], + params: DatasetsInstagramUsersFacetsParams, + *, + response_type: ResponseType = ..., + timeout: float | None = ..., + headers: Mapping[str, str] | None = ..., + retries: int | None = ..., + retry_predicate: Callable[[int, BaseException | None], bool] | None = ..., + ) -> DatasetsInstagramUsersFacetsResponse: ... + @overload + def request( + self, + operation_id: Literal['datasets-instagram-users-item'], + params: DatasetsInstagramUsersItemParams, + *, + response_type: ResponseType = ..., + timeout: float | None = ..., + headers: Mapping[str, str] | None = ..., + retries: int | None = ..., + retry_predicate: Callable[[int, BaseException | None], bool] | None = ..., + ) -> DatasetsInstagramUsersItemResponse: ... + @overload + def request( + self, + operation_id: Literal['datasets-instagram-users-search'], + params: DatasetsInstagramUsersSearchParams = ..., + *, + response_type: ResponseType = ..., + timeout: float | None = ..., + headers: Mapping[str, str] | None = ..., + retries: int | None = ..., + retry_predicate: Callable[[int, BaseException | None], bool] | None = ..., + ) -> DatasetsInstagramUsersSearchResponse: ... + @overload def request( self, operation_id: Literal['datasets-jobs-companies'], @@ -42590,6 +42938,18 @@ class CrawloraClient: retry_predicate: Callable[[int, BaseException | None], bool] | None = ..., ) -> DatasetsProducthuntTrendsSearchResponse: ... @overload + def request( + self, + operation_id: Literal['datasets-reddit-trending-search'], + params: DatasetsRedditTrendingSearchParams = ..., + *, + response_type: ResponseType = ..., + timeout: float | None = ..., + headers: Mapping[str, str] | None = ..., + retries: int | None = ..., + retry_predicate: Callable[[int, BaseException | None], bool] | None = ..., + ) -> DatasetsRedditTrendingSearchResponse: ... + @overload def request( self, operation_id: Literal['datasets-sec-companies-facets'], @@ -44102,6 +44462,18 @@ class CrawloraClient: retry_predicate: Callable[[int, BaseException | None], bool] | None = ..., ) -> GooglePlayPermissionsResponse: ... @overload + def request( + self, + operation_id: Literal['googleplay-ratings'], + params: GooglePlayRatingsParams, + *, + response_type: ResponseType = ..., + timeout: float | None = ..., + headers: Mapping[str, str] | None = ..., + retries: int | None = ..., + retry_predicate: Callable[[int, BaseException | None], bool] | None = ..., + ) -> GooglePlayRatingsResponse: ... + @overload def request( self, operation_id: Literal['googleplay-reviews'], diff --git a/crawlora/operations.py b/crawlora/operations.py index 41c3a58..5de3800 100644 --- a/crawlora/operations.py +++ b/crawlora/operations.py @@ -4272,6 +4272,105 @@ {'in': 'query', 'name': 'page', 'type': 'integer'}, {'in': 'query', 'name': 'page_size', 'type': 'integer'}], 'security': ['ApiKeyAuth']}, + 'datasets-instagram-users-facets': {'bodyParam': None, + 'bodyRequired': False, + 'consumes': ['application/json'], + 'formParams': [], + 'id': 'datasets-instagram-users-facets', + 'method': 'GET', + 'paginatable': True, + 'path': '/datasets/instagram-users/facets', + 'pathParams': [], + 'produces': ['application/json'], + 'queryParams': [{'enum': ['is_verified', + 'is_business_account', + 'has_bio', + 'has_external_url', + 'category_name', + 'source_tier'], + 'in': 'query', + 'name': 'facet', + 'required': True, + 'type': 'string'}, + {'in': 'query', 'name': 'q', 'type': 'string'}, + {'in': 'query', 'name': 'username', 'type': 'string'}, + {'in': 'query', 'name': 'category_name', 'type': 'string'}, + {'in': 'query', 'name': 'source_tier', 'type': 'string'}, + {'in': 'query', 'name': 'is_verified', 'type': 'boolean'}, + {'in': 'query', 'name': 'is_business_account', 'type': 'boolean'}, + {'in': 'query', 'name': 'has_bio', 'type': 'boolean'}, + {'in': 'query', 'name': 'has_external_url', 'type': 'boolean'}, + {'in': 'query', 'name': 'min_followers', 'type': 'integer'}, + {'in': 'query', 'name': 'max_followers', 'type': 'integer'}, + {'in': 'query', 'name': 'min_ratio', 'type': 'number'}, + {'in': 'query', 'name': 'max_ratio', 'type': 'number'}, + {'in': 'query', 'name': 'created_after', 'type': 'string'}, + {'in': 'query', 'name': 'created_before', 'type': 'string'}, + {'in': 'query', 'name': 'crawled_after', 'type': 'string'}, + {'in': 'query', 'name': 'crawled_before', 'type': 'string'}, + {'enum': ['relevance', + 'followers_desc', + 'followers_asc', + 'crawled_at_desc', + 'crawled_at_asc', + 'created_at_desc', + 'created_at_asc'], + 'in': 'query', + 'name': 'sort', + 'type': 'string'}, + {'in': 'query', 'name': 'page', 'type': 'integer'}, + {'in': 'query', 'name': 'page_size', 'type': 'integer'}], + 'security': ['ApiKeyAuth']}, + 'datasets-instagram-users-item': {'bodyParam': None, + 'bodyRequired': False, + 'consumes': ['application/json'], + 'formParams': [], + 'id': 'datasets-instagram-users-item', + 'method': 'GET', + 'path': '/datasets/instagram-users/items/{username}', + 'pathParams': ['username'], + 'produces': ['application/json'], + 'queryParams': [], + 'security': ['ApiKeyAuth']}, + 'datasets-instagram-users-search': {'bodyParam': None, + 'bodyRequired': False, + 'consumes': ['application/json'], + 'formParams': [], + 'id': 'datasets-instagram-users-search', + 'method': 'GET', + 'paginatable': True, + 'path': '/datasets/instagram-users/search', + 'pathParams': [], + 'produces': ['application/json'], + 'queryParams': [{'in': 'query', 'name': 'q', 'type': 'string'}, + {'in': 'query', 'name': 'username', 'type': 'string'}, + {'in': 'query', 'name': 'category_name', 'type': 'string'}, + {'in': 'query', 'name': 'source_tier', 'type': 'string'}, + {'in': 'query', 'name': 'is_verified', 'type': 'boolean'}, + {'in': 'query', 'name': 'is_business_account', 'type': 'boolean'}, + {'in': 'query', 'name': 'has_bio', 'type': 'boolean'}, + {'in': 'query', 'name': 'has_external_url', 'type': 'boolean'}, + {'in': 'query', 'name': 'min_followers', 'type': 'integer'}, + {'in': 'query', 'name': 'max_followers', 'type': 'integer'}, + {'in': 'query', 'name': 'min_ratio', 'type': 'number'}, + {'in': 'query', 'name': 'max_ratio', 'type': 'number'}, + {'in': 'query', 'name': 'created_after', 'type': 'string'}, + {'in': 'query', 'name': 'created_before', 'type': 'string'}, + {'in': 'query', 'name': 'crawled_after', 'type': 'string'}, + {'in': 'query', 'name': 'crawled_before', 'type': 'string'}, + {'enum': ['relevance', + 'followers_desc', + 'followers_asc', + 'crawled_at_desc', + 'crawled_at_asc', + 'created_at_desc', + 'created_at_asc'], + 'in': 'query', + 'name': 'sort', + 'type': 'string'}, + {'in': 'query', 'name': 'page', 'type': 'integer'}, + {'in': 'query', 'name': 'page_size', 'type': 'integer'}], + 'security': ['ApiKeyAuth']}, 'datasets-jobs-companies': {'bodyParam': None, 'bodyRequired': False, 'consumes': ['application/json'], @@ -5377,6 +5476,26 @@ {'in': 'query', 'name': 'page', 'type': 'integer'}, {'in': 'query', 'name': 'page_size', 'type': 'integer'}], 'security': ['ApiKeyAuth']}, + 'datasets-reddit-trending-search': {'bodyParam': None, + 'bodyRequired': False, + 'consumes': ['application/json'], + 'formParams': [], + 'id': 'datasets-reddit-trending-search', + 'method': 'GET', + 'paginatable': True, + 'path': '/datasets/reddit-trending/search', + 'pathParams': [], + 'produces': ['application/json'], + 'queryParams': [{'in': 'query', 'name': 'q', 'type': 'string'}, + {'in': 'query', 'name': 'subreddit', 'type': 'string'}, + {'in': 'query', 'name': 'date', 'type': 'string'}, + {'enum': ['rank', 'date_desc'], + 'in': 'query', + 'name': 'sort', + 'type': 'string'}, + {'in': 'query', 'name': 'page', 'type': 'integer'}, + {'in': 'query', 'name': 'page_size', 'type': 'integer'}], + 'security': ['ApiKeyAuth']}, 'datasets-sec-companies-facets': {'bodyParam': None, 'bodyRequired': False, 'consumes': ['application/json'], @@ -7856,6 +7975,10 @@ 'name': 'collection', 'type': 'string'}, {'in': 'query', 'name': 'category', 'type': 'string'}, + {'enum': ['phone', 'tablet', 'tv', 'chromebook', 'watch', 'xr', 'car'], + 'in': 'query', + 'name': 'device', + 'type': 'string'}, {'in': 'query', 'name': 'age', 'type': 'string'}, {'in': 'query', 'name': 'num', 'type': 'integer'}, {'in': 'query', 'name': 'country', 'type': 'string'}, @@ -7876,6 +7999,19 @@ {'in': 'query', 'name': 'lang', 'type': 'string'}, {'in': 'query', 'name': 'short', 'type': 'boolean'}], 'security': ['ApiKeyAuth']}, + 'googleplay-ratings': {'bodyParam': None, + 'bodyRequired': False, + 'consumes': ['application/json'], + 'formParams': [], + 'id': 'googleplay-ratings', + 'method': 'GET', + 'path': '/googleplay/ratings', + 'pathParams': [], + 'produces': ['application/json'], + 'queryParams': [{'in': 'query', 'name': 'app_id', 'required': True, 'type': 'string'}, + {'in': 'query', 'name': 'country', 'type': 'string'}, + {'in': 'query', 'name': 'lang', 'type': 'string'}], + 'security': ['ApiKeyAuth']}, 'googleplay-reviews': {'bodyParam': None, 'bodyRequired': False, 'consumes': ['application/json'], @@ -11219,7 +11355,8 @@ 'name': 'sort', 'type': 'string'}, {'in': 'query', 'name': 'limit', 'type': 'integer'}, - {'in': 'query', 'name': 'depth', 'type': 'integer'}], + {'in': 'query', 'name': 'depth', 'type': 'integer'}, + {'in': 'query', 'name': 'include_metrics', 'type': 'boolean'}], 'security': ['ApiKeyAuth']}, 'reddit-domain-posts': {'bodyParam': None, 'bodyRequired': False, @@ -11250,7 +11387,7 @@ 'path': '/reddit/post/{id}', 'pathParams': ['id'], 'produces': ['application/json'], - 'queryParams': [], + 'queryParams': [{'in': 'query', 'name': 'include_metrics', 'type': 'boolean'}], 'security': ['ApiKeyAuth']}, 'reddit-search': {'bodyParam': None, 'bodyRequired': False, @@ -15227,6 +15364,9 @@ 'housing_markets_facets': 'datasets-housing-markets-facets', 'housing_markets_item': 'datasets-housing-markets-item', 'housing_markets_search': 'datasets-housing-markets-search', + 'instagram_users_facets': 'datasets-instagram-users-facets', + 'instagram_users_item': 'datasets-instagram-users-item', + 'instagram_users_search': 'datasets-instagram-users-search', 'jobs_companies': 'datasets-jobs-companies', 'jobs_company_item': 'datasets-jobs-company-item', 'jobs_facets': 'datasets-jobs-facets', @@ -15268,6 +15408,7 @@ 'producthunt_products_search': 'datasets-producthunt-products-search', 'producthunt_trends_facets': 'datasets-producthunt-trends-facets', 'producthunt_trends_search': 'datasets-producthunt-trends-search', + 'reddit_trending_search': 'datasets-reddit-trending-search', 'sec_companies_facets': 'datasets-sec-companies-facets', 'sec_companies_financials': 'datasets-sec-companies-financials', 'sec_companies_insider': 'datasets-sec-companies-insider', @@ -15390,6 +15531,7 @@ 'developer': 'googleplay-developer', 'list': 'googleplay-list', 'permissions': 'googleplay-permissions', + 'ratings': 'googleplay-ratings', 'reviews': 'googleplay-reviews', 'search': 'googleplay-search', 'similar': 'googleplay-similar', @@ -15879,7 +16021,7 @@ 'video': 'youtube-video'}, 'zillow': {'autocomplete': 'zillow-autocomplete', 'property': 'zillow-property', 'search': 'zillow-search'}} -OPERATION_COUNT = 832 +OPERATION_COUNT = 837 class OperationId: AIRBNB_HOST = 'airbnb-host' @@ -16047,6 +16189,9 @@ class OperationId: DATASETS_HOUSING_MARKETS_FACETS = 'datasets-housing-markets-facets' DATASETS_HOUSING_MARKETS_ITEM = 'datasets-housing-markets-item' DATASETS_HOUSING_MARKETS_SEARCH = 'datasets-housing-markets-search' + DATASETS_INSTAGRAM_USERS_FACETS = 'datasets-instagram-users-facets' + DATASETS_INSTAGRAM_USERS_ITEM = 'datasets-instagram-users-item' + DATASETS_INSTAGRAM_USERS_SEARCH = 'datasets-instagram-users-search' DATASETS_JOBS_COMPANIES = 'datasets-jobs-companies' DATASETS_JOBS_COMPANY_ITEM = 'datasets-jobs-company-item' DATASETS_JOBS_FACETS = 'datasets-jobs-facets' @@ -16088,6 +16233,7 @@ class OperationId: DATASETS_PRODUCTHUNT_PRODUCTS_SEARCH = 'datasets-producthunt-products-search' DATASETS_PRODUCTHUNT_TRENDS_FACETS = 'datasets-producthunt-trends-facets' DATASETS_PRODUCTHUNT_TRENDS_SEARCH = 'datasets-producthunt-trends-search' + DATASETS_REDDIT_TRENDING_SEARCH = 'datasets-reddit-trending-search' DATASETS_SEC_COMPANIES_FACETS = 'datasets-sec-companies-facets' DATASETS_SEC_COMPANIES_FINANCIALS = 'datasets-sec-companies-financials' DATASETS_SEC_COMPANIES_INSIDER = 'datasets-sec-companies-insider' @@ -16198,6 +16344,7 @@ class OperationId: GOOGLE_PLAY_DEVELOPER = 'googleplay-developer' GOOGLE_PLAY_LIST = 'googleplay-list' GOOGLE_PLAY_PERMISSIONS = 'googleplay-permissions' + GOOGLE_PLAY_RATINGS = 'googleplay-ratings' GOOGLE_PLAY_REVIEWS = 'googleplay-reviews' GOOGLE_PLAY_SEARCH = 'googleplay-search' GOOGLE_PLAY_SIMILAR = 'googleplay-similar' diff --git a/docs/operations.md b/docs/operations.md index 6823540..3c75c8d 100644 --- a/docs/operations.md +++ b/docs/operations.md @@ -2,7 +2,7 @@ Generated from `openapi/public.json`. Deprecated, admin, and internal operations are excluded from this SDK contract. -Total operations: `832` +Total operations: `837` | Group | SDK method | Operation ID | HTTP | Params | Auth | Response | Notes | | --- | --- | --- | --- | --- | --- | --- | --- | @@ -177,6 +177,9 @@ Total operations: `832` | datasets | `datasets.housing_markets_facets` | `datasets-housing-markets-facets` | `GET /datasets/housing-markets/facets` | `facet` (query Literal['region_type', 'state_code', 'property_type', 'parent_metro', 'parent_metro_code', 'income_vintage', 'is_latest', 'period_begin'] required)
`q` (query str)
`region_type` (query Literal['national', 'metro', 'county', 'city', 'zip'])
`state_code` (query str)
`property_type` (query str)
`parent_metro_code` (query str)
`zip_code` (query str)
`period` (query str)
`latest` (query bool)
`min_median_sale_price` (query float)
`max_median_sale_price` (query float)
`min_median_list_price` (query float)
`max_median_list_price` (query float)
`min_price_to_income` (query float)
`max_price_to_income` (query float)
`min_salary_to_buy` (query int)
`max_salary_to_buy` (query int)
`min_median_dom` (query float)
`max_median_dom` (query float)
`min_inventory` (query int)
`max_inventory` (query int)
`min_homes_sold` (query int) | `ApiKeyAuth` | `DatasetsHousingMarketsFacetsResponse` | | | datasets | `datasets.housing_markets_item` | `datasets-housing-markets-item` | `GET /datasets/housing-markets/items/{region_type}/{table_id}` | `region_type` (path Literal['national', 'metro', 'county', 'city', 'zip'] required)
`table_id` (path int required)
`period` (query str)
`property_type` (query str)
`history` (query bool) | `ApiKeyAuth` | `DatasetsHousingMarketsItemResponse` | | | datasets | `datasets.housing_markets_search` | `datasets-housing-markets-search` | `GET /datasets/housing-markets/search` | `q` (query str)
`region_type` (query Literal['national', 'metro', 'county', 'city', 'zip'])
`state_code` (query str)
`property_type` (query str)
`parent_metro_code` (query str)
`zip_code` (query str)
`period` (query str)
`latest` (query bool)
`min_median_sale_price` (query float)
`max_median_sale_price` (query float)
`min_median_list_price` (query float)
`max_median_list_price` (query float)
`min_price_to_income` (query float)
`max_price_to_income` (query float)
`min_salary_to_buy` (query int)
`max_salary_to_buy` (query int)
`min_median_dom` (query float)
`max_median_dom` (query float)
`min_inventory` (query int)
`max_inventory` (query int)
`min_homes_sold` (query int)
`sort` (query Literal['relevance', 'price_desc', 'price_asc', 'list_price_desc', 'list_price_asc', 'price_to_income_desc', 'price_to_income_asc', 'salary_to_buy_desc', 'salary_to_buy_asc', 'dom_asc', 'dom_desc', 'inventory_desc', 'homes_sold_desc', 'period_desc'])
`page` (query int)
`page_size` (query int) | `ApiKeyAuth` | `DatasetsHousingMarketsSearchResponse` | | +| datasets | `datasets.instagram_users_facets` | `datasets-instagram-users-facets` | `GET /datasets/instagram-users/facets` | `facet` (query Literal['is_verified', 'is_business_account', 'has_bio', 'has_external_url', 'category_name', 'source_tier'] required)
`q` (query str)
`username` (query str)
`category_name` (query str)
`source_tier` (query str)
`is_verified` (query bool)
`is_business_account` (query bool)
`has_bio` (query bool)
`has_external_url` (query bool)
`min_followers` (query int)
`max_followers` (query int)
`min_ratio` (query float)
`max_ratio` (query float)
`created_after` (query str)
`created_before` (query str)
`crawled_after` (query str)
`crawled_before` (query str)
`sort` (query Literal['relevance', 'followers_desc', 'followers_asc', 'crawled_at_desc', 'crawled_at_asc', 'created_at_desc', 'created_at_asc'])
`page` (query int)
`page_size` (query int) | `ApiKeyAuth` | `DatasetsInstagramUsersFacetsResponse` | | +| datasets | `datasets.instagram_users_item` | `datasets-instagram-users-item` | `GET /datasets/instagram-users/items/{username}` | `username` (path str required) | `ApiKeyAuth` | `DatasetsInstagramUsersItemResponse` | | +| datasets | `datasets.instagram_users_search` | `datasets-instagram-users-search` | `GET /datasets/instagram-users/search` | `q` (query str)
`username` (query str)
`category_name` (query str)
`source_tier` (query str)
`is_verified` (query bool)
`is_business_account` (query bool)
`has_bio` (query bool)
`has_external_url` (query bool)
`min_followers` (query int)
`max_followers` (query int)
`min_ratio` (query float)
`max_ratio` (query float)
`created_after` (query str)
`created_before` (query str)
`crawled_after` (query str)
`crawled_before` (query str)
`sort` (query Literal['relevance', 'followers_desc', 'followers_asc', 'crawled_at_desc', 'crawled_at_asc', 'created_at_desc', 'created_at_asc'])
`page` (query int)
`page_size` (query int) | `ApiKeyAuth` | `DatasetsInstagramUsersSearchResponse` | | | datasets | `datasets.jobs_companies` | `datasets-jobs-companies` | `GET /datasets/jobs/companies` | `q` (query str)
`provider` (query Literal['greenhouse', 'lever', 'ashby', 'workday', 'smartrecruiters', 'workable', 'recruitee', 'rippling', 'personio', 'teamtailor', 'oracle', 'ukg', 'icims', 'eightfold', 'gem', 'pinpoint'])
`status` (query Literal['active', 'empty', 'gone', 'blocked', 'pending', 'invalid'])
`min_open_roles` (query int)
`sort` (query Literal['open_desc', 'company_asc', 'crawled_desc'])
`page` (query int)
`page_size` (query int) | `ApiKeyAuth` | `DatasetsJobsCompaniesResponse` | | | datasets | `datasets.jobs_company_item` | `datasets-jobs-company-item` | `GET /datasets/jobs/companies/{id}` | `id` (path str required) | `ApiKeyAuth` | `DatasetsJobsCompanyItemResponse` | | | datasets | `datasets.jobs_facets` | `datasets-jobs-facets` | `GET /datasets/jobs/facets` | `size` (query int) | `ApiKeyAuth` | `DatasetsJobsFacetsResponse` | | @@ -217,6 +220,7 @@ Total operations: `832` | datasets | `datasets.producthunt_products_search` | `datasets-producthunt-products-search` | `GET /datasets/producthunt-products/search` | `q` (query str)
`topic` (query str)
`maker` (query str)
`launched_after` (query str)
`launched_before` (query str)
`min_votes` (query int)
`min_rating` (query float)
`pricing_type` (query str)
`has_website` (query bool)
`is_online` (query bool)
`sort` (query Literal['relevance', 'votes_desc', 'launched_desc', 'launched_asc', 'rating_desc', 'best_rank_asc'])
`page` (query int)
`page_size` (query int) | `ApiKeyAuth` | `DatasetsProducthuntProductsSearchResponse` | | | datasets | `datasets.producthunt_trends_facets` | `datasets-producthunt-trends-facets` | `GET /datasets/producthunt-trends/facets` | `facet` (query Literal['topic', 'launch_year'] required)
`group_by` (query Literal['topic_month', 'topic_year', 'topic'])
`topic` (query str)
`launched_after` (query str)
`launched_before` (query str)
`min_votes` (query int)
`min_launches` (query int) | `ApiKeyAuth` | `DatasetsProducthuntTrendsFacetsResponse` | | | datasets | `datasets.producthunt_trends_search` | `datasets-producthunt-trends-search` | `GET /datasets/producthunt-trends/search` | `group_by` (query Literal['topic_month', 'topic_year', 'topic'])
`topic` (query str)
`launched_after` (query str)
`launched_before` (query str)
`min_votes` (query int)
`min_launches` (query int)
`sort` (query Literal['period_desc', 'period_asc', 'launch_count_desc', 'sum_votes_desc'])
`page` (query int)
`page_size` (query int) | `ApiKeyAuth` | `DatasetsProducthuntTrendsSearchResponse` | | +| datasets | `datasets.reddit_trending_search` | `datasets-reddit-trending-search` | `GET /datasets/reddit-trending/search` | `q` (query str)
`subreddit` (query str)
`date` (query str)
`sort` (query Literal['rank', 'date_desc'])
`page` (query int)
`page_size` (query int) | `ApiKeyAuth` | `DatasetsRedditTrendingSearchResponse` | | | datasets | `datasets.sec_companies_facets` | `datasets-sec-companies-facets` | `GET /datasets/sec-companies/facets` | `facet` (query Literal['sic', 'sic_description', 'exchange', 'state_of_incorporation', 'entity_type', 'reporting_currency', 'revenue_band', 'forms_filed'] required)
`q` (query str)
`ticker` (query str)
`sic` (query str)
`exchange` (query str)
`state_of_incorporation` (query str)
`entity_type` (query str)
`reporting_currency` (query str)
`has_financials` (query bool)
`min_revenue` (query float)
`form_filed` (query str) | `ApiKeyAuth` | `DatasetsSecCompaniesFacetsResponse` | | | datasets | `datasets.sec_companies_financials` | `datasets-sec-companies-financials` | `GET /datasets/sec-companies/financials/{cik}` | `cik` (path str required)
`statement` (query Literal['income', 'balance', 'cash_flow'])
`period` (query Literal['annual', 'quarterly'])
`from` (query int)
`to` (query int)
`limit` (query int) | `ApiKeyAuth` | `DatasetsSecCompaniesFinancialsResponse` | | | datasets | `datasets.sec_companies_insider` | `datasets-sec-companies-insider` | `GET /datasets/sec-companies/insider/{cik}` | `cik` (path str required)
`from` (query str)
`to` (query str)
`code` (query str)
`limit` (query int) | `ApiKeyAuth` | `DatasetsSecCompaniesInsiderResponse` | | @@ -339,8 +343,9 @@ Total operations: `832` | google_play | `google_play.categories` | `googleplay-categories` | `GET /googleplay/categories` | `country` (query str)
`lang` (query str) | `ApiKeyAuth` | `GooglePlayCategoriesResponse` | | | google_play | `google_play.datasafety` | `googleplay-datasafety` | `GET /googleplay/datasafety` | `app_id` (query str required)
`lang` (query str) | `ApiKeyAuth` | `GooglePlayDatasafetyResponse` | | | google_play | `google_play.developer` | `googleplay-developer` | `GET /googleplay/developer/{dev_id}` | `dev_id` (path str required)
`num` (query int)
`country` (query str)
`lang` (query str)
`full_detail` (query bool) | `ApiKeyAuth` | `GooglePlayDeveloperResponse` | | -| google_play | `google_play.list` | `googleplay-list` | `GET /googleplay/list` | `collection` (query Literal['TOP_FREE', 'TOP_PAID', 'GROSSING', 'NEW_FREE', 'NEW_PAID'])
`category` (query str)
`age` (query str)
`num` (query int)
`country` (query str)
`lang` (query str)
`full_detail` (query bool) | `ApiKeyAuth` | `GooglePlayListResponse` | | +| google_play | `google_play.list` | `googleplay-list` | `GET /googleplay/list` | `collection` (query Literal['TOP_FREE', 'TOP_PAID', 'GROSSING', 'NEW_FREE', 'NEW_PAID'])
`category` (query str)
`device` (query Literal['phone', 'tablet', 'tv', 'chromebook', 'watch', 'xr', 'car'])
`age` (query str)
`num` (query int)
`country` (query str)
`lang` (query str)
`full_detail` (query bool) | `ApiKeyAuth` | `GooglePlayListResponse` | | | google_play | `google_play.permissions` | `googleplay-permissions` | `GET /googleplay/permissions` | `app_id` (query str required)
`country` (query str)
`lang` (query str)
`short` (query bool) | `ApiKeyAuth` | `GooglePlayPermissionsResponse` | | +| google_play | `google_play.ratings` | `googleplay-ratings` | `GET /googleplay/ratings` | `app_id` (query str required)
`country` (query str)
`lang` (query str) | `ApiKeyAuth` | `GooglePlayRatingsResponse` | | | google_play | `google_play.reviews` | `googleplay-reviews` | `GET /googleplay/reviews` | `app_id` (query str required)
`sort` (query Literal['helpfulness', 'newest', 'rating'])
`num` (query int)
`country` (query str)
`lang` (query str)
`paginate` (query bool)
`next_pagination_token` (query str) | `ApiKeyAuth` | `GooglePlayReviewsResponse` | | | google_play | `google_play.search` | `googleplay-search` | `GET /googleplay/search` | `term` (query str required)
`num` (query int)
`country` (query str)
`lang` (query str)
`full_detail` (query bool)
`price` (query Literal['all', 'free', 'paid']) | `ApiKeyAuth` | `GooglePlaySearchResponse` | | | google_play | `google_play.similar` | `googleplay-similar` | `GET /googleplay/similar` | `app_id` (query str required)
`num` (query int)
`country` (query str)
`lang` (query str)
`full_detail` (query bool) | `ApiKeyAuth` | `GooglePlaySimilarResponse` | | @@ -571,9 +576,9 @@ Total operations: `832` | product_hunt | `product_hunt.makers` | `producthunt-makers` | `GET /producthunt/product/{id}/makers` | `id` (path str required)
`cursor` (query str) | `ApiKeyAuth` | `ProductHuntMakersResponse` | | | product_hunt | `product_hunt.reviews` | `producthunt-reviews` | `GET /producthunt/product/{id}/reviews` | `id` (path str required) | `ApiKeyAuth` | `ProductHuntReviewsResponse` | | | product_hunt | `product_hunt.search` | `producthunt-search` | `GET /producthunt/search` | `query` (query str required)
`type` (query Literal['product', 'user', 'launch'])
`page` (query int)
`featured` (query bool)
`topics` (query str) | `ApiKeyAuth` | `ProductHuntSearchResponse` | | -| reddit | `reddit.comments` | `reddit-comments` | `GET /reddit/comments/{id}` | `id` (path str required)
`sort` (query Literal['confidence', 'top', 'new', 'controversial', 'old', 'qa'])
`limit` (query int)
`depth` (query int) | `ApiKeyAuth` | `RedditCommentsResponse` | | +| reddit | `reddit.comments` | `reddit-comments` | `GET /reddit/comments/{id}` | `id` (path str required)
`sort` (query Literal['confidence', 'top', 'new', 'controversial', 'old', 'qa'])
`limit` (query int)
`depth` (query int)
`include_metrics` (query bool) | `ApiKeyAuth` | `RedditCommentsResponse` | | | reddit | `reddit.domain_posts` | `reddit-domain-posts` | `GET /reddit/domain/{domain}/posts` | `domain` (path str required)
`sort` (query Literal['hot', 'new', 'top', 'rising'])
`time` (query Literal['hour', 'day', 'week', 'month', 'year', 'all'])
`limit` (query int)
`after` (query str) | `ApiKeyAuth` | `RedditDomainPostsResponse` | | -| reddit | `reddit.post` | `reddit-post` | `GET /reddit/post/{id}` | `id` (path str required) | `ApiKeyAuth` | `RedditPostResponse` | | +| reddit | `reddit.post` | `reddit-post` | `GET /reddit/post/{id}` | `id` (path str required)
`include_metrics` (query bool) | `ApiKeyAuth` | `RedditPostResponse` | | | reddit | `reddit.search` | `reddit-search` | `GET /reddit/search` | `q` (query str required)
`subreddit` (query str)
`sort` (query Literal['relevance', 'hot', 'new', 'top', 'comments'])
`time` (query Literal['hour', 'day', 'week', 'month', 'year', 'all'])
`limit` (query int)
`after` (query str) | `ApiKeyAuth` | `RedditSearchResponse` | | | reddit | `reddit.subreddit_about` | `reddit-subreddit-about` | `GET /reddit/subreddit/{subreddit}/about` | `subreddit` (path str required)
`limit` (query int) | `ApiKeyAuth` | `RedditSubredditAboutResponse` | | | reddit | `reddit.subreddit_comments` | `reddit-subreddit-comments` | `GET /reddit/subreddit/{subreddit}/comments` | `subreddit` (path str required)
`limit` (query int)
`after` (query str) | `ApiKeyAuth` | `RedditSubredditCommentsResponse` | | diff --git a/docs/recipes.md b/docs/recipes.md index f026358..75f167c 100644 --- a/docs/recipes.md +++ b/docs/recipes.md @@ -36,9 +36,14 @@ Newer platforms are grouped like every other endpoint: ```python posts = crawlora.reddit.search(q="python", subreddit="programming") +post_with_metrics = crawlora.reddit.post(id="1v8hy3q", include_metrics=True) +comments_with_metrics = crawlora.reddit.comments(id="1v8hy3q", include_metrics=True, limit=25) brand = crawlora.brand.retrieve(domain="stripe.com") ``` +Omit `include_metrics` for the 1-credit feed mode. Set it to `True` for the +3-credit anonymous HTML mode with public post and comment engagement metrics. + ## Threads Public Lookups ```python diff --git a/openapi/public.json b/openapi/public.json index 4d16f58..b6ca113 100644 --- a/openapi/public.json +++ b/openapi/public.json @@ -11878,6 +11878,49 @@ }, "type": "object" }, + "datasets.InstagramUserFacetResponse": { + "properties": { + "dataset": { + "type": "string" + }, + "facet": { + "type": "string" + }, + "items": { + "items": { + "$ref": "#/definitions/es.InstagramUserDatasetFacetItem" + }, + "type": "array" + } + }, + "type": "object" + }, + "datasets.InstagramUserSearchResponse": { + "properties": { + "dataset": { + "type": "string" + }, + "items": { + "items": { + "$ref": "#/definitions/es.InstagramUserDatasetItem" + }, + "type": "array" + }, + "page": { + "type": "integer" + }, + "page_size": { + "type": "integer" + }, + "sort": { + "type": "string" + }, + "total": { + "type": "integer" + } + }, + "type": "object" + }, "datasets.JobCompaniesResponse": { "properties": { "companies": { @@ -12433,6 +12476,35 @@ }, "type": "object" }, + "datasets.RedditTrendingSearchResponse": { + "properties": { + "dataset": { + "type": "string" + }, + "items": { + "items": { + "$ref": "#/definitions/es.RedditTrendingEntry" + }, + "type": "array" + }, + "page": { + "type": "integer" + }, + "page_size": { + "type": "integer" + }, + "snapshot_date": { + "type": "string" + }, + "sort": { + "type": "string" + }, + "total": { + "type": "integer" + } + }, + "type": "object" + }, "datasets.ReviewsSearchResponse": { "properties": { "dataset": { @@ -13480,6 +13552,54 @@ }, "type": "object" }, + "datasets.instagramUserResponseDoc": { + "properties": { + "code": { + "example": 200, + "type": "integer" + }, + "data": { + "$ref": "#/definitions/es.InstagramUserRecord" + }, + "msg": { + "example": "OK", + "type": "string" + } + }, + "type": "object" + }, + "datasets.instagramUsersFacetResponseDoc": { + "properties": { + "code": { + "example": 200, + "type": "integer" + }, + "data": { + "$ref": "#/definitions/datasets.InstagramUserFacetResponse" + }, + "msg": { + "example": "OK", + "type": "string" + } + }, + "type": "object" + }, + "datasets.instagramUsersSearchResponseDoc": { + "properties": { + "code": { + "example": 200, + "type": "integer" + }, + "data": { + "$ref": "#/definitions/datasets.InstagramUserSearchResponse" + }, + "msg": { + "example": "OK", + "type": "string" + } + }, + "type": "object" + }, "datasets.jobsCompaniesResponseDoc": { "properties": { "code": { @@ -14105,6 +14225,22 @@ }, "type": "object" }, + "datasets.redditTrendingSearchResponseDoc": { + "properties": { + "code": { + "example": 200, + "type": "integer" + }, + "data": { + "$ref": "#/definitions/datasets.RedditTrendingSearchResponse" + }, + "msg": { + "example": "OK", + "type": "string" + } + }, + "type": "object" + }, "datasets.reviewsSearchResponseDoc": { "properties": { "code": { @@ -16317,6 +16453,13 @@ "developer_id": { "type": "string" }, + "discovery_sources": { + "description": "DiscoverySources lists the public catalogs that supplied this app ID.", + "items": { + "type": "string" + }, + "type": "array" + }, "first_seen": { "type": "string" }, @@ -16336,7 +16479,7 @@ "type": "string" }, "platforms": { - "description": "Platforms is the set of Apple device platforms this app is confirmed on,\nusing Apple's own appPlatforms vocabulary: phone, pad, mac, tv, watch,\nvision. Only ever set for Store \"ios\" (Apple's App Store ecosystem);\nabsent/empty on existing docs means \"iPhone catalog, platform not yet\nclassified\" rather than \"phone-only\" — do not treat it as authoritative\nuntil backfilled. Not used for Android.", + "description": "Platforms is the set of store-specific device platforms this app is\nconfirmed on. iOS uses Apple's appPlatforms vocabulary (phone, pad, mac,\ntv, watch, vision). Android uses Google Play device-tab/source values\n(phone, tablet, tv, chromebook, watch, xr, car, windows). Empty means the\nrecord has not been classified by platform yet.", "items": { "type": "string" }, @@ -17035,6 +17178,13 @@ "developer_email": { "type": "string" }, + "discovery_sources": { + "description": "DiscoverySources lists the public catalogs that supplied this extension ID.", + "items": { + "type": "string" + }, + "type": "array" + }, "first_seen": { "type": "string" }, @@ -18248,6 +18398,141 @@ }, "type": "object" }, + "es.InstagramUserDatasetFacetItem": { + "properties": { + "count": { + "type": "integer" + }, + "value": { + "type": "string" + } + }, + "type": "object" + }, + "es.InstagramUserDatasetItem": { + "properties": { + "avatar_url": { + "type": "string" + }, + "biography": { + "type": "string" + }, + "category_name": { + "type": "string" + }, + "crawled_at": { + "type": "string" + }, + "created_at": { + "type": "string" + }, + "external_url": { + "type": "string" + }, + "follower_following_ratio": { + "type": "number" + }, + "followers": { + "type": "integer" + }, + "following": { + "type": "integer" + }, + "full_name": { + "type": "string" + }, + "has_bio": { + "type": "boolean" + }, + "has_external_url": { + "type": "boolean" + }, + "id": { + "type": "string" + }, + "is_business_account": { + "type": "boolean" + }, + "is_verified": { + "type": "boolean" + }, + "posts": { + "type": "integer" + }, + "schema_version": { + "type": "integer" + }, + "source_tier": { + "type": "string" + }, + "username": { + "type": "string" + } + }, + "type": "object" + }, + "es.InstagramUserRecord": { + "properties": { + "avatar_url": { + "type": "string" + }, + "biography": { + "type": "string" + }, + "category_name": { + "type": "string" + }, + "crawled_at": { + "type": "string" + }, + "created_at": { + "type": "string" + }, + "external_url": { + "type": "string" + }, + "follower_following_ratio": { + "type": "number" + }, + "followers": { + "type": "integer" + }, + "following": { + "type": "integer" + }, + "full_name": { + "type": "string" + }, + "has_bio": { + "type": "boolean" + }, + "has_external_url": { + "type": "boolean" + }, + "id": { + "type": "string" + }, + "is_business_account": { + "type": "boolean" + }, + "is_verified": { + "type": "boolean" + }, + "posts": { + "type": "integer" + }, + "schema_version": { + "type": "integer" + }, + "source_tier": { + "type": "string" + }, + "username": { + "type": "string" + } + }, + "type": "object" + }, "es.JobPostingFacets": { "properties": { "by_department": { @@ -19374,6 +19659,47 @@ }, "type": "object" }, + "es.RedditTrendingEntry": { + "properties": { + "author": { + "type": "string" + }, + "crawled_at": { + "type": "string" + }, + "created_utc": { + "type": "integer" + }, + "domain": { + "type": "string" + }, + "permalink": { + "type": "string" + }, + "post_id": { + "type": "string" + }, + "post_uid": { + "type": "string" + }, + "rank": { + "type": "integer" + }, + "snapshot_date": { + "type": "string" + }, + "subreddit": { + "type": "string" + }, + "title": { + "type": "string" + }, + "url": { + "type": "string" + } + }, + "type": "object" + }, "es.SecCompanyFacetItem": { "properties": { "count": { @@ -24750,6 +25076,12 @@ "example": 100000000, "type": "integer" }, + "more_by_developer": { + "items": { + "$ref": "#/definitions/googleplay.ListApp" + }, + "type": "array" + }, "offers_iap": { "example": true, "type": "boolean" @@ -24812,6 +25144,12 @@ }, "type": "array" }, + "similar_apps": { + "items": { + "$ref": "#/definitions/googleplay.ListApp" + }, + "type": "array" + }, "summary": { "example": "The official app by OpenAI", "type": "string" @@ -24920,6 +25258,34 @@ }, "type": "object" }, + "googleplay.DeviceRating": { + "properties": { + "device": { + "example": "phone", + "type": "string" + }, + "histogram": { + "type": "object" + }, + "ratings": { + "example": 326809, + "type": "integer" + }, + "reviews": { + "example": 8946, + "type": "integer" + }, + "score": { + "example": 4.7, + "type": "number" + }, + "score_text": { + "example": "4.7", + "type": "string" + } + }, + "type": "object" + }, "googleplay.Feature": { "properties": { "description": { @@ -24933,6 +25299,63 @@ }, "type": "object" }, + "googleplay.ListApp": { + "properties": { + "app_id": { + "example": "com.openai.chatgpt", + "type": "string" + }, + "currency": { + "example": "USD", + "type": "string" + }, + "developer": { + "example": "OpenAI", + "type": "string" + }, + "developer_id": { + "example": "7577165439232992817", + "type": "string" + }, + "free": { + "example": true, + "type": "boolean" + }, + "icon": { + "example": "https://play-lh.googleusercontent.com/lmG9HlI0awHie0cyBieWXeNjpyXvHPwDBb8MNOVIyp0P8VEh95AiBHtUZSDVR3HLe3A", + "type": "string" + }, + "price": { + "example": 0, + "type": "number" + }, + "price_text": { + "example": "FREE", + "type": "string" + }, + "score": { + "example": 4.8, + "type": "number" + }, + "score_text": { + "example": "4.8", + "type": "string" + }, + "summary": { + "example": "The official app by OpenAI", + "type": "string" + }, + "title": { + "example": "ChatGPT", + "type": "string" + }, + "url": { + "example": "https://play.google.com/store/apps/details?id=com.openai.chatgpt", + "type": "string" + } + }, + "type": "object" + }, "googleplay.Review": { "properties": { "criterias": { @@ -25132,6 +25555,25 @@ }, "type": "object" }, + "googleplay.ratingsResponseDoc": { + "properties": { + "code": { + "example": 200, + "type": "integer" + }, + "data": { + "items": { + "$ref": "#/definitions/googleplay.DeviceRating" + }, + "type": "array" + }, + "msg": { + "example": "OK", + "type": "string" + } + }, + "type": "object" + }, "googleplay.reviewsResponseDoc": { "properties": { "code": { @@ -39399,6 +39841,9 @@ "author": { "$ref": "#/definitions/reddit.Author" }, + "award_count": { + "type": "integer" + }, "body": { "example": "I agree with this post.", "type": "string" @@ -39451,6 +39896,9 @@ }, "type": "array" }, + "metrics_source": { + "$ref": "#/definitions/reddit.SourceDetail" + }, "post": { "$ref": "#/definitions/reddit.Post" }, @@ -39542,6 +39990,9 @@ "author": { "$ref": "#/definitions/reddit.Author" }, + "award_count": { + "type": "integer" + }, "comment_count": { "type": "integer" }, @@ -39557,6 +40008,12 @@ "example": "self.OpenAI", "type": "string" }, + "estimated_downvotes": { + "type": "integer" + }, + "estimated_upvotes": { + "type": "integer" + }, "flair": { "example": "Discussion", "type": "string" @@ -39617,12 +40074,18 @@ "url": { "example": "https://www.reddit.com/r/OpenAI/comments/1abcxyz/openai_discussion_thread/", "type": "string" + }, + "vote_counts_estimated": { + "type": "boolean" } }, "type": "object" }, "reddit.PostResponse": { "properties": { + "metrics_source": { + "$ref": "#/definitions/reddit.SourceDetail" + }, "post": { "$ref": "#/definitions/reddit.Post" }, @@ -76885,170 +77348,591 @@ "ApiKeyAuth": [] } ], - "summary": "Get a US housing market record from the dataset", + "summary": "Get a US housing market record from the dataset", + "tags": [ + "Datasets" + ] + } + }, + "/datasets/housing-markets/search": { + "get": { + "consumes": [ + "application/json" + ], + "description": "Searches monthly Redfin housing-market statistics per region and property type since 2012, joined to Census ACS income for affordability metrics. region_type enum: `national`, `metro`, `county`, `city`, `zip`. property_type enum: `All Residential`, `Single Family Residential`, `Condo/Co-op`, `Townhouse`, `Multi-Family (2-4 Unit)`, `Single Units Only`. Sort enum: `relevance`, `price_desc`, `price_asc`, `list_price_desc`, `list_price_asc`, `price_to_income_desc`, `price_to_income_asc`, `salary_to_buy_desc`, `salary_to_buy_asc`, `dom_asc`, `dom_desc`, `inventory_desc`, `homes_sold_desc`, `period_desc`. Use `latest=true` for the most recent period per region series.", + "operationId": "datasets-housing-markets-search", + "parameters": [ + { + "description": "Full-text query over region name and city, max 256 characters", + "in": "query", + "name": "q", + "type": "string" + }, + { + "description": "Region level enum: national, metro, county, city, zip", + "enum": [ + "national", + "metro", + "county", + "city", + "zip" + ], + "in": "query", + "name": "region_type", + "type": "string" + }, + { + "description": "Exact two-letter state code filter, e.g. CA", + "in": "query", + "name": "state_code", + "type": "string" + }, + { + "description": "Property type enum: All Residential, Single Family Residential, Condo/Co-op, Townhouse, Multi-Family (2-4 Unit), Single Units Only", + "in": "query", + "name": "property_type", + "type": "string" + }, + { + "description": "Exact parent metro (CBSA) code filter, e.g. 16980", + "in": "query", + "name": "parent_metro_code", + "type": "string" + }, + { + "description": "Exact zip code filter (zip-level rows only), e.g. 60616", + "in": "query", + "name": "zip_code", + "type": "string" + }, + { + "description": "Exact period start date filter, YYYY-MM-DD", + "in": "query", + "name": "period", + "type": "string" + }, + { + "description": "Filter for the most recent period per region and property type", + "in": "query", + "name": "latest", + "type": "boolean" + }, + { + "description": "Minimum median sale price in USD", + "in": "query", + "name": "min_median_sale_price", + "type": "number" + }, + { + "description": "Maximum median sale price in USD", + "in": "query", + "name": "max_median_sale_price", + "type": "number" + }, + { + "description": "Minimum median list price in USD", + "in": "query", + "name": "min_median_list_price", + "type": "number" + }, + { + "description": "Maximum median list price in USD", + "in": "query", + "name": "max_median_list_price", + "type": "number" + }, + { + "description": "Minimum price-to-income ratio", + "in": "query", + "name": "min_price_to_income", + "type": "number" + }, + { + "description": "Maximum price-to-income ratio", + "in": "query", + "name": "max_price_to_income", + "type": "number" + }, + { + "description": "Minimum salary needed to buy in USD per year", + "in": "query", + "name": "min_salary_to_buy", + "type": "integer" + }, + { + "description": "Maximum salary needed to buy in USD per year", + "in": "query", + "name": "max_salary_to_buy", + "type": "integer" + }, + { + "description": "Minimum median days on market", + "in": "query", + "name": "min_median_dom", + "type": "number" + }, + { + "description": "Maximum median days on market", + "in": "query", + "name": "max_median_dom", + "type": "number" + }, + { + "description": "Minimum active inventory", + "in": "query", + "name": "min_inventory", + "type": "integer" + }, + { + "description": "Maximum active inventory", + "in": "query", + "name": "max_inventory", + "type": "integer" + }, + { + "description": "Minimum homes sold in the period", + "in": "query", + "name": "min_homes_sold", + "type": "integer" + }, + { + "description": "Sort enum: relevance, price_desc, price_asc, list_price_desc, list_price_asc, price_to_income_desc, price_to_income_asc, salary_to_buy_desc, salary_to_buy_asc, dom_asc, dom_desc, inventory_desc, homes_sold_desc, period_desc", + "enum": [ + "relevance", + "price_desc", + "price_asc", + "list_price_desc", + "list_price_asc", + "price_to_income_desc", + "price_to_income_asc", + "salary_to_buy_desc", + "salary_to_buy_asc", + "dom_asc", + "dom_desc", + "inventory_desc", + "homes_sold_desc", + "period_desc" + ], + "in": "query", + "name": "sort", + "type": "string" + }, + { + "description": "Page number, defaults to 1", + "in": "query", + "name": "page", + "type": "integer" + }, + { + "description": "Page size, defaults to 20 and maxes at 100; page * page_size must be <= 10000", + "in": "query", + "name": "page_size", + "type": "integer" + } + ], + "produces": [ + "application/json" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/datasets.housingMarketsSearchResponseDoc" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/app.Response" + } + }, + "429": { + "description": "Too Many Requests", + "schema": { + "$ref": "#/definitions/app.Response" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/app.Response" + } + } + }, + "security": [ + { + "ApiKeyAuth": [] + } + ], + "summary": "Search the US housing markets dataset", + "tags": [ + "Datasets" + ] + } + }, + "/datasets/instagram-users/facets": { + "get": { + "consumes": [ + "application/json" + ], + "description": "Returns terms aggregation counts for the Instagram users dataset. Facet enum: `is_verified`, `is_business_account`, `has_bio`, `has_external_url`, `category_name`, `source_tier`.", + "operationId": "datasets-instagram-users-facets", + "parameters": [ + { + "description": "Facet enum: is_verified, is_business_account, has_bio, has_external_url, category_name, source_tier", + "enum": [ + "is_verified", + "is_business_account", + "has_bio", + "has_external_url", + "category_name", + "source_tier" + ], + "in": "query", + "name": "facet", + "required": true, + "type": "string" + }, + { + "description": "Full-text query over username, full_name and biography, max 256 characters", + "in": "query", + "name": "q", + "type": "string" + }, + { + "description": "Exact username filter (case-insensitive), max 128 characters", + "in": "query", + "name": "username", + "type": "string" + }, + { + "description": "Exact category filter (case-insensitive, e.g. Digital Creator), max 128 characters", + "in": "query", + "name": "category_name", + "type": "string" + }, + { + "description": "Exact filter for seed tier (e.g. crossref, vertical-hashtags, mention-graph, head-directory)", + "in": "query", + "name": "source_tier", + "type": "string" + }, + { + "description": "Filter by the Instagram verification checkmark", + "in": "query", + "name": "is_verified", + "type": "boolean" + }, + { + "description": "Filter by business or creator accounts", + "in": "query", + "name": "is_business_account", + "type": "boolean" + }, + { + "description": "Filter by a non-empty profile biography", + "in": "query", + "name": "has_bio", + "type": "boolean" + }, + { + "description": "Filter by a linked external URL", + "in": "query", + "name": "has_external_url", + "type": "boolean" + }, + { + "description": "Minimum follower count", + "in": "query", + "name": "min_followers", + "type": "integer" + }, + { + "description": "Maximum follower count", + "in": "query", + "name": "max_followers", + "type": "integer" + }, + { + "description": "Minimum follower-to-following ratio", + "in": "query", + "name": "min_ratio", + "type": "number" + }, + { + "description": "Maximum follower-to-following ratio", + "in": "query", + "name": "max_ratio", + "type": "number" + }, + { + "description": "Accounts created on or after this date (RFC3339 or YYYY-MM-DD)", + "in": "query", + "name": "created_after", + "type": "string" + }, + { + "description": "Accounts created on or before this date (RFC3339 or YYYY-MM-DD)", + "in": "query", + "name": "created_before", + "type": "string" + }, + { + "description": "Records last refreshed on or after this date (RFC3339 or YYYY-MM-DD)", + "in": "query", + "name": "crawled_after", + "type": "string" + }, + { + "description": "Records last refreshed on or before this date (RFC3339 or YYYY-MM-DD)", + "in": "query", + "name": "crawled_before", + "type": "string" + }, + { + "description": "Sort enum: relevance, followers_desc, followers_asc, crawled_at_desc, crawled_at_asc, created_at_desc, created_at_asc", + "enum": [ + "relevance", + "followers_desc", + "followers_asc", + "crawled_at_desc", + "crawled_at_asc", + "created_at_desc", + "created_at_asc" + ], + "in": "query", + "name": "sort", + "type": "string" + }, + { + "description": "Page number, defaults to 1", + "in": "query", + "name": "page", + "type": "integer" + }, + { + "description": "Page size, defaults to 20 and maxes at 100; page * page_size must be <= 10000", + "in": "query", + "name": "page_size", + "type": "integer" + } + ], + "produces": [ + "application/json" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/datasets.instagramUsersFacetResponseDoc" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/app.Response" + } + }, + "429": { + "description": "Too Many Requests", + "schema": { + "$ref": "#/definitions/app.Response" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/app.Response" + } + } + }, + "security": [ + { + "ApiKeyAuth": [] + } + ], + "summary": "Facet the Instagram users dataset", + "tags": [ + "Datasets" + ] + } + }, + "/datasets/instagram-users/items/{username}": { + "get": { + "consumes": [ + "application/json" + ], + "description": "Returns one Instagram user record by username from dataset id enum value `instagram-users`.", + "operationId": "datasets-instagram-users-item", + "parameters": [ + { + "description": "Instagram username, with or without a leading @, max 128 characters", + "in": "path", + "name": "username", + "required": true, + "type": "string" + } + ], + "produces": [ + "application/json" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/datasets.instagramUserResponseDoc" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/app.Response" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/app.Response" + } + }, + "429": { + "description": "Too Many Requests", + "schema": { + "$ref": "#/definitions/app.Response" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/app.Response" + } + } + }, + "security": [ + { + "ApiKeyAuth": [] + } + ], + "summary": "Get an Instagram user from the dataset", "tags": [ "Datasets" ] } }, - "/datasets/housing-markets/search": { + "/datasets/instagram-users/search": { "get": { "consumes": [ "application/json" ], - "description": "Searches monthly Redfin housing-market statistics per region and property type since 2012, joined to Census ACS income for affordability metrics. region_type enum: `national`, `metro`, `county`, `city`, `zip`. property_type enum: `All Residential`, `Single Family Residential`, `Condo/Co-op`, `Townhouse`, `Multi-Family (2-4 Unit)`, `Single Units Only`. Sort enum: `relevance`, `price_desc`, `price_asc`, `list_price_desc`, `list_price_asc`, `price_to_income_desc`, `price_to_income_asc`, `salary_to_buy_desc`, `salary_to_buy_asc`, `dom_asc`, `dom_desc`, `inventory_desc`, `homes_sold_desc`, `period_desc`. Use `latest=true` for the most recent period per region series.", - "operationId": "datasets-housing-markets-search", + "description": "Searches public Instagram user profiles stored in a search index. Sort enum: `relevance`, `followers_desc`, `followers_asc`, `crawled_at_desc`, `crawled_at_asc`, `created_at_desc`, `created_at_asc`.", + "operationId": "datasets-instagram-users-search", "parameters": [ { - "description": "Full-text query over region name and city, max 256 characters", + "description": "Full-text query over username, full_name and biography, max 256 characters", "in": "query", "name": "q", "type": "string" }, { - "description": "Region level enum: national, metro, county, city, zip", - "enum": [ - "national", - "metro", - "county", - "city", - "zip" - ], - "in": "query", - "name": "region_type", - "type": "string" - }, - { - "description": "Exact two-letter state code filter, e.g. CA", - "in": "query", - "name": "state_code", - "type": "string" - }, - { - "description": "Property type enum: All Residential, Single Family Residential, Condo/Co-op, Townhouse, Multi-Family (2-4 Unit), Single Units Only", - "in": "query", - "name": "property_type", - "type": "string" - }, - { - "description": "Exact parent metro (CBSA) code filter, e.g. 16980", + "description": "Exact username filter (case-insensitive), max 128 characters", "in": "query", - "name": "parent_metro_code", + "name": "username", "type": "string" }, { - "description": "Exact zip code filter (zip-level rows only), e.g. 60616", + "description": "Exact category filter (case-insensitive, e.g. Digital Creator), max 128 characters", "in": "query", - "name": "zip_code", + "name": "category_name", "type": "string" }, { - "description": "Exact period start date filter, YYYY-MM-DD", + "description": "Exact filter for seed tier (e.g. crossref, vertical-hashtags, mention-graph, head-directory), max 128 characters", "in": "query", - "name": "period", + "name": "source_tier", "type": "string" }, { - "description": "Filter for the most recent period per region and property type", + "description": "Filter by the Instagram verification checkmark", "in": "query", - "name": "latest", + "name": "is_verified", "type": "boolean" }, { - "description": "Minimum median sale price in USD", - "in": "query", - "name": "min_median_sale_price", - "type": "number" - }, - { - "description": "Maximum median sale price in USD", - "in": "query", - "name": "max_median_sale_price", - "type": "number" - }, - { - "description": "Minimum median list price in USD", + "description": "Filter by business or creator accounts", "in": "query", - "name": "min_median_list_price", - "type": "number" + "name": "is_business_account", + "type": "boolean" }, { - "description": "Maximum median list price in USD", + "description": "Filter by a non-empty profile biography", "in": "query", - "name": "max_median_list_price", - "type": "number" + "name": "has_bio", + "type": "boolean" }, { - "description": "Minimum price-to-income ratio", + "description": "Filter by a linked external URL", "in": "query", - "name": "min_price_to_income", - "type": "number" + "name": "has_external_url", + "type": "boolean" }, { - "description": "Maximum price-to-income ratio", + "description": "Minimum follower count", "in": "query", - "name": "max_price_to_income", - "type": "number" + "name": "min_followers", + "type": "integer" }, { - "description": "Minimum salary needed to buy in USD per year", + "description": "Maximum follower count", "in": "query", - "name": "min_salary_to_buy", + "name": "max_followers", "type": "integer" }, { - "description": "Maximum salary needed to buy in USD per year", + "description": "Minimum follower-to-following ratio", "in": "query", - "name": "max_salary_to_buy", - "type": "integer" + "name": "min_ratio", + "type": "number" }, { - "description": "Minimum median days on market", + "description": "Maximum follower-to-following ratio", "in": "query", - "name": "min_median_dom", + "name": "max_ratio", "type": "number" }, { - "description": "Maximum median days on market", + "description": "Accounts created on or after this date (RFC3339 or YYYY-MM-DD)", "in": "query", - "name": "max_median_dom", - "type": "number" + "name": "created_after", + "type": "string" }, { - "description": "Minimum active inventory", + "description": "Accounts created on or before this date (RFC3339 or YYYY-MM-DD)", "in": "query", - "name": "min_inventory", - "type": "integer" + "name": "created_before", + "type": "string" }, { - "description": "Maximum active inventory", + "description": "Records last refreshed on or after this date (RFC3339 or YYYY-MM-DD)", "in": "query", - "name": "max_inventory", - "type": "integer" + "name": "crawled_after", + "type": "string" }, { - "description": "Minimum homes sold in the period", + "description": "Records last refreshed on or before this date (RFC3339 or YYYY-MM-DD)", "in": "query", - "name": "min_homes_sold", - "type": "integer" + "name": "crawled_before", + "type": "string" }, { - "description": "Sort enum: relevance, price_desc, price_asc, list_price_desc, list_price_asc, price_to_income_desc, price_to_income_asc, salary_to_buy_desc, salary_to_buy_asc, dom_asc, dom_desc, inventory_desc, homes_sold_desc, period_desc", + "description": "Sort enum: relevance, followers_desc, followers_asc, crawled_at_desc, crawled_at_asc, created_at_desc, created_at_asc", "enum": [ "relevance", - "price_desc", - "price_asc", - "list_price_desc", - "list_price_asc", - "price_to_income_desc", - "price_to_income_asc", - "salary_to_buy_desc", - "salary_to_buy_asc", - "dom_asc", - "dom_desc", - "inventory_desc", - "homes_sold_desc", - "period_desc" + "followers_desc", + "followers_asc", + "crawled_at_desc", + "crawled_at_asc", + "created_at_desc", + "created_at_asc" ], "in": "query", "name": "sort", @@ -77074,7 +77958,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/datasets.housingMarketsSearchResponseDoc" + "$ref": "#/definitions/datasets.instagramUsersSearchResponseDoc" } }, "400": { @@ -77101,7 +77985,7 @@ "ApiKeyAuth": [] } ], - "summary": "Search the US housing markets dataset", + "summary": "Search the Instagram users dataset", "tags": [ "Datasets" ] @@ -80957,36 +81841,181 @@ "ApiKeyAuth": [] } ], - "summary": "Get a Product Hunt product from the dataset", + "summary": "Get a Product Hunt product from the dataset", + "tags": [ + "Datasets" + ] + } + }, + "/datasets/producthunt-products/search": { + "get": { + "consumes": [ + "application/json" + ], + "description": "Searches individual Product Hunt launches from the dataset id enum value `producthunt-products` — the searchable launch archive. Each result is one product with its topics, upvotes, ranks and launch history; description/website/twitter_url/pricing/makers are filled in as hydration runs. Sort enum: `relevance`, `votes_desc`, `launched_desc`, `launched_asc`, `rating_desc`, `best_rank_asc`.", + "operationId": "datasets-producthunt-products-search", + "parameters": [ + { + "description": "Full-text query over product name and tagline, max 256 characters", + "in": "query", + "name": "q", + "type": "string" + }, + { + "description": "Exact topic-slug filter, e.g. artificial-intelligence, max 128 characters", + "in": "query", + "name": "topic", + "type": "string" + }, + { + "description": "Exact maker-username filter (populated by hydration), max 128 characters", + "in": "query", + "name": "maker", + "type": "string" + }, + { + "description": "Lower bound on first-launch date, an ISO-8601 date (YYYY-MM-DD)", + "in": "query", + "name": "launched_after", + "type": "string" + }, + { + "description": "Upper bound on first-launch date, an ISO-8601 date (YYYY-MM-DD)", + "in": "query", + "name": "launched_before", + "type": "string" + }, + { + "description": "Minimum upvotes, 0 or greater", + "in": "query", + "name": "min_votes", + "type": "integer" + }, + { + "description": "Minimum review rating, from 0 through 5 (populated by hydration)", + "in": "query", + "name": "min_rating", + "type": "number" + }, + { + "description": "Exact pricing-type filter (populated by hydration), e.g. free, paid, freemium", + "in": "query", + "name": "pricing_type", + "type": "string" + }, + { + "description": "Website presence filter (populated by hydration)", + "in": "query", + "name": "has_website", + "type": "boolean" + }, + { + "description": "true keeps only products still online, false only retired products", + "in": "query", + "name": "is_online", + "type": "boolean" + }, + { + "description": "Sort enum: relevance, votes_desc, launched_desc, launched_asc, rating_desc, best_rank_asc", + "enum": [ + "relevance", + "votes_desc", + "launched_desc", + "launched_asc", + "rating_desc", + "best_rank_asc" + ], + "in": "query", + "name": "sort", + "type": "string" + }, + { + "description": "Page number, defaults to 1", + "in": "query", + "name": "page", + "type": "integer" + }, + { + "description": "Page size, defaults to 20 and maxes at 100; page * page_size must be <= 10000", + "in": "query", + "name": "page_size", + "type": "integer" + } + ], + "produces": [ + "application/json" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/datasets.producthuntProductsSearchResponseDoc" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/app.Response" + } + }, + "429": { + "description": "Too Many Requests", + "schema": { + "$ref": "#/definitions/app.Response" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/app.Response" + } + } + }, + "security": [ + { + "ApiKeyAuth": [] + } + ], + "summary": "Search the Product Hunt products dataset", "tags": [ "Datasets" ] } }, - "/datasets/producthunt-products/search": { + "/datasets/producthunt-trends/facets": { "get": { "consumes": [ "application/json" ], - "description": "Searches individual Product Hunt launches from the dataset id enum value `producthunt-products` — the searchable launch archive. Each result is one product with its topics, upvotes, ranks and launch history; description/website/twitter_url/pricing/makers are filled in as hydration runs. Sort enum: `relevance`, `votes_desc`, `launched_desc`, `launched_asc`, `rating_desc`, `best_rank_asc`.", - "operationId": "datasets-producthunt-products-search", + "description": "Returns suppressed distribution counts over the Product Hunt trends dataset (dataset id enum value `producthunt-trends`), honoring the same filters as search. Facet enum: `topic`, `launch_year`.", + "operationId": "datasets-producthunt-trends-facets", "parameters": [ { - "description": "Full-text query over product name and tagline, max 256 characters", + "description": "Facet enum: topic, launch_year", + "enum": [ + "topic", + "launch_year" + ], "in": "query", - "name": "q", + "name": "facet", + "required": true, "type": "string" }, { - "description": "Exact topic-slug filter, e.g. artificial-intelligence, max 128 characters", + "description": "Aggregate cell dimension enum: topic_month, topic_year, topic. Defaults to topic_month", + "enum": [ + "topic_month", + "topic_year", + "topic" + ], "in": "query", - "name": "topic", + "name": "group_by", "type": "string" }, { - "description": "Exact maker-username filter (populated by hydration), max 128 characters", + "description": "Exact topic-slug filter, e.g. artificial-intelligence, max 128 characters", "in": "query", - "name": "maker", + "name": "topic", "type": "string" }, { @@ -81002,59 +82031,15 @@ "type": "string" }, { - "description": "Minimum upvotes, 0 or greater", + "description": "Minimum product upvotes, 0 or greater", "in": "query", "name": "min_votes", "type": "integer" }, { - "description": "Minimum review rating, from 0 through 5 (populated by hydration)", - "in": "query", - "name": "min_rating", - "type": "number" - }, - { - "description": "Exact pricing-type filter (populated by hydration), e.g. free, paid, freemium", - "in": "query", - "name": "pricing_type", - "type": "string" - }, - { - "description": "Website presence filter (populated by hydration)", - "in": "query", - "name": "has_website", - "type": "boolean" - }, - { - "description": "true keeps only products still online, false only retired products", - "in": "query", - "name": "is_online", - "type": "boolean" - }, - { - "description": "Sort enum: relevance, votes_desc, launched_desc, launched_asc, rating_desc, best_rank_asc", - "enum": [ - "relevance", - "votes_desc", - "launched_desc", - "launched_asc", - "rating_desc", - "best_rank_asc" - ], - "in": "query", - "name": "sort", - "type": "string" - }, - { - "description": "Page number, defaults to 1", - "in": "query", - "name": "page", - "type": "integer" - }, - { - "description": "Page size, defaults to 20 and maxes at 100; page * page_size must be <= 10000", + "description": "Minimum launches per bucket; raises the small-cell suppression floor", "in": "query", - "name": "page_size", + "name": "min_launches", "type": "integer" } ], @@ -81065,7 +82050,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/datasets.producthuntProductsSearchResponseDoc" + "$ref": "#/definitions/datasets.producthuntTrendsFacetResponseDoc" } }, "400": { @@ -81092,31 +82077,20 @@ "ApiKeyAuth": [] } ], - "summary": "Search the Product Hunt products dataset", + "summary": "Facet the Product Hunt trends dataset", "tags": [ "Datasets" ] } }, - "/datasets/producthunt-trends/facets": { + "/datasets/producthunt-trends/search": { "get": { "consumes": [ "application/json" ], - "description": "Returns suppressed distribution counts over the Product Hunt trends dataset (dataset id enum value `producthunt-trends`), honoring the same filters as search. Facet enum: `topic`, `launch_year`.", - "operationId": "datasets-producthunt-trends-facets", + "description": "Returns aggregate Product Hunt launch trends from the dataset id enum value `producthunt-trends`. Aggregate-only: each row is a category-over-time cell (a topic, optionally within a calendar period), reporting launch count, total and average upvotes, average rating and the top product — never an individual product record. Thin cells are suppressed. group_by enum: `topic_month`, `topic_year`, `topic`. Sort enum: `period_desc`, `period_asc`, `launch_count_desc`, `sum_votes_desc`.", + "operationId": "datasets-producthunt-trends-search", "parameters": [ - { - "description": "Facet enum: topic, launch_year", - "enum": [ - "topic", - "launch_year" - ], - "in": "query", - "name": "facet", - "required": true, - "type": "string" - }, { "description": "Aggregate cell dimension enum: topic_month, topic_year, topic. Defaults to topic_month", "enum": [ @@ -81153,10 +82127,34 @@ "type": "integer" }, { - "description": "Minimum launches per bucket; raises the small-cell suppression floor", + "description": "Minimum launches per cell; raises the small-cell suppression floor (never lowered below the built-in minimum)", "in": "query", "name": "min_launches", "type": "integer" + }, + { + "description": "Sort enum: period_desc, period_asc, launch_count_desc, sum_votes_desc", + "enum": [ + "period_desc", + "period_asc", + "launch_count_desc", + "sum_votes_desc" + ], + "in": "query", + "name": "sort", + "type": "string" + }, + { + "description": "Page number, defaults to 1", + "in": "query", + "name": "page", + "type": "integer" + }, + { + "description": "Page size, defaults to 20 and maxes at 100; page * page_size must be <= 10000", + "in": "query", + "name": "page_size", + "type": "integer" } ], "produces": [ @@ -81166,7 +82164,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/datasets.producthuntTrendsFacetResponseDoc" + "$ref": "#/definitions/datasets.producthuntTrendsSearchResponseDoc" } }, "400": { @@ -81193,68 +82191,43 @@ "ApiKeyAuth": [] } ], - "summary": "Facet the Product Hunt trends dataset", + "summary": "Search the Product Hunt trends dataset", "tags": [ "Datasets" ] } }, - "/datasets/producthunt-trends/search": { + "/datasets/reddit-trending/search": { "get": { "consumes": [ "application/json" ], - "description": "Returns aggregate Product Hunt launch trends from the dataset id enum value `producthunt-trends`. Aggregate-only: each row is a category-over-time cell (a topic, optionally within a calendar period), reporting launch count, total and average upvotes, average rating and the top product — never an individual product record. Thin cells are suppressed. group_by enum: `topic_month`, `topic_year`, `topic`. Sort enum: `period_desc`, `period_asc`, `launch_count_desc`, `sum_votes_desc`.", - "operationId": "datasets-producthunt-trends-search", + "description": "Searches daily snapshots of each tracked subreddit's hot-feed post order, stored in a search index (one document per subreddit × snapshot × rank) so history accumulates. With no `date` the latest snapshot is returned (today's trending); pair `subreddit` with `sort=date_desc` for a subreddit's trending history over time. There is no score or comment-count field — the underlying credential-free scraper does not expose vote counts, so `rank` reflects Reddit's own hot-feed order rather than a locally computed score.", + "operationId": "datasets-reddit-trending-search", "parameters": [ { - "description": "Aggregate cell dimension enum: topic_month, topic_year, topic. Defaults to topic_month", - "enum": [ - "topic_month", - "topic_year", - "topic" - ], + "description": "Full-text query over the post title, max 256 characters", "in": "query", - "name": "group_by", - "type": "string" - }, - { - "description": "Exact topic-slug filter, e.g. artificial-intelligence, max 128 characters", - "in": "query", - "name": "topic", + "name": "q", "type": "string" }, { - "description": "Lower bound on first-launch date, an ISO-8601 date (YYYY-MM-DD)", + "description": "Exact subreddit-name filter, max 128 characters", "in": "query", - "name": "launched_after", + "name": "subreddit", "type": "string" }, { - "description": "Upper bound on first-launch date, an ISO-8601 date (YYYY-MM-DD)", + "description": "Snapshot date filter yyyy-MM-dd; defaults to the latest snapshot", "in": "query", - "name": "launched_before", + "name": "date", "type": "string" }, { - "description": "Minimum product upvotes, 0 or greater", - "in": "query", - "name": "min_votes", - "type": "integer" - }, - { - "description": "Minimum launches per cell; raises the small-cell suppression floor (never lowered below the built-in minimum)", - "in": "query", - "name": "min_launches", - "type": "integer" - }, - { - "description": "Sort enum: period_desc, period_asc, launch_count_desc, sum_votes_desc", + "description": "Sort enum: rank, date_desc", "enum": [ - "period_desc", - "period_asc", - "launch_count_desc", - "sum_votes_desc" + "rank", + "date_desc" ], "in": "query", "name": "sort", @@ -81280,7 +82253,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/datasets.producthuntTrendsSearchResponseDoc" + "$ref": "#/definitions/datasets.redditTrendingSearchResponseDoc" } }, "400": { @@ -81307,7 +82280,7 @@ "ApiKeyAuth": [] } ], - "summary": "Search the Product Hunt trends dataset", + "summary": "Search the reddit-trending dataset", "tags": [ "Datasets" ] @@ -91272,7 +92245,7 @@ "consumes": [ "application/json" ], - "description": "Returns normalized app metadata from a Google Play details page, including installs, ratings, pricing, version info, developer metadata, media assets, release state, and selected user comments. Defaults: `country=us`, `lang=en`.", + "description": "Returns normalized app metadata from a Google Play details page, including installs, ratings, pricing, version info, developer metadata, media assets, release state, selected user comments, and \"More by this developer\" and \"Similar apps\" recommendation rails. For a per-device (phone/tablet/Chromebook) ratings-and-reviews breakdown, see `/googleplay/ratings`. Defaults: `country=us`, `lang=en`.", "operationId": "googleplay-app", "parameters": [ { @@ -91603,6 +92576,22 @@ "type": "string", "x-example": "TOOLS" }, + { + "description": "Google Play device tab: phone, tablet, tv, chromebook, watch, xr, car", + "enum": [ + "phone", + "tablet", + "tv", + "chromebook", + "watch", + "xr", + "car" + ], + "in": "query", + "name": "device", + "type": "string", + "x-example": "tablet" + }, { "description": "Family age range", "in": "query", @@ -91769,6 +92758,83 @@ ] } }, + "/googleplay/ratings": { + "get": { + "consumes": [ + "application/json" + ], + "description": "Returns the ratings-and-reviews breakdown Google Play shows under the details page's device tabs, one entry each for phone, tablet, and Chromebook. Defaults: `country=us`, `lang=en`.", + "operationId": "googleplay-ratings", + "parameters": [ + { + "description": "Google Play package name", + "in": "query", + "name": "app_id", + "required": true, + "type": "string", + "x-example": "com.openai.chatgpt" + }, + { + "description": "Two-letter storefront country code", + "in": "query", + "name": "country", + "type": "string", + "x-example": "us" + }, + { + "description": "Two-letter language code", + "in": "query", + "name": "lang", + "type": "string", + "x-example": "en" + } + ], + "produces": [ + "application/json" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/googleplay.ratingsResponseDoc" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/app.Response" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/app.Response" + } + }, + "429": { + "description": "Too Many Requests", + "schema": { + "$ref": "#/definitions/app.Response" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/app.Response" + } + } + }, + "security": [ + { + "ApiKeyAuth": [] + } + ], + "summary": "Get Google Play ratings by device", + "tags": [ + "GooglePlay" + ] + } + }, "/googleplay/reviews": { "get": { "consumes": [ @@ -109077,7 +110143,7 @@ "consumes": [ "application/json" ], - "description": "Returns a Reddit post with its public comments. A post that exists but has no comments yet returns a 200 response with an empty comments list; a post that does not exist returns 404, and a temporary block or upstream failure returns 503 (retryable) rather than 404. A `503` with a `Retry-After` header means Reddit is temporarily throttling the request; wait that many seconds and retry.", + "description": "Returns a Reddit post with its public comments. The default 1-credit mode uses RSS. Set `include_metrics=true` to use the anonymous HTML post page as the sole content request and return the server-rendered comments with public net score and award count plus post engagement metrics for 3 credits. Large threads may expose only an initial comment subset in anonymous HTML. Reddit does not expose per-comment upvote ratios or exact upvote/downvote totals anonymously. A post that exists but has no comments yet returns a 200 response with an empty comments list; a post that does not exist returns 404, and a temporary block or upstream failure returns 503 (retryable) rather than 404.", "operationId": "reddit-comments", "parameters": [ { @@ -109089,7 +110155,7 @@ }, { "default": "confidence", - "description": "Accepted for compatibility: confidence, top, new, controversial, old, or qa. Public comment data is flat and may ignore sort.", + "description": "Comment order: confidence, top, new, controversial, old, or qa. Applied to the anonymous HTML request when metrics are enabled.", "enum": [ "confidence", "top", @@ -109110,10 +110176,17 @@ }, { "default": 3, - "description": "Accepted for compatibility. Public comment data is flat and may ignore depth.", + "description": "Maximum flat comment depth returned in metrics mode.", "in": "query", "name": "depth", "type": "integer" + }, + { + "default": false, + "description": "Include public post and per-comment engagement metrics; costs 3 credits instead of 1", + "in": "query", + "name": "include_metrics", + "type": "boolean" } ], "produces": [ @@ -109268,7 +110341,7 @@ "consumes": [ "application/json" ], - "description": "Returns a normalized public Reddit post entry. A `503` with a `Retry-After` header means Reddit is temporarily throttling the request; wait that many seconds and retry.", + "description": "Returns a normalized public Reddit post. The default 1-credit mode uses RSS. Set `include_metrics=true` to use the anonymous HTML post page as the sole content request and return public net score, upvote ratio, comment count, award count, and estimated upvote/downvote totals for 3 credits. Reddit fuzzes voting data, so estimates are approximate; share, repost/crosspost, and view counts are not exposed anonymously.", "operationId": "reddit-post", "parameters": [ { @@ -109277,6 +110350,13 @@ "name": "id", "required": true, "type": "string" + }, + { + "default": false, + "description": "Include public engagement metrics; costs 3 credits instead of 1", + "in": "query", + "name": "include_metrics", + "type": "boolean" } ], "produces": [ diff --git a/pyproject.toml b/pyproject.toml index 162ba39..458d562 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "crawlora" -version = "1.25.0.dev1" +version = "1.26.0.dev1" description = "Official Python SDK for the Crawlora web-scraping API: typed grouped and dynamic operation calls for every public endpoint, with retries, pagination, hooks, and an async client." readme = "README.md" requires-python = ">=3.10" diff --git a/tests/test_client.py b/tests/test_client.py index ed68a8e..908dd53 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -267,7 +267,7 @@ def transport(_request, _timeout): self.assertIs(raised.exception.__cause__, cause) def test_operation_metadata_count(self): - self.assertEqual(OPERATION_COUNT, 832) + self.assertEqual(OPERATION_COUNT, 837) def test_deprecated_endpoints_are_not_generated(self): self.assertFalse(hasattr(CrawloraClient(api_key="api_test", base_url=self.base_url).google, "lens")) @@ -296,7 +296,7 @@ def test_docs_cover_operations_and_recipes(self): recipes_doc = root.joinpath("docs", "recipes.md").read_text() for expected in [ - "Total operations: `832`", + "Total operations: `837`", "`bing-search`", "`GET /bing/search`", "`bing.search`",