From 061b1e27385b033eb8966ebf8a02815b7dde26e4 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 15 May 2026 04:01:02 +0000 Subject: [PATCH 01/12] fix(api): move RawScraperError to shared types --- .stats.yml | 4 ++-- api.md | 3 +-- src/influship/types/__init__.py | 2 +- src/influship/types/raw/__init__.py | 1 - src/influship/types/raw/instagram_get_posts_response.py | 2 +- src/influship/types/raw/instagram_get_transcripts_response.py | 2 +- src/influship/types/shared/__init__.py | 1 + src/influship/types/{raw => shared}/raw_scraper_error.py | 0 8 files changed, 7 insertions(+), 8 deletions(-) rename src/influship/types/{raw => shared}/raw_scraper_error.py (100%) diff --git a/.stats.yml b/.stats.yml index 9671093..403376c 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 19 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/inf-labs/influship-api-3a7359b6f1bc29e6ba39142f71e31055407138bc92aac108c9de72dc3b0604a5.yml +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/inf-labs/influship-api-c2ab51fadef78fb9ff5c0da3a457f41e7393271cc686679d6a57ef4994a8abe1.yml openapi_spec_hash: b5814219a0ab7727c3571b1bbfc14ce3 -config_hash: 32cf7a70e5eb35a8bead35d220e1eedb +config_hash: b5ad949b042c744292f5af283a1e54bd diff --git a/api.md b/api.md index b7922bf..c7d313f 100644 --- a/api.md +++ b/api.md @@ -1,7 +1,7 @@ # Shared Types ```python -from influship.types import CreatorBasic, ProfileSummary +from influship.types import CreatorBasic, ProfileSummary, RawScraperError ``` # Health @@ -91,7 +91,6 @@ Types: from influship.types.raw import ( InstagramSinglePostResponse, InstagramTranscriptResponse, - RawScraperError, InstagramGetPostResponse, InstagramGetPostsResponse, InstagramGetProfileResponse, diff --git a/src/influship/types/__init__.py b/src/influship/types/__init__.py index 88a1500..0afe204 100644 --- a/src/influship/types/__init__.py +++ b/src/influship/types/__init__.py @@ -2,7 +2,7 @@ from __future__ import annotations -from .shared import CreatorBasic as CreatorBasic, ProfileSummary as ProfileSummary +from .shared import CreatorBasic as CreatorBasic, ProfileSummary as ProfileSummary, RawScraperError as RawScraperError from .match_info import MatchInfo as MatchInfo from .profile_growth import ProfileGrowth as ProfileGrowth from .profile_metrics import ProfileMetrics as ProfileMetrics diff --git a/src/influship/types/raw/__init__.py b/src/influship/types/raw/__init__.py index 2afb1d6..aa51c72 100644 --- a/src/influship/types/raw/__init__.py +++ b/src/influship/types/raw/__init__.py @@ -2,7 +2,6 @@ from __future__ import annotations -from .raw_scraper_error import RawScraperError as RawScraperError from .transcript_segment import TranscriptSegment as TranscriptSegment from .youtube_search_params import YoutubeSearchParams as YoutubeSearchParams from .youtube_search_response import YoutubeSearchResponse as YoutubeSearchResponse diff --git a/src/influship/types/raw/instagram_get_posts_response.py b/src/influship/types/raw/instagram_get_posts_response.py index 18e9d0d..31dc28c 100644 --- a/src/influship/types/raw/instagram_get_posts_response.py +++ b/src/influship/types/raw/instagram_get_posts_response.py @@ -5,7 +5,7 @@ from typing_extensions import Literal, TypeAlias from ..._models import BaseModel -from .raw_scraper_error import RawScraperError +from ..shared.raw_scraper_error import RawScraperError from .instagram_single_post_response import InstagramSinglePostResponse __all__ = [ diff --git a/src/influship/types/raw/instagram_get_transcripts_response.py b/src/influship/types/raw/instagram_get_transcripts_response.py index d82bb35..bfc7e9d 100644 --- a/src/influship/types/raw/instagram_get_transcripts_response.py +++ b/src/influship/types/raw/instagram_get_transcripts_response.py @@ -5,7 +5,7 @@ from typing_extensions import Literal, TypeAlias from ..._models import BaseModel -from .raw_scraper_error import RawScraperError +from ..shared.raw_scraper_error import RawScraperError from .instagram_transcript_response import InstagramTranscriptResponse __all__ = [ diff --git a/src/influship/types/shared/__init__.py b/src/influship/types/shared/__init__.py index 7e07f42..4d440b3 100644 --- a/src/influship/types/shared/__init__.py +++ b/src/influship/types/shared/__init__.py @@ -2,3 +2,4 @@ from .creator_basic import CreatorBasic as CreatorBasic from .profile_summary import ProfileSummary as ProfileSummary +from .raw_scraper_error import RawScraperError as RawScraperError diff --git a/src/influship/types/raw/raw_scraper_error.py b/src/influship/types/shared/raw_scraper_error.py similarity index 100% rename from src/influship/types/raw/raw_scraper_error.py rename to src/influship/types/shared/raw_scraper_error.py From 9d881aadfbbc7d742d739042a96c973a9824573f Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 15 May 2026 06:05:55 +0000 Subject: [PATCH 02/12] docs(api): update instagram method docstrings --- .stats.yml | 4 +-- src/influship/resources/raw/instagram.py | 34 +++++++----------------- 2 files changed, 12 insertions(+), 26 deletions(-) diff --git a/.stats.yml b/.stats.yml index 403376c..1612c8e 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 19 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/inf-labs/influship-api-c2ab51fadef78fb9ff5c0da3a457f41e7393271cc686679d6a57ef4994a8abe1.yml -openapi_spec_hash: b5814219a0ab7727c3571b1bbfc14ce3 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/inf-labs/influship-api-f7979663b382b11aa243f1d27bb3f30d505df1ce71f1808fd2468b0377e6a486.yml +openapi_spec_hash: a64a5b76be4336ab9ca0a951e8046957 config_hash: b5ad949b042c744292f5af283a1e54bd diff --git a/src/influship/resources/raw/instagram.py b/src/influship/resources/raw/instagram.py index decb1e2..3bc63de 100644 --- a/src/influship/resources/raw/instagram.py +++ b/src/influship/resources/raw/instagram.py @@ -73,8 +73,8 @@ def get_post( product mentions, music attribution, location, display resources, and video versions. - **Note:** These fields are only guaranteed on this raw single-post lookup for - now. Regular cached post-list endpoints may not include them yet. + **Note:** These fields are only guaranteed on this raw single-post lookup. + Cached post-list endpoints may not include them. **Pricing**: 1 credit per post scraped ($0.01) @@ -218,12 +218,7 @@ def get_transcript( ) -> InstagramGetTranscriptResponse: """ Transcribe an Instagram video post by shortcode and return the raw post-page - data used for transcription. For now this raw endpoint retranscribes every - request and piggybacks the post plus transcript into our database when the owner - account exists. - - **Note:** Cached transcript reads are a planned follow-up; public pricing stays - the same for live and cached transcript delivery. + data used for transcription. **Pricing**: 5 credits per transcript ($0.05) @@ -273,10 +268,8 @@ def get_transcripts( item per requested shortcode with per-item success or error details. Successful items include the raw post-page data used for transcription. - **Note:** Batch transcription is capped at 10 shortcodes per request, - retranscribes every request for now, and is charged for every requested - shortcode. Cached transcript reads are a planned follow-up; public pricing stays - the same for live and cached transcript delivery. + **Note:** Batch transcription is capped at 10 shortcodes per request and is + charged for every requested shortcode. **Pricing**: 5 credits per transcript ($0.05) @@ -352,8 +345,8 @@ async def get_post( product mentions, music attribution, location, display resources, and video versions. - **Note:** These fields are only guaranteed on this raw single-post lookup for - now. Regular cached post-list endpoints may not include them yet. + **Note:** These fields are only guaranteed on this raw single-post lookup. + Cached post-list endpoints may not include them. **Pricing**: 1 credit per post scraped ($0.01) @@ -499,12 +492,7 @@ async def get_transcript( ) -> InstagramGetTranscriptResponse: """ Transcribe an Instagram video post by shortcode and return the raw post-page - data used for transcription. For now this raw endpoint retranscribes every - request and piggybacks the post plus transcript into our database when the owner - account exists. - - **Note:** Cached transcript reads are a planned follow-up; public pricing stays - the same for live and cached transcript delivery. + data used for transcription. **Pricing**: 5 credits per transcript ($0.05) @@ -554,10 +542,8 @@ async def get_transcripts( item per requested shortcode with per-item success or error details. Successful items include the raw post-page data used for transcription. - **Note:** Batch transcription is capped at 10 shortcodes per request, - retranscribes every request for now, and is charged for every requested - shortcode. Cached transcript reads are a planned follow-up; public pricing stays - the same for live and cached transcript delivery. + **Note:** Batch transcription is capped at 10 shortcodes per request and is + charged for every requested shortcode. **Pricing**: 5 credits per transcript ($0.05) From 8c8a2af99ae7c0e79e4c96401e2f21a850c71b41 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 15 May 2026 07:04:08 +0000 Subject: [PATCH 03/12] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 1612c8e..ba01414 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 19 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/inf-labs/influship-api-f7979663b382b11aa243f1d27bb3f30d505df1ce71f1808fd2468b0377e6a486.yml +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/inf-labs/influship-api-485e410cd6fe9928531dafb60e958309e8ab5df20a6e5e334fabe5c21d488cee.yml openapi_spec_hash: a64a5b76be4336ab9ca0a951e8046957 -config_hash: b5ad949b042c744292f5af283a1e54bd +config_hash: 966d29acec6f22dbfc8ebd2b82e4b3c6 From 7a89dc4774dfd5bd2e2ac9cd07156082262e2bab Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 15 May 2026 16:46:08 +0000 Subject: [PATCH 04/12] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index ba01414..cd8c69d 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 19 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/inf-labs/influship-api-485e410cd6fe9928531dafb60e958309e8ab5df20a6e5e334fabe5c21d488cee.yml +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/inf-labs/influship-api-07cf00b55db1b29b29f464b01abf56a7969c674c9ced8d304c00f55654cdbf64.yml openapi_spec_hash: a64a5b76be4336ab9ca0a951e8046957 -config_hash: 966d29acec6f22dbfc8ebd2b82e4b3c6 +config_hash: 53ef2d006f4f4d6f594b1dad6822f9e6 From 6dff17264841521a2f66619d47db3cea1a4143b1 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 15 May 2026 16:47:03 +0000 Subject: [PATCH 05/12] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index cd8c69d..fa1d2ac 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 19 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/inf-labs/influship-api-07cf00b55db1b29b29f464b01abf56a7969c674c9ced8d304c00f55654cdbf64.yml +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/inf-labs/influship-api-5ecf9344fde7d2917b33a013d400cbe3b8fc724b67e2ec3b1b981a6e9952f456.yml openapi_spec_hash: a64a5b76be4336ab9ca0a951e8046957 -config_hash: 53ef2d006f4f4d6f594b1dad6822f9e6 +config_hash: c98b7c9708fc0ee48d8b8170de41d163 From 6619d0b5fb3471804bb159a9ed55bc7eb32cba85 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 21 May 2026 23:05:45 +0000 Subject: [PATCH 06/12] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index fa1d2ac..dcee06c 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 19 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/inf-labs/influship-api-5ecf9344fde7d2917b33a013d400cbe3b8fc724b67e2ec3b1b981a6e9952f456.yml -openapi_spec_hash: a64a5b76be4336ab9ca0a951e8046957 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/inf-labs/influship-api-054b02bcedc6386e08d10961c2666007f205ab5690ff03ef5edb59c8d4a00fe8.yml +openapi_spec_hash: 176d6848a8602e7977797ee83ff6122d config_hash: c98b7c9708fc0ee48d8b8170de41d163 From 72b71e36366b017314942b78436a0ea6e7fd1e24 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 27 May 2026 19:52:40 +0000 Subject: [PATCH 07/12] feat: honest cached /v1/posts video URLs + transcript read-through cache + discovery seeding --- .stats.yml | 4 +-- src/influship/resources/raw/instagram.py | 22 +++++++++++++ src/influship/types/post_list_response.py | 32 +++++++++++++++---- .../raw/instagram_transcript_response.py | 4 +-- 4 files changed, 52 insertions(+), 10 deletions(-) diff --git a/.stats.yml b/.stats.yml index dcee06c..7932d2a 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 19 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/inf-labs/influship-api-054b02bcedc6386e08d10961c2666007f205ab5690ff03ef5edb59c8d4a00fe8.yml -openapi_spec_hash: 176d6848a8602e7977797ee83ff6122d +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/inf-labs/influship-api-217c47eef43dd430e5bf8aa6445da278c0dca6ac39e33d2e5e7a0fecef1b7991.yml +openapi_spec_hash: c26a6ce3ddc0faa13be8c0600a5ae0af config_hash: c98b7c9708fc0ee48d8b8170de41d163 diff --git a/src/influship/resources/raw/instagram.py b/src/influship/resources/raw/instagram.py index 3bc63de..29e1e65 100644 --- a/src/influship/resources/raw/instagram.py +++ b/src/influship/resources/raw/instagram.py @@ -76,6 +76,10 @@ def get_post( **Note:** These fields are only guaranteed on this raw single-post lookup. Cached post-list endpoints may not include them. + Returns fresh `video_url` (single best stream) and `video_versions[]` + (multi-bitrate). These are signed Instagram CDN URLs valid for ~24h — download + promptly. For carousels with embedded videos, see `carousel_items[].video_url`. + **Pricing**: 1 credit per post scraped ($0.01) Args: @@ -118,6 +122,9 @@ def get_posts( **Note:** Batch post lookup is capped at 20 shortcodes per request and is charged for every requested shortcode. + Returns fresh `video_url` and `video_versions[]` per post (signed IG CDN URLs, + ~24h validity). Batch up to 20 posts at 1 credit ($0.01) each. + **Pricing**: 1 credit per post scraped ($0.01) Args: @@ -167,6 +174,10 @@ def get_profile( **Note:** Live scraping is slower than cached data (2-5 seconds) and costs more. Use cached endpoints when freshness isn't critical. + The `posts[]` array returns up to 12 recent posts with fresh `video_url` for + each video post. This is the cheapest bulk-download path: 0.5 credits ($0.005) + per profile call vs 1 credit per individual raw-post call. + **Pricing**: 0.5 credits per profile scraped ($0.005) Args: @@ -348,6 +359,10 @@ async def get_post( **Note:** These fields are only guaranteed on this raw single-post lookup. Cached post-list endpoints may not include them. + Returns fresh `video_url` (single best stream) and `video_versions[]` + (multi-bitrate). These are signed Instagram CDN URLs valid for ~24h — download + promptly. For carousels with embedded videos, see `carousel_items[].video_url`. + **Pricing**: 1 credit per post scraped ($0.01) Args: @@ -390,6 +405,9 @@ async def get_posts( **Note:** Batch post lookup is capped at 20 shortcodes per request and is charged for every requested shortcode. + Returns fresh `video_url` and `video_versions[]` per post (signed IG CDN URLs, + ~24h validity). Batch up to 20 posts at 1 credit ($0.01) each. + **Pricing**: 1 credit per post scraped ($0.01) Args: @@ -441,6 +459,10 @@ async def get_profile( **Note:** Live scraping is slower than cached data (2-5 seconds) and costs more. Use cached endpoints when freshness isn't critical. + The `posts[]` array returns up to 12 recent posts with fresh `video_url` for + each video post. This is the cheapest bulk-download path: 0.5 credits ($0.005) + per profile call vs 1 credit per individual raw-post call. + **Pricing**: 0.5 credits per profile scraped ($0.005) Args: diff --git a/src/influship/types/post_list_response.py b/src/influship/types/post_list_response.py index 48cd5e8..130bae5 100644 --- a/src/influship/types/post_list_response.py +++ b/src/influship/types/post_list_response.py @@ -6,7 +6,7 @@ from .._models import BaseModel -__all__ = ["PostListResponse", "Location", "Media", "Metrics"] +__all__ = ["PostListResponse", "Location", "Media", "MediaCarouselItem", "Metrics"] class Location(BaseModel): @@ -16,20 +16,40 @@ class Location(BaseModel): """Location name""" +class MediaCarouselItem(BaseModel): + index: int + """Zero-based position in the carousel.""" + + is_video: bool + """True if this item is a video.""" + + thumbnail_url: Optional[str] = None + """Thumbnail URL for this item. Cover frame for videos.""" + + class Media(BaseModel): """Post media information""" + carousel_items: Optional[List[MediaCarouselItem]] = None + """Per-item structure for carousel posts. + + Null for non-carousel posts. Per-item video_url is intentionally omitted (would + be stale). For fresh video URLs, call GET /v1/raw/instagram/post/{shortcode}. + """ + duration_seconds: Optional[float] = None - """Video duration in seconds""" + """Video duration in seconds. Null for non-video posts.""" thumbnail_url: Optional[str] = None - """Thumbnail URL""" + """Thumbnail URL. For videos, this is the cover frame.""" url: Optional[str] = None - """Media URL""" + """Cover/primary image URL for image and carousel posts. - video_url: Optional[str] = None - """Video URL (for video content)""" + Null for video posts — call GET /v1/raw/instagram/post/{shortcode} for a fresh, + downloadable video URL. Note: returned image URLs are Instagram CDN URLs and may + expire; a future change will migrate to persistent R2-hosted URLs. + """ class Metrics(BaseModel): diff --git a/src/influship/types/raw/instagram_transcript_response.py b/src/influship/types/raw/instagram_transcript_response.py index 84646ac..1394fe7 100644 --- a/src/influship/types/raw/instagram_transcript_response.py +++ b/src/influship/types/raw/instagram_transcript_response.py @@ -154,8 +154,6 @@ class InstagramTranscriptResponse(BaseModel): language: str - post: Post - scraped_at: datetime shortcode: str @@ -165,3 +163,5 @@ class InstagramTranscriptResponse(BaseModel): word_count: float duration_seconds: Optional[float] = None + + post: Optional[Post] = None From 17de04a149b10c676fe01cdf338ee9af40ae1e57 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 5 Jun 2026 22:29:01 +0000 Subject: [PATCH 08/12] feat(api): add creator_emails resource with lookup method --- .stats.yml | 8 +- api.md | 12 ++ src/influship/_client.py | 63 +++++- src/influship/resources/__init__.py | 14 ++ src/influship/resources/creator_emails.py | 197 ++++++++++++++++++ src/influship/types/__init__.py | 2 + .../types/creator_email_lookup_params.py | 33 +++ .../types/creator_email_lookup_response.py | 104 +++++++++ tests/api_resources/test_creator_emails.py | 92 ++++++++ 9 files changed, 520 insertions(+), 5 deletions(-) create mode 100644 src/influship/resources/creator_emails.py create mode 100644 src/influship/types/creator_email_lookup_params.py create mode 100644 src/influship/types/creator_email_lookup_response.py create mode 100644 tests/api_resources/test_creator_emails.py diff --git a/.stats.yml b/.stats.yml index 7932d2a..895cd69 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 19 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/inf-labs/influship-api-217c47eef43dd430e5bf8aa6445da278c0dca6ac39e33d2e5e7a0fecef1b7991.yml -openapi_spec_hash: c26a6ce3ddc0faa13be8c0600a5ae0af -config_hash: c98b7c9708fc0ee48d8b8170de41d163 +configured_endpoints: 20 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/inf-labs/influship-api-4da1003315e6380cbd4e0148c0a0641cfc92461e4511932aea6ab2ccace5f31a.yml +openapi_spec_hash: 9ec2a91b1cfe712e71db2bcebd0433c3 +config_hash: 7ea006cb87abb30bfc76a6af984a7b88 diff --git a/api.md b/api.md index c7d313f..9c1aa7b 100644 --- a/api.md +++ b/api.md @@ -69,6 +69,18 @@ Methods: - client.profiles.get(username, \*, platform) -> ProfileGetResponse - client.profiles.lookup(\*\*params) -> ProfileLookupResponse +# CreatorEmails + +Types: + +```python +from influship.types import CreatorEmailLookupResponse +``` + +Methods: + +- client.creator_emails.lookup(\*\*params) -> CreatorEmailLookupResponse + # Posts Types: diff --git a/src/influship/_client.py b/src/influship/_client.py index 55a6663..40c00f2 100644 --- a/src/influship/_client.py +++ b/src/influship/_client.py @@ -35,13 +35,14 @@ ) if TYPE_CHECKING: - from .resources import raw, posts, health, search, creators, profiles + from .resources import raw, posts, health, search, creators, profiles, creator_emails from .resources.posts import PostsResource, AsyncPostsResource from .resources.health import HealthResource, AsyncHealthResource from .resources.search import SearchResource, AsyncSearchResource from .resources.raw.raw import RawResource, AsyncRawResource from .resources.creators import CreatorsResource, AsyncCreatorsResource from .resources.profiles import ProfilesResource, AsyncProfilesResource + from .resources.creator_emails import CreatorEmailsResource, AsyncCreatorEmailsResource __all__ = [ "Timeout", @@ -154,6 +155,16 @@ def profiles(self) -> ProfilesResource: return ProfilesResource(self) + @cached_property + def creator_emails(self) -> CreatorEmailsResource: + """Look up known creator email addresses by creator ID or social username. + + Empty or unresolved results are not billable. + """ + from .resources.creator_emails import CreatorEmailsResource + + return CreatorEmailsResource(self) + @cached_property def posts(self) -> PostsResource: """ @@ -381,6 +392,16 @@ def profiles(self) -> AsyncProfilesResource: return AsyncProfilesResource(self) + @cached_property + def creator_emails(self) -> AsyncCreatorEmailsResource: + """Look up known creator email addresses by creator ID or social username. + + Empty or unresolved results are not billable. + """ + from .resources.creator_emails import AsyncCreatorEmailsResource + + return AsyncCreatorEmailsResource(self) + @cached_property def posts(self) -> AsyncPostsResource: """ @@ -550,6 +571,16 @@ def profiles(self) -> profiles.ProfilesResourceWithRawResponse: return ProfilesResourceWithRawResponse(self._client.profiles) + @cached_property + def creator_emails(self) -> creator_emails.CreatorEmailsResourceWithRawResponse: + """Look up known creator email addresses by creator ID or social username. + + Empty or unresolved results are not billable. + """ + from .resources.creator_emails import CreatorEmailsResourceWithRawResponse + + return CreatorEmailsResourceWithRawResponse(self._client.creator_emails) + @cached_property def posts(self) -> posts.PostsResourceWithRawResponse: """ @@ -607,6 +638,16 @@ def profiles(self) -> profiles.AsyncProfilesResourceWithRawResponse: return AsyncProfilesResourceWithRawResponse(self._client.profiles) + @cached_property + def creator_emails(self) -> creator_emails.AsyncCreatorEmailsResourceWithRawResponse: + """Look up known creator email addresses by creator ID or social username. + + Empty or unresolved results are not billable. + """ + from .resources.creator_emails import AsyncCreatorEmailsResourceWithRawResponse + + return AsyncCreatorEmailsResourceWithRawResponse(self._client.creator_emails) + @cached_property def posts(self) -> posts.AsyncPostsResourceWithRawResponse: """ @@ -664,6 +705,16 @@ def profiles(self) -> profiles.ProfilesResourceWithStreamingResponse: return ProfilesResourceWithStreamingResponse(self._client.profiles) + @cached_property + def creator_emails(self) -> creator_emails.CreatorEmailsResourceWithStreamingResponse: + """Look up known creator email addresses by creator ID or social username. + + Empty or unresolved results are not billable. + """ + from .resources.creator_emails import CreatorEmailsResourceWithStreamingResponse + + return CreatorEmailsResourceWithStreamingResponse(self._client.creator_emails) + @cached_property def posts(self) -> posts.PostsResourceWithStreamingResponse: """ @@ -721,6 +772,16 @@ def profiles(self) -> profiles.AsyncProfilesResourceWithStreamingResponse: return AsyncProfilesResourceWithStreamingResponse(self._client.profiles) + @cached_property + def creator_emails(self) -> creator_emails.AsyncCreatorEmailsResourceWithStreamingResponse: + """Look up known creator email addresses by creator ID or social username. + + Empty or unresolved results are not billable. + """ + from .resources.creator_emails import AsyncCreatorEmailsResourceWithStreamingResponse + + return AsyncCreatorEmailsResourceWithStreamingResponse(self._client.creator_emails) + @cached_property def posts(self) -> posts.AsyncPostsResourceWithStreamingResponse: """ diff --git a/src/influship/resources/__init__.py b/src/influship/resources/__init__.py index c54bbd6..abeb1ca 100644 --- a/src/influship/resources/__init__.py +++ b/src/influship/resources/__init__.py @@ -48,6 +48,14 @@ ProfilesResourceWithStreamingResponse, AsyncProfilesResourceWithStreamingResponse, ) +from .creator_emails import ( + CreatorEmailsResource, + AsyncCreatorEmailsResource, + CreatorEmailsResourceWithRawResponse, + AsyncCreatorEmailsResourceWithRawResponse, + CreatorEmailsResourceWithStreamingResponse, + AsyncCreatorEmailsResourceWithStreamingResponse, +) __all__ = [ "HealthResource", @@ -74,6 +82,12 @@ "AsyncProfilesResourceWithRawResponse", "ProfilesResourceWithStreamingResponse", "AsyncProfilesResourceWithStreamingResponse", + "CreatorEmailsResource", + "AsyncCreatorEmailsResource", + "CreatorEmailsResourceWithRawResponse", + "AsyncCreatorEmailsResourceWithRawResponse", + "CreatorEmailsResourceWithStreamingResponse", + "AsyncCreatorEmailsResourceWithStreamingResponse", "PostsResource", "AsyncPostsResource", "PostsResourceWithRawResponse", diff --git a/src/influship/resources/creator_emails.py b/src/influship/resources/creator_emails.py new file mode 100644 index 0000000..061bb9f --- /dev/null +++ b/src/influship/resources/creator_emails.py @@ -0,0 +1,197 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Iterable + +import httpx + +from ..types import creator_email_lookup_params +from .._types import Body, Query, Headers, NotGiven, not_given +from .._utils import maybe_transform, async_maybe_transform +from .._compat import cached_property +from .._resource import SyncAPIResource, AsyncAPIResource +from .._response import ( + to_raw_response_wrapper, + to_streamed_response_wrapper, + async_to_raw_response_wrapper, + async_to_streamed_response_wrapper, +) +from .._base_client import make_request_options +from ..types.creator_email_lookup_response import CreatorEmailLookupResponse + +__all__ = ["CreatorEmailsResource", "AsyncCreatorEmailsResource"] + + +class CreatorEmailsResource(SyncAPIResource): + """Look up known creator email addresses by creator ID or social username. + + Empty or unresolved results are not billable. + """ + + @cached_property + def with_raw_response(self) -> CreatorEmailsResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/Influship/influship-sdk-python#accessing-raw-response-data-eg-headers + """ + return CreatorEmailsResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> CreatorEmailsResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/Influship/influship-sdk-python#with_streaming_response + """ + return CreatorEmailsResourceWithStreamingResponse(self) + + def lookup( + self, + *, + creators: Iterable[creator_email_lookup_params.Creator], + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> CreatorEmailLookupResponse: + """ + Look up known email addresses for creators by creator ID or social username. + + **Billing behavior:** + + - Charged only for unique resolved creators with at least one returned email + - Empty and unresolved results are not billable + - Returns validation status so unvalidated emails are explicit + + **Pricing**: 5 credits per creator with at least one returned email ($0.05) + + Args: + creators: Creator lookups to resolve. Response rows preserve this input order. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return self._post( + "/v1/creator-emails/lookup", + body=maybe_transform({"creators": creators}, creator_email_lookup_params.CreatorEmailLookupParams), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=CreatorEmailLookupResponse, + ) + + +class AsyncCreatorEmailsResource(AsyncAPIResource): + """Look up known creator email addresses by creator ID or social username. + + Empty or unresolved results are not billable. + """ + + @cached_property + def with_raw_response(self) -> AsyncCreatorEmailsResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/Influship/influship-sdk-python#accessing-raw-response-data-eg-headers + """ + return AsyncCreatorEmailsResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncCreatorEmailsResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/Influship/influship-sdk-python#with_streaming_response + """ + return AsyncCreatorEmailsResourceWithStreamingResponse(self) + + async def lookup( + self, + *, + creators: Iterable[creator_email_lookup_params.Creator], + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> CreatorEmailLookupResponse: + """ + Look up known email addresses for creators by creator ID or social username. + + **Billing behavior:** + + - Charged only for unique resolved creators with at least one returned email + - Empty and unresolved results are not billable + - Returns validation status so unvalidated emails are explicit + + **Pricing**: 5 credits per creator with at least one returned email ($0.05) + + Args: + creators: Creator lookups to resolve. Response rows preserve this input order. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return await self._post( + "/v1/creator-emails/lookup", + body=await async_maybe_transform( + {"creators": creators}, creator_email_lookup_params.CreatorEmailLookupParams + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=CreatorEmailLookupResponse, + ) + + +class CreatorEmailsResourceWithRawResponse: + def __init__(self, creator_emails: CreatorEmailsResource) -> None: + self._creator_emails = creator_emails + + self.lookup = to_raw_response_wrapper( + creator_emails.lookup, + ) + + +class AsyncCreatorEmailsResourceWithRawResponse: + def __init__(self, creator_emails: AsyncCreatorEmailsResource) -> None: + self._creator_emails = creator_emails + + self.lookup = async_to_raw_response_wrapper( + creator_emails.lookup, + ) + + +class CreatorEmailsResourceWithStreamingResponse: + def __init__(self, creator_emails: CreatorEmailsResource) -> None: + self._creator_emails = creator_emails + + self.lookup = to_streamed_response_wrapper( + creator_emails.lookup, + ) + + +class AsyncCreatorEmailsResourceWithStreamingResponse: + def __init__(self, creator_emails: AsyncCreatorEmailsResource) -> None: + self._creator_emails = creator_emails + + self.lookup = async_to_streamed_response_wrapper( + creator_emails.lookup, + ) diff --git a/src/influship/types/__init__.py b/src/influship/types/__init__.py index 0afe204..de3a20f 100644 --- a/src/influship/types/__init__.py +++ b/src/influship/types/__init__.py @@ -25,4 +25,6 @@ from .creator_retrieve_response import CreatorRetrieveResponse as CreatorRetrieveResponse from .creator_lookalike_response import CreatorLookalikeResponse as CreatorLookalikeResponse from .creator_autocomplete_params import CreatorAutocompleteParams as CreatorAutocompleteParams +from .creator_email_lookup_params import CreatorEmailLookupParams as CreatorEmailLookupParams from .creator_autocomplete_response import CreatorAutocompleteResponse as CreatorAutocompleteResponse +from .creator_email_lookup_response import CreatorEmailLookupResponse as CreatorEmailLookupResponse diff --git a/src/influship/types/creator_email_lookup_params.py b/src/influship/types/creator_email_lookup_params.py new file mode 100644 index 0000000..2e77b44 --- /dev/null +++ b/src/influship/types/creator_email_lookup_params.py @@ -0,0 +1,33 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Union, Iterable +from typing_extensions import Literal, Required, TypeAlias, TypedDict + +__all__ = ["CreatorEmailLookupParams", "Creator", "CreatorCreatorEmailLookupByID", "CreatorCreatorEmailLookupByHandle"] + + +class CreatorEmailLookupParams(TypedDict, total=False): + creators: Required[Iterable[Creator]] + """Creator lookups to resolve. Response rows preserve this input order.""" + + +class CreatorCreatorEmailLookupByID(TypedDict, total=False): + """Creator email lookup input by creator ID""" + + creator_id: Required[str] + """Creator profile ID to look up directly""" + + +class CreatorCreatorEmailLookupByHandle(TypedDict, total=False): + """Creator email lookup input by social handle""" + + platform: Required[Literal["instagram"]] + """Social platform for handle-based lookup""" + + username: Required[str] + """Social username for handle-based lookup""" + + +Creator: TypeAlias = Union[CreatorCreatorEmailLookupByID, CreatorCreatorEmailLookupByHandle] diff --git a/src/influship/types/creator_email_lookup_response.py b/src/influship/types/creator_email_lookup_response.py new file mode 100644 index 0000000..823f219 --- /dev/null +++ b/src/influship/types/creator_email_lookup_response.py @@ -0,0 +1,104 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Union, Optional +from datetime import datetime +from typing_extensions import Literal, TypeAlias + +from .._models import BaseModel + +__all__ = [ + "CreatorEmailLookupResponse", + "Data", + "DataBilling", + "DataResult", + "DataResultEmail", + "DataResultInput", + "DataResultInputCreatorEmailLookupByIDOutput", + "DataResultInputCreatorEmailLookupByHandleOutput", +] + + +class DataBilling(BaseModel): + """Creator email lookup billing summary""" + + billable_results: int + """Unique resolved creators with at least one returned email""" + + credits_charged: float + """Preview of credits charged for this lookup""" + + +class DataResultEmail(BaseModel): + """API-visible creator email""" + + confidence: Optional[float] = None + """Nullable confidence score for the email""" + + email: str + """Email address as stored, preserving original casing""" + + first_seen_at: datetime + """When Influship first observed this email""" + + is_primary: bool + """Whether this is the primary email for the creator""" + + last_seen_at: datetime + """When Influship most recently observed this email""" + + status: Literal["unvalidated", "valid", "risky", "creator_verified"] + """API-visible email validation status""" + + validated_at: Optional[datetime] = None + """When the email was last validated, if known""" + + +class DataResultInputCreatorEmailLookupByIDOutput(BaseModel): + """Creator email lookup input by creator ID""" + + creator_id: str + """Creator profile ID to look up directly""" + + +class DataResultInputCreatorEmailLookupByHandleOutput(BaseModel): + """Creator email lookup input by social handle""" + + platform: Literal["instagram"] + """Social platform for handle-based lookup""" + + username: str + """Social username for handle-based lookup""" + + +DataResultInput: TypeAlias = Union[ + DataResultInputCreatorEmailLookupByIDOutput, DataResultInputCreatorEmailLookupByHandleOutput +] + + +class DataResult(BaseModel): + """Creator email lookup result""" + + creator_id: Optional[str] = None + """Resolved creator ID, or null when the input could not be resolved""" + + emails: List[DataResultEmail] + """API-visible emails for the resolved creator. Empty results are not billable.""" + + input: DataResultInput + """Creator email lookup input by creator ID or social handle""" + + resolved: bool + """Whether the lookup resolved to a creator profile""" + + +class Data(BaseModel): + billing: DataBilling + """Creator email lookup billing summary""" + + results: List[DataResult] + + +class CreatorEmailLookupResponse(BaseModel): + """Creator email lookup response""" + + data: Data diff --git a/tests/api_resources/test_creator_emails.py b/tests/api_resources/test_creator_emails.py new file mode 100644 index 0000000..f1e6772 --- /dev/null +++ b/tests/api_resources/test_creator_emails.py @@ -0,0 +1,92 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import os +from typing import Any, cast + +import pytest + +from influship import Influship, AsyncInfluship +from tests.utils import assert_matches_type +from influship.types import CreatorEmailLookupResponse + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestCreatorEmails: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_lookup(self, client: Influship) -> None: + creator_email = client.creator_emails.lookup( + creators=[{"creator_id": "123e4567-e89b-12d3-a456-426614174000"}], + ) + assert_matches_type(CreatorEmailLookupResponse, creator_email, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_lookup(self, client: Influship) -> None: + response = client.creator_emails.with_raw_response.lookup( + creators=[{"creator_id": "123e4567-e89b-12d3-a456-426614174000"}], + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + creator_email = response.parse() + assert_matches_type(CreatorEmailLookupResponse, creator_email, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_lookup(self, client: Influship) -> None: + with client.creator_emails.with_streaming_response.lookup( + creators=[{"creator_id": "123e4567-e89b-12d3-a456-426614174000"}], + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + creator_email = response.parse() + assert_matches_type(CreatorEmailLookupResponse, creator_email, path=["response"]) + + assert cast(Any, response.is_closed) is True + + +class TestAsyncCreatorEmails: + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_lookup(self, async_client: AsyncInfluship) -> None: + creator_email = await async_client.creator_emails.lookup( + creators=[{"creator_id": "123e4567-e89b-12d3-a456-426614174000"}], + ) + assert_matches_type(CreatorEmailLookupResponse, creator_email, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_lookup(self, async_client: AsyncInfluship) -> None: + response = await async_client.creator_emails.with_raw_response.lookup( + creators=[{"creator_id": "123e4567-e89b-12d3-a456-426614174000"}], + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + creator_email = await response.parse() + assert_matches_type(CreatorEmailLookupResponse, creator_email, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_lookup(self, async_client: AsyncInfluship) -> None: + async with async_client.creator_emails.with_streaming_response.lookup( + creators=[{"creator_id": "123e4567-e89b-12d3-a456-426614174000"}], + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + creator_email = await response.parse() + assert_matches_type(CreatorEmailLookupResponse, creator_email, path=["response"]) + + assert cast(Any, response.is_closed) is True From 075fe17ecb4214501b9cc0c0d4c3cc906ffad09e Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 8 Jun 2026 14:04:04 +0000 Subject: [PATCH 09/12] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 895cd69..b98161d 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 20 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/inf-labs/influship-api-4da1003315e6380cbd4e0148c0a0641cfc92461e4511932aea6ab2ccace5f31a.yml -openapi_spec_hash: 9ec2a91b1cfe712e71db2bcebd0433c3 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/inf-labs/influship-api-8771d2891571a81026caec99caed8ed4b09fcc709c8c0f32fdde436fe4bc1baa.yml +openapi_spec_hash: f67aa0b2e45c592af2d68b2c2fec0c37 config_hash: 7ea006cb87abb30bfc76a6af984a7b88 From 6a2e78096c26748f43db6c4aee15676753776370 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 10 Jun 2026 12:41:24 +0000 Subject: [PATCH 10/12] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index b98161d..32087bf 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 20 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/inf-labs/influship-api-8771d2891571a81026caec99caed8ed4b09fcc709c8c0f32fdde436fe4bc1baa.yml -openapi_spec_hash: f67aa0b2e45c592af2d68b2c2fec0c37 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/inf-labs/influship-api-0ee1a9a55be313c0b0794f896933255c95be7e50145917c85de8a121db8141e5.yml +openapi_spec_hash: c5689cbfd91a5790b5420dc5535ef3bb config_hash: 7ea006cb87abb30bfc76a6af984a7b88 From ef29fd64380a379c0589b4bec19996ae85da389a Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 16 Jun 2026 14:15:03 +0000 Subject: [PATCH 11/12] docs(api): clarify handle parameter format in youtube resource --- .stats.yml | 4 ++-- src/influship/resources/raw/youtube.py | 20 ++++++++++++++++---- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/.stats.yml b/.stats.yml index 32087bf..c174044 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 20 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/inf-labs/influship-api-0ee1a9a55be313c0b0794f896933255c95be7e50145917c85de8a121db8141e5.yml -openapi_spec_hash: c5689cbfd91a5790b5420dc5535ef3bb +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/inf-labs/influship-api-d2f171507de2ec0f4a5420e2ea170135523d8bc82c3b4baa7fd45fe261f311e4.yml +openapi_spec_hash: d812fcd5e16d62bc562e0f4618602647 config_hash: 7ea006cb87abb30bfc76a6af984a7b88 diff --git a/src/influship/resources/raw/youtube.py b/src/influship/resources/raw/youtube.py index e98c1fb..c4db0c7 100644 --- a/src/influship/resources/raw/youtube.py +++ b/src/influship/resources/raw/youtube.py @@ -76,7 +76,10 @@ def get_channel( **Pricing**: 0.5 credits per channel scraped ($0.005) Args: - handle: YouTube channel handle + handle: YouTube channel handle. Accepts a bare handle (`techreviews`), an `@handle` + (`@techreviews`), or a full channel URL (`https://youtube.com/@techreviews`); + surrounding share tokens and trailing paths are ignored. A value that is not a + channel handle returns a 400 validation error. include_videos: Include recent videos in response @@ -140,7 +143,10 @@ def get_channel_transcripts( **Pricing**: 0.5 credits per transcript fetched ($0.005) Args: - handle: YouTube channel handle + handle: YouTube channel handle. Accepts a bare handle (`techreviews`), an `@handle` + (`@techreviews`), or a full channel URL (`https://youtube.com/@techreviews`); + surrounding share tokens and trailing paths are ignored. A value that is not a + channel handle returns a 400 validation error. include_segments: Include timestamped transcript segments in response @@ -334,7 +340,10 @@ async def get_channel( **Pricing**: 0.5 credits per channel scraped ($0.005) Args: - handle: YouTube channel handle + handle: YouTube channel handle. Accepts a bare handle (`techreviews`), an `@handle` + (`@techreviews`), or a full channel URL (`https://youtube.com/@techreviews`); + surrounding share tokens and trailing paths are ignored. A value that is not a + channel handle returns a 400 validation error. include_videos: Include recent videos in response @@ -398,7 +407,10 @@ async def get_channel_transcripts( **Pricing**: 0.5 credits per transcript fetched ($0.005) Args: - handle: YouTube channel handle + handle: YouTube channel handle. Accepts a bare handle (`techreviews`), an `@handle` + (`@techreviews`), or a full channel URL (`https://youtube.com/@techreviews`); + surrounding share tokens and trailing paths are ignored. A value that is not a + channel handle returns a 400 validation error. include_segments: Include timestamped transcript segments in response From bc1363672964f94fb20a91e0181566c2c48ba6d3 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 16 Jun 2026 14:15:49 +0000 Subject: [PATCH 12/12] release: 0.1.0 --- .release-please-manifest.json | 2 +- CHANGELOG.md | 70 +++++++++++++++++++++++++++++++++++ pyproject.toml | 2 +- src/influship/_version.py | 2 +- 4 files changed, 73 insertions(+), 3 deletions(-) create mode 100644 CHANGELOG.md diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 1332969..3d2ac0b 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.0.1" + ".": "0.1.0" } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..e9bd85d --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,70 @@ +# Changelog + +## 0.1.0 (2026-06-16) + +Full Changelog: [v0.0.1...v0.1.0](https://github.com/Influship/influship-sdk-python/compare/v0.0.1...v0.1.0) + +### Features + +* **api:** add audience, brand alignment, key facts, vibe fields to creator response ([4c7bf09](https://github.com/Influship/influship-sdk-python/commit/4c7bf09985211ae6cb5c9784e8c60e186cf1f58f)) +* **api:** add creator_emails resource with lookup method ([17de04a](https://github.com/Influship/influship-sdk-python/commit/17de04a149b10c676fe01cdf338ee9af40ae1e57)) +* **api:** add creator_kinds parameter to search.create method ([712759a](https://github.com/Influship/influship-sdk-python/commit/712759ae241285079b0060ff896dc25c5cb25237)) +* **api:** add get_post/get_transcript methods to instagram, update post types ([c5d60ec](https://github.com/Influship/influship-sdk-python/commit/c5d60ec1b410ffcb49ece5ff68299d695ba9da36)) +* **api:** add pagination to creators lookalike, extract MatchInfo type, fix cursor passing ([3be1022](https://github.com/Influship/influship-sdk-python/commit/3be10226051e066b82f26fd99170612908ddda3a)) +* **api:** add raw resource with instagram/youtube endpoints ([d765413](https://github.com/Influship/influship-sdk-python/commit/d765413037084f7ad577d00b201a636a864c2f6b)) +* **api:** add search_id/total fields, remove cursor param from search.create ([bbd32c2](https://github.com/Influship/influship-sdk-python/commit/bbd32c2e4391a9f31543862afed49f9fa9ca3d8a)) +* **api:** remove source field from instagram transcript response types ([2c24026](https://github.com/Influship/influship-sdk-python/commit/2c240264f2abd9865713409ac1fb151f2479f261)) +* **api:** update instagram profile and youtube channel/transcript responses ([8b83650](https://github.com/Influship/influship-sdk-python/commit/8b83650ce59ca2f00bb2b8c0f7f8005862a1849d)) +* Fix Stainless pagination and model warnings in SDK config ([2ae3c29](https://github.com/Influship/influship-sdk-python/commit/2ae3c29275bfe74e3399f0ef0c0d950ae388531c)) +* Fix timeout enforcement and migrate Instagram scraper to curl ([c1a121d](https://github.com/Influship/influship-sdk-python/commit/c1a121d337de698699c7dac5a1fb5814648083c9)) +* honest cached /v1/posts video URLs + transcript read-through cache + discovery seeding ([72b71e3](https://github.com/Influship/influship-sdk-python/commit/72b71e36366b017314942b78436a0ea6e7fd1e24)) +* **internal/types:** support eagerly validating pydantic iterators ([252fe69](https://github.com/Influship/influship-sdk-python/commit/252fe69b3d9652bb8ff9f2bf731d63006ec5b0af)) +* **internal:** implement indices array format for query and form serialization ([b0fb922](https://github.com/Influship/influship-sdk-python/commit/b0fb922140eac09079b68be14a023d14a3f3a510)) +* Remove app-level quota system and align billing/rate-limit enforcement with Stripe + Redis ([c7d8a60](https://github.com/Influship/influship-sdk-python/commit/c7d8a6012df2e31b92554e9a8374f1b3217bbe44)) + + +### Bug Fixes + +* **api:** make include parameter optional in creators retrieve method ([7dc834c](https://github.com/Influship/influship-sdk-python/commit/7dc834c23ef1d68df710b2de3baa996510c97b0d)) +* **api:** move RawScraperError to shared types ([061b1e2](https://github.com/Influship/influship-sdk-python/commit/061b1e27385b033eb8966ebf8a02815b7dde26e4)) +* **client:** add missing f-string prefix in file type error message ([cdd7fdb](https://github.com/Influship/influship-sdk-python/commit/cdd7fdb4104a72d2be89f7c6b48517abdb4285f4)) +* **client:** preserve hardcoded query params when merging with user params ([77f87f2](https://github.com/Influship/influship-sdk-python/commit/77f87f2cca5dbacc34e894cf2c69e3f8f208842c)) +* **deps:** bump minimum typing-extensions version ([1ebf842](https://github.com/Influship/influship-sdk-python/commit/1ebf84221a6cc9da7c4bcb414f47c4455f9b2dbe)) +* ensure file data are only sent as 1 parameter ([76674d4](https://github.com/Influship/influship-sdk-python/commit/76674d4a000df97be89864108b9bf3923b4604f3)) +* **pydantic:** do not pass `by_alias` unless set ([dba41e9](https://github.com/Influship/influship-sdk-python/commit/dba41e990d67482fc211cf0674e547c310a8eb26)) +* sanitize endpoint path params ([825e363](https://github.com/Influship/influship-sdk-python/commit/825e363c5eb9b02a3e5fc5baa994fb711ea5cdab)) +* **types:** remove model and provider from instagram transcript response types ([8944d7f](https://github.com/Influship/influship-sdk-python/commit/8944d7f405ad6e3597f397bebce7f13bc0df6fe3)) + + +### Performance Improvements + +* **client:** optimize file structure copying in multipart requests ([eca9767](https://github.com/Influship/influship-sdk-python/commit/eca97676e9a6a75faf45ea3bea0b8eefeac55b8b)) + + +### Chores + +* **ci:** skip lint on metadata-only changes ([5ee4369](https://github.com/Influship/influship-sdk-python/commit/5ee43696849a917cf7a65f66a8b298ebbc4fa2e7)) +* **ci:** skip uploading artifacts on stainless-internal branches ([2c985c8](https://github.com/Influship/influship-sdk-python/commit/2c985c8141c06115d531bc9293bb1291a3d04d45)) +* **internal:** add request options to SSE classes ([fa680d0](https://github.com/Influship/influship-sdk-python/commit/fa680d005639f7836e614b03c165791f1c64c0b3)) +* **internal:** codegen related update ([6ed3406](https://github.com/Influship/influship-sdk-python/commit/6ed3406334c705ae2278a09a040b916c0432d9ae)) +* **internal:** codegen related update ([a7d0c03](https://github.com/Influship/influship-sdk-python/commit/a7d0c03f03bae935f64b076c211d283ad9069495)) +* **internal:** make `test_proxy_environment_variables` more resilient ([1775e30](https://github.com/Influship/influship-sdk-python/commit/1775e30216baabb1affe64be26b9455a35bc7a30)) +* **internal:** make `test_proxy_environment_variables` more resilient to env ([2042983](https://github.com/Influship/influship-sdk-python/commit/20429833fae8ecd9dbe6eee1d140cdb9e0763260)) +* **internal:** more robust bootstrap script ([09db9ca](https://github.com/Influship/influship-sdk-python/commit/09db9caf00714de6ccb7eccd314c0a903b6ea55f)) +* **internal:** refactor Instagram response types to shared models, fix address_json type ([1ce31a9](https://github.com/Influship/influship-sdk-python/commit/1ce31a9406b653b08e333139febfb5acb01ca641)) +* **internal:** reformat pyproject.toml ([c63d362](https://github.com/Influship/influship-sdk-python/commit/c63d362a824ea0145bb90d8be4e493463d32028c)) +* **internal:** regenerate SDK with no functional changes ([2f56132](https://github.com/Influship/influship-sdk-python/commit/2f561321662c817f965ff9d4ad61e3b13f15de38)) +* **internal:** tweak CI branches ([5eea6ab](https://github.com/Influship/influship-sdk-python/commit/5eea6ab384a360852d54e5617e92e0d8d090a12e)) +* **internal:** update gitignore ([a47bc6c](https://github.com/Influship/influship-sdk-python/commit/a47bc6c615c786a620fad78eafb31927cbecc718)) +* update Stainless production repos to influship org ([f92ef39](https://github.com/Influship/influship-sdk-python/commit/f92ef39428d669160509c279e52deb10343e2b2c)) + + +### Documentation + +* **api:** add MCP tool references to creators/posts/profiles/search methods ([fb75a8e](https://github.com/Influship/influship-sdk-python/commit/fb75a8eedb6c1e86edb35b94e82d0eb27b9f4537)) +* **api:** clarify handle parameter format in youtube resource ([ef29fd6](https://github.com/Influship/influship-sdk-python/commit/ef29fd64380a379c0589b4bec19996ae85da389a)) +* **api:** correct profile to channel terminology in youtube channel method ([a8f561f](https://github.com/Influship/influship-sdk-python/commit/a8f561fde0da698d26689d699c394cbcb3475f8d)) +* **api:** update instagram method docstrings ([9d881aa](https://github.com/Influship/influship-sdk-python/commit/9d881aadfbbc7d742d739042a96c973a9824573f)) +* **api:** update pricing documentation across creators/posts/profiles/raw/search ([b82801e](https://github.com/Influship/influship-sdk-python/commit/b82801e0c5cc55dc0509e3a8ac412518ca9745ce)) +* **internal:** update MCP server package name in installation links ([7d78559](https://github.com/Influship/influship-sdk-python/commit/7d78559d721175e453eea56d8fab60a0f4c9a229)) +* update examples ([53aa0d6](https://github.com/Influship/influship-sdk-python/commit/53aa0d622795bdc2076f69d67ac51525b814f7d6)) diff --git a/pyproject.toml b/pyproject.toml index 0355ae6..b23b700 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "influship" -version = "0.0.1" +version = "0.1.0" description = "The official Python library for the Influship API" dynamic = ["readme"] license = "Apache-2.0" diff --git a/src/influship/_version.py b/src/influship/_version.py index de0c280..388cde9 100644 --- a/src/influship/_version.py +++ b/src/influship/_version.py @@ -1,4 +1,4 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. __title__ = "influship" -__version__ = "0.0.1" # x-release-please-version +__version__ = "0.1.0" # x-release-please-version