# API Reference
Source: https://docs.influship.com/api-reference
Authoritative endpoint contracts, request fields, response schemas, and examples for the Influship API.
The endpoint reference is generated from the same OpenAPI contract used to
build the Influship SDKs. Use the **Endpoints** navigation to inspect exact
request fields, response schemas, authentication requirements, and examples.
Make your first authenticated request.
Use the generated TypeScript client or call the REST API from any language.
# Check service dependency readiness
Source: https://docs.influship.com/api-reference/check-service-dependency-readiness
/openapi/openapi.documented.yml get /ready
Checks whether the API is ready to serve requests. Use /health for process liveness.
# Lookup Creator Emails
Source: https://docs.influship.com/api-reference/creator-emails/lookup-creator-emails
/openapi/openapi.documented.yml post /v1/creator-emails/lookup
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)
# Autocomplete Search
Source: https://docs.influship.com/api-reference/creators/autocomplete-search
/openapi/openapi.documented.yml get /v1/creators/autocomplete
Fast typeahead search for creators by name or username. Optimized for search-as-you-type UIs with sub-100ms response times.
**Matching behavior:**
- Matches against creator name, username, and display name
- Results include which field matched and the matching value
- Prefix matching (e.g., "fit" matches "fitness_coach")
**Scope options:**
- `creator_only`: Return only the creator entity
- `matched_platforms`: Return only profiles that matched the query
- `all_platforms`: Return all linked profiles (default)
Also callable as the `autocomplete_creators` MCP tool — see [the MCP server guide](/guides/mcp-server) for setup.
**Pricing**: 0.05 credits per request ($0.0005)
# Find Similar Creators
Source: https://docs.influship.com/api-reference/creators/find-similar-creators
/openapi/openapi.documented.yml post /v1/creators/lookalike
Find creators similar to provided seed creators using AI-powered similarity matching. Analyzes content themes, audience overlap, posting style, and engagement patterns.
**Use cases:**
- Expand campaigns with creators similar to proven performers
- Find alternatives when preferred creators are unavailable
- Discover emerging creators in the same niche
**How it works:**
1. Provide 1-10 seed creators (by ID or platform/username)
2. Optionally weight seeds to prioritize certain creators
3. Get ranked results with similarity scores and shared traits
If none of the supplied seeds is available for similarity matching, the endpoint returns `404 seed_not_found`. Choose another seed instead of retrying the same request.
Also callable as the `find_lookalike_creators` MCP tool — see [the MCP server guide](/guides/mcp-server) for setup.
**Pricing**: 1.5 credits per creator returned ($0.015)
# Get Creator by ID
Source: https://docs.influship.com/api-reference/creators/get-creator-by-id
/openapi/openapi.documented.yml get /v1/creators/{id}
Retrieve a creator's profile including AI-generated summary, content themes, and optionally their linked social profiles.
**What is a Creator?**
A creator is a cross-platform entity representing a person or brand. They may have profiles on multiple social networks (Instagram, YouTube, TikTok, etc.) that are linked together.
**Include options:**
- `profiles`: Include all linked social profiles with metrics
Also callable as the `get_creator` MCP tool — see [the MCP server guide](/guides/mcp-server) for setup.
**Pricing**: 0.1 credits per request ($0.001)
# Ingest a Creator On Demand
Source: https://docs.influship.com/api-reference/creators/ingest-a-creator-on-demand
/openapi/openapi.documented.yml post /v1/creators/ingest
Request ingestion of a creator we do not yet have. The handle is validated live before anything is created, then a profile is seeded and enrichment begins asynchronously.
**How it works:**
1. The handle is normalized and validated live to confirm it exists
2. If we already have the creator, you get `200` with `status: already_exists` and are not charged
3. Otherwise a profile is seeded and you get `202` with `status: ingesting`
**Polling for results:**
Use the returned `status_url` (`GET /v1/creators/{id}`) to poll for the built profile. Basic header details are usually available within about a minute; full analysis and synthesized fields fill in within about a day. While the profile is still building, that endpoint may return `404` or sparse fields.
**Limits:**
- Only `instagram` is supported today
- Each account has a daily ingest quota; exceeding it returns `429` with `quota_exceeded` and a `Retry-After` header
- Handles that do not exist return `404` and are not charged
**Pricing**: 5 credits per creator ingested ($0.05). Charged only when a new creator is seeded — existing, not-found, and invalid handles are free.
# Score Campaign Fit
Source: https://docs.influship.com/api-reference/creators/score-campaign-fit
/openapi/openapi.documented.yml post /v1/creators/match
Evaluate how well creators match a specific campaign using AI analysis. Returns a fit score (0-1), decision recommendation (good/neutral/avoid), and evidence-based explanations.
**Use cases:**
- Vet shortlisted creators before outreach
- Rank candidates for a specific campaign
- Get AI-generated talking points for why a creator fits
**How it works:**
1. Describe your campaign intent and target audience
2. Provide up to 100 creators to evaluate
3. Get detailed scores with explanations and evidence
Also callable as the `match_creators` MCP tool — see [the MCP server guide](/guides/mcp-server) for setup.
**Pricing**: 1 credit per creator scored ($0.01)
# Health Check
Source: https://docs.influship.com/api-reference/health/health-check
/openapi/openapi.documented.yml get /health
Check API health status. No authentication required.
# Get Instagram Post Transcript
Source: https://docs.influship.com/api-reference/live-scraping/get-instagram-post-transcript
/openapi/openapi.documented.yml get /v1/raw/instagram/transcript/{shortcode}
Transcribe an Instagram video post by shortcode and return the raw post-page data used for transcription.
**Pricing**: 5 credits per transcript ($0.05)
# Get Instagram Post Transcripts
Source: https://docs.influship.com/api-reference/live-scraping/get-instagram-post-transcripts
/openapi/openapi.documented.yml post /v1/raw/instagram/transcripts
Transcribe a bounded list of Instagram video posts by shortcode and return one 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. API-key and OAuth calls are charged only for successful items; x402 and MPP use the advertised request price.
**Pricing**: 5 credits per transcript ($0.05)
# Get Live Instagram Post
Source: https://docs.influship.com/api-reference/live-scraping/get-live-instagram-post
/openapi/openapi.documented.yml get /v1/raw/instagram/post/{shortcode}
Fetch fresh Instagram post-page data by shortcode. This raw endpoint includes rich post-page fields like coauthors, tagged users, paid partnership metadata, product mentions, music attribution, location, display resources, and video versions.
**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)
# Get Live Instagram Posts
Source: https://docs.influship.com/api-reference/live-scraping/get-live-instagram-posts
/openapi/openapi.documented.yml post /v1/raw/instagram/posts
Fetch fresh Instagram post-page data for a bounded list of shortcodes. This returns one item per requested shortcode with per-item success or error details. Transient upstream recovery is handled automatically within the request deadline.
**Note:** Batch post lookup is capped at 20 shortcodes per request. API-key and OAuth calls are charged only for successful items; x402 and MPP use the advertised request price.
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)
# Get Live Instagram Profile
Source: https://docs.influship.com/api-reference/live-scraping/get-live-instagram-profile
/openapi/openapi.documented.yml get /v1/raw/instagram/profile/{username}
Fetch fresh Instagram profile data directly from Instagram in real-time. Use this when you need the most current follower counts, bio, or recent activity.
**When to use live scraping:**
- Profile not found in our database
- Need real-time follower/engagement data
- Verifying current profile status before campaign
**Note:** Live scraping is slower than cached data (2-5 seconds) and costs more. Use cached endpoints when freshness isn't critical.
The profile response returns an empty `posts[]` array unless `include_posts=true`. When posts are included, `post_limit` accepts 1-50 and defaults to 12. The array contains the recent posts available in Instagram's source response, up to that limit. Video posts include a fresh `video_url`. 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)
# Get Live TikTok Profile
Source: https://docs.influship.com/api-reference/live-scraping/get-live-tiktok-profile
/openapi/openapi.documented.yml get /v1/raw/tiktok/profile/{username}
Fetch a normalized TikTok profile with current identity, biography, verification, and audience metrics.
**Pricing**: 0.2 credits per profile scraped ($0.002)
# Get Live TikTok Video
Source: https://docs.influship.com/api-reference/live-scraping/get-live-tiktok-video
/openapi/openapi.documented.yml get /v1/raw/tiktok/video
Fetch normalized details and current engagement metrics for a TikTok video URL. Signed media URLs are temporary and should be downloaded promptly.
**Pricing**: 0.2 credits per video scraped ($0.002)
# Get Live YouTube Channel
Source: https://docs.influship.com/api-reference/live-scraping/get-live-youtube-channel
/openapi/openapi.documented.yml get /v1/raw/youtube/channel/{handle}
Fetch fresh YouTube channel data including subscriber count, video count, and total views.
**Pricing**: 0.5 credits per channel scraped ($0.005)
# Get TikTok Hashtag Videos
Source: https://docs.influship.com/api-reference/live-scraping/get-tiktok-hashtag-videos
/openapi/openapi.documented.yml get /v1/raw/tiktok/hashtag/videos
Fetch one page of videos under a hashtag, supplied without #. Continue with next_cursor and the same hashtag; cursors are opaque. Duplicate results are preserved. Each successful page, including an empty page, is charged once. Media links are temporary.
**Pricing**: 0.2 credits per hashtag video page ($0.002)
# Get TikTok Music Videos
Source: https://docs.influship.com/api-reference/live-scraping/get-tiktok-music-videos
/openapi/openapi.documented.yml get /v1/raw/tiktok/music/videos
Fetch one page of TikTok videos using a sound clip, identified by music_id. Continue with next_cursor and the same music_id; cursors are opaque. Duplicate results are preserved. Each successful page, including an empty page, is charged once. Media links are temporary.
**Pricing**: 0.2 credits per music video page ($0.002)
# Get TikTok Sound Details
Source: https://docs.influship.com/api-reference/live-scraping/get-tiktok-sound-details
/openapi/openapi.documented.yml get /v1/raw/tiktok/music
Fetch metadata for a TikTok sound clip by music_id. Unknown fields are null. Audio and cover URLs are temporary upstream links, not durable downloads.
**Pricing**: 0.2 credits per sound lookup ($0.002)
# Get TikTok Transcripts in a Batch
Source: https://docs.influship.com/api-reference/live-scraping/get-tiktok-transcripts-in-a-batch
/openapi/openapi.documented.yml post /v1/raw/tiktok/video/transcripts
Process up to 10 video URLs with ordered per-item results. Choose auto (default, $0.025 per item) or captions ($0.002 per item, never generates). Account credits charge successful items only. Premium payments quote all requested items and are nonrefundable once settled, including partial or failed items in a completed batch.
# Get TikTok Video Captions
Source: https://docs.influship.com/api-reference/live-scraping/get-tiktok-video-captions
/openapi/openapi.documented.yml get /v1/raw/tiktok/video/captions
Return available TikTok captions without generating a transcript. Returns transcript_not_available when captions are unavailable. Successful cached results are charged at the ordinary rate.
**Pricing**: 0.2 credits per successful caption response ($0.002)
# Get TikTok Video Transcript
Source: https://docs.influship.com/api-reference/live-scraping/get-tiktok-video-transcript
/openapi/openapi.documented.yml get /v1/raw/tiktok/video/transcript
Fetch or generate a normalized TikTok transcript with plain text and timestamped segments. The detected-language transcript is reused on later requests.
**Pricing**: 2.5 credits per transcript ($0.025)
# Get TikTok Videos in a Batch
Source: https://docs.influship.com/api-reference/live-scraping/get-tiktok-videos-in-a-batch
/openapi/openapi.documented.yml post /v1/raw/tiktok/videos
Fetch up to 20 video URLs with ordered per-item results. Duplicate entries remain distinct requested items. Account credits charge successful items only at $0.002 each. Premium payments quote all requested items and are nonrefundable once settled, including partial or failed items in a completed batch.
# Get YouTube Channel Transcripts
Source: https://docs.influship.com/api-reference/live-scraping/get-youtube-channel-transcripts
/openapi/openapi.documented.yml get /v1/raw/youtube/channel-transcripts/{handle}
Fetch transcripts for multiple videos from a YouTube channel. Videos can be sorted by popularity, newest, or oldest before selection.
**Features:**
- Fetches up to 20 video transcripts per request
- Sort by popular (most views), newest, or oldest
- Partial success — individual video failures don't block the response
- Optional timestamped segments for each transcript
**Pricing**: 0.5 credits per transcript fetched ($0.005)
# Get YouTube Search Suggestions
Source: https://docs.influship.com/api-reference/live-scraping/get-youtube-search-suggestions
/openapi/openapi.documented.yml get /v1/raw/youtube/typeahead
Get localized YouTube search suggestions for a partial query.
**Pricing**: 0.5 credits per request ($0.005)
# Get YouTube Video Details
Source: https://docs.influship.com/api-reference/live-scraping/get-youtube-video-details
/openapi/openapi.documented.yml get /v1/raw/youtube/video/{video_id}
Fetch fresh video metadata including description, exact publish timestamp when available, views, likes, comments, tags, categories, and channel identity.
**Pricing**: 0.5 credits per video fetched ($0.005)
# Get YouTube Video Transcript
Source: https://docs.influship.com/api-reference/live-scraping/get-youtube-video-transcript
/openapi/openapi.documented.yml get /v1/raw/youtube/transcript/{video_id}
Fetch YouTube video transcript/captions. Returns timestamped segments and full text. Useful for content analysis.
**Supported sources:**
- Manual captions (highest quality)
- Auto-generated captions
- Multiple language tracks
**Pricing**: 0.5 credits per transcript ($0.005)
# List Live TikTok Comment Replies
Source: https://docs.influship.com/api-reference/live-scraping/list-live-tiktok-comment-replies
/openapi/openapi.documented.yml get /v1/raw/tiktok/video/comment/replies
Fetch one cursor-paginated page of replies to a numeric parent comment ID. Keep the same video URL and parent comment ID when continuing with next_cursor.
**Pricing**: 0.2 credits per reply page scraped ($0.002)
# List Live TikTok Profile Videos
Source: https://docs.influship.com/api-reference/live-scraping/list-live-tiktok-profile-videos
/openapi/openapi.documented.yml get /v1/raw/tiktok/profile/{username}/videos
Fetch one cursor-paginated page of normalized TikTok videos. Signed media URLs are temporary and should be downloaded promptly.
**Pricing**: 0.2 credits per video page scraped ($0.002)
# List Live TikTok Video Comments
Source: https://docs.influship.com/api-reference/live-scraping/list-live-tiktok-video-comments
/openapi/openapi.documented.yml get /v1/raw/tiktok/video/comments
Fetch one cursor-paginated page of normalized comments for a TikTok video URL.
**Pricing**: 0.2 credits per comment page scraped ($0.002)
# Search TikTok Users
Source: https://docs.influship.com/api-reference/live-scraping/search-tiktok-users
/openapi/openapi.documented.yml get /v1/raw/tiktok/search/users
Fetch one page of TikTok user search results. Unknown profile fields are null. Continue with next_cursor and the same query; treat cursors as opaque. A successful page is charged once, including an empty page.
**Pricing**: 0.2 credits per user search page ($0.002)
# Search TikTok Videos
Source: https://docs.influship.com/api-reference/live-scraping/search-tiktok-videos
/openapi/openapi.documented.yml get /v1/raw/tiktok/search/videos
Fetch one relevance-ordered page of TikTok videos matching a query. Continue with next_cursor and the same query; cursors are opaque. Duplicate results are preserved. Each successful page, including an empty page, is charged once. Media links are temporary.
**Pricing**: 0.2 credits per video search page ($0.002)
# Search YouTube
Source: https://docs.influship.com/api-reference/live-scraping/search-youtube
/openapi/openapi.documented.yml get /v1/raw/youtube/search
Search YouTube videos and channels.
Each request fetches one page. Pass `next_cursor` back as `cursor` to fetch and bill the next page.
**Pricing**: 0.5 credits per fetched page ($0.005)
# Get OAuth Protected Resource Metadata
Source: https://docs.influship.com/api-reference/oauth/get-oauth-protected-resource-metadata
/openapi/openapi.documented.yml get /.well-known/oauth-protected-resource
OAuth 2.0 protected resource metadata for MCP and partner clients.
# Get Posts
Source: https://docs.influship.com/api-reference/posts/get-posts
/openapi/openapi.documented.yml get /v1/posts
Retrieve posts for a creator or profile with engagement metrics and media data.
**Query options:**
- By creator: Use `creator_id` to get posts across all their profiles
- By profile: Use `platform` + `username` for a specific profile's posts
**Sort options:**
- `recent`: Most recent posts first (default)
- `top_engagement`: Highest view-based engagement rate first, calculated as (likes + comments) / views. Posts without measurable views sort last
- `most_likes`: Most likes first
- `most_views`: Most views first (video content)
- `most_comments`: Most comments first
Pagination uses an opaque keyset cursor. Pass `next_cursor` back with the same `sort` value; cursors cannot be reused across sort orders.
Also callable as the `get_posts` MCP tool — see [the MCP server guide](/guides/mcp-server) for setup.
**Pricing**: 0.05 credits per post returned ($0.0005)
# Batch Lookup Profiles
Source: https://docs.influship.com/api-reference/profiles/batch-lookup-profiles
/openapi/openapi.documented.yml post /v1/profiles/lookup
Look up multiple profiles in a single request. Efficiently retrieve data for up to 100 profiles at once.
**Response includes:**
- `found`: Array of profiles that exist in our database
- `not_found`: Array of profiles that weren't found (consider live scraping these)
Also callable as the `lookup_profiles` MCP tool — see [the MCP server guide](/guides/mcp-server) for setup.
**Pricing**: 0.1 credits per profile ($0.001)
# Get Profile by Platform and Username
Source: https://docs.influship.com/api-reference/profiles/get-profile-by-platform-and-username
/openapi/openapi.documented.yml get /v1/profiles/{platform}/{username}
Retrieve detailed profile data including metrics, growth statistics, and activity information from our database.
**Response includes:**
- Basic info (bio, avatar, verification status)
- Performance metrics (followers, engagement rate, avg likes/comments)
- Growth data (30-day follower growth, monthly rate)
- Activity data (last post date, posting frequency)
Also callable as the `get_profile` MCP tool — see [the MCP server guide](/guides/mcp-server) for setup.
**Pricing**: 0.1 credits per request ($0.001)
# AI-Powered Creator Search
Source: https://docs.influship.com/api-reference/search/ai-powered-creator-search
/openapi/openapi.documented.yml post /v1/search
Search for creators using natural language queries. The AI understands intent and context to match creators based on content themes, audience demographics, and style.
The response includes a `search_id` that can be used with `GET /v1/search/{id}` to paginate through results for free.
**Use cases:**
- Find creators in a specific niche ("vegan food bloggers in LA")
- Discover creators with specific audience characteristics ("fitness influencers with millennial audience")
- Search by content style ("creators who post cinematic travel videos")
Also callable as the `search_creators` MCP tool — see [the MCP server guide](/guides/mcp-server) for setup.
**Pricing**: 25 credits base + 2 credits per creator returned
# Get Search Results Page
Source: https://docs.influship.com/api-reference/search/get-search-results-page
/openapi/openapi.documented.yml get /v1/search/{id}
Paginate through results from a previous search. Use the `search_id` returned by `POST /v1/search` to fetch additional pages.
Search sessions expire after 1 hour. After expiry, a new search must be run.
**Pricing**: 0 credits (included with initial search)
# What's New
Source: https://docs.influship.com/changelog
Recent changes and updates to the Influship API
# What's New
## YouTube discovery, pagination, and video details
YouTube search now supports upload-date, popularity, content-type, duration, country, and language filters. Responses include an opaque `next_cursor`; pass it back as `cursor` to fetch another page. Search costs 0.5 credits per fetched page, independent of the number of results returned.
Two new endpoints expand topic discovery and validation:
* `GET /v1/raw/youtube/typeahead` returns localized query suggestions
* `GET /v1/raw/youtube/video/{video_id}` returns fresh views, likes, comments, duration, tags, and exact publication data when available
Channel lookup now accepts handles, channel IDs, and full channel URLs. The same six YouTube workflows are available as MCP tools and dedicated n8n and Make operations. See [YouTube Live Data](/guides/youtube-live-data) for examples and pricing.
## Search response type parity
Generated TypeScript types now include the documented `confidence`, `low_confidence`, and structured `evidence` fields on search matches. Structured evidence stays in the same order as the plain-text `reasons` list.
## Automatic recovery for raw Instagram requests
Raw Instagram profile, post, and transcript requests now recover automatically from temporary source-platform interruptions. Confirmed missing posts, missing profiles, and private profiles continue to return their documented errors.
Batch post and transcript requests now stop queued upstream work when the calling request expires or disconnects. Batch results remain in the same order as the requested shortcodes.
## Raw Instagram post & transcript reliability
We resolved an issue where single Instagram post lookups and video transcripts could return errors after a change on the source platform's side. Individual post lookup, batch post lookup, and the transcript endpoints now return their documented response shapes consistently across the REST API, MCP tools, and no-code actors.
We also hardened how transient upstream hiccups surface on these endpoints: a temporary soft-block from the source platform is now returned as a retryable `429`/`503` with `Retry-After` (matching our other live endpoints) instead of a generic `500`. Handle it with the same backoff you use for other live data — see [Error Handling](/guides/error-handling).
Affected endpoints:
* `GET /v1/raw/instagram/post/{shortcode}`
* `POST /v1/raw/instagram/posts`
* `GET /v1/raw/instagram/transcript/{shortcode}`
* `POST /v1/raw/instagram/transcripts`
## Raw Instagram post lookup and transcripts
You can now look up an individual Instagram post by shortcode and fetch video transcripts directly from the raw API. These endpoints return fresh raw post data, including fields that are not guaranteed on cached post-list responses, such as coauthors, paid partnership flags, tagged users, product mentions, display resources, video versions, music attribution, and location data.
Available endpoints:
* `GET /v1/raw/instagram/post/{shortcode}` for one post
* `POST /v1/raw/instagram/posts` for up to 20 posts in one request
* `GET /v1/raw/instagram/transcript/{shortcode}` for one video post transcript
* `POST /v1/raw/instagram/transcripts` for up to 10 video post transcripts in one request
Transcript responses include the post lookup payload on cache misses. Cached transcript responses omit `post`; call the post lookup endpoint separately when you need post metadata alongside a cached transcript.
We've also added two Apify actors for no-code and workflow use cases:
* Instagram Post Lookup
* Instagram Post Transcripts
Both actors use your Influship API key and mirror the raw API response shapes.
## MCP Server
The Influship MCP server launched at `mcp.influship.com/mcp` with eight typed tools. Connect any [Model Context Protocol](https://modelcontextprotocol.io)-compatible client, including Claude Desktop, Claude Code, Cursor, Windsurf, ChatGPT Connectors, and VS Code. The [MCP Server guide](/guides/mcp-server) lists the current 14-tool surface.
```bash theme={null}
claude mcp add influship --transport http https://mcp.influship.com/mcp --header "X-API-Key: YOUR_KEY"
```
Or paste the JSON config into your client's MCP settings panel:
```json theme={null}
{
"mcpServers": {
"influship": {
"url": "https://mcp.influship.com/mcp",
"headers": { "X-API-Key": "YOUR_KEY" }
}
}
}
```
Auth, billing, and rate limits are all the same as the REST API — same key, same tier, same dashboard. There's no separate "MCP plan" to set up.
See the [MCP Server guide](/guides/mcp-server) for the full setup walkthrough and the [tool reference](/api-reference) (each REST endpoint with an MCP equivalent now shows the corresponding tool name).
## Pay per request with x402 (no API key needed)
Anonymous AI agents can now call supported paid Influship endpoints via the [x402 payment protocol](https://www.x402.org). The agent makes a request without an `X-API-Key`, gets a `402 Payment Required` response with a USDC-on-Base price, signs a payment, and retries without signup or billing setup.
```typescript theme={null}
import { x402Client, wrapFetchWithPayment } from '@x402/fetch';
import { registerExactEvmScheme } from '@x402/evm/exact/client';
import { privateKeyToAccount } from 'viem/accounts';
const signer = privateKeyToAccount(process.env.EVM_PRIVATE_KEY as `0x${string}`);
const client = new x402Client();
registerExactEvmScheme(client, { signer });
const fetchWithPayment = wrapFetchWithPayment(fetch, client);
const response = await fetchWithPayment('https://api.influship.com/v1/search', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ query: 'fitness creators in NYC', limit: 25 }),
});
```
Influship endpoints are listed in the [x402 Bazaar](https://docs.cdp.coinbase.com/x402/bazaar) for programmatic discovery. See the [x402 guide](/guides/x402) for pricing and quickstart with [AgentCash](https://agentcash.dev) or the Coinbase SDK.
## Pay with MPP (Stripe cards or USDC on Tempo)
The [Machine Payments Protocol](https://mpp.dev/overview) — Stripe and Tempo's open standard for HTTP-native machine-to-machine payments — coexists with x402 on the same endpoints. Pay per request via Stripe SPT (Shared Payment Tokens, USD via card) or USDC on Tempo. Pick whichever rail your client supports; the API accepts both.
```typescript theme={null}
import { Mppx, tempo } from 'mppx/client';
import { privateKeyToAccount } from 'viem/accounts';
const account = privateKeyToAccount(process.env.TEMPO_PRIVATE_KEY as `0x${string}`);
const mppx = Mppx.create({
methods: [tempo({ account })],
});
const response = await mppx.fetch('https://api.influship.com/v1/search', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ query: 'fitness creators in NYC', limit: 25 }),
});
```
See the [MPP guide](/guides/mpp) for both rails. Same pricing as x402.
## Weighted lookalike seeds
Lookalike search now accepts up to 10 seeds with individual weights (0-1). Higher weights make the API lean more heavily on that seed's characteristics when ranking results.
This is particularly useful when you have campaign performance data — weight your best performers higher and the API finds more creators who skew toward that profile.
```json theme={null}
{
"seeds": [
{ "platform": "instagram", "username": "top_performer", "weight": 1.0 },
{ "platform": "instagram", "username": "decent_creator", "weight": 0.5 }
],
"limit": 25
}
```
See [Lookalikes](/concepts/lookalikes) for weighting strategies.
## Search billing and rate limit alignment
Search billing now cleanly separates the base fee (AI inference cost) from the per-creator delivery fee. Rate limit headers are consistent across all endpoints and accurately reflect credit consumption.
## Campaign match endpoint
`POST /v1/creators/match` scores creators against a campaign brief. Each result includes a decision (`good`, `neutral`, or `avoid`), a numeric score, and human-readable reasoning.
The `intent.query` field (500 chars) describes the campaign. The optional `intent.context` field (2,000 chars) adds background — target demographics, content format preferences, brand guidelines.
See [Match Reasons](/concepts/match-reasons) for how to interpret the output.
## Credit-based rate limiting with trust tiers
Rate limits are now enforced using credit budgets instead of simple request counts. Heavier endpoints consume more budget than lighter ones. Trust tiers increase your limits based on lifetime spend — and never downgrade.
See [Rate Limits & Tiers](/concepts/quotas-and-limits) for the full tier table.
## TypeScript SDK via Stainless
The official TypeScript SDK is available on npm. Generated from the OpenAPI spec by [Stainless](https://stainlessapi.com), it provides typed methods, request/response models, and error classes like `RateLimitError` and `APIError`.
```bash theme={null}
npm install influship
```
See the [SDK guide](/sdks) for setup and common operations.
## Stripe usage billing
API usage is now billed through Stripe with automatic invoice generation. Credits accumulate until your trust tier's billing threshold is reached, then an invoice is created. Payment upgrades your tier and increases rate limits.
See [Pricing](/concepts/pricing) for credit costs and [Rate Limits & Tiers](/concepts/quotas-and-limits) for threshold details.
# Creators vs Profiles
Source: https://docs.influship.com/concepts/creators-vs-profiles
Understand when to use creator IDs and when to use platform usernames
# Creators vs Profiles
The API separates the person from their social accounts. Understanding this split helps you pick the right endpoint and avoid redundant lookups.
* A **creator** is the person or brand.
* A **profile** is one social account on one platform.
One creator can have multiple known profiles. The public creator and profile endpoints expose Instagram profiles.
```mermaid theme={null}
graph TD
A[Creator: Priya Sharma]
A --> B[Instagram Profile: @priya_fitness]
A --> C[Instagram Profile: @priyawellness]
```
## Which Endpoint to Use
| You know\... | Use... | Why |
| ----------------------------------------- | ---------------------------------------- | ---------------------------------------------------- |
| A search idea | `POST /v1/search` | Find Instagram creators by natural-language criteria |
| One exact social account | `GET /v1/profiles/{platform}/{username}` | Resolve a known profile |
| Many exact social accounts | `POST /v1/profiles/lookup` | Batch known platform + username pairs |
| A creator ID | `GET /v1/creators/{id}` | Fetch the creator record |
| A creator ID and want linked profiles too | `GET /v1/creators/{id}?include=profiles` | Expand a creator into linked accounts |
## Typical Workflow
If you start from a known username:
1. Call `GET /v1/profiles/{platform}/{username}` or `POST /v1/profiles/lookup`.
2. Read the returned `creator_id`.
3. Call `GET /v1/creators/{id}?include=profiles` to see the creator and all their linked accounts together.
If you start from discovery:
1. Call `POST /v1/search`.
2. Pick a creator from the response.
3. Call `GET /v1/creators/{id}?include=profiles` to get the full picture.
## Why the Split Exists
Creators and profiles answer different questions.
| Question | Object |
| -------------------------------------------------- | --------------------- |
| "Who is this person or brand?" | Creator |
| "What is their Instagram username?" | Profile |
| "What social profiles are linked to this creator?" | Creator with profiles |
| "Does this exact account exist?" | Profile |
Keeping them separate means you can look up a single social account without pulling in everything about the creator, and you can fetch a creator without needing to know which platform they're on.
## Common Patterns
### Search and then expand
Use `POST /v1/search` to find relevant creators, then open one by ID when you want more detail. This keeps the search response lightweight while still giving you a path to full creator data.
### Verify a single account
Use `GET /v1/profiles/{platform}/{username}` when you already know the platform and username. This is the fastest way to check whether an account exists in the system and grab its `creator_id`.
### Batch known accounts
Use `POST /v1/profiles/lookup` when you have a list of accounts to resolve. This saves you from making individual profile requests and returns all the `creator_id` mappings in one call.
# Lookalikes
Source: https://docs.influship.com/concepts/lookalikes
Find creators similar to ones you already know, with weighted seeds and filtering
# Lookalikes
Lookalike search finds creators who resemble a set of seed creators. You provide one or more examples of what you're looking for, and the API returns ranked results based on content themes, audience overlap, posting style, and engagement patterns.
This is useful when you have creators that work and want to find more like them — or when you need to replace a creator who declined and want someone with a similar profile.
## How It Works
1. You provide 1-10 seed creators (by ID or platform + username)
2. Optionally weight each seed to control how much it influences results
3. The API analyzes content, audience, and style similarities
4. You get back ranked results with similarity scores and human-readable shared traits
Each result tells you *why* a creator is similar, not just *that* they are.
## Seeds
A seed is a reference creator. You can identify seeds two ways:
```json theme={null}
// By creator ID (if you already have one from search or a previous lookup)
{ "creator_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "weight": 1.0 }
// By platform + username (if you're starting from a social handle)
{ "platform": "instagram", "username": "fitness_coach_jane", "weight": 1.0 }
```
You can mix both formats in the same request. If a platform + username can't be found, the API skips that seed and continues with the rest — the request only fails if *none* of the seeds resolve.
A resolved creator can still be unavailable for similarity matching. In that case, the endpoint returns `404 seed_not_found`. Choose another seed instead of retrying the same request.
## Weighting
Weights control how much each seed influences the results. They range from 0 to 1, with 1.0 as the default.
```json theme={null}
{
"seeds": [
{ "platform": "instagram", "username": "top_performer", "weight": 1.0 },
{ "platform": "instagram", "username": "decent_creator", "weight": 0.5 },
{ "platform": "instagram", "username": "niche_pick", "weight": 0.3 }
],
"limit": 20
}
```
A higher weight means the API leans more heavily on that seed's characteristics when ranking results. This is where lookalike search becomes genuinely useful beyond simple "find similar" — you can encode your preferences into the weights.
### Using Performance Data as Weights
If you have campaign performance data (ROI, conversion rates, engagement), turn it into weights. Your best-performing creator gets weight 1.0, and others scale relative to that.
For example, if you ran a campaign with three creators:
| Creator | Campaign ROI | Weight |
| ---------------- | ------------ | ------ |
| @top\_performer | 4.2x | 1.0 |
| @decent\_creator | 2.1x | 0.5 |
| @niche\_pick | 1.3x | 0.3 |
The resulting lookalike search finds creators who skew toward your best performer's profile while still incorporating traits from the others. Over time, this creates a feedback loop — each campaign's results improve your next lookalike search.
## Filters
Apply the same filters available on search to narrow lookalike results:
```json theme={null}
{
"seeds": [
{ "platform": "instagram", "username": "fitness_coach_jane" }
],
"filters": {
"followers": { "min": 25000, "max": 500000 },
"engagement_rate": { "min": 2.0 },
"verified": true
},
"limit": 15
}
```
| Filter | Type | Description |
| --------------------------------------------- | ------- | ---------------------------------------- |
| `followers.min` / `followers.max` | integer | Follower count range |
| `engagement_rate.min` / `engagement_rate.max` | number | Engagement rate as percentage (2.0 = 2%) |
| `verified` | boolean | Only verified accounts |
## Response
Each result includes a similarity score and shared traits explaining the match:
```json theme={null}
{
"data": [
{
"creator": {
"id": "d9e8f7a6-b5c4-3d2e-1f0a-9b8c7d6e5f4a",
"name": "Lena Park",
"bio": "Yoga & strength training | NYC",
"avatar_url": "https://cdn.example.com/lena.jpg"
},
"primary_profile": {
"platform": "instagram",
"username": "lenapark_fit",
"url": "https://www.instagram.com/lenapark_fit",
"followers": 87000,
"engagement_rate": 4.1,
"is_verified": false
},
"similarity": {
"score": 0.89,
"shared_traits": [
"Both focus on fitness and wellness content",
"Similar audience demographics (women 25-34)",
"Comparable engagement patterns on workout videos",
"Clean, professional content style"
]
}
}
],
"has_more": true,
"next_cursor": "eyJvZmZzZXQiOjI1fQ=="
}
```
The `similarity.score` ranges from 0 to 1. Scores above 0.8 typically indicate strong overlap. The `shared_traits` list explains what the seed and result have in common — useful for displaying to end users or for your own review.
## Pagination
Lookalike uses cursor pagination. Pass `next_cursor` from the response to fetch the next page:
```bash theme={null}
curl -X POST https://api.influship.com/v1/creators/lookalike \
-H 'X-API-Key: YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-d '{
"seeds": [{"platform": "instagram", "username": "fitness_coach_jane"}],
"limit": 25,
"cursor": "eyJvZmZzZXQiOjI1fQ=="
}'
```
Stop when `has_more` is `false`. See the [Pagination guide](/guides/pagination) for patterns.
## Pricing
Lookalike is billed per creator returned: **1.5 credits per creator** (\$0.015). No base fee. See [Pricing](/concepts/pricing) for the full table.
## Limits
| Parameter | Min | Max | Default |
| --------------- | --- | --- | ------- |
| Seeds | 1 | 10 | -- |
| Weight per seed | 0 | 1 | 1.0 |
| Limit (results) | 1 | 100 | 25 |
## Implementation Advice
* **Start with one seed** to calibrate. Add more seeds once you understand what the single-seed results look like.
* **Use weights to encode knowledge.** If you know one creator drives better results than another, the weights should reflect that. Don't default everything to 1.0 if you have data.
* **Combine with match scoring.** Run lookalike to expand your list, then pass the results through `POST /v1/creators/match` with your campaign brief to filter for actual campaign fit. Lookalikes find *similar* creators — match scoring tells you if they're a good fit for *this specific campaign*.
# Match Reasons
Source: https://docs.influship.com/concepts/match-reasons
Understand the AI explanations returned by search, lookalike, and match endpoints
# Match Reasons
Every scored result includes human-readable reasons explaining why a creator was returned. These reasons help you validate results, build trustworthy UIs, and debug queries that aren't landing.
## Where Reasons Appear
| Endpoint | Field | What it explains |
| ----------------------------- | --------------------------------- | ---------------------------------------------------------------- |
| `POST /v1/search` | `data[].match.reasons` | Why the creator matches your query |
| `POST /v1/creators/lookalike` | `data[].similarity.shared_traits` | Why the creator is similar to the seed |
| `POST /v1/creators/match` | `data[].match.reasons` | Why the creator is a good, neutral, or poor fit for the campaign |
## Search Reasons
Search results include a score, a plain-text `reasons` list, and — new — a structured `evidence` array that grounds each reason, plus a `confidence` value and a `low_confidence` marker:
```json theme={null}
{
"data": [
{
"creator": {
"id": "a3f1b9c2-d4e5-6f7a-8b9c-0d1e2f3a4b5c",
"name": "Nadia Kaur"
},
"match": {
"score": 0.92,
"confidence": 0.92,
"low_confidence": false,
"reasons": [
"Publishes ingredient-education Reels on sensitive-skin routines",
"High engagement rate suggests an active audience"
],
"evidence": [
{
"text": "Publishes ingredient-education Reels on sensitive-skin routines",
"provenance": "post_evidence",
"fact_id": "b7c1f0a2-3d4e-5f60-8a9b-0c1d2e3f4a5b",
"source_post_id": "23256c2e-51fa-4389-a4a1-945e461e951b",
"evidence_quote": "Today we break down why fragrance wrecks a sensitive-skin barrier…"
},
{
"text": "High engagement rate suggests an active audience",
"provenance": "inferred",
"fact_id": null,
"source_post_id": null,
"evidence_quote": null
}
]
}
}
]
}
```
`reasons` (plain strings) is unchanged and still supported. `evidence` is the same reasons in a structured form — reach for it when you want to show a buyer *why* to trust a match, not just that it scored well.
### Provenance
Every entry in `evidence` carries a `provenance` label so you can tell a grounded claim from an inference. Strongest first:
| `provenance` | Meaning | What you get |
| --------------- | ------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `post_evidence` | Backed by a specific post you can open | `source_post_id` (fetch it via `GET /v1/posts/{id}`) and, when a genuinely supporting sentence exists, a verbatim `evidence_quote` from that post's caption or transcript |
| `profile_fact` | Backed by a stored profile fact, but with no clickable source post | `fact_id`, no `source_post_id` |
| `inferred` | Model reasoning over the profile, no direct post evidence | `text` only |
The `evidence_quote` is the sentence from the source post that best supports the reason, copied verbatim — never model-generated, so it can't be a fabricated citation. When no sentence in the post actually supports the claim, the quote is omitted (`null`) and you still get the clickable `source_post_id`. Treat `profile_fact` as weaker than `post_evidence` (there's nothing to click through to) and `inferred` as the softest signal — style them accordingly.
### Confidence and the weak tail
`confidence` mirrors `score` (0–1). `low_confidence` is `true` when a result falls in the weak tail of the ranking — a non-breaking marker so you can draw a "weaker matches" divider instead of presenting every returned creator as an equally strong match. It never changes which results are returned; it only labels them.
## Lookalike Reasons
Lookalike results explain shared traits between the seed creator and the match:
```json theme={null}
{
"data": [
{
"creator": {
"id": "e8d7c6b5-a4f3-2e1d-0c9b-8a7f6e5d4c3b",
"name": "Marcus Rivera"
},
"similarity": {
"score": 0.87,
"shared_traits": [
"Both focus on fitness and wellness content",
"Similar audience demographics",
"Comparable engagement patterns on workout videos"
]
}
}
]
}
```
Typical themes: content overlap, audience similarity, style, and performance patterns.
## Campaign Match Reasons
`POST /v1/creators/match` returns structured campaign-fit output with a decision and supporting reasons:
```json theme={null}
{
"data": [
{
"creator": {
"id": "f9e8d7c6-b5a4-3f2e-1d0c-9b8a7f6e5d4c"
},
"match": {
"score": 0.88,
"decision": "good",
"reasons": [
{
"text": "Reviews protein bars and macro-friendly snacks in weekly Reels",
"provenance": "post_evidence",
"fact_id": "fact_abc123",
"source_post_id": "9b8a7f6e-5d4c-3b2a-1f0e-9d8c7b6a5f4e",
"evidence_quote": "This bar packs 20g of protein and actually tastes like dessert…"
}
]
}
}
]
}
```
| Decision | Meaning |
| --------- | ----------------------------------- |
| `good` | Strong fit for the campaign |
| `neutral` | Could work — review manually |
| `avoid` | Weak fit, likely not worth pursuing |
Campaign-match reasons carry the same `provenance` label as search evidence (`post_evidence`, `profile_fact`, `inferred`). When present, `source_post_id` points at a post you can open via `GET /v1/posts/{id}`, and `evidence_quote` is a verbatim snippet from that post. The `fact_id` is an internal reference to the supporting data point — use `source_post_id` and `evidence_quote` for anything user-facing.
## How to Use Reasons
* **Surface them in your UI.** Reasons make AI-driven results feel transparent. Showing "Strong sustainable fashion focus" next to a creator helps your users trust the ranking.
* **Validate your queries.** If the reasons don't match your intent, the query needs refining — tighten the language or add filters.
* **Compare across results.** Reasons help you understand why one creator ranked higher than another, beyond just the numeric score.
* **Debug broad searches.** When results feel off, the reasons usually reveal whether the query was too vague or the filters too loose.
## Scores vs Reasons
Treat the score as the summary and the reasons as the explanation. A high score with reasons that don't match your intent is a signal to refine the query, not to trust the number.
# Pricing
Source: https://docs.influship.com/concepts/pricing
Credit-based pricing for the Influship API
# Pricing
The Influship API uses credits at **\$0.01 per credit**. API-key and OAuth calls are billed for successful operations.
API-key and OAuth requests that return a `4xx` or `5xx` response are not charged. Agentic payment rails have separate settlement timing; see [x402 pricing](/guides/x402) and [MPP pricing](/guides/mpp).
## Price Table
| Endpoint | Cost model | Credits | Effective price |
| -------------------------------------------------- | -------------------------------------------- | ---------------: | ------------------------: |
| `POST /v1/search` | Base + per creator delivered | `25 + 2/creator` | `\$0.25 + \$0.02/creator` |
| `GET /v1/search/{id}` | Free pagination | `0` | `\$0.00` |
| `POST /v1/creators/lookalike` | Per creator delivered | `1.5/creator` | `\$0.015/creator` |
| `POST /v1/creators/match` | Per creator scored | `1/creator` | `\$0.01/creator` |
| `GET /v1/creators/{id}` | Per request | `0.1` | `\$0.001` |
| `GET /v1/creators/autocomplete` | Per request | `0.05` | `\$0.0005` |
| `POST /v1/creators/ingest` | Per creator ingested (new only) | `5` | `\$0.05` |
| `GET /v1/profiles/{platform}/{username}` | Per request | `0.1` | `\$0.001` |
| `POST /v1/profiles/lookup` | Per profile found | `0.1/profile` | `\$0.001/profile` |
| `POST /v1/creator-emails/lookup` | Per creator with at least one email returned | `5/creator` | `\$0.05/creator` |
| `GET /v1/posts` | Per post returned | `0.05/post` | `\$0.0005/post` |
| `GET /v1/raw/instagram/profile/{username}` | Per profile | `0.5` | `\$0.005` |
| `GET /v1/raw/instagram/post/{shortcode}` | Per post | `1` | `\$0.01` |
| `POST /v1/raw/instagram/posts` | Per successful post | `1/post` | `\$0.01/post` |
| `GET /v1/raw/instagram/transcript/{shortcode}` | Per transcript | `5` | `\$0.05` |
| `POST /v1/raw/instagram/transcripts` | Per successful transcript | `5/transcript` | `\$0.05/transcript` |
| `GET /v1/raw/tiktok/profile/{username}` | Per profile | `0.2` | `\$0.002` |
| `GET /v1/raw/tiktok/profile/{username}/videos` | Per source page | `0.2` | `\$0.002` |
| `GET /v1/raw/tiktok/video` | Per video | `0.2` | `\$0.002` |
| `GET /v1/raw/tiktok/video/comments` | Per source page | `0.2` | `\$0.002` |
| `GET /v1/raw/tiktok/video/comment/replies` | Per reply page | `0.2` | `\$0.002` |
| `GET /v1/raw/tiktok/music` | Per sound lookup | `0.2` | `\$0.002` |
| `GET /v1/raw/tiktok/search/users` | Per source page | `0.2` | `\$0.002` |
| `GET /v1/raw/tiktok/search/videos` | Per source page | `0.2` | `\$0.002` |
| `GET /v1/raw/tiktok/hashtag/videos` | Per source page | `0.2` | `\$0.002` |
| `GET /v1/raw/tiktok/music/videos` | Per source page | `0.2` | `\$0.002` |
| `GET /v1/raw/tiktok/video/captions` | Per delivered caption response | `0.2` | `\$0.002` |
| `GET /v1/raw/tiktok/video/transcript` | Per transcript | `2.5` | `\$0.025` |
| `POST /v1/raw/tiktok/videos` | Per successful video (1–20 URLs) | `0.2` | `\$0.002` |
| `POST /v1/raw/tiktok/video/transcripts`, auto | Per successful transcript (1–10 URLs) | `2.5` | `\$0.025` |
| `POST /v1/raw/tiktok/video/transcripts`, captions | Per successful caption response (1–10 URLs) | `0.2` | `\$0.002` |
| `GET /v1/raw/youtube/channel/{handle}` | Per channel | `0.5` | `\$0.005` |
| `GET /v1/raw/youtube/transcript/{video_id}` | Per transcript | `0.5` | `\$0.005` |
| `GET /v1/raw/youtube/channel-transcripts/{handle}` | Per transcript returned | `0.5/transcript` | `\$0.005/transcript` |
| `GET /v1/raw/youtube/search` | Per fetched page | `0.5` | `\$0.005` |
| `GET /v1/raw/youtube/video/{video_id}` | Per video | `0.5` | `\$0.005` |
| `GET /v1/raw/youtube/typeahead` | Per request | `0.5` | `\$0.005` |
Batch Instagram and TikTok raw endpoints charge credit-metered API-key and OAuth calls only for successful items. TikTok transcript pricing is fixed for every delivered transcript, including a cached result. Pay-per-request x402 and MPP batches quote all requested items. Settled payments are nonrefundable, including partial or entirely failed batches. The premium and whole-cent rounding apply once to the total batch, not separately to each item.
## Why Search Has a Base Fee
Search runs AI inference on every query — your natural language input is processed through embedding models and matched against the creator index. The 25-credit base fee covers that compute cost, regardless of how many results match. The per-creator fee scales with what you actually receive.
This means a search that finds 3 results costs less than one that finds 25, even though the same inference ran on both.
## Search Pricing in Detail
* Base fee: **25 credits** per search
* Per creator: **2 credits** per delivered result
* Limit sets the cap on how many results the search session can return
* Pagination via `GET /v1/search/{id}` is free
| Scenario | Credits | Cost |
| ---------------------------------- | ------: | -----: |
| `limit: 5`, 5 creators delivered | 35 | \$0.35 |
| `limit: 10`, 7 creators delivered | 39 | \$0.39 |
| `limit: 10`, 10 creators delivered | 45 | \$0.45 |
| `limit: 25`, 20 creators delivered | 65 | \$0.65 |
| `limit: 25`, 25 creators delivered | 75 | \$0.75 |
## What Does a Typical Month Cost?
Building a creator discovery tool, running 100 searches/month with some lookups and matching.
```
100 searches (limit: 10 avg) = 4,500 credits
200 creator lookups = 20 credits
50 match scorings (5 creators each) = 250 credits
─────────────────────────────────────
Total = 4,770 credits
Monthly cost = $47.70
```
Running campaigns for multiple clients, 500 searches/month with heavy lookalike usage.
```
500 searches (limit: 15 avg) = 27,500 credits
1,000 creator lookups = 100 credits
200 lookalike searches (15 results) = 4,500 credits
500 match scorings (10 creators) = 5,000 credits
─────────────────────────────────────
Total = 37,100 credits
Monthly cost = $371.00
```
Integrating search into a product, 5,000+ searches/month with autocomplete.
```
5,000 searches (limit: 10 avg) = 225,000 credits
50,000 autocomplete requests = 2,500 credits
10,000 creator lookups = 1,000 credits
1,000 lookalike searches (20 results)= 30,000 credits
─────────────────────────────────────
Total = 258,500 credits
Monthly cost = $2,585.00
```
At this volume, reach out for volume pricing — [elliot@influship.com](mailto:elliot@influship.com).
## Free Tier
Every new account starts with credits to explore the API. The free tier includes:
* **1,500 credits/hour** rate limit budget
* **150 credits/minute** rate limit budget
* Credits to run searches, lookups, and match scoring
This is enough to prototype an integration, test query quality, and evaluate the response format before committing to a paid plan. Once you make your first payment, your account upgrades to Tier 1 with higher rate limits.
See [Rate Limits & Tiers](/concepts/quotas-and-limits) for the full tier breakdown.
## Track Cost Per Request
Every successful response includes billing headers:
```http theme={null}
X-Credits-Charged: 45.00
X-Credits-Features: creators.search
X-Billing-Plan: free
RateLimit-Remaining-Minute: 105
```
```typescript TypeScript theme={null}
const response = await fetch('https://api.influship.com/v1/search', {
method: 'POST',
headers: { 'X-API-Key': API_KEY, 'Content-Type': 'application/json' },
body: JSON.stringify({ query: 'fitness creators', limit: 10 }),
});
const charged = response.headers.get('X-Credits-Charged');
const feature = response.headers.get('X-Credits-Features');
console.log(`Charged ${charged} credits for ${feature}`);
```
```python Python theme={null}
response = requests.post(
'https://api.influship.com/v1/search',
headers={'X-API-Key': API_KEY},
json={'query': 'fitness creators', 'limit': 10},
)
print(f"Charged {response.headers['X-Credits-Charged']} credits")
print(f"Feature: {response.headers['X-Credits-Features']}")
```
## What Tiers Change
Trust tiers do not change endpoint prices. They change your rate-limit budgets and billing thresholds. See [Rate Limits & Tiers](/concepts/quotas-and-limits) for details.
## Cost Controls
* **Keep search `limit` tight.** Start with 5-10 while prototyping. Results past the top 15-20 are usually lower relevance anyway.
* **Reuse creator and profile responses where appropriate.** Creator data changes less often than live platform data, so repeated lookups may be unnecessary.
* **Use autocomplete for search-as-you-type.** At 0.05 credits per request, it's 500x cheaper than running a full search on every keystroke.
* **Batch known work.** If you have a list of usernames, use `POST /v1/profiles/lookup` instead of individual lookups.
API-key and OAuth requests are not billed when they return a `4xx` or `5xx` response. This includes validation errors, authentication or permission failures, unavailable data, rate limits, and temporary service failures.
Pagination via `GET /v1/search/{id}` is also free — you're stepping through results you already paid for.
x402 settlement is final when `PAYMENT-RESPONSE` reports success, including on an error response. MPP authorizes and settles before the endpoint runs, so an error response can still carry a `Payment-Receipt`. See [x402](/guides/x402) and [MPP](/guides/mpp) for the settlement contracts.
There are no monthly credit allocations or rollover mechanics. Credits are charged per request as you use them. Your bill reflects actual usage.
You get a `429` response. No credits are charged for rate-limited requests. Wait for the reset window or reduce your request rate. See [Rate Limits & Tiers](/concepts/quotas-and-limits).
**Enterprise customers** may have custom pricing, rate limits, and billing terms negotiated outside the standard tiers. If your current plan doesn't reflect your agreement, reach out at [elliot@influship.com](mailto:elliot@influship.com).
If you're an early-stage startup, check out the [startup program](mailto:elliot@influship.com) for discounted access.
# Rate Limits & Tiers
Source: https://docs.influship.com/concepts/quotas-and-limits
Credit budgets, trust tiers, and how to handle 429 and 402 responses
# Rate Limits & Tiers
The Influship API uses credit-based rate limiting. Each request consumes part of your per-minute and per-hour budget based on the credit cost of that operation.
## How Limits Work
Two windows are enforced for every API key:
| Window | Purpose | Free tier budget |
| ---------- | ------------------------- | ---------------: |
| Per minute | Prevent short spikes | 150 credits |
| Per hour | Prevent sustained overuse | 1,500 credits |
Heavier endpoints use more of that budget than lighter ones. A search with `limit: 10` consumes roughly 45 credits of budget, while an autocomplete call consumes 0.05. This means you can make thousands of autocomplete requests in the time it takes to exhaust the budget on a few dozen searches.
See [Pricing](/concepts/pricing) for the full credit cost table.
## Trust Tiers
Trust tiers increase your rate limits as your account matures. They're based on lifetime spend — not monthly spend — and they never downgrade. A slow month doesn't reduce your limits.
| Tier | Credits/min | Credits/hour | Billing threshold | How to reach |
| ------------ | ----------: | -----------: | ----------------: | ----------------------------------------- |
| `free` | 150 | 1,500 | \$5 | Signup |
| `tier_1` | 750 | 7,500 | \$25 | First successful payment |
| `tier_2` | 3,000 | 30,000 | \$100 | \$500 lifetime spend |
| `tier_3` | 15,000 | 150,000 | \$250 | \$2,000 lifetime spend |
| `enterprise` | custom | custom | custom | [Contact us](mailto:elliot@influship.com) |
Tiers affect rate limits and billing thresholds only. They do not change endpoint prices — a search costs the same credits on the free tier as on Tier 3.
### How Billing Thresholds Work
An invoice is generated when your accumulated usage reaches your tier's billing threshold. On the free tier, that's \$5. After your first successful payment, you move to Tier 1 and the threshold increases to \$25. This means you're invoiced less frequently as your account matures.
### Checking Your Current Tier
Every response includes the `X-Billing-Plan` header with your current tier code:
```http theme={null}
X-Billing-Plan: tier_1
```
## Response Headers
Every successful response includes your current rate limit state:
| Header | Description |
| ---------------------------- | -------------------------------------------- |
| `RateLimit-Limit-Minute` | Credits allowed in the current minute window |
| `RateLimit-Remaining-Minute` | Credits left in the current minute window |
| `RateLimit-Reset-Minute` | Unix timestamp when the minute window resets |
| `RateLimit-Limit-Hour` | Credits allowed in the current hour window |
| `RateLimit-Remaining-Hour` | Credits left in the current hour window |
| `RateLimit-Reset-Hour` | Unix timestamp when the hour window resets |
| `X-Billing-Plan` | Current trust tier code |
Example after a search on the free tier:
```http theme={null}
RateLimit-Limit-Minute: 150
RateLimit-Remaining-Minute: 105
RateLimit-Reset-Minute: 1703571600
RateLimit-Limit-Hour: 1500
RateLimit-Remaining-Hour: 1455
RateLimit-Reset-Hour: 1703575200
X-Billing-Plan: free
```
Monitor `RateLimit-Remaining-Minute` and `RateLimit-Remaining-Hour` if you're running batch operations. When either hits zero, the next request gets a 429.
## What Happens at the Limit
There's no warning before you hit a rate limit — the API doesn't send a "you're close" signal. When a request would push usage above either the minute or hour budget, it's rejected with a `429` immediately. The request is not charged.
This means for production integrations, you should track the remaining budget headers proactively rather than waiting for a 429.
## 429 Rate Limit Exceeded
```json theme={null}
{
"error": {
"code": "rate_limit_exceeded",
"message": "Rate limit exceeded (per minute)",
"status_code": 429
}
}
```
How to handle it:
1. Check the `Retry-After` header if present — it tells you how many seconds to wait
2. Otherwise, read `RateLimit-Reset-Minute` or `RateLimit-Reset-Hour` for the next window
3. Implement exponential backoff: wait `2^attempt` seconds, capped at 60s, with jitter
4. If this happens regularly, reduce concurrency or increase your tier
### Failed-authentication throttling
Repeated requests with a missing or invalid API key are also throttled. After several failed attempts, subsequent requests return `429 rate_limit_exceeded` with the message `"Too many failed authentication attempts. Please try again later."` and a `Retry-After` header indicating when the block lifts. This response has no `RateLimit-*` headers — fix the API key rather than retrying.
## 503 Is Not Your Account Rate Limit
Live data endpoints can return `503 service_unavailable` when an upstream platform temporarily throttles or blocks a live scrape. These responses may include `Retry-After` plus `error.details.retry_after_seconds`.
Handle them as retryable temporary upstream failures, but don't show them to users as "your API key is rate limited." Your account-level rate limit is always `429 rate_limit_exceeded`.
## 402 Payment Required
```json theme={null}
{
"error": {
"code": "payment_required",
"message": "Payment required to continue API access",
"status_code": 402,
"reason_code": "PAYMENT_FAILED",
"next_step": "update_payment_method"
}
}
```
Use `reason_code` for the specific billing or subscription state and `next_step` for the recovery action. Don't retry 402 automatically.
Search can return a different 402 body when remaining credits cannot cover the request:
```json theme={null}
{
"error": {
"code": "insufficient_credits",
"message": "Not enough credits remaining for this search. Add a payment method to continue.",
"details": {
"remaining": 10,
"required": 75,
"add_payment_method": true
}
}
}
```
That shape has no `reason_code` or `next_step`. Add a payment method and retry; do not treat it as a transient failure.
For `payment_required`:
1. Check the [dashboard](https://developers.influship.com) for outstanding invoices
2. Update your payment method if needed
3. Pay the invoice
4. Access resumes immediately after payment
## Daily Ingest Quota
On-demand creator ingest (`POST /v1/creators/ingest`) has a separate per-account daily quota on top of the credit rate limits, because each ingest kicks off background profile building. The default is **50 ingests per UTC day**.
Exceeding it returns `429` with `error.code: "quota_exceeded"` and a `Retry-After` header pointing to the next UTC midnight. This is distinct from the credit `rate_limit_exceeded` throttle — it is a volume guard specific to ingest, and like other `429` responses it is not charged.
Ingest itself costs **5 credits (\$0.05)** and is charged only when a new creator is seeded. See [Ingest Creators On Demand](/guides/ingest-creators-on-demand) for the full flow.
## Good Practices
* **Monitor your budget headers.** Log `RateLimit-Remaining-Minute` and `RateLimit-Remaining-Hour` on every response. Set alerts before they hit zero.
* **Keep search `limit` tight.** A `limit: 25` search consumes 75 credits of your minute budget. Five of those in quick succession can exhaust a free-tier minute window.
* **Batch known work.** `POST /v1/profiles/lookup` resolves multiple profiles in one request with minimal rate-limit impact, compared to calling `GET /v1/profiles/{platform}/{username}` in a loop.
* **Treat 429, 503, and 402 differently.** 429 is your account throttle — back off and retry. 503 from live data is an upstream/platform throttle — retry later without blaming the user's key. 402 is a billing issue — surface it to your ops team and stop retrying.
* **Budget for the free tier.** On the free tier, you can run roughly 3 searches per minute (at `limit: 10`) or \~33 per hour. That's enough for prototyping but not for a production integration with real traffic. Upgrade early.
# Semantic Search
Source: https://docs.influship.com/concepts/semantic-search
How AI-powered search finds relevant creators
# Semantic Search
Search understands intent, not just keywords. You describe the kind of creator you're looking for and the API ranks results by relevance. Instead of matching exact words in bios or hashtags, it interprets the meaning behind your query and finds creators whose content, audience, and style align with what you need.
## What Search Understands
Search works at two levels: **factual knowledge** and **style and vibes**.
### Factual Knowledge
Influship indexes specific facts about creators — things they've done, places they've been, preferences they've expressed. You can search for concrete details and the engine matches against real data points from creator content and bios.
Examples of factual queries:
* `went to Coachella`
* `is a frequent flyer`
* `likes Thai food and lives in LA`
* `is going to college next year`
* `has a golden retriever`
* `recently moved to New York`
These work because the engine has extracted and indexed specific facts from creator content, captions, and bios. If a creator posted about attending Coachella, a search for "went to Coachella" will find them.
### Style and Vibes
Search also understands more subjective qualities — the overall feel of a creator's content, their tone, and the kind of audience they attract. This is where it goes beyond a database lookup and into genuine semantic matching.
Examples of style-based queries:
* `funny creators who don't take themselves too seriously`
* `calm, aesthetic, minimalist content`
* `raw and unfiltered — not polished or aspirational`
* `educational but not boring`
* `creators who feel like your friend, not a brand`
You can combine both in a single query: `fitness creators in LA who went to Coachella and have a funny, relatable style` works because the engine handles factual and stylistic signals together.
### Hard Filters
On top of the semantic matching, hard filters constrain results to creators who meet specific numeric or boolean requirements:
* follower ranges
* engagement rate floors
* verification status
* platform
Filters are applied after semantic ranking, so they narrow the pool without changing how relevance is scored.
### Geography
When your query names a country (for example `UK skincare creators` or `American fitness influencers`), geography is treated as a hard requirement, not a preference. A creator whose verified location contradicts the requested country is excluded from results. A creator whose location can't be verified is still returned, but flagged with `location_unverified: true` so you can tell an assumed match from a confirmed one. When your query names no country, `location_unverified` is `null` on every result.
## Write Better Queries
Good queries usually include:
* a niche or topic
* an audience trait or outcome
* optional platform context
* optional content style or vibe
Examples:
* `fitness creators focused on home workouts`
* `sustainable fashion creators with engaged audiences`
* `educational skincare creators on Instagram`
* `travel photographers who feel authentic and adventurous, not luxury or aspirational`
* `tech reviewers who explain things simply — like they're talking to a friend`
Weak queries are too vague to guide ranking:
* `influencer`
* `someone popular`
* `good creator`
Queries can be up to 500 characters. That's plenty for a detailed brief — use the space. The more specific you are about both facts and feel, the better the results.
## What You Get Back
Each result includes:
* `creator`: the canonical creator record
* `relevant_profile`: the profile most relevant to the search query, or `null` when no profile data is available
* `primary_profile`: the creator's largest profile, or `null` when no profile data is available
* `match.score`: a 0-1 relevance score
* `match.confidence`: the same 0-1 relevance, named for callers that want an explicit confidence signal
* `match.low_confidence`: `true` for results in the weak tail, so you can separate "weaker matches" instead of treating every result as strong
* `match.reasons`: short plain-text explanations for why the creator matched
* `match.evidence`: the same reasons in structured form, each with a `provenance` label and, where the reason rests on a post, a `source_post_id` and a verbatim `evidence_quote` — see [Match Reasons](/concepts/match-reasons)
* `location_unverified`: geography honesty flag (see below); `null` when your query named no country
These fields can differ when the profile that best explains the match is not the creator's largest profile.
Example:
```json theme={null}
{
"data": [
{
"creator": {
"id": "c7a3e9d1-f5b2-4e8c-a6d0-3b9f1c7e5a2d",
"name": "Jamie Torres"
},
"relevant_profile": {
"platform": "instagram",
"username": "jamietravels"
},
"primary_profile": {
"platform": "instagram",
"username": "jamietravels"
},
"match": {
"score": 0.92,
"confidence": 0.92,
"low_confidence": false,
"reasons": [
"Strong sustainable travel focus with eco-tourism content",
"High engagement on destination and gear reviews"
],
"evidence": [
{
"text": "Strong sustainable travel focus with eco-tourism content",
"provenance": "post_evidence",
"fact_id": "b7c1f0a2-3d4e-5f60-8a9b-0c1d2e3f4a5b",
"source_post_id": "23256c2e-51fa-4389-a4a1-945e461e951b",
"evidence_quote": "Skipping the resort — here's how to travel this coast low-impact…"
},
{
"text": "High engagement on destination and gear reviews",
"provenance": "inferred",
"fact_id": null,
"source_post_id": null,
"evidence_quote": null
}
]
},
"location_unverified": null
}
],
"search_id": "123e4567-e89b-12d3-a456-426614174000",
"total": 1,
"has_more": false,
"next_cursor": null
}
```
## Read the Score Correctly
The score is a ranking signal, not a guarantee.
* `0.90+` usually means a strong match
* `0.75-0.89` is often usable
* lower scores usually need tighter queries or harder filters
Use the reasons to understand why a creator ranked well before you trust the list.
## Combine Search with Filters
Use semantic search for discovery, then hard filters for boundaries.
```bash theme={null}
curl -X POST https://api.influship.com/v1/search \
-H 'X-API-Key: YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-d '{
"query": "sustainable fashion creators",
"platforms": ["instagram"],
"filters": {
"followers": {
"min": 10000,
"max": 500000
},
"engagement_rate": {
"min": 2.0
},
"verified": true
},
"limit": 25
}'
```
That gives you creators who:
1. match the semantic intent of `sustainable fashion creators`
2. are on Instagram
3. fall within the follower range you care about
4. clear your engagement floor
5. have a verified account
### Available Filters
| Filter | Type | Description |
| ----------------------------- | ------- | ------------------------------------------- |
| `filters.followers.min` | integer | Minimum follower count |
| `filters.followers.max` | integer | Maximum follower count |
| `filters.engagement_rate.min` | number | Minimum engagement rate (0-100, percentage) |
| `filters.engagement_rate.max` | number | Maximum engagement rate (0-100, percentage) |
| `filters.verified` | boolean | Only return verified accounts |
### Platforms
The public search API accepts only `instagram` in the `platforms` array. Omit the field to use that default:
```json theme={null}
{
"query": "tech review creators",
"platforms": ["instagram"],
"limit": 10
}
```
### Limit
`limit` sets the maximum number of results the search session can return. Range: 1-100, default: 25. This determines the billing cap for the session — start small (5-10) while prototyping and increase once you understand how your UI consumes results.
## Search Pagination
Search uses a two-step model: create, then paginate.
**`POST /v1/search`** creates a search session. You set a `limit` that caps the total number of results the session can ever return. You're billed once based on the number of results delivered, up to that limit.
**`GET /v1/search/{id}`** paginates through the results using cursors. These requests are free — you're just stepping through results you've already paid for.
The key thing to understand: `limit` sets a ceiling, not a page size. If you create a session with `limit: 25`, that session will contain at most 25 results total. Pagination lets you retrieve them in smaller batches, but it doesn't unlock additional results beyond the limit.
For cursor mechanics and page size options, see the [Pagination guide](/guides/pagination).
## Implementation Advice
Search accepts natural language, but result quality depends on input quality. If your end users aren't marketers or developers, consider using an LLM to clean up or refine their input before submitting it to the search endpoint. Test both approaches — sometimes raw user input works fine, sometimes a preprocessing step makes a real difference.
Use the [API Reference](/api-reference) for the current generated request and SDK examples. This page explains how search behaves; the reference is the source of truth for exact shapes.
# Build a Creator Shortlist
Source: https://docs.influship.com/cookbook/build-a-shortlist
Search for creators, score them against a campaign brief, and build a ranked shortlist
# Build a Creator Shortlist
This recipe combines search, profile expansion, and campaign match scoring to produce a ranked shortlist of creators for a specific campaign. It has three billable API stages and makes up to 12 requests when you expand ten creators.
## The Flow
1. **Search** for creators matching your criteria
2. **Score** the candidates against your campaign brief
3. **Expand** the top picks with full profile data
## Step 1: Search for Candidates
Start broad. Search returns creators ranked by relevance to your query, so you want a large enough pool to filter down from.
```typescript theme={null}
import Influship from 'influship';
const client = new Influship();
const search = await client.search.create({
query: 'health and wellness creators who make educational content about nutrition',
platforms: ['instagram'],
filters: {
followers: { min: 25000, max: 500000 },
engagement_rate: { min: 2.0 },
},
limit: 30,
});
console.log(`Found ${search.data.length} candidates`);
```
A limit of 30 gives you a good candidate pool. When the search returns all 30 results, the 25 base + (30 x 2) per-creator credits costs 85 credits (\$0.85). Searches that return fewer results cost less.
## Step 2: Score Against Your Campaign Brief
Pass the candidate IDs to the match endpoint with your campaign details. The `query` field (up to 500 chars) describes the campaign, and `context` (up to 2,000 chars) adds background.
```typescript theme={null}
const creatorIds = search.data.map((r) => r.creator.id);
const scored = await client.creators.match({
creators: creatorIds.map((creator_id) => ({ creator_id })),
intent: {
query: 'Promote a new line of plant-based protein supplements',
context:
'Brand is targeting health-conscious millennials aged 25-35. ' +
'Looking for creators who can make authentic educational content, ' +
'not just product placements. Budget is mid-range.',
},
});
```
Each result comes back with a decision (`good`, `neutral`, or `avoid`) and a numeric `score`. At 1 credit per creator scored, this adds up to 30 credits (\$0.30).
## Step 3: Filter and Rank
Pull out the strong fits and sort by score:
```typescript theme={null}
const shortlist = scored.data
.filter((r) => r.match.decision === 'good')
.sort((a, b) => b.match.score - a.match.score);
console.log(`${shortlist.length} creators passed campaign fit scoring`);
for (const item of shortlist.slice(0, 10)) {
console.log(
`${item.creator.id} — score: ${item.match.score}, reason: ${item.match.reasons[0]?.text}`
);
}
```
## Step 4: Expand Top Picks
For the creators you're actually going to pitch, fetch full profiles with linked social accounts:
```typescript theme={null}
const topPicks = await Promise.all(
shortlist.slice(0, 10).map((item) =>
client.creators.retrieve(item.creator.id, { include: ['profiles'] })
),
);
for (const creator of topPicks) {
console.log(creator.data.name);
for (const profile of creator.data.profiles ?? []) {
console.log(` ${profile.platform}: @${profile.username} (${profile.followers} followers)`);
}
}
```
At 0.1 credits per lookup, 10 lookups add 1 credit (\$0.01).
## Maximum Cost
This maximum assumes the search returns 30 creators, all 30 are scored, and ten creator records are expanded. Fewer returned or expanded creators reduce the total.
| Step | Endpoint | Credits | Cost |
| -------------------- | ------------------------- | ------: | ---------: |
| Search (30 results) | `POST /v1/search` | 85 | \$0.85 |
| Score (30 creators) | `POST /v1/creators/match` | 30 | \$0.30 |
| Expand (10 creators) | `GET /v1/creators/{id}` | 1 | \$0.01 |
| **Maximum total** | | **116** | **\$1.16** |
## Tips
* **Write a detailed campaign brief.** The match endpoint uses an LLM to evaluate fit — more context in the `query` and `context` fields produces more accurate decisions. Don't just write "fitness campaign."
* **Search broad, score narrow.** It's cheaper to over-search and then filter with match scoring than to run multiple targeted searches.
* **Cache creator lookups.** If you're building shortlists frequently for similar campaigns, the creator data doesn't change often. Cache the Step 4 responses.
* **Iterate on the query.** If match scoring flags most candidates as `neutral` or `avoid`, your search query may be too broad. Tighten the search, not the scoring threshold.
# Expand a Roster with Lookalikes
Source: https://docs.influship.com/cookbook/expand-with-lookalikes
Use weighted seeds and performance data to find more creators like your best performers
# Expand a Roster with Lookalikes
You have creators that work. Now you need more like them. This recipe uses the lookalike endpoint with weighted seeds to find similar creators, filtered to your requirements, and scored for campaign fit.
The key insight: if you have performance data from previous campaigns, encode it in the weights. Your best-performing creator gets the highest weight, and the API finds more creators who skew toward that profile.
## The Flow
1. **Identify** your seed creators and assign weights based on performance
2. **Run** a lookalike search with filters
3. **Score** results against your next campaign (optional but recommended)
## Step 1: Build Weighted Seeds
Start with creators you've worked with. If you have ROI or engagement data, normalize it to weights:
```typescript theme={null}
import Influship from 'influship';
const client = new Influship();
// Your past campaign data
const campaignResults = [
{ username: 'wellness_maya', roi: 4.2 },
{ username: 'fit_with_dani', roi: 2.8 },
{ username: 'nutrition_neil', roi: 1.5 },
];
// Normalize ROI to 0-1 weights
const maxRoi = Math.max(...campaignResults.map((c) => c.roi));
const seeds = campaignResults.map((c) => ({
platform: 'instagram' as const,
username: c.username,
weight: Math.round((c.roi / maxRoi) * 100) / 100,
}));
// seeds:
// [
// { platform: 'instagram', username: 'wellness_maya', weight: 1.0 },
// { platform: 'instagram', username: 'fit_with_dani', weight: 0.67 },
// { platform: 'instagram', username: 'nutrition_neil', weight: 0.36 },
// ]
```
No performance data? Start with equal weights (1.0). You can also manually weight based on gut feel — give your favorite seed a 1.0 and the others less.
## Step 2: Run the Lookalike Search
```typescript theme={null}
const similar = await client.creators.lookalike({
seeds,
filters: {
followers: { min: 15000, max: 300000 },
engagement_rate: { min: 2.5 },
},
limit: 25,
});
console.log(`Found ${similar.data.length} similar creators`);
for (const result of similar.data.slice(0, 5)) {
console.log(
`${result.creator.name} (@${result.primary_profile?.username})`,
`— similarity: ${result.similarity.score}`,
);
console.log(` Shared traits: ${result.similarity.shared_traits.join(', ')}`);
}
```
At 1.5 credits per result, 25 results costs 37.5 credits (\$0.375).
## Step 3: Score for Campaign Fit (Optional)
Lookalikes find *similar* creators — but similar to your past performers doesn't automatically mean they're right for your *next* campaign. If the campaign is different, score the results:
```typescript theme={null}
const candidateIds = similar.data.map((r) => r.creator.id);
const scored = await client.creators.match({
creators: candidateIds.map((creator_id) => ({ creator_id })),
intent: {
query: 'Launch campaign for a new organic snack brand',
context:
'We need creators who feel authentic, not overly polished. ' +
'The product is a healthy snack bar. Target audience is active ' +
'millennials who care about ingredients.',
},
});
const goodFits = scored.data
.filter((r) => r.match.decision === 'good')
.sort((a, b) => b.match.score - a.match.score);
console.log(`${goodFits.length} of ${candidateIds.length} passed campaign fit`);
```
## Combining Similarity and Fit Scores
If you want a single ranking that blends both signals, weight them based on what matters more:
```typescript theme={null}
// Build a combined score
const combined = similar.data
.map((lookalike) => {
const matchResult = scored.data.find(
(s) => s.creator.id === lookalike.creator.id,
);
if (!matchResult || matchResult.match.decision === 'avoid') return null;
return {
creator: lookalike.creator,
profile: lookalike.primary_profile,
similarityScore: lookalike.similarity.score,
campaignScore: matchResult.match.score,
// 40% similarity, 60% campaign fit
combined: lookalike.similarity.score * 0.4 + matchResult.match.score * 0.6,
traits: lookalike.similarity.shared_traits,
reasons: matchResult.match.reasons,
};
})
.filter((item) => item !== null)
.sort((a, b) => b.combined - a.combined);
```
The blend ratio depends on your use case. If you're expanding a proven formula, lean toward similarity (0.7 / 0.3). If the new campaign is different, lean toward campaign fit (0.3 / 0.7).
## Total Cost
| Step | Endpoint | Credits | Cost |
| --------------------------- | ----------------------------- | -------: | ----------: |
| Lookalike (25 results) | `POST /v1/creators/lookalike` | 37.5 | \$0.375 |
| Match scoring (25 creators) | `POST /v1/creators/match` | 25 | \$0.25 |
| **Total** | | **62.5** | **\$0.625** |
## The Feedback Loop
This workflow gets better over time:
1. Run a campaign with your shortlist
2. Measure performance (ROI, engagement, conversions)
3. Feed those numbers back as weights in the next lookalike search
4. Repeat
Each iteration refines what "similar to our best creators" means. The weights encode accumulated campaign knowledge that no amount of manual research can replicate.
## Tips
* **Don't over-seed.** 3-5 seeds is usually enough. More seeds dilute the signal unless each one genuinely represents a different trait you want.
* **Vary the weights meaningfully.** If all your seeds have weight 1.0, you're not using the feature. Even rough estimates (1.0, 0.7, 0.3) are better than equal weights.
* **Filter aggressively.** Lookalike search returns creators who are *stylistically* similar — they may not meet your follower or engagement requirements. Filters prevent you from scoring creators you'd never work with.
# Score Campaign Fit for an Existing List
Source: https://docs.influship.com/cookbook/score-campaign-fit
Take a list of creator handles, resolve them, and score each one against a campaign brief
# Score Campaign Fit for an Existing List
You already have a list of creators — maybe from a spreadsheet, a CRM export, or a previous campaign. You want to evaluate how well each one fits a specific campaign brief. This recipe resolves social handles to creator IDs, then scores them all at once.
## The Flow
1. **Batch lookup** your creator handles to get IDs
2. **Score** them against your campaign brief
3. **Sort** by fit and build your final list
## Step 1: Resolve Handles to Creator IDs
If you're starting from Instagram usernames, batch lookup resolves them in a single request:
```typescript theme={null}
import Influship from 'influship';
const client = new Influship();
// Your existing creator list — from a spreadsheet, CRM, wherever
const handles = [
{ platform: 'instagram' as const, username: 'clean_eating_co' },
{ platform: 'instagram' as const, username: 'mealprep_marcus' },
{ platform: 'instagram' as const, username: 'plantbased_priya' },
{ platform: 'instagram' as const, username: 'fit_kitchen_lee' },
{ platform: 'instagram' as const, username: 'wholesome_hannah' },
{ platform: 'instagram' as const, username: 'nutrition_nate' },
{ platform: 'instagram' as const, username: 'vegan_chef_rio' },
{ platform: 'instagram' as const, username: 'healthy_habits_jo' },
];
const lookup = await client.profiles.lookup({
profiles: handles,
});
// Some handles may not be in the system — check what resolved
const resolved = lookup.data.filter((p) => p.creator_id);
const missing = handles.length - resolved.length;
if (missing > 0) {
console.log(`${missing} handle(s) not found in the system — skipping`);
}
console.log(`Resolved ${resolved.length} of ${handles.length} handles`);
```
At 0.1 credits per profile found, eight resolved profiles cost 0.8 credits (\$0.008). Missing profiles are not charged.
## Step 2: Score Against Campaign Brief
Pass the resolved creator IDs to the match endpoint. The more detail you put in the brief, the more accurate the scoring.
```typescript theme={null}
const creatorIds = [...new Set(resolved.flatMap((p) => (p.creator_id ? [p.creator_id] : [])))];
const scored = await client.creators.match({
creators: creatorIds.map((creator_id) => ({ creator_id })),
intent: {
query: 'Launch campaign for an organic meal delivery service',
context:
'Brand targets busy professionals aged 28-40 who want healthy meals ' +
'without the prep time. Looking for creators who feel authentic and ' +
'relatable — not aspirational fitness models. Must be comfortable ' +
'with recipe-style content and unboxing formats. Budget per creator ' +
'is \$2,000-\$5,000 for a 3-post series.',
},
});
```
The `context` field accepts up to 2,000 characters. Use it for details that don't fit in the main query — target demographics, content format preferences, budget range, brand tone. The scoring model reads all of it.
## Step 3: Sort and Review
```typescript theme={null}
// Group by decision
const good = scored.data.filter((r) => r.match.decision === 'good');
const neutral = scored.data.filter((r) => r.match.decision === 'neutral');
const avoid = scored.data.filter((r) => r.match.decision === 'avoid');
console.log(`Good fit: ${good.length} | Review: ${neutral.length} | Weak fit: ${avoid.length}`);
// Rank the good fits
const ranked = good.sort((a, b) => b.match.score - a.match.score);
for (const item of ranked) {
const handle = resolved.find((p) => p.creator_id === item.creator.id);
console.log(
`@${handle?.username} — score: ${item.match.score} (${item.match.decision})`,
);
for (const reason of item.match.reasons) {
console.log(` ${reason.text}`);
}
}
```
## What the Decisions Mean
| Decision | What it tells you |
| --------- | -------------------------------------------------------------------------------- |
| `good` | Strong fit. The creator's content, audience, and style align with the brief. |
| `neutral` | Could work, but there are trade-offs. Worth a manual review. |
| `avoid` | Weak fit. The reasons will explain why — usually a content or audience mismatch. |
Don't automatically reject `neutral` creators. Read the reasons — sometimes a creator scores `neutral` because they're slightly outside the follower range you implied in the brief, but their content is an excellent match.
## Total Cost
| Step | Endpoint | Credits | Cost |
| -------------------------- | -------------------------- | ------: | ----------: |
| Batch lookup (8 handles) | `POST /v1/profiles/lookup` | 0.8 | \$0.008 |
| Match scoring (8 creators) | `POST /v1/creators/match` | 8 | \$0.08 |
| **Total** | | **8.8** | **\$0.088** |
Scoring an existing list is cheap. The expensive part of the API is search — if you already have the list, you skip that cost entirely.
## Tips
* **Write the brief like you'd brief an agency.** Include brand values, target audience, content formats, budget range, and what you're trying to avoid. Vague briefs produce vague scores.
* **Don't filter on score alone.** The reasons are often more useful than the number. A creator scoring 0.78 with the right reasons may be a better choice than one scoring 0.85 with generic reasons.
* **Re-score for different campaigns.** The same creator can score `good` for one brief and `avoid` for another. Campaign fit is relative to the brief, not absolute.
* **Batch lookup handles missing profiles.** If some handles aren't in the system, those creators may not be in the Influship index yet. Reach out to support if you need specific creators added.
# Authentication
Source: https://docs.influship.com/guides/authentication
How to authenticate requests to the Influship API
# Authentication
Every request needs an API key passed in the `X-API-Key` header.
## Get your API key
Sign up at [developers.influship.com](https://developers.influship.com) and find your API key in the dashboard under **Settings > API Keys**.
## Set it as an environment variable
```bash theme={null}
export INFLUSHIP_API_KEY="your_api_key_here"
```
Or add it to your `.env` file:
```bash .env theme={null}
INFLUSHIP_API_KEY="your_api_key_here"
```
Never commit API keys to version control. Use environment variables or a secrets manager.
## Pass it in requests
```typescript SDK theme={null}
import Influship from 'influship';
const client = new Influship({
apiKey: process.env.INFLUSHIP_API_KEY,
});
```
```bash cURL theme={null}
curl https://api.influship.com/v1/creators/autocomplete?q=travel \
-H 'X-API-Key: YOUR_API_KEY'
```
The SDK reads from the `INFLUSHIP_API_KEY` environment variable automatically, so you can also omit the constructor argument entirely if the variable is set.
## When authentication fails
A missing or invalid key returns a `401` response:
```json theme={null}
{
"error": {
"code": "unauthorized",
"message": "Invalid or missing API key",
"status_code": 401
}
}
```
If you receive this unexpectedly, check that the key is correctly set and has not been revoked.
## Key rotation
Generate a new key from the dashboard at any time. Old keys are revoked immediately when a new one is created — update your environment variables before generating a replacement if you have live traffic.
## Organization and billing
Each API key belongs to one organization. [Rate limits](/concepts/quotas-and-limits) and [billing](/concepts/pricing) are tracked per key.
# Download Instagram Videos
Source: https://docs.influship.com/guides/download-instagram-videos
How to retrieve fresh, downloadable URLs for Instagram video posts via the raw endpoints.
# Download Instagram Videos
The raw Instagram endpoints return fresh signed CDN URLs you can download directly. Cached endpoints like `GET /v1/posts` do not expose video URLs — those would be stale by the time you fetch them.
## Single video
Call `GET /v1/raw/instagram/post/:shortcode` (1 credit, \$0.01). The response includes `video_url` (single best stream) and `video_versions[]` (multi-bitrate variants).
```bash theme={null}
SHORTCODE="CXY123abc"
curl -s "https://api.influship.com/v1/raw/instagram/post/$SHORTCODE" \
-H "X-API-Key: $INFLUSHIP_API_KEY" \
| jq -r '.data.video_url' \
| xargs -I{} wget -O "$SHORTCODE.mp4" "{}"
```
Use `video_versions[]` if you need a specific bitrate or resolution — each entry includes a `url` and a `type` field identifying the stream quality.
## All recent videos from a creator (bulk)
Call `GET /v1/raw/instagram/profile/:username` (0.5 credits, \$0.005). The `posts[]` array returns up to 12 recent posts with `video_url` for each video post.
This is the cheapest bulk-download path — a single profile call covers up to 12 posts, significantly cheaper than calling the single-post endpoint per shortcode.
```bash theme={null}
USERNAME="creator"
curl -s "https://api.influship.com/v1/raw/instagram/profile/$USERNAME" \
-H "X-API-Key: $INFLUSHIP_API_KEY" \
| jq -r '.data.posts[] | select(.is_video) | "\(.shortcode)\t\(.video_url)"' \
| while IFS=$'\t' read -r sc url; do
wget -O "${sc}.mp4" "$url"
done
```
## Carousel posts with videos
For carousel posts that contain video items, each slide is exposed in `carousel_items[]`. Filter by `is_video` to isolate the video items:
```bash theme={null}
SHORTCODE="CXY456def"
curl -s "https://api.influship.com/v1/raw/instagram/post/$SHORTCODE" \
-H "X-API-Key: $INFLUSHIP_API_KEY" \
| jq -r '.data.carousel_items[] | select(.is_video) | "\(.index)\t\(.video_url)"' \
| while IFS=$'\t' read -r idx url; do
wget -O "${SHORTCODE}_${idx}.mp4" "$url"
done
```
## URL lifetime
`video_url` and `video_versions[].url` are signed Instagram CDN URLs valid for approximately 24 hours from the moment of the API call. Download promptly. If you need to retain videos long-term, store them on your own infrastructure — re-requesting the same shortcode after the URLs expire costs an additional credit.
## Cost summary
| Pattern | Endpoint | Credits | Cost |
| -------------------------------- | ------------------------------------------ | ------: | ------: |
| Single video | `GET /v1/raw/instagram/post/{shortcode}` | 1 | \$0.01 |
| Up to 12 videos from one creator | `GET /v1/raw/instagram/profile/{username}` | 0.5 | \$0.005 |
| Carousel (per post) | `GET /v1/raw/instagram/post/{shortcode}` | 1 | \$0.01 |
## Implementation advice
* **Prefer the profile endpoint for bulk work.** If you want the recent video content from a specific creator, one profile call is cheaper than calling the post endpoint per shortcode.
* **Download before storing the URL.** Don't cache the signed URL itself — it expires. Either download the file immediately or re-fetch the URL when you need it.
* **Check `is_video` before downloading.** Both profile `posts[]` and carousel `carousel_items[]` contain mixed photo and video items. Filtering on `is_video: true` avoids requesting video fields that aren't present on photo posts.
## Terms of service
Instagram's terms of service govern downloaded content. Use videos in accordance with applicable law and Instagram's ToS.
# Error Handling
Source: https://docs.influship.com/guides/error-handling
How to handle errors from the Influship API
# Error Handling
Authenticated API errors use a consistent JSON shape. Use the HTTP status code to decide what to do, and the error body for details. Unauthenticated x402 and MPP payment challenges carry their details in response headers; see the [x402](/guides/x402) and [MPP](/guides/mpp) guides.
## Error response shape
Authenticated API errors return this structure:
```json theme={null}
{
"error": {
"code": "error_code_here",
"message": "Human-readable description"
}
}
```
The `code` field is a stable, machine-readable string. The `message` field is human-readable and may change between versions — don't match against it programmatically.
Optional fields inside `error` provide more context: `param` identifies an invalid parameter, and `details` contains structured error information. Read the HTTP response status even when `error.status_code` is absent.
Save the `X-Request-Id` response header when reporting a failed request to support. `error.request_id` is optional; your client should not require a request ID or timestamp in the JSON body.
Most authenticated 402 responses use `payment_required` and also include a `reason_code` and `next_step`. Branch on `code` first. For `payment_required`, then branch on `reason_code` when deciding which recovery action to show. Search can instead return `insufficient_credits` when remaining credits cannot cover the request; that body does not include `reason_code` or `next_step`.
## Error code reference
| Status | Code | Meaning | What to do |
| ------ | -------------------------- | ---------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- |
| 400 | `validation_error` | Bad request body or params | Fix the request. Check required fields and types. |
| 401 | `unauthorized` | Missing or invalid API key | Check your `X-API-Key` header. See [Authentication](/guides/authentication). |
| 402 | `payment_required` | Account billing requires attention | Open the billing dashboard and follow the supplied next step. |
| 402 | `insufficient_credits` | Remaining credits cannot cover this request | Add a payment method, then retry. Do not retry automatically. |
| 404 | `not_found` | Resource doesn't exist. For live/raw profile scrapes, the account is missing, deleted, or returns no public data | Check the ID or username. |
| 404 | `seed_not_found` | A lookalike seed is not available for similarity matching | Choose another seed. Retrying the same seed does not change the result. |
| 429 | `rate_limit_exceeded` | Over your per-minute or per-hour budget | Read `Retry-After` header or wait for the reset window. See [Rate Limits](/concepts/quotas-and-limits). |
| 500 | `internal_error` | Something broke on the Influship side | Retry with backoff. If persistent, contact support. |
| 502 | `upstream_contract_broken` | The API could not process the source data | Don't retry automatically. Fall back to cached data and contact support if it persists. |
| 503 | `service_unavailable` | A live data upstream is temporarily unavailable | Retry after `Retry-After` if present, then back off with jitter. |
## Handling errors in code
```typescript SDK theme={null}
import Influship, { APIError, RateLimitError } from 'influship';
const client = new Influship();
try {
const results = await client.search.create({
query: 'fitness creators',
});
} catch (error) {
if (error instanceof RateLimitError) {
// Your Influship API key hit its account-level quota.
const retryAfter = error.headers?.get('retry-after');
console.log(`Rate limited. Retry after ${retryAfter}s`);
} else if (error instanceof APIError && error.status === 503) {
// Temporary issue while fetching fresh live data.
const retryAfter = error.headers?.get('retry-after');
console.log(`Service unavailable. Retry after ${retryAfter ?? 'a short backoff'}s`);
} else if (error instanceof APIError && error.status === 502) {
// Source data could not be processed; do not retry automatically.
console.log('Upstream data unusable. Do not retry; use cached data instead.');
} else if (error instanceof APIError) {
console.log(`API error ${error.status}: ${error.message}`);
} else {
throw error;
}
}
```
```bash cURL theme={null}
curl -w "\n%{http_code}\n" \
-X POST https://api.influship.com/v1/search \
-H 'X-API-Key: YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-d '{"query": "fitness creators", "limit": 10}'
```
The SDK throws typed error classes, so you can catch specific error types and handle them differently. For raw HTTP, check the status code of the response.
## Rate limit headers
Every response includes rate limit headers so you can track your budget before hitting 429. See [Rate Limits & Tiers](/concepts/quotas-and-limits) for the full header reference and trust tier table.
## Implementation advice
For production integrations, handle 429 and retryable 503 responses with exponential backoff. A simple strategy: wait `2^attempt` seconds, capped at 60 seconds, with jitter. If `Retry-After` is present, use it as the first delay.
Treat 429 as your API key's account-level rate limit. Treat 503 `service_unavailable` from live data endpoints as temporary unavailability, not as your quota being exhausted. Honor `Retry-After` when present, including for Instagram post and transcript lookups.
For lookalike requests, treat `404 seed_not_found` as a seed-level result rather than a temporary outage. Select another seed; don't retry the same request with backoff.
Do not fold `502 upstream_contract_broken` into your `503` retry path. A `503` indicates temporary unavailability; honor `Retry-After` when present and use bounded backoff. A `502 upstream_contract_broken` means the API could not process the source data. Do not retry automatically; use your last cached value and contact support if the issue persists. Retrying an already-settled x402 or MPP request requires another payment.
Treat 402 as a billing issue that needs human intervention. Do not retry it automatically. Surface `payment_required` to your ops team or billing dashboard, and treat `insufficient_credits` as a prompt to add a payment method. Temporary failures while checking billing state return retryable 503 responses instead.
# Ingest Creators On Demand
Source: https://docs.influship.com/guides/ingest-creators-on-demand
Request ingestion of a creator we do not have yet, then poll for the built profile.
# Ingest Creators On Demand
Most creators you search for are already in Influship. When one is not, use `POST /v1/creators/ingest` to request it. We validate the handle live to confirm it exists, seed a profile, and start building it in the background. You then poll for the result.
Only Instagram is supported today.
```bash theme={null}
curl -s "https://api.influship.com/v1/creators/ingest" \
-H "X-API-Key: $INFLUSHIP_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"platform": "instagram",
"username": "fitness_coach_jane",
"source_query": "vegan fitness coaches in Austin"
}'
```
The `source_query` field is optional. It is a free-text note for your own attribution — for example the search that surfaced this creator — and does not affect processing.
## Responses
A new ingest returns `202 Accepted`:
```json theme={null}
{
"data": {
"status": "ingesting",
"creator": {
"id": "123e4567-e89b-12d3-a456-426614174000",
"username": "fitness_coach_jane",
"platform": "instagram"
},
"status_url": "/v1/creators/123e4567-e89b-12d3-a456-426614174000"
}
}
```
If we already have the creator, you get `200 OK` with `status: "already_exists"` and the same shape. This path is **not charged**.
## Polling for the Profile
The profile builds asynchronously. Poll the returned `status_url` (which is `GET /v1/creators/{id}`) to retrieve it:
* Basic header details (name, bio) are usually available within about a minute.
* Full analysis and synthesized fields fill in within about a day.
* While the profile is still building, `GET /v1/creators/{id}` may return `404` or sparse fields. Keep polling with a sensible backoff — every few minutes is plenty.
```bash theme={null}
curl -s "https://api.influship.com/v1/creators/123e4567-e89b-12d3-a456-426614174000" \
-H "X-API-Key: $INFLUSHIP_API_KEY"
```
## Billing
Ingest costs **5 credits (\$0.05)**, charged only when a new creator is seeded (the `202` path). You are not charged when:
* the creator already exists (`200 already_exists`),
* the handle does not exist (`404`),
* the handle format is invalid (`422`),
* or you exceed the daily quota (`429`).
## Limits
Each account has a daily ingest quota (default 50 per UTC day). Exceeding it returns `429` with `error.code: "quota_exceeded"` and a `Retry-After` header pointing to the next UTC midnight:
```json theme={null}
{
"error": {
"code": "quota_exceeded",
"message": "Daily ingest quota of 50 exceeded. Try again after it resets at UTC midnight."
}
}
```
If you need a higher quota, reach out at [elliot@influship.com](mailto:elliot@influship.com).
## Error Reference
| Status | Meaning | Charged |
| ------ | ------------------------------------------------------- | ------- |
| `202` | New creator seeded; enrichment started | Yes |
| `200` | Creator already exists | No |
| `400` | Unsupported platform | No |
| `404` | Handle does not exist | No |
| `422` | Invalid handle format | No |
| `429` | Daily quota exceeded (`quota_exceeded`) or rate limit | No |
| `503` | Could not validate the handle right now — retry shortly | No |
# Lookup Creator Emails
Source: https://docs.influship.com/guides/lookup-creator-emails
How to fetch known creator email addresses by creator ID or social username.
# Lookup Creator Emails
Use `POST /v1/creator-emails/lookup` to fetch known email addresses for creators. You can look up creators by Influship creator ID or by social username.
The endpoint returns every API-visible email we have for each resolved creator. Emails can be `unvalidated`, so check `status` before treating an address as deliverable.
```bash theme={null}
curl -s "https://api.influship.com/v1/creator-emails/lookup" \
-H "X-API-Key: $INFLUSHIP_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"creators": [
{ "platform": "instagram", "username": "creator" },
{ "creator_id": "123e4567-e89b-12d3-a456-426614174000" }
]
}'
```
## Billing
Creator email lookup costs 5 credits per unique resolved creator with at least one returned email. Empty results and unresolved creators are not charged.
The response includes a billing preview:
```json theme={null}
{
"data": {
"billing": {
"billable_results": 1,
"credits_charged": 5
}
}
}
```
## Response fields
Each email includes:
| Field | Meaning |
| --------------- | ------------------------------------------------------ |
| `email` | Email address as stored |
| `status` | `unvalidated`, `valid`, `risky`, or `creator_verified` |
| `confidence` | Nullable score from import or enrichment |
| `is_primary` | Whether this is the selected primary email |
| `validated_at` | Last validation time, if known |
| `first_seen_at` | First time Influship observed the email |
| `last_seen_at` | Most recent observation time |
# MCP Server
Source: https://docs.influship.com/guides/mcp-server
Connect AI agents to the Influship API using the Model Context Protocol
The Influship MCP server exposes the API to AI agents through 28 typed tools. It works with Claude Desktop, Cursor, ChatGPT Connectors, VS Code Copilot, and any [Model Context Protocol](https://modelcontextprotocol.io)-compatible client.
The server is hosted at `https://mcp.influship.com/mcp` and uses the [Streamable HTTP transport](https://modelcontextprotocol.io/specification/2025-06-18/basic/transports) (spec `2025-06-18`). Stdio-only clients connect via the `mcp-remote` bridge.
## How it works
Generic MCP clients authenticate with an Influship API key. Clients that support account linking can use OAuth instead. Calls use the billing route and rate limits associated with the credential.
1. The agent connects to `https://mcp.influship.com/mcp` with an `X-API-Key` or linked Influship account
2. The agent discovers 28 typed tools, each with a full description and parameter schema
3. The agent picks the right tool, such as `semantic_search_creators`, and calls it with its arguments
4. The result includes the REST response fields plus MCP-specific `suggested_followups`
Clients can list available tools without authentication. `get_sample_creator` provides an unauthenticated preview. The remaining tools require an API key or OAuth account link.
## Set up with AI
Copy this prompt into your coding agent.
Connect this development environment to the Influship MCP server.
First inspect the repository and available MCP configuration to identify the active client and whether configuration belongs at project or user scope. Preserve existing MCP servers.
Add an MCP server named `influship` using Streamable HTTP:
* URL: [https://mcp.influship.com/mcp](https://mcp.influship.com/mcp)
* Header: `X-API-Key: YOUR_INFLUSHIP_API_KEY`
Use a placeholder only. Never paste, read, print, or commit a real API key. If this client supports environment-variable expansion in MCP headers, use the client's documented syntax for `INFLUSHIP_API_KEY`. Otherwise, explain exactly where I must add the key locally after you finish.
Verify that the server connects and its tools can be listed. If credentials are available, run a small creator lookup to confirm authenticated tools work. Preserve all unrelated configuration and finish by naming the file or setting changed plus any remaining step I must take.
## Tools
| Tool | Method | Endpoint |
| --------------------------------- | ----------- | -------------------------------------------------------- |
| `get_sample_creator` | GET | Configured creator preview |
| `search_creators` | GET or POST | `/v1/creators/autocomplete` or `/v1/search` |
| `semantic_search_creators` | POST | `/v1/search` |
| `autocomplete_creators` | GET | `/v1/creators/autocomplete` |
| `find_lookalike_creators` | POST | `/v1/creators/lookalike` |
| `match_creators` | POST | `/v1/creators/match` |
| `get_creator` | GET | `/v1/creators/:id` or `/v1/profiles/:platform/:username` |
| `get_profile` | GET | `/v1/profiles/:platform/:username` |
| `lookup_profiles` | POST | `/v1/profiles/lookup` |
| `get_posts` | GET | `/v1/posts` |
| `get_instagram_post` | GET | `/v1/raw/instagram/post/:shortcode` |
| `get_instagram_posts` | POST | `/v1/raw/instagram/posts` |
| `get_instagram_post_transcript` | GET | `/v1/raw/instagram/transcript/:shortcode` |
| `get_instagram_post_transcripts` | POST | `/v1/raw/instagram/transcripts` |
| `get_tiktok_profile` | GET | `/v1/raw/tiktok/profile/:username` |
| `get_tiktok_music` | GET | `/v1/raw/tiktok/music` |
| `search_tiktok_users` | GET | `/v1/raw/tiktok/search/users` |
| `search_tiktok_videos` | GET | `/v1/raw/tiktok/search/videos` |
| `list_tiktok_hashtag_videos` | GET | `/v1/raw/tiktok/hashtag/videos` |
| `list_tiktok_music_videos` | GET | `/v1/raw/tiktok/music/videos` |
| `get_tiktok_video_captions` | GET | `/v1/raw/tiktok/video/captions` |
| `list_tiktok_profile_videos` | GET | `/v1/raw/tiktok/profile/:username/videos` |
| `get_tiktok_video` | GET | `/v1/raw/tiktok/video` |
| `list_tiktok_video_comments` | GET | `/v1/raw/tiktok/video/comments` |
| `list_tiktok_comment_replies` | GET | `/v1/raw/tiktok/video/comment/replies` |
| `get_tiktok_video_transcript` | GET | `/v1/raw/tiktok/video/transcript` |
| `get_tiktok_videos` | POST | `/v1/raw/tiktok/videos` |
| `get_tiktok_video_transcripts` | POST | `/v1/raw/tiktok/video/transcripts` |
| `get_youtube_channel` | GET | `/v1/raw/youtube/channel/:handle` |
| `get_youtube_video_transcript` | GET | `/v1/raw/youtube/transcript/:video_id` |
| `get_youtube_channel_transcripts` | GET | `/v1/raw/youtube/channel-transcripts/:handle` |
| `search_youtube` | GET | `/v1/raw/youtube/search` |
| `get_youtube_video` | GET | `/v1/raw/youtube/video/:video_id` |
| `get_youtube_typeahead` | GET | `/v1/raw/youtube/typeahead` |
| `render_creator_shortlist` | Composite | Search page or creator lookups |
| `render_creator_profile` | Composite | Creator and post lookups |
| `render_creator_comparison` | Composite | Creator lookups and match scoring |
Each tool description tells the agent when to use it. Use `semantic_search_creators` for topical or campaign discovery, `search_creators` for a name or partial handle, and `find_lookalike_creators` when you already have seed creators.
## Quickstart
Choose the setup for your client below. Config-based clients need an API key from the [dashboard](https://developers.influship.com); account-linking clients use OAuth.
### Claude Code (CLI)
One command:
```bash theme={null}
claude mcp add influship --transport http https://mcp.influship.com/mcp --header "X-API-Key: YOUR_INFLUSHIP_API_KEY"
```
Add `--scope user` to install across every project, not just the current directory.
### Claude Desktop
Open **Customize → Connectors → Add custom connector**, enter `https://mcp.influship.com/mcp`, then complete Influship account linking when prompted. Claude's remote custom-connector flow uses OAuth rather than an arbitrary API-key header.
If you prefer an API-key-backed local bridge, add this to `~/Library/Application Support/Claude/claude_desktop_config.json`:
```json theme={null}
{
"mcpServers": {
"influship": {
"command": "npx",
"args": [
"-y",
"mcp-remote",
"https://mcp.influship.com/mcp",
"--header",
"X-API-Key:YOUR_INFLUSHIP_API_KEY"
]
}
}
}
```
### Cursor and Windsurf
Both clients use the same remote-server configuration. Set `INFLUSHIP_API_KEY` in the environment that launches the app, then add this JSON to `.cursor/mcp.json` for Cursor or `~/.codeium/windsurf/mcp_config.json` for Windsurf:
```json theme={null}
{
"mcpServers": {
"influship": {
"url": "https://mcp.influship.com/mcp",
"headers": {
"X-API-Key": "${env:INFLUSHIP_API_KEY}"
}
}
}
}
```
### VS Code
Run **MCP: Add Server**, or add the server to `.vscode/mcp.json`. VS Code uses a top-level `servers` object rather than Cursor's `mcpServers` key:
```json theme={null}
{
"inputs": [
{
"type": "promptString",
"id": "influship-api-key",
"description": "Influship API key",
"password": true
}
],
"servers": {
"influship": {
"type": "http",
"url": "https://mcp.influship.com/mcp",
"headers": {
"X-API-Key": "${input:influship-api-key}"
}
}
}
}
```
### ChatGPT (Apps & Connectors)
In an eligible workspace, enable developer mode, create a custom app from **Settings → Apps**, and use `https://mcp.influship.com/mcp` as the remote MCP endpoint. Complete Influship account linking when prompted.
### Stdio-only clients
Some clients only support stdio transport. Bridge them with [`mcp-remote`](https://www.npmjs.com/package/mcp-remote):
```bash theme={null}
npx -y mcp-remote https://mcp.influship.com/mcp --header "X-API-Key:YOUR_INFLUSHIP_API_KEY"
```
## Authentication and billing
The MCP server supports two authentication paths:
* Generic clients send `X-API-Key`; calls use the associated API account's metering and rate limits
* Account-linking clients send an OAuth bearer token; calls use the linked account's billing route and allowance
* `get_sample_creator` is an unauthenticated preview and does not expose arbitrary creator data
If you don't have an API key, [create one in the dashboard](https://developers.influship.com).
## Pricing
MCP tool calls bill at the same per-credit price as the underlying REST endpoint. There's no MCP surcharge.
| Tool | Cost |
| ---------------------------------------- | ------------------------------------------------------------------------------------------- |
| `get_sample_creator` | No user charge |
| `search_creators` | 0.05 credits for indexed creator lookup, or the search price when routed to semantic search |
| `semantic_search_creators` | 25 credits + 2 per result returned |
| `find_lookalike_creators` | 1.5 per creator returned |
| `match_creators` | 1 per creator scored |
| `autocomplete_creators` | 0.05 per call |
| `get_creator` | 0.1 per call |
| `get_profile` | 0.1 per call |
| `lookup_profiles` | 0.1 per profile returned |
| `get_posts` | 0.05 per post returned |
| `get_instagram_post` | 1 per post |
| `get_instagram_posts` | 1 per successful post |
| `get_instagram_post_transcript` | 5 per transcript |
| `get_instagram_post_transcripts` | 5 per successful transcript |
| TikTok profile, video, or comments tools | 0.2 per request or source page |
| `get_tiktok_video_transcript` | 2.5 per transcript |
| `get_tiktok_videos` | 0.2 per successful entry; 1–20 URLs |
| `get_tiktok_video_transcripts` | 2.5 per successful auto entry or 0.2 per captions entry; 1–10 URLs |
| `get_youtube_channel` | 0.5 per channel |
| `get_youtube_video_transcript` | 0.5 per transcript |
| `get_youtube_channel_transcripts` | 0.5 per transcript returned |
| `search_youtube` | 0.5 per fetched page |
| `get_youtube_video` | 0.5 per video |
| `get_youtube_typeahead` | 0.5 per request |
| `render_creator_*` | Sum of the REST calls the selected composite tool makes |
One credit is \$0.01. See the [REST pricing reference](/concepts/pricing) for the full breakdown.
## Rate limits
The credential's account limits apply, matching direct REST usage. There's also a per-IP cap of 60 requests per minute. If you hit it, the server returns `429` with a `retry-after` header.
If you're connecting many agents from the same IP (a corporate proxy, for example), reach out and we'll tune the IP cap.
## Error codes
When a tool call fails, the error message is surfaced as readable text in the MCP client.
| Error | Meaning |
| ----- | ------------------------------------------------------------------------------------ |
| `400` | Missing or invalid parameter |
| `401` | Missing or invalid API key or account authorization |
| `402` | Payment required |
| `403` | Credential valid but lacks permission for this tool |
| `404` | Creator, profile, or post not found |
| `429` | Rate limit exceeded — check `retry_after_seconds` in the response |
| `5xx` | Server or temporary upstream error; live data 503s may include `retry_after_seconds` |
## Anonymous agents (no API key)
For one-off agents without an API key or linked account, use the direct HTTP API with [x402](/guides/x402) or [MPP](/guides/mpp). These payment protocols apply to supported REST endpoints rather than MCP tool calls.
## Implementation tips
* **Trust tool descriptions.** Each tool's `description` is written for the LLM. It explains when to pick that tool over the others. Don't override or rewrite it client-side.
* **Pass real IDs.** Tools that take a `creator_id` expect a UUID from a previous tool's response. Resolving by `platform + username` is supported on lookalike, match, and posts — useful when the user types a handle.
* **Bound multi-step workflows.** Cursor pagination and composite render tools can make additional billed calls. Set a page or result ceiling before handing control to an autonomous agent.
## Next steps
Sign up and grab your key from the dashboard
Full endpoint specs and response schemas — the tools mirror these
Anonymous per-request payment for one-off agents
Stripe cards or Tempo USDC for agent-native payments
# Pay with MPP (cards, Tempo USDC, agent-native)
Source: https://docs.influship.com/guides/mpp
Use the Influship API with Stripe cards or USDC on Tempo via the Machine Payments Protocol
The Influship API supports the [Machine Payments Protocol (MPP)](https://mpp.dev/overview) on its paid public data endpoints. AI agents can pay per-request via Stripe cards (Shared Payment Tokens) or USDC on Tempo, no API key required.
MPP coexists with [x402](/guides/x402) on the same endpoints. Pick whichever your client supports — we accept both.
## How it works
1. Your agent makes a request to a supported paid endpoint without an `X-API-Key` header.
2. The API responds with `402 Payment Required` and a `WWW-Authenticate: Payment ...` header advertising the supported MPP methods.
3. Your agent attaches an `Authorization: Payment ` header proving payment authorization (signed by the user's wallet or backed by a Stripe SPT).
4. The API verifies, runs the request, and returns the response with a `Payment-Receipt` header.
The same 402 response includes both MPP and x402 challenges, so the client can pick.
MPP settles before the endpoint runs. Once settlement succeeds, the payment is final and the response keeps its `Payment-Receipt` even if the endpoint later returns an error.
## Pricing
MPP prices match [x402 pricing](/guides/x402#pricing) — same 20% surcharge over the credit-based pricing.
The total is rounded up once to whole cents, with a \$0.01 minimum. Stripe card payments are offered only when that quote is at least \$0.50; lower-priced requests use USDC or account credits. The API does not increase a quote to meet the card minimum.
| Endpoint | Price |
| -------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ |
| `POST /v1/search` | `\$0.3000 + \$0.0240 × requested_limit`, rounded up to the next whole cent with a \$0.01 minimum (capped at 100 results) |
| `GET /v1/creators/:id` | `\$0.0100` |
| `POST /v1/creators/lookalike` | `\$0.0180 × requested_limit`, rounded up to the next whole cent with a \$0.01 minimum (capped at 100 results) |
| `POST /v1/creators/match` | `\$0.0120 × creators_in_request`, rounded up to the next whole cent with a \$0.01 minimum |
| `GET /v1/raw/instagram/post/:shortcode` | `\$0.0200` |
| `GET /v1/raw/instagram/transcript/:shortcode` | `\$0.0600` |
| `GET /v1/raw/tiktok/profile/{username}` | `\$0.0100` |
| `GET /v1/raw/tiktok/profile/{username}/videos` | `\$0.0100` |
| `GET /v1/raw/tiktok/video` | `\$0.0100` |
| `GET /v1/raw/tiktok/video/comments` | `\$0.0100` |
| `GET /v1/raw/tiktok/video/comment/replies` | `\$0.0100` |
| `GET /v1/raw/tiktok/music` | `\$0.0100` |
| `GET /v1/raw/tiktok/video/captions` | `\$0.0100` |
| `GET /v1/raw/tiktok/video/transcript` | `\$0.0300` |
| `GET /v1/raw/youtube/channel/{handle}` | `\$0.0100` |
| `GET /v1/raw/youtube/transcript/{video_id}` | `\$0.0100` |
| `GET /v1/raw/youtube/channel-transcripts/{handle}` | `\$0.0060 × requested video_limit`, rounded up to the next whole cent |
| `GET /v1/raw/youtube/search` | `\$0.0100` per fetched page |
| `GET /v1/raw/youtube/video/{video_id}` | `\$0.0100` |
| `GET /v1/raw/youtube/typeahead` | `\$0.0100` |
| `GET /v1/raw/*` | starts at `\$0.0100` unless the endpoint cost is higher |
You pay for what you ask for — limits and array sizes determine the price, not what we deliver.
## Supported rails
| Rail | Method | Settlement |
| ----------------- | --------------- | ------------------------------------------------------- |
| **Stripe card** | `stripe/charge` | Stripe SPT (Shared Payment Token), USD via card or Link |
| **USDC on Tempo** | `tempo/charge` | On-chain USDC, settled in seconds |
Eligible methods are advertised in the `WWW-Authenticate` header. Your client picks from that request's offers. For variable-price operations, larger batches can qualify for cards even when smaller requests do not.
## Quickstart
Use any MPP-compatible client. The reference SDK is [mppx](https://github.com/wevm/mppx) by wevm:
```typescript theme={null}
import { Mppx, tempo } from 'mppx/client';
import { privateKeyToAccount } from 'viem/accounts';
const account = privateKeyToAccount(process.env.TEMPO_PRIVATE_KEY as `0x${string}`);
const mppx = Mppx.create({
methods: [tempo({ account })],
});
const response = await mppx.fetch('https://api.influship.com/v1/search', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ query: 'fitness creators in NYC', limit: 25 }),
});
const data = await response.json();
```
Or use [AgentCash](https://agentcash.dev) for a turnkey CLI wallet that speaks both x402 and MPP:
```bash theme={null}
npx agentcash@latest discover https://api.influship.com
```
## Discovery
Influship endpoints are listed in the [MPP services directory](https://mpp.dev/services). Search for "Influship" or "influencer search" to find them programmatically.
## Pick your protocol
| If your agent supports... | Use |
| ------------------------- | -------------------------------------------------------------------------------------------- |
| Both x402 and MPP | Either — pick based on rail availability |
| Only MPP | MPP (this guide) |
| Only x402 | [x402 guide](/guides/x402) |
| Neither (only API keys) | Get an [API key](/guides/authentication) for lower per-request cost and per-tier rate limits |
## Need higher rate limits or volume pricing?
Get an [API key](/guides/authentication) — same endpoints, lower per-request cost, no x402/MPP surcharge.
# Pagination
Source: https://docs.influship.com/guides/pagination
How search pagination works and how to page through results without extra charges
# Pagination
Search pagination works differently from most APIs. You pay once when you create a search, then paginate through results for free.
## How it works
`POST /v1/search` creates a search session. The `limit` parameter (1-100, default 25) sets the maximum number of results that session can ever return. You're billed once at creation time: 25 base credits plus 2 per creator delivered.
The response includes three pagination fields:
* `search_id` - identifies the session for follow-up requests
* `has_more` - whether additional results are available
* `next_cursor` - pass this to fetch the next page
`GET /v1/search/{search_id}` fetches the next page using the cursor. This costs nothing -- no additional credits are charged.
Pagination does not unlock more results beyond the original limit. If you searched with `limit: 10`, the session exposes at most 10 results total across all pages.
## Posts pagination
`GET /v1/posts` uses stable keyset pagination rather than numeric offsets. Its `limit` is the page size, and each returned post is billed normally. When `has_more` is `true`, pass `next_cursor` into the next request with the same `sort` value.
Post cursors are tied to their ordering. A cursor created with `sort=most_likes` cannot be reused with `sort=recent`; the API returns `400` instead of restarting from the first page. This prevents duplicate or skipped posts when paginating changing datasets.
For `sort=top_engagement`, the ordering is `(likes + comments) / views`. Posts without measurable views are returned after posts with a calculated engagement rate.
## Code example
```typescript SDK theme={null}
import Influship from 'influship';
const client = new Influship();
// Create the search session (billed)
const first = await client.search.create({
query: 'travel content creators',
limit: 20,
});
console.log(`Got ${first.data.length} results, has_more: ${first.has_more}`);
// Paginate through remaining results (free)
let cursor = first.next_cursor;
while (cursor) {
const page = await client.search.retrieve(first.search_id, {
cursor,
});
console.log(`Got ${page.data.length} more results`);
cursor = page.next_cursor;
}
```
```bash cURL theme={null}
# Step 1: Create search session (billed)
curl -X POST https://api.influship.com/v1/search \
-H 'X-API-Key: YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-d '{"query": "travel content creators", "limit": 20}'
# Step 2: Paginate (free) — use search_id and next_cursor from the response
curl "https://api.influship.com/v1/search/SEARCH_ID?cursor=NEXT_CURSOR" \
-H 'X-API-Key: YOUR_API_KEY'
```
## Key things to understand
| Concept | Detail |
| ------------------------------- | -------------------------------------------------------------------------------------- |
| `limit` is a billing cap | It controls the max results for the entire session, not the page size. |
| Page size is fixed | Results are returned in chunks, typically 10 at a time. |
| `has_more` is the stop signal | Once it returns `false`, there are no more results to fetch. |
| Free pagination is rate-limited | Follow-up requests are free but still subject to light rate limiting to prevent abuse. |
## Implementation advice
Start with a small limit (5-10) while prototyping. Increase once you know how your UI consumes results. Larger limits cost more and results past the top 15-20 tend to be lower relevance.
## Further reading
See [Pricing](/concepts/pricing) for the full cost breakdown.
# TikTok Live Data
Source: https://docs.influship.com/guides/tiktok-live-data
Fetch current TikTok profiles, videos, comments, media URLs, and transcripts.
The TikTok live endpoints return normalized profile and video data. The API can reuse recent source data, so use `scraped_at` to assess when each result was collected.
## Endpoints
| Endpoint | Returns | Credits |
| ---------------------------------------------- | -------------------------------------- | ----------------------------------------------: |
| `GET /v1/raw/tiktok/profile/{username}` | Profile identity and current metrics | `0.2` |
| `GET /v1/raw/tiktok/profile/{username}/videos` | One cursor-paginated video page | `0.2` |
| `GET /v1/raw/tiktok/video` | Video details, metrics, and media URLs | `0.2` |
| `GET /v1/raw/tiktok/video/comments` | One cursor-paginated comment page | `0.2` |
| `GET /v1/raw/tiktok/video/comment/replies` | One cursor-paginated reply page | `0.2` |
| `GET /v1/raw/tiktok/music` | Sound clip metadata by `music_id` | `0.2` |
| `GET /v1/raw/tiktok/search/users` | One page of user search results | `0.2` |
| `GET /v1/raw/tiktok/search/videos` | One page of video search results | `0.2` |
| `GET /v1/raw/tiktok/hashtag/videos` | One page of videos under a hashtag | `0.2` |
| `GET /v1/raw/tiktok/music/videos` | One page of videos using a sound clip | `0.2` |
| `GET /v1/raw/tiktok/video/captions` | Available captions without generation | `0.2` |
| `GET /v1/raw/tiktok/video/transcript` | Plain text and timestamped segments | `2.5` |
| `POST /v1/raw/tiktok/videos` | Up to 20 video results | `0.2` per successful item |
| `POST /v1/raw/tiktok/video/transcripts` | Up to 10 transcript results | `2.5` auto / `0.2` captions per successful item |
Sound metadata uses the TikTok sound clip ID, not an album or recording ID. Unknown fields are `null`; audio and cover URLs are temporary upstream links, not durable downloads.
Use a video's `music.music_id` to request sound metadata or videos using that sound. Keep the ID as a string: converting it to a JavaScript number can lose precision. A `null` ID means the sound cannot be identified from that response.
To list videos using a sound, pass its clip ID as `music_id` to
`GET /v1/raw/tiktok/music/videos`. The response contains `data.music_id`,
`data.videos`, `data.has_more`, `data.next_cursor`, and `data.scraped_at`.
Continue with the returned cursor and the same music ID. Duplicate videos are
preserved; each successful page, including an empty page, costs 0.2 account credits.
Video media links are temporary.
Stop pagination on `404 not_found`, including when a previous page returned
`has_more: true`. A continuation cursor does not guarantee another available page.
A `404` is an error, not proof that you retrieved every video. Account billing does
not charge for that failed page; settled x402 and MPP payments are not refunded.
```bash theme={null}
curl --get 'https://api.influship.com/v1/raw/tiktok/music/videos' \
-H "X-API-Key: $INFLUSHIP_API_KEY" \
--data-urlencode "music_id=$TIKTOK_MUSIC_ID"
```
An empty terminal page has this shape:
```json theme={null}
{
"data": {
"music_id": "789",
"videos": [],
"has_more": false,
"next_cursor": null,
"scraped_at": "2026-09-06T12:00:00Z"
}
}
```
User search accepts a `query` of 1–100 characters and an optional opaque `cursor`.
Pass `next_cursor` with the same query to continue. Results include profile identity,
biography, verification, and audience counts; unknown fields are `null`, not zero.
Each successful page costs 0.2 credits, including an empty page.
Video search uses the same `query` and `cursor` parameters at
`GET /v1/raw/tiktok/search/videos`. Results are relevance-ordered and returned in
`data.videos`, using the same video fields as video lookup. Duplicate results are
preserved. Keep the query unchanged across pages and use `has_more` and
`next_cursor`, not the number of videos, to determine whether to continue.
Hashtag videos use `GET /v1/raw/tiktok/hashtag/videos` with a `hashtag` name
without `#` or spaces. The response contains `data.hashtag`, `data.videos`,
`has_more`, and `next_cursor`. Keep the hashtag unchanged when continuing.
Each successful page costs 0.2 account credits, including empty pages.
```bash theme={null}
curl --get 'https://api.influship.com/v1/raw/tiktok/hashtag/videos' \
-H "X-API-Key: $INFLUSHIP_API_KEY" \
--data-urlencode 'hashtag=cooking'
```
```bash theme={null}
curl --get 'https://api.influship.com/v1/raw/tiktok/search/users' \
-H "X-API-Key: $INFLUSHIP_API_KEY" \
--data-urlencode 'query=cooking'
```
```json theme={null}
{
"data": {
"query": "cooking",
"users": [],
"has_more": false,
"next_cursor": null,
"scraped_at": "2026-09-06T12:00:00Z"
}
}
```
For captions only, call `GET /v1/raw/tiktok/video/captions?url=...`. This never generates a transcript. Unavailable captions return `404 transcript_not_available`; successful cached captions cost the ordinary 0.2-credit rate. Use the transcript endpoint when you want automatic transcription if captions are unavailable.
One credit is \$0.01. See [Pricing](/concepts/pricing) for billing and payment-rail rules.
The listed credit price applies to each successful response, including one that reuses recent source data.
TikTok content is always resolved against the US region. The optional `region`
parameter is retained for compatibility and only accepts `US`.
## Fetch a profile
Pass a bare username or include the leading `@`.
```bash theme={null}
curl 'https://api.influship.com/v1/raw/tiktok/profile/creator' \
-H "X-API-Key: $INFLUSHIP_API_KEY"
```
The response includes the stable TikTok user ID, username, display name, biography, profile URL, audience counts, verification, privacy, and business status.
## List profile videos
```bash theme={null}
curl 'https://api.influship.com/v1/raw/tiktok/profile/creator/videos?sort_by=latest®ion=US' \
-H "X-API-Key: $INFLUSHIP_API_KEY"
```
Pass `next_cursor` back as `cursor` while `has_more` is `true`. Each request returns the complete source page. Cursors are opaque, so store and return the value unchanged.
Keep the same resource and query options for every page. Cursors may contain up to 2,048 characters and are temporary; do not reuse them for another profile, video, or sort order. If a cursor is invalid or expired, restart pagination without it.
Each video has a stable `video_id`, canonical TikTok URL, author, description, timestamps, engagement counts, hashtags, music metadata, and media fields. Slideshows use `media_type: "slideshow"` and place image URLs in `images`.
## Fetch one video and its file URL
Pass the TikTok URL as a query parameter.
```bash theme={null}
VIDEO_URL='https://www.tiktok.com/@creator/video/7517114944362499342'
curl --get 'https://api.influship.com/v1/raw/tiktok/video' \
-H "X-API-Key: $INFLUSHIP_API_KEY" \
--data-urlencode "url=$VIDEO_URL" \
--data-urlencode 'region=US'
```
For a regular video, `data.video.video_url` contains a directly downloadable media URL when the source exposes one. The URL is signed and temporary. Download the file promptly instead of storing the URL for later use. `video_url` is `null` when no downloadable video stream is available, including slideshow-only posts.
```bash theme={null}
curl --get -s 'https://api.influship.com/v1/raw/tiktok/video' \
-H "X-API-Key: $INFLUSHIP_API_KEY" \
--data-urlencode "url=$VIDEO_URL" \
| jq -r '.data.video.video_url // empty' \
| xargs -r wget -O tiktok-video.mp4
```
## Fetch comments
```bash theme={null}
curl --get 'https://api.influship.com/v1/raw/tiktok/video/comments' \
-H "X-API-Key: $INFLUSHIP_API_KEY" \
--data-urlencode "url=$VIDEO_URL"
```
Comments include text, creation time, likes, replies, pinned status, and normalized author data. Use `next_cursor` for the next source page.
`video_id` can be `null` when a short share URL returns an empty comment page and the source does
not provide the resolved video ID.
## Fetch comment replies
```bash theme={null}
curl --get 'https://api.influship.com/v1/raw/tiktok/video/comment/replies' \
-H "X-API-Key: $INFLUSHIP_API_KEY" \
--data-urlencode "url=$VIDEO_URL" \
--data-urlencode "comment_id=$COMMENT_ID"
```
Use a numeric `comment_id` from the comments response. IDs starting with `synthetic_` cannot be used to fetch replies. The response contains `video_id`, `parent_comment_id`, `comments`, `total`, `has_more`, `next_cursor`, and `scraped_at`. Keep the video URL and parent ID unchanged when passing `next_cursor` to fetch another page. Each successful page costs 0.2 credits, including an empty final page. An invalid or expired cursor returns `400`; restart without a cursor.
## Fetch a transcript
```bash theme={null}
curl --get 'https://api.influship.com/v1/raw/tiktok/video/transcript' \
-H "X-API-Key: $INFLUSHIP_API_KEY" \
--data-urlencode "url=$VIDEO_URL"
```
```json theme={null}
{
"data": {
"video_id": "7517114944362499342",
"url": "https://www.tiktok.com/@creator/video/7517114944362499342",
"transcript": "Welcome back. Today we are testing the new recipe.",
"full_text": "Welcome back. Today we are testing the new recipe.",
"segments": [
{ "start_ms": 0, "end_ms": 1480, "text": "Welcome back." },
{
"start_ms": 1480,
"end_ms": 4210,
"text": "Today we are testing the new recipe."
}
],
"word_count": 9,
"language": "en",
"source": "generated",
"duration_seconds": 4.21,
"scraped_at": "2026-08-12T10:00:00.000Z"
}
}
```
`source` is `captions` or `generated`, and `language` reports the detected language. The detected-language transcript is reused on later requests. Every delivered transcript costs 2.5 credits, including a reused response. This is a flat price within the supported processing limits, not a per-minute charge.
Transcript generation can run for up to 180 seconds. Set a timeout of at least 190 seconds when you call this endpoint with a custom HTTP client. The generated Influship SDK uses a 210-second default timeout.
Automatic generation supports videos up to 10 minutes long. Longer videos without usable captions return `422 transcription_limit_exceeded`; increasing your client timeout does not remove this limit.
## Batch videos and transcripts
Send 1–20 URLs to `POST /v1/raw/tiktok/videos`, or 1–10 URLs to
`POST /v1/raw/tiktok/video/transcripts`. Transcript batches accept `mode: "auto"`
(the default) or `mode: "captions"`. Captions mode never generates a transcript.
```bash theme={null}
curl 'https://api.influship.com/v1/raw/tiktok/video/transcripts' \
-H "X-API-Key: $INFLUSHIP_API_KEY" \
-H 'Content-Type: application/json' \
-d '{"urls":["https://www.tiktok.com/@creator/video/7517114944362499342"],"mode":"captions"}'
```
The response has `data.requested`, `data.succeeded`, `data.failed`, and ordered
`data.items`. Each item contains its input `url`, a `success` boolean, and either
`data` or an error `status` and `error`. Transcript batches also return `data.mode`.
An HTTP `200` batch can contain failed items, including an entirely failed batch;
check each item rather than only the HTTP status.
Duplicate URLs remain separate entries. API-key and OAuth billing counts successful
entries only. x402 and MPP quote all requested entries and do not refund settled
payments for failed items. The premium is applied to the total batch price, rounded
up once to whole cents with a one-cent minimum. Ten auto transcripts quote \$0.30;
ten caption-only transcripts quote \$0.03. Retry only the entries you need, and
remember that each new premium payment is a separate charge.
## URL and retry rules
Video-level endpoints accept HTTPS URLs on `tiktok.com` and its subdomains, including `vm.tiktok.com` and `vt.tiktok.com`. Other hosts return `400 validation_error` before the source request runs.
| Status | Code | Meaning |
| -----: | ------------------------------ | -------------------------------------------------------------- |
| `400` | `validation_error` | Invalid input or an invalid or expired pagination cursor |
| `403` | `forbidden` | The requested resource is private |
| `404` | `not_found` | The requested resource was not found |
| `404` | `transcript_not_available` | The video has no usable caption or media source |
| `422` | `transcription_limit_exceeded` | The uncaptioned media exceeds the synchronous transcript limit |
| `503` | `transcription_unavailable` | Transcript generation is temporarily unavailable |
| `503` | `service_unavailable` | Live TikTok data is temporarily unavailable |
| `502` | `upstream_contract_broken` | Source data cannot be processed; the failure has been reported |
Retry `503` responses with bounded exponential backoff and jitter. Do not automatically retry `400`, `403`, `404`, `422`, or `502 upstream_contract_broken`. Retrying a settled x402 or MPP request requires another payment; use account billing when you need successful-operations-only charging.
## Payment rails
The endpoints accept API keys, OAuth, x402, and MPP when those payment methods are enabled. API-key and OAuth requests are charged for successful operations. x402 and MPP use the advertised request price once payment settles, including when the final endpoint response is an error. A successful x402 settlement returns a `PAYMENT-RESPONSE` header, while MPP returns a `Payment-Receipt`. See [x402](/guides/x402) and [MPP](/guides/mpp) before choosing a no-key rail.
# Pay with x402 (no API key needed)
Source: https://docs.influship.com/guides/x402
Use the Influship API with USDC on Base, per-request, no signup
The Influship API supports the [x402 payment protocol](https://www.x402.org/) on its paid public data endpoints, so AI agents can pay per-request in USDC on Base without an API key, account, or billing setup.
## How it works
1. Your agent makes a request to a supported paid endpoint without an `X-API-Key` header.
2. The API responds with `402 Payment Required` and a `PAYMENT-REQUIRED` header containing the price and payment instructions.
3. Your agent signs a USDC payment on Base and retries the request with a `PAYMENT-SIGNATURE` header.
4. The API verifies the payment, runs the request, and settles the payment on-chain.
`PAYMENT-SIGNATURE` is the current x402 v2 header. Influship also accepts `X-PAYMENT` for compatibility with x402 clients that still emit the earlier header name.
Once settlement succeeds, the payment is final, including when the endpoint response is an error. Successful settlement is reported in the `PAYMENT-RESPONSE` header.
## Pricing
x402 prices include a 20% surcharge over the credit-based pricing — the "x402 tax" covers settlement costs. For high-volume use, an API key is cheaper.
| Endpoint | Price |
| -------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ |
| `POST /v1/search` | `\$0.3000 + \$0.0240 × requested_limit`, rounded up to the next whole cent with a \$0.01 minimum (capped at 100 results) |
| `GET /v1/creators/:id` | `\$0.0100` |
| `GET /v1/creators/autocomplete` | `\$0.0100` |
| `POST /v1/creators/lookalike` | `\$0.0180 × requested_limit`, rounded up to the next whole cent with a \$0.01 minimum (capped at 100 results) |
| `POST /v1/creators/match` | `\$0.0120 × creators_in_request`, rounded up to the next whole cent with a \$0.01 minimum |
| `GET /v1/raw/instagram/post/:shortcode` | `\$0.0200` |
| `GET /v1/raw/instagram/transcript/:shortcode` | `\$0.0600` |
| `GET /v1/raw/tiktok/profile/{username}` | `\$0.0100` |
| `GET /v1/raw/tiktok/profile/{username}/videos` | `\$0.0100` |
| `GET /v1/raw/tiktok/video` | `\$0.0100` |
| `GET /v1/raw/tiktok/video/comments` | `\$0.0100` |
| `GET /v1/raw/tiktok/video/comment/replies` | `\$0.0100` |
| `GET /v1/raw/tiktok/music` | `\$0.0100` |
| `GET /v1/raw/tiktok/video/captions` | `\$0.0100` |
| `GET /v1/raw/tiktok/video/transcript` | `\$0.0300` |
| `GET /v1/raw/youtube/channel/{handle}` | `\$0.0100` |
| `GET /v1/raw/youtube/transcript/{video_id}` | `\$0.0100` |
| `GET /v1/raw/youtube/channel-transcripts/{handle}` | `\$0.0060 × requested video_limit`, rounded up to the next whole cent |
| `GET /v1/raw/youtube/search` | `\$0.0100` per fetched page |
| `GET /v1/raw/youtube/video/{video_id}` | `\$0.0100` |
| `GET /v1/raw/youtube/typeahead` | `\$0.0100` |
| `GET /v1/raw/*` | starts at `\$0.0100` unless the endpoint cost is higher |
You pay for what you ask for, not what we deliver. If a search returns fewer creators than requested, the price still reflects the requested cap.
## Quickstart
Use any x402-compatible client. The Coinbase SDK is the reference:
```bash theme={null}
npm install @x402/fetch @x402/evm viem
```
```typescript theme={null}
import { x402Client, wrapFetchWithPayment } from '@x402/fetch';
import { registerExactEvmScheme } from '@x402/evm/exact/client';
import { privateKeyToAccount } from 'viem/accounts';
const signer = privateKeyToAccount(process.env.EVM_PRIVATE_KEY as `0x${string}`);
const client = new x402Client();
registerExactEvmScheme(client, { signer });
const fetchWithPayment = wrapFetchWithPayment(fetch, client);
const response = await fetchWithPayment('https://api.influship.com/v1/search', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ query: 'fitness creators in NYC', limit: 25 }),
});
const data = await response.json();
```
Or use [AgentCash](https://agentcash.dev) for a turnkey CLI wallet:
```bash theme={null}
npx agentcash@latest discover https://api.influship.com
```
## Discovery
Influship endpoints are listed in the [x402 Bazaar](https://docs.cdp.coinbase.com/x402/bazaar). Search for "Influship" or "influencer search" to discover them programmatically.
## Need higher rate limits or volume pricing?
Get an [API key](/guides/authentication) — same endpoints, lower per-request cost, and per-tier rate limits.
# YouTube Live Data
Source: https://docs.influship.com/guides/youtube-live-data
Discover current YouTube topics, paginate search results, and fetch channel, video, and transcript data.
# YouTube Live Data
The YouTube live endpoints cover topic discovery, channel research, video validation, and transcripts. Search is designed for bounded discovery jobs: choose filters, inspect one page, and continue with the returned cursor only when you need more candidates.
## Endpoints and pricing
| Endpoint | Returns | Credits |
| -------------------------------------------------- | ---------------------------------------------- | ------------------------: |
| `GET /v1/raw/youtube/search` | One filtered result page and `next_cursor` | `0.5/page` |
| `GET /v1/raw/youtube/typeahead` | Localized query suggestions | `0.5/request` |
| `GET /v1/raw/youtube/video/{video_id}` | Fresh video metadata and engagement | `0.5/video` |
| `GET /v1/raw/youtube/channel/{handle}` | Channel identity, metrics, and optional videos | `0.5/channel` |
| `GET /v1/raw/youtube/transcript/{video_id}` | One normalized transcript | `0.5/transcript` |
| `GET /v1/raw/youtube/channel-transcripts/{handle}` | Selected channel-video transcripts | `0.5/transcript returned` |
One credit is \$0.01. API-key and OAuth requests are charged only when they succeed. See [Pricing](/concepts/pricing) for the payment-rail rules.
## Search for emerging videos
Use topic phrases or entities in `q`. Hashtags are accepted as ordinary query text, but phrases usually cover more of the language people use in titles and descriptions.
```bash theme={null}
curl --get 'https://api.influship.com/v1/raw/youtube/search' \
-H "X-API-Key: $INFLUSHIP_API_KEY" \
--data-urlencode 'q=mini documentary urban planning' \
--data-urlencode 'upload_date=this_week' \
--data-urlencode 'sort_by=popular' \
--data-urlencode 'content_type=videos' \
--data-urlencode 'duration=long' \
--data-urlencode 'country_code=US' \
--data-urlencode 'language_code=en' \
--data-urlencode 'limit=20'
```
Search supports these controls:
| Parameter | Values |
| --------------- | ------------------------------------------------------------------- |
| `upload_date` | `any`, `last_hour`, `today`, `this_week`, `this_month`, `this_year` |
| `sort_by` | `relevance`, `popular` |
| `content_type` | `all`, `videos` |
| `duration` | `any`, `short`, `medium`, `long` |
| `country_code` | Two-letter country code, such as `US` or `GB` |
| `language_code` | Language code, such as `en` or `en-GB` |
| `limit` | 1 to 50 results per page |
Video search results include channel identity, duration, view count, thumbnail, and relative and approximate publication data. Use the video endpoint when exact publication data or current likes and comments affect your ranking.
## Continue to the next page
Each successful search returns `next_cursor`. Treat it as opaque and return it unchanged with the original query and filters.
```bash theme={null}
curl --get 'https://api.influship.com/v1/raw/youtube/search' \
-H "X-API-Key: $INFLUSHIP_API_KEY" \
--data-urlencode 'q=mini documentary urban planning' \
--data-urlencode 'upload_date=this_week' \
--data-urlencode 'sort_by=popular' \
--data-urlencode 'content_type=videos' \
--data-urlencode 'duration=long' \
--data-urlencode 'cursor=PASTE_NEXT_CURSOR_HERE'
```
Every continuation request is another 0.5-credit page. Set a page ceiling in scheduled jobs so a changing result set cannot create unbounded work.
## Expand a topic seed
Typeahead returns current localized suggestions for a partial phrase.
```bash theme={null}
curl --get 'https://api.influship.com/v1/raw/youtube/typeahead' \
-H "X-API-Key: $INFLUSHIP_API_KEY" \
--data-urlencode 'q=why do cities' \
--data-urlencode 'country_code=US' \
--data-urlencode 'language_code=en'
```
Use a small set of distinct suggestions as search seeds, then deduplicate videos by `video_id` before scoring them.
## Fetch exact video details
```bash theme={null}
curl 'https://api.influship.com/v1/raw/youtube/video/dQw4w9WgXcQ' \
-H "X-API-Key: $INFLUSHIP_API_KEY"
```
The response includes views, likes, comments, duration, tags, categories, channel identity, and `published_at` when YouTube supplies an exact timestamp.
## Resolve a channel
Channel routes accept a bare handle, an `@handle`, a `UC`-prefixed channel ID, or a full channel URL.
```bash theme={null}
curl --get 'https://api.influship.com/v1/raw/youtube/channel/@techreviews' \
-H "X-API-Key: $INFLUSHIP_API_KEY" \
--data-urlencode 'include_videos=true' \
--data-urlencode 'video_limit=12'
```
## MCP and no-code access
The six workflows are available through the Influship MCP server as `search_youtube`, `get_youtube_typeahead`, `get_youtube_video`, `get_youtube_channel`, `get_youtube_video_transcript`, and `get_youtube_channel_transcripts`.
n8n and Make expose the same YouTube operations as dedicated fields and actions. Zapier users can call these REST endpoints from a Webhooks step.
# Influship API
Source: https://docs.influship.com/index
Find the right creators for any campaign — search by natural language, explore profiles, discover lookalikes, and score campaign fit.
# Influship API
Describe the kind of creator you need, and the API finds them. Search returns ranked results with match scores and explanations, so you can build creator discovery into your product without training a model or managing data pipelines.
## Core Workflows
Pass a natural-language query with audience traits and content style, then get back ranked Instagram creators with match reasons.
Resolve a known social account by platform and username. Returns profile metadata, follower counts, engagement rates, growth, and recent activity.
Start from a creator that fits and find more like them. Useful for expanding a shortlist or replacing a creator who declined.
Score how well a set of creators fits a specific campaign brief. Each result includes a fit score and the reasoning behind it.
## Quick Example
```typescript TypeScript SDK theme={null}
import Influship from 'influship';
const client = new Influship({
apiKey: process.env.INFLUSHIP_API_KEY,
});
const response = await client.search.create({
query: 'travel content creators with practical destination guides',
limit: 5,
});
console.log(response);
```
```bash cURL theme={null}
curl -X POST https://api.influship.com/v1/search \
-H 'X-API-Key: YOUR_KEY' \
-H 'Content-Type: application/json' \
-d '{"query": "travel content creators with practical destination guides", "limit": 5}'
```
Abbreviated response:
```json theme={null}
{
"data": [
{
"creator": {
"id": "b2d4f6a8-e1c3-4b7d-9f2a-8c6e0d4b3a1f",
"name": "Priya Mehta"
},
"primary_profile": {
"platform": "instagram",
"username": "priyatravels"
},
"match": {
"score": 0.94,
"reasons": ["Consistent travel content with practical destination advice"]
}
}
],
"search_id": "123e4567-e89b-12d3-a456-426614174000",
"total": 1,
"has_more": false,
"next_cursor": null
}
```
Search accepts natural language, but result quality depends on input quality. If your users are not marketers or developers, consider running their input through an LLM to tighten the query before sending it to the API.
## Get Started
Make your first request and inspect the response shape.
Full endpoint specs with request examples for every SDK.
Install the TypeScript SDK and start making typed requests.
Credit costs, billing tiers, and usage examples.
If you're an early-stage startup, check out the [startup program](mailto:elliot@influship.com) for discounted access.
Need custom rate limits or volume pricing? Reach out at [elliot@influship.com](mailto:elliot@influship.com).
# Integrations
Source: https://docs.influship.com/integrations/index
Wire Influship into Zapier, n8n, or Make. Enrich any workflow with creator data — no code required.
Influship is an **enrichment API**, not an event source. In a no-code platform, your scenario is started by something *you* already track — a new Instagram comment, a Slack message, a Google Sheet row, an inbound email — and Influship runs as a step inside that scenario to enrich, score, search, or look up.
That model decides which capabilities are exposed: **Actions** (do work, return data) and **Searches** (find a single record, used with Find-or-Create). There are no Triggers, because Influship doesn't emit events that fire on real-world time.
## Pick a platform
4 Actions + 2 Searches. API-key auth. In Private Beta; email us to be added.
Community node with 15 operations across 4 resources. Marked `usableAsTool`, so n8n AI Agents can call it.
12 Actions, 3 Searches, plus a Universal API module.
## What you can do across all three
| Capability | Endpoint | Use it for |
| ----------------------------------- | ------------------------------------------------- | ------------------------------------------------------------------------------------- |
| **Search Creators** | `POST /v1/search` | Pull a ranked list of creators matching a natural-language brief. |
| **Find Creator** | `POST /v1/search` (top 1) | Find-or-Create entry — return the single best match for a brief. |
| **Get Creator** | `GET /v1/creators/:id` | Hydrate a stored creator ID with profiles + AI summary. |
| **Score Creator Match** | `POST /v1/creators/match` | Score a creator against a campaign brief; returns `good`/`neutral`/`avoid` + reasons. |
| **Find Lookalikes** | `POST /v1/creators/lookalike` | Given a seed creator, return similar ones. |
| **Get Profile** | `GET /v1/profiles/instagram/:username` | Cached Instagram profile lookup by handle. |
| **Lookup Profiles** | `POST /v1/profiles/lookup` | Batch profile enrichment, up to 50 handles per call. |
| **Get Posts** | `GET /v1/posts` | A creator's recent posts. |
| **Get Live Instagram Profile** | `GET /v1/raw/instagram/profile/:username` | Bypass cache; fresh-scrape a profile (≤90s). |
| **Get Live YouTube Channel** | `GET /v1/raw/youtube/channel/:handle` | Live YouTube channel fetch. |
| **Get YouTube Video Transcript** | `GET /v1/raw/youtube/transcript/:video_id` | Pull a single video transcript. |
| **Get YouTube Channel Transcripts** | `GET /v1/raw/youtube/channel-transcripts/:handle` | Batch transcripts for a channel. |
| **Search YouTube** | `GET /v1/raw/youtube/search` | Free-text YouTube search. |
| **Get YouTube Video** | `GET /v1/raw/youtube/video/:video_id` | Fresh video metadata and engagement. |
| **YouTube Typeahead** | `GET /v1/raw/youtube/typeahead` | Localized topic suggestions. |
The YouTube channel actions accept 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 isn't a channel handle returns a `400` validation error.
The video transcript action accepts the canonical 11-character YouTube video ID from the `v` query parameter. Full video URLs, channel handles, and shortened identifiers return a `400` validation error before a scrape starts.
Creator workflows are available across all three platforms. Dedicated YouTube actions are available in n8n and Make. Zapier users can call the REST endpoints from a Webhooks step.
## How costs work
Every call is metered in credits. **1 credit = \$0.01**.
* Reads are cheap: profile or post lookups cost 0.05–0.1 credits.
* AI calls (search, match, lookalike) are pricier: 1.5–25+ credits depending on what they return.
* Most live scrapes cost 0.5 credits per request or source page. Batch transcript endpoints charge per transcript returned.
Each per-platform page lists the cost for every capability so you can budget before you build.
## Three workflow patterns that fit Influship
A new row appears in a sheet or CRM → look up the handle → write back metrics.
A creator pitches you in email or Slack → score them against your brief → route the good ones into your pipeline.
A form submission or slash command → search for matching creators → drop results into Notion, Linear, or Slack.
Each per-platform page walks one of these end-to-end with a concrete recipe.
# Make
Source: https://docs.influship.com/integrations/make
Add Influship modules to any Make scenario — creator search, profile lookups, campaign-fit scoring.
The Influship Make app adds **12 Actions, 3 Searches, and a Universal API module** you can drop into any scenario. It doesn't ship Triggers. Your scenario is started by something you track, and Influship runs as an enrichment module inside it.
## Install
The Make app is in private distribution. Email [support@influship.com](mailto:support@influship.com) with your Make account email to be added.
Once you have access, the **Influship** app appears in the module picker when you build a scenario.
## Authenticate
From the [developer dashboard](https://developers.influship.com/api/keys). Keys start with `inf_`.
In the Make editor, add an Influship module to your scenario. Click **Add** under **Connection**, paste your API key, click **Save**.
Make hits `/v1/creators/autocomplete` (0.05 credits) to verify the key works. The connection appears in your **Connections** list as `Influship (…abc1)` so you can tell multiple accounts apart.
## Capabilities
### Searches
| Module | What it does | Cost |
| ------------------------- | ---------------------------------------------------- | ------ |
| **Find Creator** | Returns the single best-matching creator for a brief | 25 + 2 |
| **Get Creator by ID** | Hydrate a creator (with profiles) from a stored ID | 0.1 |
| **Get Profile by Handle** | Look up an Instagram profile by handle | 0.1 |
### Actions
| Module | What it does | Cost |
| ----------------------------------- | ---------------------------------------------------------- | ------------- |
| **Search Creators** | AI search returning up to 50 creators with score + reasons | 25 + 2/result |
| **Get Posts** | Fetch a creator's recent posts | 0.05/post |
| **Find Lookalike Creators** | Given a seed, find similar creators | 1.5/result |
| **Score Creator Match** | Score a single creator against a campaign brief | \~10 |
| **Lookup Profiles** | Batch-look-up Instagram handles (up to 50) | 0.1/profile |
| **Get Live Instagram Profile** | Bypass cache; fresh-scrape a profile | 0.5 |
| **Get Live YouTube Channel** | Fetch a YouTube channel by handle | 0.5 |
| **Get YouTube Video Transcript** | Pull transcript by video ID | 0.5 |
| **Get YouTube Channel Transcripts** | Batch transcripts for a channel | 0.5/result |
| **Search YouTube** | Filtered YouTube search with cursor pagination | 0.5/page |
| **Get Live YouTube Video** | Fetch exact publication data and current engagement | 0.5 |
| **Get YouTube Search Suggestions** | Expand a partial topic phrase | 0.5 |
The Search YouTube action returns the full page, including `results` and `next_cursor`. Map `next_cursor` into a later Search YouTube module to continue. Upload date, popularity, content type, duration, country, and language are available as fields.
### Universal
| Module | What it does |
| -------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
| **Make an API Call** | Escape hatch — hit any `api.influship.com` endpoint with method/path/query/body of your choice. Use when there isn't a dedicated module yet. |
All costs are in credits. **1 credit = \$0.01**.
## Build your first scenario
### Recipe — Enrich an Airtable handles list
You keep a research base of Instagram handles; this scenario fills in follower count, engagement, and verified status as new rows are added.
Watch your `Creators to Research` table for new rows. Output one bundle per new record.
In the **Profiles** array field, click **Add Item** and map `platform: instagram` (hard-coded) and `username` (from the Airtable bundle's `handle` column).
The module accepts up to 50 profiles per call. If you're iterating row-by-row from Airtable you'll pass one; if you batch with an **Aggregator** beforehand, you can compress 50 records into a single 0.1×50 = 5-credit call.
Write `followers`, `engagement_rate`, and `is_verified` back into the same row.
Per-row cost: **0.1 credits** = \$0.001 unbatched. Batched via Aggregator: **0.002/row** at 50-row batches.
### Recipe — Score inbound creator pitches
A creator pitches you; Make scores them and routes the winners into a Linear issue.
Filter inbound mail to your creator outreach inbox.
Extract the `@handle` from the email body with a regex.
Confirm the handle exists and pull the creator's profile ID.
Pass the creator ID and your stored brief. Returns `match_score` and a `decision` of `good`/`neutral`/`avoid`.
Use a **Router** to branch; filter the "good" route on `{{decision}} === "good"`.
On the good branch, file an issue in `#partnerships` with `match_score` and `reasons` in the body.
Per-pitch cost: **\~10 credits** (\$0.10). The match step is the LLM-heavy call.
## Cost expectations
Rough monthly spend by volume:
| Workflow | Per-event cost | At 100/day | At 1,000/day |
| ------------------------------------- | -------------- | ---------- | ------------ |
| Airtable enrichment (1 row at a time) | \$0.001 | \$3 | \$30 |
| Airtable enrichment (50-row batches) | \$0.005 / 50 | \$0.30 | \$3 |
| Pitch scoring | \$0.10 | \$300 | \$3,000 |
| On-demand search via webhook | \$0.45+ | \$1,350 | \$13,500 |
The **Search Creators** and **Score Creator Match** modules dominate — they run AI inference. Profile and post lookups are effectively free at agency scale.
## Troubleshooting
Your key was revoked or rotated. Get a fresh one from the [developer dashboard](https://developers.influship.com/api/keys), then in Make go to **Connections → Influship → Reauthorize**.
Make's per-module retry honors the `Retry-After` header on 429 responses — the scenario waits then resumes automatically. If you hit limits constantly, contact [support@influship.com](mailto:support@influship.com) to discuss raising them.
Live data modules can return `503 service_unavailable` when an upstream platform temporarily throttles a scrape. Treat that as retryable with `Retry-After`; it is not the same as your Influship account hitting a 429 rate limit.
`502 upstream_contract_broken` means the API could not process the source data. Do not configure automatic retries for this response. Stop the scenario or use your last cached value; contact support if the issue persists. Retrying an already-settled x402 or MPP request requires another payment.
Metered usage requires a payment method on file. Update it in [developer billing](https://developers.influship.com/api/billing) — the scenario resumes the next time it runs.
Influship doesn't emit real-time events. The app is **enrichment-only** — your scenario is started by something *you* track (a webhook from Instagram Business, a database change, a calendar event), and Influship runs as a module inside it. A trigger that fires when we *happen* to re-fetch a creator hours later would create scenarios that miss real events.
Use the **Make an API Call** Universal module. Set the method, relative path (e.g. `/v1/health`), query string, and body. The connection's API key is attached automatically.
## Support
* Docs: [docs.influship.com](https://docs.influship.com)
* Email: [support@influship.com](mailto:support@influship.com)
# n8n
Source: https://docs.influship.com/integrations/n8n
Add Influship as a step in any n8n workflow — usable as a tool by n8n AI Agents.
The Influship n8n community node adds **15 operations across 4 resources** (Creator, Profile, Post, YouTube) to your n8n instance. Pick a resource, pick an operation, fill in the parameters, and run it.
The node is marked `usableAsTool: true`, so n8n AI Agents can call any of its operations as a tool.
There are no trigger nodes — Influship is an enrichment API. Your workflow is started by something *you* track (an Instagram Business webhook, a Postgres trigger, an inbound email), and Influship runs as a step inside it.
## Install
1. Open **Settings → Community Nodes**.
2. Click **Install** and enter `@influship/n8n`.
3. Accept the risks of running a community node.
4. Refresh the editor — the **Influship** node appears in the actions panel.
Clone the monorepo and link the package into your local n8n install:
```bash theme={null}
cd integrations/n8n
pnpm build
npm link
cd ~/.n8n/custom
npm link @influship/n8n
```
Restart n8n. The node appears under **Influship** in the actions panel.
## Authenticate
From the [developer dashboard](https://developers.influship.com/api/keys). Keys start with `inf_`.
In n8n, go to **Credentials → New**, search **Influship API**, paste your key, and click **Save**.
n8n hits `/v1/creators/autocomplete` (0.05 credits) to verify the key works. If you see a green check, you're connected.
## Capabilities
### Resource: Creator
| Operation | Endpoint | Cost |
| ------------------- | --------------------------------------- | ------------- |
| **Search** | `POST /v1/search` | 25 + 2/result |
| **Find** | `POST /v1/search` (top 1) | 25 + 2 |
| **Get** | `GET /v1/creators/:id?include=profiles` | 0.1 |
| **Find Lookalikes** | `POST /v1/creators/lookalike` | 1.5/result |
| **Score Match** | `POST /v1/creators/match` | \~10 |
### Resource: Profile
| Operation | Endpoint | Cost |
| ------------------ | ----------------------------------------- | ----------- |
| **Get** | `GET /v1/profiles/instagram/:username` | 0.1 |
| **Lookup (Batch)** | `POST /v1/profiles/lookup` | 0.1/profile |
| **Get Live** | `GET /v1/raw/instagram/profile/:username` | 0.5 |
### Resource: Post
| Operation | Endpoint | Cost |
| ----------------------- | --------------------------- | --------- |
| **Get Creator's Posts** | `GET /v1/posts?creator_id=` | 0.05/post |
### Resource: YouTube
| Operation | Endpoint | Cost |
| --------------------------- | ------------------------------------------------- | ---------- |
| **Get Channel** | `GET /v1/raw/youtube/channel/:handle` | 0.5 |
| **Get Transcript** | `GET /v1/raw/youtube/transcript/:video_id` | 0.5 |
| **Get Channel Transcripts** | `GET /v1/raw/youtube/channel-transcripts/:handle` | 0.5/result |
| **Search** | `GET /v1/raw/youtube/search` | 0.5/page |
| **Get Video** | `GET /v1/raw/youtube/video/:video_id` | 0.5 |
| **Typeahead** | `GET /v1/raw/youtube/typeahead` | 0.5 |
Search exposes upload date, sort, content type, duration, country, language, and cursor fields. Map `next_cursor` from one response into the next request to page through results. Each page costs 0.5 credits regardless of how many results it contains.
All costs are in credits. **1 credit = \$0.01**.
## Build your first workflow
### Recipe — Enrich a Postgres row, fan out to Slack
A new lead lands in your `creators_to_review` table; n8n looks up their Instagram profile, scores them against a stored brief, and posts a Slack summary if the score clears a threshold.
Watch the `creators_to_review` table for new rows.
Map `{{$json.handle}}` to **Instagram Username**. Returns follower count, engagement, verified status.
Pass `{{$json.id}}` (the creator ID you got from the profile lookup, hydrated via Get if needed) and your brief text. Returns `match_score` (0–1) and `decision`.
Branch on the n8n IF node.
On the true branch, post `{{$json.creator.username}} scored {{$json.match_score}}: {{$json.reasons[0].text}}` to `#marketing-leads`.
### Use it from an AI Agent
The node is `usableAsTool: true`, so any n8n AI Agent (LangChain, OpenAI Tools, etc.) can call Influship operations to answer creator-related questions in a conversation:
```
User: Find me three fitness creators with audiences in the UK under 200K followers.
Agent (internal): Calls Influship.Creator.Search with query="fitness creators in the UK"
filters via the natural-language query (UK, <200K followers).
Returns ranked results.
Agent (reply): "I found Jane Doe (124K, 5.8% ER), …"
```
Add the **Influship** node as a tool on your AI Agent node; the agent picks operations based on the user's request. Bound by your account's credit limits — keep an eye on cost if the agent gets chatty.
## Cost expectations
n8n's polling cadence and "Retry on Fail" defaults mean per-event cost matters more than throughput. A rough budget:
| Workflow | Per-event cost | At 100/day | At 1,000/day |
| ---------------------------------------- | --------------- | ------------------------------ | ------------------- |
| Postgres → enrich → Slack (recipe above) | \~10.2 credits | \$10/day | \$100/day |
| Bulk enrich via Lookup Profiles | 0.1/handle | \$1 per 100 handles | \$10 per 1k handles |
| AI Agent — exploratory chat | varies (5–100+) | depends on agent talkativeness | |
## Troubleshooting
Your API key was revoked or rotated. Go to **Credentials → Influship API → Reconnect** and paste a fresh key from the [developer dashboard](https://developers.influship.com/api/keys).
n8n's per-node **Retry On Fail** setting handles this automatically. The `Retry-After` header on the 429 response tells n8n how long to wait. If you're seeing it constantly, your account is at its tier's rate limit — email [support@influship.com](mailto:support@influship.com).
Live data nodes can return `503 service_unavailable` when an upstream platform temporarily throttles a scrape. Use **Retry On Fail** and honor `Retry-After`; this is not your API key hitting its Influship account rate limit.
`502 upstream_contract_broken` means the API could not process the source data. Do not use **Retry On Fail** for this response. Stop the workflow or use your last cached value; contact support if the issue persists. Retrying an already-settled x402 or MPP request requires another payment.
Almost always means a previous node returned an empty array and you're accessing `$json[0].x`. Use the IF node or `?? null` to guard.
Influship doesn't emit real-time events. The node is **enrichment-only** — your workflow is started by something *you* track (a Postgres change, an HTTP webhook, a schedule), and Influship runs as a step inside it. A trigger that fires when we *happen* to re-fetch a creator hours later would create workflows that "missed" real events.
## Support
* Docs: [docs.influship.com](https://docs.influship.com)
* Email: [support@influship.com](mailto:support@influship.com)
* Source: [github.com/Influship/influship](https://github.com/Influship/influship/tree/main/integrations/n8n)
# Zapier
Source: https://docs.influship.com/integrations/zapier
Enrich any Zap with creator search, creator records, posts, lookalikes, and campaign-fit scoring.
The Influship Zapier integration adds **4 Actions and 2 Searches** you can drop into any Zap. It doesn't ship Triggers — your Zap is started by something *you* already track (a new message, a spreadsheet row, a form submission, or an inbound email), and Influship runs as a step inside that Zap to enrich, score, or search.
The integration is in **Private Beta**. Email [support@influship.com](mailto:support@influship.com) with the Zapier account you want invited.
## Connect your account
In the Zap editor, search for **Influship** in the action picker and add the action you want.
Click **Connect** on the Influship step. A modal asks for your API key.
Get your key from the [developer dashboard](https://developers.influship.com/api/keys). Keys start with `inf_`. Paste it, then click **Yes, Continue**.
Zapier validates the key without billing a data lookup, then saves the connection with a short account identifier. Your API key is never included in the displayed label.
## Capabilities
### Searches
Find Creator returns the best match for a brief and can feed creator-ID fields in later steps. Get Creator by ID returns at most one.
| Search | What it does | Cost |
| --------------------- | -------------------------------------------------- | ------------------- |
| **Find Creator** | Returns the best match for a brief | 25 + 2 when matched |
| **Get Creator by ID** | Hydrate a creator (with profiles) from a stored ID | 0.1 |
### Actions
| Action | What it does | Cost |
| -------------------------------------- | ---------------------------------------------------------- | ------------- |
| **Search Creators (Multiple Results)** | AI search returning up to 50 creators with score + reasons | 25 + 2/result |
| **Get Posts** | Fetch a creator's recent posts | 0.05/post |
| **Find Lookalike Creators** | Given a seed, find similar creators | 1.5/result |
| **Score Creator Match** | Score a single creator against a campaign brief | 1 |
All costs are in credits. **1 credit = \$0.01**.
## Build your first Zap
Three concrete workflows, all started by Zaps you may already have.
### Recipe 1 — Hydrate a saved creator shortlist
You save Influship creator IDs during research; this Zap keeps the corresponding creator records current in your working sheet.
Watch a sheet with a `creator_id` column.
Map the saved ID into **Creator ID**. The result includes the creator record and its known profiles.
Write the creator name, summary, themes, and profile fields you need back into the same row.
Per-row cost: **0.1 credits** = \$0.001. Hydrating 1,000 saved creators costs about a dollar.
### Recipe 2 — Score inbound creator pitches
When a creator emails you, score them against your campaign brief and route the strong matches into a "Worth a meeting" board.
Filter inbound mail to your creator-outreach inbox.
Use the creator's name, niche, and other details from the email as a short search brief. The search returns the best matching creator record.
Score the creator against a stored campaign brief. The action returns `match.decision` (`good`, `neutral`, or `avoid`) and `match.score` from 0–1.
Only create the card when `match.decision = good`. Add `match.score` and `match.reasons` to the card body.
Typical per-pitch cost: **28 credits** (\$0.28).
### Recipe 3 — On-demand shortlist via Slack command
Marketing types a brief in Slack; a Notion database fills with ranked candidates.
Set up `/find-creators ` in your workspace.
Pass the slash-command text as the **Search Query**, set **Number of Results** to 10.
Loop over the `results` line items so each creator becomes its own Notion row with score, reasons, and the primary profile.
Acknowledge in Slack with a link to the Notion view.
Per-search cost: **25 + (2 × 10) = 45 credits** (\$0.45).
## Cost expectations
A rough sense of monthly spend, assuming typical agency volume:
| Workflow | Per-event cost | At 100/day | At 1,000/day |
| ------------------------- | -------------- | ---------- | ------------ |
| Creator hydration | \$0.001 | \$3 | \$30 |
| Pitch discovery + scoring | \$0.28 | \$840 | \$8,400 |
| On-demand search | \$0.45 | \$1,350 | \$13,500 |
The search and match actions dominate cost — they're the AI-heavy paths. Hydrating a saved creator record is inexpensive.
## Troubleshooting
Your key was revoked or rotated. Get a fresh one from the [developer dashboard](https://developers.influship.com/api/keys) and reconnect — in Zapier, go to **My Connections** → Influship → **Reconnect**.
Your account hit its per-minute rate limit. Zapier reads `Retry-After` from the response and waits before retrying — no action needed. If you're hitting limits regularly, contact [support@influship.com](mailto:support@influship.com) to discuss raising them.
A live data request was temporarily unavailable. Zapier reads `Retry-After` from the response and retries automatically. This is different from your Influship account rate limit.
Metered usage requires a payment method on file. Update it in [developer billing](https://developers.influship.com/api/billing) — the Zap resumes the next time it fires.
Influship doesn't have real-time post events to emit. The integration is intentionally **enrichment-only** — your Zap is started by something *you* track (a source-app webhook, spreadsheet row, form submission, etc.) and Influship runs as an enrichment step inside it. Faking a trigger that fires when we *happen* to discover a post hours later would create confused Zaps that "missed" real events.
No. The API is read-only — every operation here is `GET` or query-style `POST`. Influship doesn't store your data; it returns what we know about creators.
## Support
* Docs: [docs.influship.com](https://docs.influship.com)
* Email: [support@influship.com](mailto:support@influship.com)
# Quickstart
Source: https://docs.influship.com/quickstart
Search for creators, fetch a creator record, and understand billing in under five minutes
# Quickstart
By the end of this page, you'll have searched for creators, fetched a full creator record, and inspected the usage headers on both requests.
## Install and configure
Install the SDK and set your API key as an environment variable.
```bash npm theme={null}
npm install influship
```
```bash pnpm theme={null}
pnpm add influship
```
```bash yarn theme={null}
yarn add influship
```
```bash theme={null}
export INFLUSHIP_API_KEY="your_api_key_here"
```
If you prefer raw HTTP, skip the install -- you only need the API key in the `X-API-Key` header.
For details on key management, scopes, and rotation, see the [Authentication guide](/guides/authentication).
Never commit API keys to version control. Use environment variables or a secrets manager.
## Search for creators
Search is the primary discovery endpoint. You pass a natural-language query describing the kind of creator you need, and the API returns ranked matches with scores and explanations.
The `query` field accepts up to 500 characters of free text. The `limit` sets the maximum number of results for that search session.
```typescript SDK theme={null}
import Influship from 'influship';
const client = new Influship({
apiKey: process.env.INFLUSHIP_API_KEY,
});
const response = await client.search.create({
query: 'fitness creators focused on home workouts, consistent posting schedule',
limit: 5,
platforms: ['instagram'],
filters: {
followers: { min: 50000 },
engagement_rate: { min: 2.0 },
},
});
console.log(response);
```
```bash cURL theme={null}
curl -X POST https://api.influship.com/v1/search \
-H 'X-API-Key: YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-d '{
"query": "fitness creators focused on home workouts, consistent posting schedule",
"limit": 5,
"filters": {
"followers": { "min": 50000 },
"engagement_rate": { "min": 2.0 }
},
"platforms": ["instagram"]
}'
```
Filters are optional but useful for narrowing results. Available filter fields:
| Filter | Type | Description |
| --------------------------------------------- | --------- | ------------------------------------------------ |
| `followers.min` / `followers.max` | integer | Follower count range |
| `engagement_rate.min` / `engagement_rate.max` | number | Engagement rate as percentage (2.0 = 2%) |
| `verified` | boolean | Only verified accounts |
| `platforms` (top-level) | string\[] | Platforms to search, defaults to `["instagram"]` |
## Inspect the response
Here's an abbreviated version of what comes back:
```json theme={null}
{
"data": [
{
"creator": {
"id": "a3f1b9c2-7d4e-4a8f-b6e1-2c9d5f8a0b3e",
"name": "Alex Rivera"
},
"relevant_profile": {
"platform": "instagram",
"username": "alexrivera.fit"
},
"primary_profile": {
"platform": "instagram",
"username": "alexrivera.fit"
},
"match": {
"score": 0.91,
"reasons": [
"Consistent home workout content with strong audience engagement"
]
}
},
{
"creator": {
"id": "d7e4c1a8-3b2f-49d6-8e5c-1a7f3b9d2e6c",
"name": "Maya Chen"
},
"relevant_profile": {
"platform": "instagram",
"username": "mayachen.fitness"
},
"primary_profile": {
"platform": "instagram",
"username": "mayachen.fitness"
},
"match": {
"score": 0.87,
"reasons": [
"Home fitness tutorials with high save rate and comment engagement"
]
}
}
],
"search_id": "8f3a1b2c-4d5e-4678-9abc-1234567890de",
"total": 2,
"has_more": false,
"next_cursor": null
}
```
A few fields worth noting:
* **`creator`** -- the canonical creator record. The `id` is what you use to fetch full profiles and pass to other endpoints.
* **`relevant_profile`** -- the profile most relevant to the query, or `null` when no profile data is available.
* **`primary_profile`** -- the creator's largest profile, or `null` when no profile data is available.
* **`match.score`** -- a 0-to-1 relevance score. Higher means a closer fit to your query. Scores above 0.8 are typically strong matches.
* **`match.reasons`** -- human-readable explanations of why the creator matched. Useful for displaying to end users or for your own review.
Search accepts natural language. If your end users aren't marketers, consider preprocessing their input with an LLM to improve result quality. Test both approaches -- sometimes raw user input works fine, sometimes a refinement step makes a real difference.
The [API Reference](/api-reference) is the source of truth for exact response shapes, required fields, and edge cases. The examples on this page are abbreviated for clarity.
## Fetch a creator by ID
Use the `id` from a search result to pull the full creator record. Add `?include=profiles` to expand linked social profiles in the same response, so you don't need a separate call for each platform.
```typescript SDK theme={null}
const creator = await client.creators.retrieve(
'a3f1b9c2-7d4e-4a8f-b6e1-2c9d5f8a0b3e',
{ include: ['profiles'] }
);
console.log(creator);
```
```bash cURL theme={null}
curl "https://api.influship.com/v1/creators/a3f1b9c2-7d4e-4a8f-b6e1-2c9d5f8a0b3e?include=profiles" \
-H 'X-API-Key: YOUR_API_KEY'
```
The response includes the creator's metadata and an array of linked profile summaries with usernames, follower counts, engagement rates, and verification status.
## Check cost and remaining budget
Every response includes billing and rate-limit headers. After the search request above, you'd see something like:
```http theme={null}
X-Credits-Charged: 35.00
X-Credits-Features: creators.search
X-Billing-Plan: free
RateLimit-Remaining-Minute: 115
RateLimit-Remaining-Hour: 1465
```
Search billing breaks down like this:
| Component | Cost |
| --------------------- | ----------------------------- |
| Base fee per search | 25 credits |
| Per creator delivered | 2 credits |
The base fee covers the AI inference that runs on every query. The per-creator fee scales with how many results you actually receive.
With `limit: 5` and five results returned, that's 25 + (5 x 2) = **35 credits**, or **\$0.35**. If the API only finds 3 matches, you'd pay 25 + (3 x 2) = 31 credits -- you're never charged for results that don't exist.
The `RateLimit-Remaining-*` headers tell you how many rate-limit credits remain in the current window. Monitor these if you're running batch searches.
See [Pricing](/concepts/pricing) for full cost rules and [Rate Limits & Tiers](/concepts/quotas-and-limits) for current budgets by plan.
## Next steps
Understand the data model and when to use each resource
Query syntax, scoring, and how to get the best results
Typed client setup, error handling, and pagination
Full endpoint specs with generated examples for every route
# SDKs
Source: https://docs.influship.com/sdks/index
Install the TypeScript SDK and start making API calls in minutes
# SDKs
The TypeScript SDK is auto-generated from the OpenAPI spec. It gives you typed methods, request/response models, and automatic error classes — so you spend less time reading docs and more time building.
## Install with AI
Copy this prompt into Codex, Claude Code, Cursor, or another coding agent.
Add the Influship API to this project.
First inspect the repository to identify its language, framework, package manager, environment-variable conventions, and existing API client patterns. Preserve those conventions.
For a TypeScript or JavaScript project:
1. Install the official `influship` package with the repository's existing package manager.
2. Configure a server-side Influship client that reads `INFLUSHIP_API_KEY` from the environment.
3. Add `INFLUSHIP_API_KEY=` to the appropriate example environment file. Never put a real key in source code, generated files, logs, client-side bundles, or version control.
4. Add a small, reusable example for natural-language creator search using `client.search.create({ query, limit: 5 })`. Keep it behind an existing server-side boundary such as a server action, route handler, backend service, or CLI command.
5. Handle API and rate-limit errors using the SDK's exported error classes and honor `Retry-After` when present.
For another language, use the REST API at [https://api.influship.com](https://api.influship.com) with an `X-API-Key` header and follow the project's existing HTTP-client conventions.
Use [https://docs.influship.com/sdks](https://docs.influship.com/sdks) and [https://docs.influship.com/api-reference](https://docs.influship.com/api-reference) as the contract. Run the relevant local formatting, type-check, and test commands. If `INFLUSHIP_API_KEY` is available, make a small creator search with `limit: 1` to verify the integration. Finish by listing the files changed, where I should set `INFLUSHIP_API_KEY`, and the verification result.
## TypeScript / JavaScript
### Installation
```bash theme={null}
npm install influship
```
```bash theme={null}
yarn add influship
```
```bash theme={null}
pnpm add influship
```
```bash theme={null}
bun add influship
```
### Client Setup
```typescript theme={null}
import Influship from 'influship';
const client = new Influship({
apiKey: process.env.INFLUSHIP_API_KEY,
});
```
If `INFLUSHIP_API_KEY` is set in your environment, you can skip the config object entirely:
```typescript theme={null}
const client = new Influship();
```
### Common Operations
#### Search
Search accepts a natural language query and returns ranked creators. Describe the kind of creator you need — the API handles the matching.
```typescript theme={null}
const results = await client.search.create({
query: 'sustainable fashion creators',
limit: 10,
filters: {
followers: { min: 10000, max: 500000 },
engagement_rate: { min: 2.0 },
},
});
for (const result of results.data) {
console.log(result.creator.name, result.match.score);
}
```
Start with a small limit (5-10) while prototyping. Larger limits cost more credits and usually return diminishing-value results past the top 15-20.
#### Lookalike
Find creators similar to ones you already know. You can weight seeds to influence which traits matter more in the results.
```typescript theme={null}
const similar = await client.creators.lookalike({
seeds: [
{ platform: 'instagram', username: 'fitness_coach_jane', weight: 1.0 },
{ platform: 'instagram', username: 'wellness_daily', weight: 0.5 },
],
limit: 15,
});
```
A higher weight means the API leans more heavily on that seed's profile characteristics. Use this when one seed is a better example of what you want than the others.
#### Campaign Match
Score how well specific creators fit a campaign brief. Each result includes a decision (strong fit, moderate fit, or weak fit) and a numeric score.
```typescript theme={null}
const fit = await client.creators.match({
creators: [
{ creator_id: '123e4567-e89b-12d3-a456-426614174000' },
{ creator_id: '987fcdeb-51a2-43d7-8b90-123456789abc' },
],
intent: {
query: 'Promote a new plant-based protein bar',
context: 'Target audience is health-conscious millennials aged 22-35',
},
});
for (const result of fit.data) {
console.log(result.match.decision, result.match.score);
}
```
#### Profile Lookup
Retrieve a single creator profile by platform and username.
```typescript theme={null}
const profile = await client.profiles.get('jamietravels', { platform: 'instagram' });
```
#### Batch Lookup
Look up multiple profiles in a single request. This is more efficient than calling `profiles.get` in a loop — one request, one billing event.
```typescript theme={null}
const profiles = await client.profiles.lookup({
profiles: [
{ platform: 'instagram', username: 'jamietravels' },
{ platform: 'instagram', username: 'chefmarco' },
],
});
```
Profile lookups are cheap but add up at scale. Cache these responses if your use case allows it — creator data doesn't change often.
#### Creator Email Lookup
Fetch known email addresses for creators. Identify each creator by Influship `creator_id` or by `platform` + `username` — you can mix both in one request. Response rows preserve the input order.
```typescript theme={null}
const emails = await client.creatorEmails.lookup({
creators: [
{ platform: 'instagram', username: 'jamietravels' },
{ creator_id: '123e4567-e89b-12d3-a456-426614174000' },
],
});
```
Emails can be `unvalidated`, so check each `status` before treating an address as deliverable. You're charged only for resolved creators that return at least one email.
#### TikTok Video Transcript
Fetch a transcript from a TikTok video URL. The response contains plain text and timestamped segments with millisecond offsets.
Each successful transcript costs 2.5 credits (\$0.025), including reused results. TikTok profile, video-detail, sound-detail and comment-page requests cost 0.2 credits (\$0.002).
Sound details are available through `GET /v1/raw/tiktok/music?music_id=...`. Use the exact sound clip ID as a string. Unknown fields are `null`; audio and cover URLs are temporary links rather than durable downloads.
Pass `video.music.music_id` unchanged when it is non-null. Do not use `Number()` or `parseInt()` on TikTok IDs; large IDs exceed JavaScript's safe integer range.
Caption-only responses are available through `GET /v1/raw/tiktok/video/captions?url=...` (OpenAPI operation `getLiveTikTokVideoCaptions`). This returns existing captions without generating a transcript and costs 0.2 credits per successful response. Missing captions return `transcript_not_available`.
```typescript theme={null}
const result = await client.raw.tiktok.getVideoTranscript({
url: 'https://www.tiktok.com/@creator/video/7517114944362499342',
});
console.log(result.data.full_text);
for (const segment of result.data.segments) {
console.log(segment.start_ms, segment.end_ms, segment.text);
}
```
The response reports the detected language. The generated client uses a 210-second request timeout so a transcript can complete within the API's 180-second execution budget. See [TikTok live data](/guides/tiktok-live-data) for profile, video, comment, media URL, and transcript behavior.
For TikTok profile-video and comment pagination, pass `next_cursor` unchanged with the same resource and query options. Cursors are opaque strings of up to 2,048 characters; do not parse them or convert them to numbers. If the API returns `400 validation_error` for an invalid or expired cursor, restart without a cursor rather than retrying the same page token.
### Error Handling
The SDK exports typed error classes so you can handle failures precisely.
```typescript theme={null}
import Influship, { APIError, RateLimitError } from 'influship';
try {
const results = await client.search.create({ query: 'fitness' });
} catch (error) {
if (error instanceof RateLimitError) {
console.log('Account rate limited, retry after:', error.headers?.get('retry-after'));
} else if (error instanceof APIError && error.status === 402) {
console.log('Billing or subscription action required:', error.message);
} else if (error instanceof APIError && error.status === 503) {
console.log('Temporary upstream issue, retry after:', error.headers?.get('retry-after'));
} else if (error instanceof APIError && error.status === 502) {
console.log('Upstream data unusable — do not retry, use cached data');
} else if (error instanceof APIError) {
console.log('API error:', error.status, error.message);
}
}
```
Most authenticated 402 responses use `payment_required` with a `reason_code` for the billing or subscription state and a `next_step` for the recovery action. Search can return `insufficient_credits` instead when remaining credits cannot cover the request. Branch on `error.code`. Do not retry automatically. Temporary failures while checking billing state use retryable 503 responses instead.
`429 rate_limit_exceeded` means your API key hit its account-level quota. Live-data requests can return `503 service_unavailable` when they cannot be completed. Honor `Retry-After` when present, use bounded exponential backoff, and add jitter between attempts.
YouTube search retries one eligible connection failure within the request deadline. A `503` can also represent another temporary upstream failure. Apply the normal bounded backoff instead of immediately replaying the request in a tight loop.
Instagram profile requests attempt recovery from temporary source failures within the request budget. A successful recovery uses the same response schema; an unsuccessful recovery returns an error, not a partial successful profile. Keep retries bounded and honor `Retry-After` when present.
Keep `502 upstream_contract_broken` out of that retry path. It means the API could not process the source data. Do not retry automatically; use your last cached value and contact support if the issue persists. Retrying an already-settled x402 or MPP request requires another payment.
### Health and Readiness
`GET /health` is the unauthenticated process-liveness check. It answers when the API process is running, even if a downstream dependency is temporarily unavailable.
`GET /ready` is the unauthenticated dependency-readiness check for operators and load balancers. It checks required downstream dependencies in parallel, returning `200` only when every dependency is ready and `503` otherwise. The response exposes status and latency per dependency without credentials or upstream error details.
See [Error Handling](/guides/error-handling) for the full error reference.
## Python
There is no official Python SDK. Use the REST API directly with `requests` or `httpx`.
```python theme={null}
import requests
response = requests.post(
'https://api.influship.com/v1/search',
headers={'X-API-Key': 'your_api_key'},
json={
'query': 'sustainable fashion creators',
'limit': 10,
},
)
data = response.json()
for result in data['data']:
print(result['creator']['name'], result['match']['score'])
```
## API Reference
The [API Reference](/api-reference) is generated from the same spec as the SDK. Use it for the most up-to-date method signatures and response shapes. If the SDK types and the reference ever seem to disagree, the reference reflects the latest deployed version.