# Look up many creators

> For the complete documentation index, see [llms.txt](https://www.shortsintel.com/llms.txt). Every docs page is also available as markdown: add .md to its URL. To connect, read [agents.md](https://www.shortsintel.com/agents.md).

POST `/v1/creators/lookup/batch`

Up to 50 creators as `{ platform, handle }` pairs, any mix of platforms, in one Run. Each distinct pair is looked up as `GET /v1/creators/{platform}/{handle}` would, without videos.

- Validation: one unknown platform or empty handle refuses the whole call with 400 `invalid_request` naming it (`creators[2]`), uncharged.
- Results: `result.items` lists each pair with its `creator` or its `error`, also at `GET /v1/runs/{id}/items`.
- Partial Runs: `completed`, `partial` or `failed` as on the batch video lookup. A failed pair is not charged.
- Long batches: over 10 distinct pairs answer 202 at once unless `wait` is passed.

## Price

6 credits per creator, charged only for the distinct pairs that succeed.

Supports `"estimate": true` in the body: the reply is the price in Credits and whether it would be `cached`, with no Run created and nothing charged.

A cached result costs the same as a fresh one; `cached` says which you got.

## Parameters

| Name | In | Type | Required | Default | Description |
| --- | --- | --- | --- | --- | --- |
| `Idempotency-Key` | header | `string` | Optional | — | 1-255 printable ASCII characters. The same key and payload returns the original Run (202 while running); a different payload or operation is a 409 `idempotency_conflict`. |

## Request body

`application/json`

object

- `creators` array of object required items 1 to 50 1 to 50 creators, any mix of platforms. The same platform and handle (any case, with or without `@`) is looked up once.
  - `platform` string required one of `tiktok`, `instagram`, `youtube`, `facebook` The creator's platform.
  - `handle` string required length at least 1 A handle, `@handle` or profile URL.
- `wait` number value 0 to 120 Default `30` Seconds to hold the response open before returning a running Run to poll. Default 30, max 120.
- `max_credits` integer value at least 0 As in the query.
- `estimate` boolean If a source the call would read is unavailable and the cache cannot answer, the estimate adds `unavailable` (the `{ platform, capability }` parts it cannot reach), or is a 503 `source_unavailable` when it can reach none.

## Responses

### 200 OK

The Run finished inside the wait budget: `{ run, result }`. The example found one of two creators: `partial`, charged for one. With `estimate=true`, `{ estimate_credits, cached, items, credits_per_item }`.

any of 2 shapes

- Option 1 object The envelope every charged operation answers with: `{ run }` while the Run is running (plus `poll_url` on the 202), joined by `result` once it completes or `error` once it fails.
  - `run` object required Every charged operation creates a Run; the envelope is the same inline or polled.
    - `id` string required
    - `kind` string required What was run, e.g. `video_lookup`.
    - `status` string required one of `running`, `completed`, `partial`, `failed` `partial` keeps the completed items and charges for them, up to what the Balance covers; `failed` charges nothing.
    - `created_at` string required RFC 3339.
    - `completed_at` string required nullable Null while the Run is still running.
    - `charge_credits` integer required What this Run actually cost, in Credits. A stored answer costs the same as a fresh one.
    - `list_price_credits` integer required The full price of the work asked for, in Credits. Equal to `charge_credits` unless the Run charged for only part of it.
    - `cached` boolean required True when a stored result answered without a fresh fetch.
    - `progress` object A running Research's `stage` and counts so far, such as `analysed` of `shortlisted`; a count is absent until known. Absent once the Run settles and on other kinds.
      - `stage` string required one of `keywords`, `searching`, `reading_creators`, `filtering`, `analysing`, `writing_digest`
      - `keywords` integer value at least 0
      - `creators` integer value at least 0
      - `creators_read` integer value at least 0
      - `searches` integer value at least 0
      - `found` integer value at least 0
      - `judged` integer value at least 0
      - `kept` integer value at least 0
      - `dropped_off_topic` integer value at least 0
      - `dropped_unsure` integer value at least 0
      - `shortlisted` integer value at least 0
      - `analysed` integer value at least 0
      - `updated_at` string required
  - `result` object required
    - `requested` integer required Distinct inputs looked up.
    - `completed` integer required Inputs answered, and charged.
    - `failed` integer required Inputs that failed, uncharged.
    - `items` array of object required
      - `input` any The input this item answers, as you sent it.
      - `status` string required one of `completed`, `failed`
      - `creator` object On a completed item: the same object the single lookup returns.
        - `platform` string required
        - `id` string required
        - `handle` string required nullable
        - `name` string required
        - `avatar_url` string required nullable
        - `follower_count` number required nullable Deprecated: use `stats.followers`. Null when unreported.
        - `bio` string required nullable
        - `verified` boolean The verified badge, where the platform reports it (TikTok, Instagram, YouTube).
        - `video_count` number nullable Deprecated: use `stats.videos`. Videos the platform says the creator has (TikTok, YouTube).
        - `total_likes` number nullable Deprecated: use `stats.likes`. Likes the creator's videos have received, lifetime (TikTok). TikTok reports no lifetime views.
        - `following_count` number required nullable Deprecated: use `stats.following`. Accounts the creator follows (TikTok, Instagram). Null when unreported.
        - `links` array of object required nullable Bio or channel links, in the platform's order (TikTok and Instagram bio links, YouTube channel links, a Facebook Page's website). Null when none.
          - `title` string required nullable The link's label, null where the platform gives none.
          - `url` string required
        - `joined_at` string required nullable When the account was created, RFC 3339 (TikTok; YouTube and Facebook give a date, so the time is midnight UTC). Null when unreported.
        - `country` string required nullable The account's country or region as the platform reports it: a code on TikTok (`US`), a name on YouTube (`United States`). Null when unreported.
        - `business` object required nullable Whether the account is a business or organisation, and its category. Null when unreported.
          - `is_business` boolean required nullable A business or organisation account (TikTok, Instagram, Facebook); null when the platform did not say, or on an Instagram professional account whose logged-out flag is unreliable (use `category`).
          - `category` string required nullable The account's category, e.g. `Artist`.
        - `total_views` number required nullable Deprecated: use `stats.views`. Lifetime views across the channel (YouTube). Null when unreported.
        - `contact` object required nullable Contact details the account publishes itself, never inferred or enriched from elsewhere. Null when it publishes none; at least one detail is set otherwise. You are responsible for using them lawfully: follow the anti-spam and data-protection rules that apply to you (e.g. CAN-SPAM, GDPR, PECR) before contacting anyone. Stored only with the creator and deleted with it, under our data retention terms.
          - `email` string required nullable
          - `phone` string required nullable
          - `address` string required nullable The address as one line of text.
          - `website` string required nullable
          - `source` string required one of `profile`, `bio` `profile`: the contact details a Facebook Page shows publicly. `bio`: the first email address written in the creator's bio (every platform); phone numbers are never read from a bio.
        - `snapshot` object required nullable
          - `at` string required
          - `followers` number required nullable
        - `stats` object required The creator's counts, the same names on every platform. Each is null when the platform did not report it.
          - `followers` number required nullable Followers or subscribers.
          - `following` number required nullable Accounts the creator follows (TikTok, Instagram).
          - `videos` number required nullable Videos the platform says the creator has (TikTok, YouTube).
          - `likes` number required nullable Likes the creator's videos have received, lifetime (TikTok). A Facebook Page's own likes stay on `like_count`.
          - `views` number required nullable Lifetime views across the channel (YouTube).
        - `baseline` object required nullable The yardstick every Score on this creator is measured against.
          - `median_views` number required
          - `p90_views` number required
          - `engagement_rate` number required nullable
          - `posts_per_week` number required nullable
          - `sample` integer required
          - `confidence` string required one of `high`, `low`
          - `source` string required one of `videos`, `follower_tier`
          - `computed_at` string required nullable
          - `stale` boolean required True past 7 days; the next lookup refreshes it.
        - `videos` array of object With `include=videos`.
          - `platform` string required
          - `id` string required
          - `url` string required nullable
          - `description` string required nullable Null when the read fetched no caption.
          - `posted_at` string required nullable
          - `duration_seconds` number required nullable
          - `thumbnail_url` string required nullable
          - `hashtags` array of string required
          - `sound` object required nullable
            - `id` string required
            - `title` string required nullable
            - `author` string required nullable Who made the sound, as the platform names them. Null when the platform did not say (Facebook never does).
            - `is_original` boolean required nullable True for the creator's own audio, false for a catalogue track. Null when not reported.
          - `creator` object required nullable
            - `id` string required
            - `handle` string required nullable
            - `name` string required
            - `follower_count` number required nullable
            - `avatar_url` string required nullable Our archived copy, else the platform's URL, which may expire: download it rather than store the link.
            - `verified` boolean required nullable The verified badge, from the latest profile read, else this video's. Null when unreported.
          - `region` string required nullable Where the video was posted, as the platform reports it (a country code on TikTok). Null when not reported.
          - `language` string required nullable Platform-declared caption language, e.g. `en` (TikTok). Null when not reported.
          - `title` string required nullable The video's own title (YouTube, Facebook). Null when none or not reported.
          - `commerce` object required nullable What the Platform declares, never inferred from the content. A flag is null when not reported, never false; the object is null when nothing was.
            - `is_ad` boolean required nullable The Platform marks the video as an ad (TikTok, Instagram).
            - `paid_partnership` boolean required nullable The Platform marks a paid partnership (TikTok, Instagram; on YouTube, its "Includes paid promotion" label).
            - `affiliate` boolean required nullable The Platform marks affiliate content (Instagram).
            - `shop_url` string required nullable The product link the video carries (TikTok Shop).
            - `anchors` array of object required The links the video carries under its caption (an editing template, a product, a place). Empty when none were reported.
              - `kind` string required The Platform's own anchor type id, e.g. `54`.
              - `label` string required What the anchor shows, e.g. `CapCut · Editing made easy`.
          - `people` object required nullable Accounts the Video mentions or names (on Instagram, tagged users first). Null when none.
            - `mentions` array of string required Handles the caption mentions (lowercased).
            - `collaborators` array of object required Co-authors the Platform names on the Video (an Instagram collab, a Facebook collaborator).
              - `handle` string required nullable
              - `name` string required nullable
          - `location` object required nullable The place the Video names (Instagram). Null when it named none or the read did not say.
            - `id` string required nullable The Platform's own place id. Null when not sent.
            - `name` string required The place, e.g. `Central Park, New York`.
          - `topics` object required nullable Platform-declared topics. Null when the Platform reported none.
            - `keywords` array of string required The creator's own tags (YouTube).
            - `genre` string required nullable The Platform's category, e.g. `Education` (YouTube).
            - `labels` array of string required The Platform's own category labels (TikTok).
          - `chapters` array of object required nullable The description's chapters, in order (YouTube). Null when the video has none or they were not reported.
            - `title` string required
            - `start_seconds` number required Where the chapter starts, in seconds from the start.
          - `ai_generated` boolean required nullable The Platform labels the video AI-generated (TikTok). Null when not reported.
          - `is_pinned` boolean required nullable Pinned to the top of the creator's feed (Instagram). Null when not reported.
          - `is_sponsored` boolean required nullable Ad flag, #ad or #…partner tag, or a brand collaborator. Null: unchecked.
          - `sponsor` string required nullable The sponsoring brand's handle when is_sponsored.
          - `snapshot` object required nullable Deprecated: use `engagement`.
            - `at` string required
            - `views` number required nullable
            - `likes` number required nullable
            - `comments` number required nullable
            - `shares` number required nullable
            - `saves` number required nullable
          - `engagement` object required nullable A count the platform did not report is null, never 0.
            - `views` number required nullable
            - `likes` number required nullable
            - `comments` number required nullable
            - `shares` number required nullable
            - `saves` number required nullable
            - `at` string required
          - `scores` object required nullable Null when the creator has no baseline yet.
            - `outlier` number required nullable Views over the creator's median views.
            - `outlier_p90` number required nullable
            - `percentile` number required nullable Where this video sits in the creator's own sample, 0-100.
            - `velocity` object required nullable
              - `views_per_hour` number required
              - `window` string required
              - `since` string required nullable When the window starts.
            - `engagement_rate` number required nullable This video's reported interactions (likes, comments, shares, saves) over its views. Null when unknown.
            - `anomaly` boolean required nullable True when `engagement_rate` is under 20% of the baseline's, as paid or boosted views read. Null when unknown.
            - `reason` string required nullable always `aged_out` `aged_out` when the video is over 30 days old and the view Scores are null.
            - `baseline` object required The yardstick every Score on this creator is measured against.
              - `median_views` number required
              - `p90_views` number required
              - `engagement_rate` number required nullable
              - `posts_per_week` number required nullable
              - `sample` integer required
              - `confidence` string required one of `high`, `low`
              - `source` string required one of `videos`, `follower_tier`
              - `computed_at` string required nullable
              - `stale` boolean required True past 7 days; the next lookup refreshes it.
          - `coverage` string always `partial` Present only where the platform's index is best-effort.
        - `next_cursor` string nullable With `include=videos` on a platform that pages the feed (every one but TikTok): pass it back as `cursor`, with the same creator, for the next page; null on the last page.
        - `like_count` number nullable Page likes (Facebook).
        - `category` string nullable The Page's category, e.g. `Artist` (Facebook).
        - `advertiser` object Facebook: the Meta Advertiser with this Page's id, when we already hold it (`GET /advertisers/{page_id}`). Absent otherwise.
          - `page_id` string required
          - `name` string required nullable
          - `page_url` string required
      - `error` object On a failed item: why, e.g. `not_found` or `source_unavailable`. Not charged. Its fields are on [Errors](https://www.shortsintel.com/docs/reference/errors).
- Option 2 object Returned instead of a Run when `estimate=true`. Nothing is charged; some operations add members.
  - `estimate_credits` integer required What the call would be charged, in Credits.
  - `cached` boolean required Whether a stored result can already answer. It does not change the price.

### 202 Accepted

Still running: `{ run }`. Poll `GET /v1/runs/{id}`.

object

Still running. Poll `poll_url` (`GET /v1/runs/{id}`), waiting the 202's `Retry-After` seconds between polls.

- `run` object required Every charged operation creates a Run; the envelope is the same inline or polled. Its fields are on [Poll or re-read a run](https://www.shortsintel.com/docs/reference/runs/get-run#response-200).
- `poll_url` string required format `uri` Absolute URL of `GET /v1/runs/{id}`, the body's copy of the `Location` header (for MCP). Present only while `running`.

202 · Example

```json
{
  "run": {
    "id": "run_8f2c1ad04b",
    "kind": "creator_lookup_batch",
    "status": "running",
    "created_at": "2026-09-08T09:14:02.418Z",
    "completed_at": null,
    "charge_credits": 0,
    "list_price_credits": 0,
    "cached": false
  },
  "poll_url": "https://www.shortsintel.com/v1/runs/run_8f2c1ad04b"
}
```

### 400 Bad Request

`invalid_request` (a malformed id, `wait`, `estimate` or Idempotency-Key) or `unsupported_platform`, refused before any Run opens. Nothing is charged.

Codes: `invalid_request`, `unsupported_platform`. The problem body and every code are on [Errors](https://www.shortsintel.com/docs/reference/errors).

### 401 Unauthorized

Codes: `missing_authorization`, `invalid_key`, `key_revoked`, `key_expired`, `invalid_token`. The problem body and every code are on [Errors](https://www.shortsintel.com/docs/reference/errors).

### 402 Payment Required

`insufficient_balance`: the Balance cannot cover the quoted price (the worst case for Research and enriched search). No Run opens and nothing is charged; a multi-item Run that runs short later charges its completed items up to the Balance and ends `partial`.

Code: `insufficient_balance`. The problem body and every code are on [Errors](https://www.shortsintel.com/docs/reference/errors).

### 409 Conflict

`idempotency_conflict` — the same Idempotency-Key with a different payload.

Code: `idempotency_conflict`. The problem body and every code are on [Errors](https://www.shortsintel.com/docs/reference/errors).

### 429 Too Many Requests

`rate_limit_exceeded` or `concurrency_limit_exceeded`, with `Retry-After`.

Codes: `rate_limit_exceeded`, `concurrency_limit_exceeded`. The problem body and every code are on [Errors](https://www.shortsintel.com/docs/reference/errors).

### 502 Bad Gateway

A Run that opened and then failed answers `application/problem+json` with its problem's status (`vendor_error` here, `not_found` as 404) and the Run envelope, keeping the Run id. Never charged. The example is a Video lookup's.

Code: `vendor_error`. The problem body and every code are on [Errors](https://www.shortsintel.com/docs/reference/errors).

### 503 Service Unavailable

`source_unavailable`: every source this Run reads failed or is switched off. The Run fails uncharged, envelope alongside; `endpoints` names the source. Retry after `retry_after_seconds` (also `Retry-After`); it does not mean empty. The example is a Video lookup's.

Code: `source_unavailable`. The problem body and every code are on [Errors](https://www.shortsintel.com/docs/reference/errors).

## Related guides

This call creates a Run. With `wait` it holds the response open until the Run finishes or the wait runs out, then answers with the finished result or `202` and the running Run. Poll [`GET /v1/runs/{id}`](https://www.shortsintel.com/docs/reference/runs/get-run) until it settles; re-reading a Run is free.

- [Runs](https://www.shortsintel.com/docs/concepts/runs): How a call becomes a Run, waiting inline, polling and free re-reads.
- [Pricing and estimates](https://www.shortsintel.com/docs/concepts/pricing-and-estimates): Credits, estimates and why a cached result costs the same as a fresh one.

## Request samples

curl:

```bash
curl -X POST "https://www.shortsintel.com/v1/creators/lookup/batch" \
  -H "Authorization: Bearer sk_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"creators":[{"platform":"tiktok","handle":"@someone"},{"platform":"instagram","handle":"natgeo"}]}'
```

TypeScript:

```typescript
const response = await fetch(
  "https://www.shortsintel.com/v1/creators/lookup/batch",
  {
    method: "POST",
    headers: {
      "Authorization": "Bearer sk_live_YOUR_KEY",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      "creators": [
        {
          "platform": "tiktok",
          "handle": "@someone"
        },
        {
          "platform": "instagram",
          "handle": "natgeo"
        }
      ]
    }),
  },
);

if (!response.ok) {
  throw new Error(`ShortsIntel ${response.status}`);
}

const data = await response.json();
```

Python:

```python
import requests

response = requests.post(
    "https://www.shortsintel.com/v1/creators/lookup/batch",
    headers={
        "Authorization": "Bearer sk_live_YOUR_KEY",
        "Content-Type": "application/json",
    },
    json={
        "creators": [
            {
                "platform": "tiktok",
                "handle": "@someone",
            },
            {
                "platform": "instagram",
                "handle": "natgeo",
            },
        ],
    },
)
response.raise_for_status()

data = response.json()
```

200 · The Run finished inside the wait budget: `{ run, result }`. The example found one of two creators: `partial`, charged for one. With `estimate=true`, `{ estimate_credits, cached, items, credits_per_item }`.

```json
{
  "run": {
    "id": "run_8f2c1ad04b",
    "kind": "creator_lookup_batch",
    "status": "partial",
    "created_at": "2026-09-08T09:14:02.418Z",
    "completed_at": "2026-09-08T09:14:04.930Z",
    "charge_credits": 6,
    "list_price_credits": 12,
    "cached": false
  },
  "result": {
    "requested": 2,
    "completed": 1,
    "failed": 1,
    "items": [
      {
        "input": {
          "platform": "tiktok",
          "handle": "@someone"
        },
        "status": "completed",
        "creator": {
          "platform": "tiktok",
          "id": "cre_9d4b2a7f1c",
          "handle": "someone",
          "name": "Someone",
          "avatar_url": "https://p16-sign.tiktokcdn.com/obj/tos-avatar-someone.jpeg",
          "follower_count": 184300,
          "bio": "Cold water, early mornings, and the numbers behind both. hello@someone.example",
          "verified": false,
          "video_count": 214,
          "total_likes": 4210000,
          "following_count": 312,
          "links": [
            {
              "title": null,
              "url": "https://linktr.ee/someone"
            }
          ],
          "joined_at": "2020-01-14T09:12:40.000Z",
          "country": "US",
          "business": {
            "is_business": false,
            "category": null
          },
          "total_views": null,
          "contact": {
            "email": "hello@someone.example",
            "phone": null,
            "address": null,
            "website": null,
            "source": "bio"
          },
          "snapshot": {
            "at": "2026-09-08T09:14:04.219Z",
            "followers": 184300
          },
          "stats": {
            "followers": 184300,
            "following": 312,
            "videos": 214,
            "likes": 4210000,
            "views": null
          },
          "baseline": {
            "median_views": 305000,
            "p90_views": 802000,
            "engagement_rate": 0.1342,
            "posts_per_week": 4.1,
            "sample": 20,
            "confidence": "high",
            "source": "videos",
            "computed_at": "2026-09-08T09:14:03.902Z",
            "stale": false
          }
        }
      },
      {
        "input": {
          "platform": "instagram",
          "handle": "someone.private"
        },
        "status": "failed",
        "error": {
          "type": "https://www.shortsintel.com/docs/reference/errors/not_found",
          "title": "Not found",
          "status": 404,
          "code": "not_found",
          "detail": "This account is private.",
          "retryable": false,
          "action": "Check the id or handle; list your resources to find the right one."
        }
      }
    ]
  }
}
```

200 · With `estimate=true`: the price, no Run, no charge.

```json
{
  "estimate_credits": 12,
  "cached": false,
  "items": 2,
  "credits_per_item": 6
}
```

[Previous Look up a creator and baseline](https://www.shortsintel.com/docs/reference/creators/get-creator)[Next Page a creator's stored videos](https://www.shortsintel.com/docs/reference/creators/list-creator-videos)
