Tokfluence
Tokfluence
API Docs
API reference

Ultra Search

Give Ultra Search a brief in plain words and get back a finished creator list. It reads the brief, searches our index, crawls TikTok for creators we don't have yet, and has a model judge every candidate against your brief. Each creator comes back with a tier, a fit score and a one-sentence reason.

What it does

  • The same Ultra Search as in the app, with the same checks, the same pipeline and the same list. A search started here shows up in your account's Ultra Search history and in Lists.
  • It runs in the background: from a few minutes to a few hours, depending on how much of the niche we need to crawl. You start it, poll its status, then read the list.
  • The list keeps the judge's order, best first: bullseye creators, then adjacent, then craft, then near misses.
  • Words like "ideally" or "bonus if" in the brief rank creators higher; they never filter anyone out. A number or a contact email is a hard requirement only when the brief says so ("at least", "must").

What it costs

Ultra Search uses no API credits. Each search you start uses one of your plan's monthly Ultra Searches, exactly as in the app, and the count is shared between the app, the API and the MCP server. How many you get depends on your plan; meta.quota always says. A search that stops on our side gives its Ultra Search back. Reading the status and the results is free.

Every response carries meta.quota so you can see what's left:

json
"quota": {
  "unlimited": false,
  "remaining": 14,
  "monthly_limit": 15,
  "bonus": 0,
  "period_end": "2026-11-05T00:00:00Z",
  "left": "14 of 15 left"
}
One at a time
Each account runs one Ultra Search at a time, in the app and through the API together, unless it has been set up to run more. Starting one more than that returns 409 already_running with the newest running search's id.

POST/v1/ultra_searches#

Starts a search. Your brief is read before anything is spent: if it names no topic, or asks for one specific account or link, you get a 422 with suggestions and nothing is used.

Body

ParamTypeNotes
briefrequiredstringWho you want to find, in plain words, up to 500 characters. Say what they post about and where.
countriesstring[]Optional. Two-letter country codes the creators must be in, e.g. ["GB", "IE"]. Leave it out and any countries named in the brief are used.
min_followersintOptional. Smallest follower count. Leave it out and a floor stated in the brief is used.
max_followersintOptional. Largest follower count.
languagestringOptional. Two-letter language code the creators post in, e.g. en.
bash
curl -X POST "https://developers.tokfluence.com/v1/ultra_searches" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "brief": "UK fitness creators who review sports drinks, ideally with 50k+ followers",
    "countries": ["GB"]
  }'

The answer is 201 with the same object the status endpoint returns, below.

GET/v1/ultra_searches/:id#

Where the search is. Poll it every minute or two until results_ready is true.

json
{
  "data": {
    "id": 4812,
    "brief": "UK fitness creators who review sports drinks, ideally with 50k+ followers",
    "stage": "judging",
    "stage_label": "Checking every creator against your brief",
    "started_at": "2026-10-22T09:14:03Z",
    "updated_at": "2026-10-22T09:31:40Z",
    "estimate_seconds_remaining": 420,
    "estimate_note": null,
    "reading": "UK fitness creators who review sports drinks, ideally 50k+ followers",
    "keywords": ["sports drink review", "gym supplements uk"],
    "countries": ["GB"],
    "counts": { "creators_found": 38, "bullseye": 11, "near_misses": 4, "below_floor": 6, "profiles_scanned": 912, ... },
    "country_split": { "confirmed": 30, "unconfirmed": 8, "countries": ["GB"] },
    "crawl": null,
    "list": { "id": 20931, "name": "Fitness creators in the UK", "url": "https://app.tokfluence.com/lists/20931" },
    "results_ready": true,
    "free_preview": false,
    "brief_reason": null,
    "brief_message": null,
    "brief_suggestions": [],
    "error": null
  },
  "meta": { "quota": { ... } }
}
ParamTypeNotes
stagestringqueued, expanding_hashtags, crawling, scanning_profiles, judging, building, then done or failed.
estimate_seconds_remainingint | nullOur estimate from past searches. null when the search has run past it; estimate_note then says which step is still running and how long it usually takes.
results_readyboolThe list exists and /results can be read. The list can appear before done and keeps growing while the search runs.
crawlobject | nullSet when the list was delivered while our crawl keeps adding to it: { running, added }.
errorstring | nullWhy a failed search stopped, in words you can show your user.

GET/v1/ultra_searches/:id/results#

One page of the list, best first. Each creator uses the same schema as creators.search (tkc_ id, stats, contact emails), plus an ultra block with the judge's verdict.

Query

ParamTypeNotes
pageintFrom 1. Defaults to 1.
per_pageintDefaults to 50, max 100.
json
{
  "data": [
    {
      "id": "tkc_a1b2c3d4e5f6a7b8",
      "username": "liftwithjo",
      "follower_count": 84000,
      "region": "GB",
      ...,
      "ultra": {
        "rank": 1,
        "tier": "bullseye",
        "fit": 92,
        "reason": "Reviews protein and sports drinks from a Manchester gym, weekly.",
        "evidence": { "quote": "Honest protein reviews from my gym in Manchester",
                      "url": null },
        "audience_type": "consumers",
        "near_miss": false,
        "country_confirmed": true,
        "country_confidence": "confirmed",
        "country_signal": "profile_region",
        "platform": "tiktok"
      }
    }
  ],
  "meta": { "page": 1, "per_page": 50, "total": 38, "final": true, "list_id": 20931,
            "age_filter": { "excluded_likely_minors": 0 } }
}
ParamTypeNotes
ultra.tierstring | nullbullseye (exactly the brief), adjacent (close, worth a look), craft (makes this kind of content for others). null for a creator you added to the list yourself.
ultra.fitint | nullThe judge's fit from 0 to 100, against your brief. null when the judge did not score that creator.
ultra.reasonstring | nullOne sentence on why the creator is on the list.
ultra.evidenceobject | nullThe creator's own words that back the judge's read: quote, copied exactly from their bio or one of their recent captions (200 characters at most), and url, the post it came from, or null when it is their bio. null when the judge found no quote we could check against what they wrote.
ultra.audience_typestring | nullWho mostly watches them: consumers, professionals, b2b_buyers, students, parents, local_community or other. null when the judge did not read that creator.
ultra.near_missboolListed below everyone else: nearly a fit, worth a human look.
ultra.country_confirmedbool | nullWhen the brief names countries: true when we saw a sign the creator is there, false when we saw none either way. null when the brief names no country.
ultra.country_confidencestring | nullWhen the brief names countries: confirmed (their profile country is one of them), likely (a sign short of that) or unknown. null when the brief names no country.
ultra.country_signalstring | nullThe sign behind country_confidence: profile_region, language (they write in its language), bio_text (their own words place them there), phone_country_code (the calling code of a contact phone; the number itself is never returned), audience_regions (only their audience is mostly there, which is not where they live) or none.
ultra.platformstringAlways tiktok today.
profile_unavailableboolPresent and true when we could not read the creator's profile just now. The creator is still on the list; try again later for the stats.
meta.finalboolfalse while the list can still grow.
meta.lockedintFree accounts only: how many more creators a paid plan shows. A free Ultra Search shows its 10 best.

Creators whose own bio states an age under 18 are always left out, as on every search, and counted in meta.age_filter.

Reading results counts like browsing
Results pages count towards the same limits as browsing search results in the app. An account we have paused for unusual activity gets 423 account_held until we have reviewed it.

Errors

ParamTypeNotes
422missing_parameterNo brief.
422brief_needs_nicheThe brief names no topic we can search. error.details.suggestions lists topics to add. Nothing was spent.
422brief_is_lookupThe brief asks for one account or link. Describe the kind of creators instead. Nothing was spent.
422invalid_filtersA country, language or follower bound we cannot read. The message names it.
422invalid_briefThe brief is too long, or asks for a niche we don't search.
402no_searches_leftThis period's Ultra Searches are used. The message says when more arrive; error.details.quota has the numbers.
403ultra_not_includedYour plan has no Ultra Searches.
409already_runningAs many as your account may run at once are running (one, unless set up for more). error.details.running_search_id is the newest one's id.
429free_daily_capFree accounts' Ultra Searches for today are used up. Try again tomorrow.
404ultra_search_not_foundNo Ultra Search with that id on your account.
409results_not_readyThe list does not exist yet. error.details.stage says where the search is.
409ultra_search_failedThe search stopped before it built a list. The message says why.
423account_heldYour account is paused while we review unusual activity.

From an AI agent

The MCP server has the same thing as two tools. start_ultra_search asks first: its first call starts nothing and returns how many Ultra Searches you have left, so your assistant can check with you before using one. get_ultra_search reads the status and, once the list exists, a page of it. Over OAuth, starting a search needs the crawl permission.