Developer docs

    Creator Search API Documentation & Hosted MCP Server

    Janney AI's 180M+ creator database as a REST API and a hosted, drop-in MCP server. Search creators, find lookalikes, extract available contact emails, and pull audience demographics — from your own code or straight inside an AI agent.

    Included with Growth ($299/month), Scale ($599/month), and Custom plans. New accounts can try the API and the MCP server with their free signup credits before choosing a plan. Scale includes higher API and MCP rate limits. Create and manage keys in the app.

    What it is

    A REST API and MCP server for programmatic creator discovery across TikTok, Instagram, and YouTube.

    What it returns

    Creator profiles, lookalikes, available contact emails, audience demographics, and remaining API credits.

    Who should use it

    Teams building agency dashboards, CRMs, data pipelines, marketplaces, or AI agents around creator search.

    Authentication

    All requests go to the base URL https://backend.janney.ai and carry your API key. Send it as an x-api-key header, or as Authorization: Bearer <key>. Create a key on the API & MCP page in the app.

    two ways to authenticate
    # header
    curl https://backend.janney.ai/api/v1/credits -H "x-api-key: YOUR_API_KEY"
    
    # bearer
    curl https://backend.janney.ai/api/v1/credits -H "Authorization: Bearer YOUR_API_KEY"

    Requests without a valid key return 401. Accounts without the required plan return 403.

    Send JSON with Content-Type: application/json. A body that is not a JSON object returns 400 with {"error": "..."}; HTTP errors share that shape.

    Endpoints

    Machine-readable spec: GET https://backend.janney.ai/api/v1/openapi.json (OpenAPI 3.1, no key required). Import it into Postman, an HTTP client, or your agent framework.

    From search to contact

    Call POST /api/v1/search to shortlist creators, then pass the selected handles to POST /api/v1/enrich for live profiles and available contact emails. Add audience to fields only when you need demographics. To find N new creators who each have an email, start a POST /api/v1/enrich/bulk job.

    Use filters.platforms, filters.countries, filters.min_followers, and filters.max_followers for exact creator constraints. filters.min_engagement_rate is a percentage, so 3 means 3%. Inspect applied_filters in the response. Audience demographics are returned per creator through /audience, not used to filter search results.

    POST/api/v1/enrich
    profile free; email / audience metered

    Enrich selected creators

    After /search, send the handles you selected to get their live profile cards and available contact emails in one call. Choose fields from profile, email, and audience; the default is profile + email. Profile cards are free up to 500 per account per 24 hours; after that, profile requests return 429, so request fields: ["email"] alone. Email and audience use their existing per-hit credit rates. An email bought by this account within 30 days comes back free, while a creator checked within 24 hours with no public email is answered from memory unless recheck is true. The cap is 50 creators for email alone, 25 when profile is included, or 10 when audience is included. Set an HTTP client timeout of at least 180 seconds: a cold Instagram profile can take about 30 seconds. For finding N new creators with emails, use /enrich/bulk instead.

    Body parameters

    FieldTypeRequiredDescription
    creators{platform, username}[]optionalCreators you already picked, in order. Or send platform + username for one creator. Maximum 50, reduced to 25 with profile or 10 with audience.
    platformstringoptionalSingle-creator form, together with username.
    usernamestringoptionalSingle-creator form, together with platform.
    fieldsstring[]optionalAny non-empty selection of profile, email, audience. Default: profile + email. Add audience only when needed.
    recheckbooleanoptionalDefault false. Look again after a no-email check in the last 24 hours instead of answering from memory.
    refreshbooleanoptionalDefault false. For audience only, force a fresh compute instead of a cached result.

    Response

    FieldTypeDescription
    resultsEnrichResult[]One row per distinct creator in the order asked. Requested fields appear on each row; an unreadable profile or unavailable audience gets a row-level error.
    requestedintegerNumber of creators requested.
    foundintegerNumber of rows with an email.
    chargedobject{ email, audience, credits }: new emails billed, audience hits billed, and total credits charged.
    already_checkedintegerPresent when non-zero: no-email results answered from this account's 24-hour memory.
    noticestringPresent with already_checked; explains what was skipped.

    Request

    curl
    curl -X POST https://backend.janney.ai/api/v1/enrich \
      -H "x-api-key: YOUR_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{"creators": [{"platform": "instagram", "username": "samplecreator"}]}'

    Example response

    200 OK
    {
      "requested": 1,
      "found": 1,
      "charged": { "email": 1, "audience": 0, "credits": 1 },
      "results": [
        {
          "platform": "instagram",
          "username": "samplecreator",
          "profile": {
            "platform": "instagram",
            "username": "samplecreator",
            "followers": 12000,
            "engagement_rate": 3.4,
            "bio": "Fitness creator"
          },
          "email": "[email protected]",
          "email_confidence": "high"
        }
      ]
    }
    POST/api/v1/similar
    0.01 credit / creator returned

    Find similar creators

    Return lookalike creators similar to a given one. As with /search, email_status reflects this account's own extraction history, not whether an address exists.

    Body parameters

    FieldTypeRequiredDescription
    platformstringrequiredinstagram | tiktok | youtube.
    usernamestringrequiredThe seed creator's handle.
    limitintegeroptional1–100, default 20.
    filtersobjectoptionalOptional structured filters to narrow the lookalikes.

    Response

    FieldTypeDescription
    resultsCreator[]Similar creators (Creator object). Emails not included.
    countintegerNumber returned.
    has_morebooleanWhether another page of lookalikes exists.
    notestringPresent when results is empty because the seed creator is not in the database.

    Request

    curl
    curl -X POST https://backend.janney.ai/api/v1/similar \
      -H "x-api-key: YOUR_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{"platform": "instagram", "username": "timmyunleashed", "limit": 10}'

    Example response

    200 OK
    {
      "count": 10,
      "has_more": true,
      "results": [
        {
          "platform": "tiktok",
          "username": "flytyfitness",
          "display_name": "Flyty Fitness",
          "followers": 52140,
          "engagement_rate": 3.8,
          "verified": false,
          "country": "US",
          "gender": "male",
          "niche_tags": ["fitness", "wellness"],
          "profile_url": "https://www.tiktok.com/@flytyfitness",
          "bio": "Fitness creator and coach.",
          "email_status": null
        }
      ]
    }
    POST/api/v1/enrich/email
    1 credit / new email found (misses are free)

    Extract available contact emails

    The email-only form of /enrich for creators you already picked. Synchronous extraction from bios, external links, contact pages, and linktrees. Budget about a minute per 50 creators and set your HTTP client timeout to at least 180 seconds. To find N creators with emails, use /enrich/bulk instead; it does not tie up a connection. An address this account already bought in the last 30 days comes back free — charged says what was billed — so re-running a list is safe. A creator checked in the last 24 hours with no public email is answered from memory: instant, free, counted in already_checked with a plain-language notice; pass recheck: true to look again.

    Body parameters

    FieldTypeRequiredDescription
    creators{platform, username}[]requiredUp to 200 creators to extract emails for. (Or send platform + username for a single creator.)
    recheckbooleanoptionalDefault false. Look again at creators whose last check found no public email within 24 hours.

    Response

    FieldTypeDescription
    resultsobject[]Per creator: { platform, username, email (string | null), confidence (string | null), email_confidence (string | null) }. Both confidence fields have the same value.
    foundintegerNumber of creators for which an email was found.
    chargedintegerNumber of new emails billed on this call. Addresses this account bought in the last 30 days are free.
    requestedintegerNumber of creators requested.
    already_checkedintegerPresent when non-zero: creators answered from memory after a check found no public email within 24 hours.
    noticestringWhen already_checked is present, explains what was skipped and how to force a fresh check.

    Request

    curl
    curl -X POST https://backend.janney.ai/api/v1/enrich/email \
      -H "x-api-key: YOUR_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{"creators": [{"platform": "instagram", "username": "timmyunleashed"}]}'

    Example response

    200 OK
    {
      "requested": 1,
      "found": 1,
      "charged": 1,
      "results": [
        { "platform": "instagram", "username": "timmyunleashed", "email": "tim\u0040example.com", "confidence": "high", "email_confidence": "high" }
      ]
    }
    POST/api/v1/enrich/bulk
    free to start; 1 credit / creator found

    Find creators with emails

    Start an asynchronous job that finds creators matching your description and returns only those with available contact emails. Starting a job is free. Poll its status_url about every 5 seconds; jobs usually take 1–4 minutes, or up to 15 minutes for a large target. A narrow requirement (few creators in the database post about it consistently) can take the full 30-minute budget, with a hard cap at 40 minutes, and still return few or none. found only moves when a creator passes the content check, so a long run at found 0 means the job is working; widen the requirement rather than retrying. The completed job is charged once, at 1 credit per creator returned.

    Body parameters

    FieldTypeRequiredDescription
    requirementstringoptionalDescribe the creators you want. query is accepted as an alias. Provide this or filters.
    filtersobjectoptionalStructured filters, as in /search. Provide this or requirement.
    targetintegeroptionalDesired number of creators with emails. 1–1000, default 50; the job may find fewer.
    exclude_usernamesstring[]optionalHandles already returned by a previous job, to exclude when requesting more.

    Response

    FieldTypeDescription
    job_idstringJob identifier to use when polling.
    statusstringpending or running.
    targetintegerRequested number of creators.
    status_urlstringRelative URL to GET with your API key about every 5 seconds.
    notestringPolling and timing guidance.

    Request

    curl
    curl -X POST https://backend.janney.ai/api/v1/enrich/bulk \
      -H "x-api-key: YOUR_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{"requirement": "US fitness creators", "target": 50}'

    Example response

    200 OK
    {
      "job_id": "job-example",
      "status": "pending",
      "target": 50,
      "status_url": "/api/v1/enrich/bulk/job-example",
      "note": "Poll every 5 seconds."
    }
    GET/api/v1/enrich/bulk/{job_id}
    free to poll; charged once on completion

    Check a bulk email job

    Poll about every 5 seconds. Status is pending, running, completed, failed, or unknown. While running, examined may show how many creators the job has checked, including those rejected by the content check. Polling is free; when the job completes, it is charged only once at 1 credit per creator with an email, even if you poll again.

    Response

    FieldTypeDescription
    job_idstringThe job you requested.
    statusstringpending | running | completed | failed | unknown.
    examinedintegerWhile running, creators checked so far, including those rejected. Present when reported by the upstream service.
    foundintegerCreators found so far, or the total when completed.
    targetinteger | nullRequested number of creators.
    resultsBulkResult[]Only on completion: one row per creator with an email. See fields below.
    notestringPolling guidance while the job runs.
    errorstringReason when status is failed or unknown.

    Request

    curl
    curl https://backend.janney.ai/api/v1/enrich/bulk/job-example \
      -H "x-api-key: YOUR_API_KEY"

    Example response

    200 OK
    {
      "job_id": "job-example",
      "status": "completed",
      "found": 1,
      "target": 50,
      "results": [
        {
          "username": "samplecreator",
          "platform": "instagram",
          "display_name": "Sample Creator",
          "followers": 12000,
          "engagement_rate": 3.4,
          "verified": false,
          "country": "US",
          "niche_tags": ["fitness"],
          "profile_url": "https://www.instagram.com/samplecreator/",
          "bio": "Fitness creator",
          "email": "[email protected]",
          "email_confidence": "high"
        }
      ]
    }
    POST/api/v1/audience
    1 credit / creator

    Audience demographics

    The audience-only form of /enrich for a creator you already picked: age, gender, top countries and languages. Charged only on a hit; a creator with no audience data returns { error, platform, username } and costs nothing. These figures are estimates modelled from a sample of the creator's followers, not a census — age is the roughest of them and is best read as directional, while gender and country are firmer.

    Body parameters

    FieldTypeRequiredDescription
    platformstringrequiredinstagram | tiktok | youtube.
    usernamestringrequiredThe creator's handle.
    refreshbooleanoptionalForce a fresh compute instead of a cached result.

    Response

    FieldTypeDescription
    platformstringEchoes the platform you asked about.
    usernamestringEchoes the creator you asked about.
    audience_ageobjectPercent by bracket: under_25, 25_34, 35_plus.
    audience_genderobjectPercent split, e.g. { female: 86, male: 14 }.
    audience_geo_countriesobject[][{ code, pct }] — top countries by share.
    audience_languagesobject[][{ lang, pct, region }] — top languages.

    Request

    curl
    curl -X POST https://backend.janney.ai/api/v1/audience \
      -H "x-api-key: YOUR_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{"platform": "instagram", "username": "timmyunleashed"}'

    Example response

    200 OK
    {
      "platform": "instagram",
      "username": "timmyunleashed",
      "audience_gender": { "female": 86, "male": 14 },
      "audience_age": { "under_25": 18, "25_34": 45, "35_plus": 36 },
      "audience_geo_countries": [
        { "code": "US", "pct": 59.0 },
        { "code": "PH", "pct": 6.9 },
        { "code": "GB", "pct": 4.9 }
      ],
      "audience_languages": [
        { "lang": "en", "pct": 100.0, "region": "US/UK/Global" }
      ]
    }
    GET/api/v1/credits
    free

    Remaining credits

    Check how many API credits are left on your account. Also available at /api/v1/me. Free — never charged.

    Response

    FieldTypeDescription
    available_creditnumberCredits remaining this billing period.
    used_creditnumberCredits used.
    ledger_balancenumberGranted balance.

    Request

    curl
    curl https://backend.janney.ai/api/v1/credits \
      -H "x-api-key: YOUR_API_KEY"

    Example response

    200 OK
    { "available_credit": 882.9, "used_credit": 197.1, "ledger_balance": 1080 }

    The Creator object

    Returned by /search and /similar. Both endpoints return the same Creator object. Contact emails are excluded; send selected handles to /enrich. The email_status field is this account's extraction memory, not a claim about whether the creator has an email.

    FieldTypeDescription
    platformstringinstagram | tiktok | youtube.
    usernamestringThe creator's handle.
    display_namestringDisplay name.
    followersintegerFollower count.
    engagement_ratenumberEngagement rate (%).
    verifiedbooleanPlatform-verified badge.
    countrystringISO-2 country code, where known.
    creator_citystring | nullCreator's city when the search index knows it; null for most rows.
    genderstringInferred gender, where known.
    niche_tagsstring[]Niche / category tags.
    profile_urlstringCanonical link to the creator's profile.
    biostringProfile bio text.
    email_statusstring | nullThis account's extraction memory: on_file = address bought within 30 days; no_email_24h = checked within a day and found none; null = never asked. This does not say whether the creator has an email.

    The EnrichResult row

    Returned by /enrich in the order requested. Each row contains the fields you asked for. A creator whose profile cannot be read or whose audience data is unavailable gets a row-level error; the rest of the batch still returns.

    FieldTypeDescription
    platformstringCreator platform.
    usernamestringCreator handle.
    profileProfile | nullLive card when requested; null if it could not be read.
    profile_errorstringWhy this creator's live card could not be read; the other rows still return.
    emailstring | nullAvailable contact email when requested; null when none was found.
    email_confidencestring | nullConfidence in the extracted email, where known.
    already_checkedbooleanThis creator's no-email result came from this account's 24-hour memory.
    audienceAudience | nullDemographics when requested; null if unavailable.
    audience_errorstringWhy this creator's audience data was unavailable; the other rows still return.

    The Profile object

    The live card inside an /enrich result when fields includes profile.

    FieldTypeDescription
    platformstringinstagram | tiktok | youtube.
    usernamestringThe creator's handle.
    display_namestring | nullDisplay name.
    followersinteger | nullLive follower count.
    engagement_ratenumber | nullEngagement percentage; 3.1 means 3.1%.
    verifiedboolean | nullPlatform-verified badge.
    countrystring | nullISO-2 country code, where known.
    biostring | nullProfile bio.
    avatar_urlstring | nullProfile image URL; it may expire, so fetch the card again rather than storing it.
    external_urlsarrayLinks from the profile, such as a site, linktree, or shop.
    top_hashtagsarrayHashtags from recent content.
    recent_posts{title: string | null, url: string | null, views: integer | string | null}[]Latest posts, newest first. Post cover images are omitted because their URLs expire.
    avg_viewsinteger | nullAverage views over the recent posts sampled.
    avg_likesinteger | nullAverage likes over the recent posts sampled.
    avg_commentsinteger | nullAverage comments over the recent posts sampled.
    post_countinteger | nullNumber of recent posts sampled for the averages.
    video_countinteger | nullLifetime video count, where reported.
    oldest_post_atstring | nullDate of the oldest sampled post, useful with post_count for posting frequency.
    total_viewsinteger | nullTotal views, where reported.
    total_likesinteger | nullTotal likes, where reported.

    The BulkResult object

    Returned in /enrich/bulk/{job_id} when the job completes. Each creator has an available contact email.

    FieldTypeDescription
    platformstringinstagram | tiktok | youtube.
    usernamestringThe creator's handle.
    display_namestringDisplay name.
    followersintegerFollower count.
    engagement_ratenumberEngagement rate (%).
    verifiedbooleanPlatform-verified badge.
    countrystringISO-2 country code, where known.
    niche_tagsstring[]Niche / category tags.
    profile_urlstringCanonical link to the creator's profile.
    biostringProfile bio text.
    emailstringAvailable contact email.
    email_confidencestring | nullConfidence in the extracted email, where known.

    MCP server

    The same data as a hosted, standards-compliant MCP server — drop it into any MCP client and your AI agent can call it directly. One config works everywhere; swap YOUR_API_KEY for a key from the app.

    mcp config · json
    {
      "mcpServers": {
        "janney": {
          "command": "npx",
          "args": [
            "mcp-remote",
            "https://backend.janney.ai/mcp",
            "--header",
            "Authorization: Bearer YOUR_API_KEY"
          ]
        }
      }
    }
    Eight tools: search_creators find_similar_creators enrich_creators enrich_email bulk_enrich_start bulk_enrich_status creator_audience get_remaining_credits

    After search_creators, use enrich_creators to get live profile cards and contact emails for selected handles in one call (or add audience when needed). Free profile cards are limited to 500 per account per 24 hours; after that, profile requests return 429, so use fields: ["email"] alone. enrich_email is the email-only form; creator_audience is the audience-only form. Both enrich_creators and enrich_email accept recheck: true to look again after a no-email check within 24 hours.

    Credits & rate limits

    Your plan's credits are shared across the app, REST API, and MCP, not separate quotas. In the SaaS app, search, pagination, similar creators, and profile viewing are free; credits are spent only when a contact address is successfully found, or on metered API/MCP actions. API search costs 0.01 credit per creator returned; contact email extraction costs 1 credit per email found. Growth includes 900 monthly credits, enough for up to 90,000 API search results or 900 available contact emails before renewal. Check the balance anytime with GET /api/v1/credits (or the get_remaining_credits MCP tool).

    Cost per call

    • /search · /similar 0.01 / creator
    • /enrich profile free; email / audience as below
    • /enrich/email 1 / new email found
    • /enrich/bulk free to start; 1 / email found on completion
    • /audience 1 / creator
    • /credits · /me free

    Rate limits (per key)

    • search / similar 120 / min
    • enrich / email / audience / bulk start 30 / min
    • bulk status / credits / me 300 / min

    Over the limit returns 429 with a Retry-After header.

    If the shared credit balance is exhausted, API requests return 402 and in-app credit-gated actions return 401 until the plan renews or you upgrade/contact sales. Credits roll over while a subscription remains active and expire when it ends. Self-serve one-time credit packs are discontinued.

    502 means an upstream enrichment service failed. It is safe to retry; nothing was charged.

    Related developer and campaign resources

    Use these pages to connect the API documentation with Janney AI's marketplace listings, SaaS workflow, Growth developer access, and free creator search positioning.

    Get started

    The API and hosted MCP are included with Growth ($299/month), Scale ($599/month), and Custom plans. Scale includes higher rate limits. Subscribe, then create your key on the API & MCP page in the app.