Skip to content

Read one creator by network and handle

GET
/creators/{network}/{handle}
curl --request GET \
--url 'https://atlas.aspire.io/api/v1/creators/instagram/somehandle?include=posts' \
--header 'Authorization: Bearer <token>'

Resolves to exactly one of three outcomes: 200 (we hold the document, wrapped as { data: <creator> } — a creator is expressed as its channels, always at least one, unordered), 202 (discovery just started — a fetching bucket entry; re-read after Retry-After), or 404 (not obtainable — an error envelope; branch on details.reason). Requires creators:read.

network
required
string
Allowed values: instagram tiktok

The network to look up the creator on.

Examples
Examplesomehandle
instagram
handle
required
string

The creator’s handle on that network, without an @.

Examples
Examplesomehandle
somehandle
include
string
Allowed values: posts

Comma-separated additive extras. posts attaches the creator’s recent posts (core fields only).

Example
posts
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.

We hold the data (and it’s fresh enough). The creator document is wrapped as { data: <creator> }data.channels carries this creator’s channels (always at least one, unordered — do not read position as significance; today this is always exactly one channel, multi-channel hydration is not yet implemented), and data.posts is present only when requested via include=posts.

Media typeapplication/json

Returned with HTTP 200: the document we hold, wrapped the same way a batch read’s data bucket wraps each entry.

object
data
required
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
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"
}
]
}
}
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.

We don’t hold this entity yet — THIS request just started (or joined) the work to get it. Wait Retry-After seconds and re-read the same URL: the read is the poll, there is no job resource. A read here is not free of side effects — reading an entity we don’t hold triggers discovery, and reading a stale one triggers a refresh.

Media typeapplication/json

Returned with HTTP 202: the entity isn’t held yet and THIS request just started (or joined) the work to get it. Always exactly one entry (the identifier just submitted) — an array for shape-parity with the batch envelope’s fetching bucket, not because a single read can return more than one. Wait Retry-After seconds, then re-read the same URL — the read is the poll; there is no job resource.

object
fetching
required
Array<object>
>= 1 items <= 1 items

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
Examplegenerated
{
"fetching": [
{
"id": "example",
"retryAfter": "example"
}
]
}
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.

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.