Skip to content

Read many creators in one call (request-body form)

POST
/creators/batch
curl --request POST \
--url https://atlas.aspire.io/api/v1/creators/batch \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{ "ids": [ "instagram:somehandle", "https://www.instagram.com/p/DEF456/" ], "network": "instagram" }'

Identical to GET /creators?ids= in every observable way — same buckets, same cap, same semantics — it exists only because an identifier list can outgrow a URL. Requires creators:read.

The POST twin of the GET ?ids= form — it exists only because an identifier list can outgrow a URL. ids follows the same 1–100 cap and three identifier forms; network, asOrg, and asProfile mean exactly what the query parameters of the same names mean.

Media typeapplication/json
object
ids
required

The identifiers to look up, 1–100 per request. Each is qualified (instagram:somehandle), a post/profile URL, or bare (resolved against network).

Array<string>
>= 1 items <= 100 items
network

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

string
asOrg

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

string
asProfile

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

string
Examples
Examplesomehandle
{
"ids": [
"instagram:somehandle",
"https://www.instagram.com/p/DEF456/"
],
"network": "instagram"
}

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.

string
Allowed value: instagram
externalId
required

The channel’s network-native identifier (Instagram’s numeric user 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. Sourced only from a successful Instagram Creator Marketplace lookup — null for a brand/business account (Creator Marketplace doesn’t cover them) or when Creator Marketplace credentials aren’t configured for the org.

boolean | null
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 audienceDemographics, which is absent unless we hold a live audience-insights grant.

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.

boolean | null
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

This account’s reach metric (distinct accounts that saw its content).

number | null
hasProfilePic
required

Whether the account currently has a profile picture set.

boolean | null
isPublished
required

Whether the account is published.

boolean | null
creatorEngagedAccounts
required

Number of distinct accounts that engaged with this creator’s content.

number | null
reelsInteractionRate
required

Reels interaction rate, as a percentage of reel views (e.g. 7.2 means 7.2%).

number | null
reelsHookRate
required

Reels hook rate — the percentage of viewers who kept watching past the opening seconds (e.g. 42 means 42%).

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 the v1 compatibility promise (D19) — Meta’s own payload, passed through opaquely. Meta returns 5 breakdown dimensions: country, city, gender, age, and the combined age,gender. Results may not be exhaustive.

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

boolean | null
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://example.com/pic.jpg",
"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": 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.