Skip to content

Read many creators in one call

GET
/creators
curl --request GET \
--url 'https://atlas.aspire.io/api/v1/creators?ids=instagram%3Asomehandle%2Chttps%3A%2F%2Fwww.instagram.com%2Fp%2FDEF456%2F&network=instagram' \
--header 'Authorization: Bearer <token>'

The batch form of the single read: every submitted identifier lands in exactly one of three buckets inside a single 200 — data (held, matching a single read’s own data field for the same creator with no ?include=posts — each entry is { channels: Channel[] }, never { channels, posts }, regardless of what a corresponding single read would return with include=posts set), fetching (discovery running — re-submit after Retry-After), or unavailable (not obtainable — check each entry’s reason). A data entry carries no echo of the identifier you submitted (unlike fetching/unavailable) — correlate it by matching any of its channels’ own network/externalId/username instead. Mixed networks are fine; identifiers on unsupported networks bucket as unavailable with not-supported-on-network. Batch entries never carry posts. Requires creators:read.

ids
required
string

Comma-separated identifiers, 1–100 per request (over-cap is a 400, never a silent truncation). Each identifier is one of three forms: qualified (instagram:somehandle), a post/profile URL, or bare (resolved against network). Whitespace around commas is tolerated; empty tokens are dropped.

Examples
Examplesomehandle
instagram:somehandle,https://www.instagram.com/p/DEF456/
network
string
default: instagram

Default network for BARE identifiers in ids (defaults to instagram). Never a filter — a qualified (instagram:handle) or URL identifier carries its own network.

asOrg
string

Names a target Organization to act on, when it differs from your credential’s own organization — for a delegated agency/partner relationship.

asProfile
string

Attribution only — associates this read’s discovery/refresh work with one of your Profiles, resolved within your organization.

Always 200 — per-item outcomes are buckets, never per-item HTTP statuses.

Media typeapplication/json

The three-bucket batch envelope, returned with HTTP 200 always — per-item outcomes are buckets, never per-item HTTP statuses. Every submitted identifier appears in exactly one bucket. The response’s Retry-After header is present iff fetching is non-empty.

object
data
required

Documents we hold — same shape as the single read’s 200 body.

Array<object>
object
channels
required

This creator’s channels. Always at least one. UNORDERED — carries no meaningful index; do not read position as significance. Intended to eventually return every channel a creator owns, not only the ones a search filter matched — today this is always exactly one channel; multi-channel hydration is not yet implemented.

Array<object>
>= 1 items
object
network
required

The social network this channel belongs to (e.g. instagram, tiktok). An open value — more networks may be added over time.

string
externalId
required

The channel’s network-native identifier (Instagram’s numeric user id, TikTok’s open_id), stable for the account’s lifetime.

string | null
username
required

The channel’s current @handle.

string | null
followersCount
required

Total number of followers.

number | null
verified
required

Whether the network has verified this channel’s identity. On tiktok this is the platform’s own verification flag. On instagram it is sourced only from a successful Creator Marketplace lookup — false also covers accounts Creator Marketplace doesn’t attest for (e.g. a brand/business account, which it doesn’t cover, or when Creator Marketplace credentials aren’t configured for the org). On either network, false means ‘not verified as far as this API can attest,’ not a platform statement that the account is unverified.

boolean
country
required

The channel’s country.

string | null
instagram
required

The Instagram-specific field set for this channel (see below) — every field is null if not yet observed, except the booleans hasProfilePic/isPublished/isPaidPartnershipMessagesEnabled (which publish false when not observed — see each field’s own description), audienceDemographics, which is absent unless we hold a live audience-insights grant, and creatorEngagedAccountsBreakdowns, which is absent unless a Creator Marketplace fetch found this creator with at least one breakdown.

object
name
required

The account’s display name (distinct from username).

string | null
biography
required

The account’s bio text.

string | null
website
required

The website URL listed on the account’s profile.

string | null
profilePictureUrl
required

URL of the account’s current profile picture.

string | null
followsCount
required

Number of accounts this creator follows.

number | null
mediaCount
required

Total number of posts on this account.

number | null
gender
required

The creator’s gender, when known. Common values are male, female, and unknown (undisclosed), though other values may appear over time.

string | null
ageBucket
required

The age range the creator belongs to (e.g. 18-24), or unknown when undisclosed. Other ranges may appear over time.

string | null
onboardedStatus
required

Whether the creator has been onboarded to the Creator Marketplace.

boolean | null
portfolioUrl
required

URL of the creator’s Portfolio.

string | null
email
required

Contact email on file for this creator. Not necessarily verified, and no format validation is applied.

string | null
isPaidPartnershipMessagesEnabled
required

Whether the creator has enabled paid partnership messages through the Instagram Creator Marketplace. false also covers accounts Creator Marketplace doesn’t cover (e.g. brand/business pages), where Meta exposes no such setting.

boolean
hasBrandPartnershipExperience
required

Whether the creator has branded content or partnership ads collaboration experience in the past year.

boolean | null
pastBrandPartnershipPartners
required

The brands the creator has collaborated with on branded content or partnership ads in the past year.

Array<string> | null
badges
required

The badges of the creator. Meta does not publish a closed or confirmed set of possible values — treat as opaque strings, not an enum.

Array<string> | null
reach
required

Distinct accounts reached, from Meta’s account-level insights API, over a rolling ~30-day window. null if never observed.

number | null
creatorMarketplaceReach
required

Distinct accounts reached, from Meta’s Creator Marketplace API. Reflects month-to-date (resets at the start of each calendar month) — Meta does not honor a rolling-window request for this metric. null if never observed.

number | null
hasProfilePic
required

Whether the account currently has a profile picture set. false also covers accounts where Meta exposes no value (the field is limited to Page-backed Instagram accounts).

boolean
isPublished
required

Whether the account is published. false also covers accounts where Meta exposes no value (the field is limited to Page-backed Instagram accounts).

boolean
creatorEngagedAccounts
required

Number of distinct accounts that engaged with this creator’s content. Meta’s current default lookback window is the calendar month to date (this_month), not guaranteed by Meta.

number | null
reelsInteractionRate
required

Reels interaction rate, as a percentage of reel views (e.g. 7.2 means 7.2%). Meta’s current default lookback window is a rolling 90 days (last_90_days), not guaranteed by Meta.

number | null
reelsHookRate
required

Reels hook rate — the percentage of viewers who kept watching past the opening seconds (e.g. 42 means 42%). Meta’s current default lookback window is a rolling 90 days (last_90_days), not guaranteed by Meta.

number | null
audienceDemographics

Engaged-audience demographics, present only for accounts we hold a live grant with audience-insights scope for. Its internal shape is NOT part of this API’s v1 compatibility promise and may change without notice — today it is normalized: gender labels are male/female/unknown, country is an ISO 3166-1 alpha-2 code, a city’s state segment is its 2-letter USPS abbreviation, and a result MAY carry count/percentage, both, or neither — absent when Meta supplied no value for that cell. Meta returns 5 breakdown dimensions: country, city, gender, age, and the combined age,gender. Results may not be exhaustive. Separately, for the age, gender, and combined age,gender breakdowns: a cell absent from the results may be genuinely zero or withheld by Meta — its absence alone doesn’t tell you which.

creatorEngagedAccountsBreakdowns

Creator Marketplace’s creator_engaged_accounts metric broken down by gender/age/top_countries/top_cities, present only when a Creator Marketplace fetch found this creator and returned at least one breakdown. Its internal shape is NOT part of the v1 compatibility promise — normalized the same way as audienceDemographics, but a result MAY carry percentage (Meta’s own value, already a share of the metric’s total) — absent when Meta supplied no value for that cell — and never a count, since Meta supplies no raw count for this metric to derive one from.

tiktok
required

The TikTok-specific field set for this channel (see below) — every field is null if not yet observed.

object
displayName
required

The account’s display name (distinct from username).

string | null
bioDescription
required

The account’s bio text.

string | null
profileImage
required

URL of the account’s current profile picture.

string | null
isBusinessAccount
required

Whether this is a TikTok Business Account.

boolean | null
followingCount
required

Number of accounts this creator follows.

number | null
videosCount
required

Total number of videos on this account.

number | null
cumulativeLikes
required

Total likes accumulated across this account’s videos.

number | null
creatorRate
required

The creator’s listed rate for sponsored content, when published — a currency code plus a numeric rate.

object
currency
required
string
rate
required
number
industryLabels
required

Industry categories TikTok has assigned to this creator.

Array<object> | null
object
labelId
required
Any of:
string
labelName
required
string
contentLabels
required

Content categories TikTok has assigned to this creator.

Array<object> | null
object
labelId
required
Any of:
string
labelName
required
string
audienceGenders
required

The audience’s gender breakdown, each a gender and its percentage share.

Array<object> | null
object
gender
required
string
percentage
required
number
audienceAges
required

The audience’s age-range breakdown, each a range and its percentage share.

Array<object> | null
object
age
required
string
percentage
required
number
audienceCountries
required

The audience’s country breakdown, each a country and its percentage share.

Array<object> | null
object
country
required
string
percentage
required
number
audienceDevices
required

The audience’s device breakdown, each a device and its percentage share.

Array<object> | null
object
device
required
string
percentage
required
number
audienceUsages
required

The audience’s app-usage breakdown, each a usage bucket and its percentage share.

Array<object> | null
object
usage
required
string
percentage
required
number
medianViews
required

Median view count across this creator’s recent videos.

number | null
engagementRate
required

This creator’s overall engagement rate.

number | null
creatorPrice
required

TikTok’s own estimated price for a sponsored post by this creator.

number | null
creatorPriceCurrency
required

The currency creatorPrice is denominated in.

string | null
updatedAt
required

ISO 8601 timestamp of when this channel’s current snapshot was produced — how fresh this document is.

string | null
posts

This creator’s recent posts, included only when the request asked for ?include=posts. Absent (not empty) when not requested. Posts are not nested per channel — to attribute a post back to one of channels, match its author.accountId against that channel’s externalId.

Array<object>
object
network
required

The social network this post is on.

string | null
externalId
required

The post’s network-native identifier.

string | null
url
required

The post’s public permalink.

string | null
postedAt
required

ISO 8601 timestamp of when the post was published.

string | null
text
required

The post’s caption text.

string | null
mediaKind
required

The post’s media type — video, image, or carousel.

string | null
media
required

The post’s media items, one entry per media node (multiple entries for a carousel), in order. mediaUrl/thumbnailUrl are null whenever that asset isn’t available yet (not yet archived, or the CDN isn’t configured) — the two are resolved independently, so one can be null while the other isn’t.

Array<object>
object
mediaUrl
required
string | null
thumbnailUrl
required
string | null
likeCount
required

Total like count.

number | null
commentCount
required

Total comment count.

number | null
viewCount
required

Total view count.

number | null
shareCount
required

Total share count.

number | null
saveCount
required

Total save count.

number | null
author
required

The post’s author — a thin, no-PII summary of the creator account. author.accountId is the only way to attribute a post back to one of Creator.channels — match it against that channel’s externalId.

object
accountId
required

The post author’s network-native account identifier.

string
username
required

The post author’s @handle.

string | null
followersCount
required

Total number of followers the post author has.

number | null
verified
required

Whether the post author’s identity is verified on the network. false also covers accounts Creator Marketplace doesn’t attest for — same semantics as the channel-level verified.

boolean
country
required

The post author’s country.

string | null
fetching
required
Array<object>

A submitted identifier we don’t hold yet — this batch read started (or joined) discovery for it. Re-submit it after Retry-After.

object
id
required

The identifier exactly as submitted.

string
retryAfter
required

ISO 8601 instant — every fetching entry in one response shares the same instant, and the response’s Retry-After header (present iff this bucket is non-empty) is its delta-seconds twin.

string
unavailable
required
Array<object>

A submitted identifier that resolved to ‘not obtainable’. Check reason (and retryable) — most values mean stop retrying.

object
id
required

The identifier exactly as submitted.

string
reason
required

Machine-readable, open vocabulary (additions are non-breaking). outside-recent-media-window and author-unresolved occur on posts only. internal-error means the failure was on our side — retryable is true.

string
retryable

Present, and always true, when the failure was on our side rather than a fact about the entity — retry after a few minutes. Absent means terminal: stop retrying.

boolean
Examples
Examplesomehandle
{
"data": [
{
"channels": [
{
"network": "instagram",
"externalId": "17841400000000000",
"username": "somehandle",
"followersCount": 12345,
"verified": false,
"country": "US",
"instagram": {
"name": "Some Handle",
"biography": "Creator bio goes here.",
"website": "https://example.com",
"profilePictureUrl": "https://cdn.aspire.io/media/3f9a1c2e-4b6d-4e8a-9c1f-7d2b5a6e9f10",
"followsCount": 200,
"mediaCount": 350,
"gender": "female",
"ageBucket": "25-34",
"onboardedStatus": true,
"portfolioUrl": "https://example.com/portfolio",
"email": "[email protected]",
"isPaidPartnershipMessagesEnabled": true,
"hasBrandPartnershipExperience": true,
"pastBrandPartnershipPartners": [
"brand-a",
"brand-b"
],
"badges": [
"top-creator"
],
"reach": 8200,
"creatorMarketplaceReach": 8500,
"hasProfilePic": true,
"isPublished": true,
"creatorEngagedAccounts": 1362,
"reelsInteractionRate": 7.2,
"reelsHookRate": 42
},
"updatedAt": "2026-08-01T00:00:00.000Z"
}
]
}
],
"fetching": [
{
"id": "instagram:fetching-handle",
"retryAfter": "2026-08-01T00:30:05.000Z"
}
],
"unavailable": [
{
"id": "instagram:gone-handle",
"reason": "account-not-discoverable"
}
]
}
x-request-id
string

On every response, success or failure. Quote it when contacting support — it’s the fastest way for Aspire to find exactly your request.

Retry-After
string

Present iff fetching is non-empty — delta-seconds until those entries are worth re-submitting (every fetching entry in one response shares the same instant).

A malformed request — e.g. a batch outside the 1–100 identifier cap, an unrecognized include value, url and ids supplied together, or an unparseable JSON body.

Media typeapplication/json

The one JSON shape every error response (any status other than 200/202) carries.

object
error
required

The one JSON shape every error response (any status other than 200/202) carries, wrapped under error in apiErrorResponseSchema.

object
code
required

The stable, machine-readable error code. Maps 1:1 to the HTTP status.

string
message
required

Human prose for logs and error screens. Never parse it.

string
details

Optional structured extras. Today’s one use: a read-miss 404’s reason (and retryable, when our fault) — see details.reason.

object
reason
required

Machine-readable, open vocabulary — same values a batch unavailable entry’s own reason carries.

string
retryable

Present (and true) only when the failure was on our side rather than a fact about the entity — retry after a few minutes. Absent means terminal: stop retrying.

boolean
Example
{
"error": {
"code": "invalid-input",
"message": "ids must contain between 1 and 100 identifiers, got 101"
}
}
x-request-id
string

On every response, success or failure. Quote it when contacting support — it’s the fastest way for Aspire to find exactly your request.

Missing, malformed, expired, or revoked credential.

Media typeapplication/json

The one JSON shape every error response (any status other than 200/202) carries.

object
error
required

The one JSON shape every error response (any status other than 200/202) carries, wrapped under error in apiErrorResponseSchema.

object
code
required

The stable, machine-readable error code. Maps 1:1 to the HTTP status.

string
message
required

Human prose for logs and error screens. Never parse it.

string
details

Optional structured extras. Today’s one use: a read-miss 404’s reason (and retryable, when our fault) — see details.reason.

object
reason
required

Machine-readable, open vocabulary — same values a batch unavailable entry’s own reason carries.

string
retryable

Present (and true) only when the failure was on our side rather than a fact about the entity — retry after a few minutes. Absent means terminal: stop retrying.

boolean
Example
{
"error": {
"code": "unauthorized",
"message": "invalid credential"
}
}
x-request-id
string

On every response, success or failure. Quote it when contacting support — it’s the fastest way for Aspire to find exactly your request.

Valid credential, but it lacks the <resource>:<action> permission this operation requires (stated in the operation description).

Media typeapplication/json

The one JSON shape every error response (any status other than 200/202) carries.

object
error
required

The one JSON shape every error response (any status other than 200/202) carries, wrapped under error in apiErrorResponseSchema.

object
code
required

The stable, machine-readable error code. Maps 1:1 to the HTTP status.

string
message
required

Human prose for logs and error screens. Never parse it.

string
details

Optional structured extras. Today’s one use: a read-miss 404’s reason (and retryable, when our fault) — see details.reason.

object
reason
required

Machine-readable, open vocabulary — same values a batch unavailable entry’s own reason carries.

string
retryable

Present (and true) only when the failure was on our side rather than a fact about the entity — retry after a few minutes. Absent means terminal: stop retrying.

boolean
Example
{
"error": {
"code": "forbidden",
"message": "token lacks creators:read permission"
}
}
x-request-id
string

On every response, success or failure. Quote it when contacting support — it’s the fastest way for Aspire to find exactly your request.

A read-miss (branch on details.reason — retry only if details.retryable is true, never on message prose), an unknown asProfile (deliberately indistinguishable from a nonexistent one, so slugs are not enumerable), or an unsupported network. details.reason is an open vocabulary (additions are non-breaking). Values today: account-not-discoverable (creators — terminal; a personal account and a nonexistent handle are indistinguishable), not-supported-on-network (the network isn’t supported yet — terminal until it ships), outside-recent-media-window (posts — terminal), author-unresolved (posts), unparseable-identifier, and internal-error with details.retryable: true (our fault — retry after a few minutes).

Media typeapplication/json

The one JSON shape every error response (any status other than 200/202) carries.

object
error
required

The one JSON shape every error response (any status other than 200/202) carries, wrapped under error in apiErrorResponseSchema.

object
code
required

The stable, machine-readable error code. Maps 1:1 to the HTTP status.

string
message
required

Human prose for logs and error screens. Never parse it.

string
details

Optional structured extras. Today’s one use: a read-miss 404’s reason (and retryable, when our fault) — see details.reason.

object
reason
required

Machine-readable, open vocabulary — same values a batch unavailable entry’s own reason carries.

string
retryable

Present (and true) only when the failure was on our side rather than a fact about the entity — retry after a few minutes. Absent means terminal: stop retrying.

boolean
Example
{
"error": {
"code": "not-found",
"message": "no creator found for instagram/somehandle",
"details": {
"reason": "account-not-discoverable"
}
}
}
x-request-id
string

On every response, success or failure. Quote it when contacting support — it’s the fastest way for Aspire to find exactly your request.

Over the per-principal request budget (fixed one-minute window; default 60 requests/minute, raisable per Service Account). Rejected requests still count against the window. Honour Retry-After.

Media typeapplication/json

The one JSON shape every error response (any status other than 200/202) carries.

object
error
required

The one JSON shape every error response (any status other than 200/202) carries, wrapped under error in apiErrorResponseSchema.

object
code
required

The stable, machine-readable error code. Maps 1:1 to the HTTP status.

string
message
required

Human prose for logs and error screens. Never parse it.

string
details

Optional structured extras. Today’s one use: a read-miss 404’s reason (and retryable, when our fault) — see details.reason.

object
reason
required

Machine-readable, open vocabulary — same values a batch unavailable entry’s own reason carries.

string
retryable

Present (and true) only when the failure was on our side rather than a fact about the entity — retry after a few minutes. Absent means terminal: stop retrying.

boolean
Example
{
"error": {
"code": "rate-limited",
"message": "rate limit exceeded (60 requests/minute for this principal)"
}
}
x-request-id
string

On every response, success or failure. Quote it when contacting support — it’s the fastest way for Aspire to find exactly your request.

Retry-After
string

Delta-seconds (RFC 9110 §10.2.3), always ≥ 1. The server controls the backoff — polling faster than this burns rate limit and gets the data no sooner.

Our fault. The message is deliberately generic — internal error detail is never exposed. Safe to retry with backoff.

Media typeapplication/json

The one JSON shape every error response (any status other than 200/202) carries.

object
error
required

The one JSON shape every error response (any status other than 200/202) carries, wrapped under error in apiErrorResponseSchema.

object
code
required

The stable, machine-readable error code. Maps 1:1 to the HTTP status.

string
message
required

Human prose for logs and error screens. Never parse it.

string
details

Optional structured extras. Today’s one use: a read-miss 404’s reason (and retryable, when our fault) — see details.reason.

object
reason
required

Machine-readable, open vocabulary — same values a batch unavailable entry’s own reason carries.

string
retryable

Present (and true) only when the failure was on our side rather than a fact about the entity — retry after a few minutes. Absent means terminal: stop retrying.

boolean
Example
{
"error": {
"code": "internal-error",
"message": "the request could not be completed"
}
}
x-request-id
string

On every response, success or failure. Quote it when contacting support — it’s the fastest way for Aspire to find exactly your request.

A dependency needed to verify the credential is unreachable — the credential was neither accepted nor rejected. Retry with backoff.

Media typeapplication/json

The one JSON shape every error response (any status other than 200/202) carries.

object
error
required

The one JSON shape every error response (any status other than 200/202) carries, wrapped under error in apiErrorResponseSchema.

object
code
required

The stable, machine-readable error code. Maps 1:1 to the HTTP status.

string
message
required

Human prose for logs and error screens. Never parse it.

string
details

Optional structured extras. Today’s one use: a read-miss 404’s reason (and retryable, when our fault) — see details.reason.

object
reason
required

Machine-readable, open vocabulary — same values a batch unavailable entry’s own reason carries.

string
retryable

Present (and true) only when the failure was on our side rather than a fact about the entity — retry after a few minutes. Absent means terminal: stop retrying.

boolean
Example
{
"error": {
"code": "unavailable",
"message": "temporarily unavailable"
}
}
x-request-id
string

On every response, success or failure. Quote it when contacting support — it’s the fastest way for Aspire to find exactly your request.