API reference
Every route of API v1 under https://www.adspy.sh/api/v1, generated from the OpenAPI 3.1 description the API itself is checked against.
Updated · API v1
The description
Download openapi.json (OpenAPI 3.1, JSON Schema 2020-12) for code generators and API clients. Errors on every route follow the problem format; lists page with cursors.
- GET/api/v1/brands
- GET/api/v1/brands/{brand_key}
- GET/api/v1/brands/{brand_key}/creatives
- GET/api/v1/brands/{brand_key}/xray
- GET/api/v1/brands/{brand_key}/social
- GET/api/v1/brands/{brand_key}/posts-run-as-ads
- POST/api/v1/brands/{brand_key}/full-analysis
- GET/api/v1/creatives
- GET/api/v1/creatives/by-meaning
- GET/api/v1/creatives/{id}
- GET/api/v1/creatives/{id}/analysis
- GET/api/v1/creatives/{id}/similar
- GET/api/v1/advertisers
- POST/api/v1/fetches
- GET/api/v1/fetches/{id}
- GET/api/v1/social/accounts
- POST/api/v1/social/fetches
- GET/api/v1/social/posts
- GET/api/v1/social/posts/{id}
- POST/api/v1/compare/brands
- POST/api/v1/compare/social
- GET/api/v1/collections
- POST/api/v1/collections
- GET/api/v1/collections/{id}
- POST/api/v1/collections/{id}/creatives
- PATCH/api/v1/collections/{id}/creatives/{creative_id}
- POST/api/v1/exports
- GET/api/v1/exports
- GET/api/v1/exports/{id}
- GET/api/v1/usage
Brands
Search brands
GET/api/v1/brands
Brands in Adspy's library, by name. Each brand carries its key (brand_key), which every brand route takes. social_only_brands lists brands Adspy knows only from a TikTok or YouTube account matching the query (first page only). Needs the read permission.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
query | query | string | Part of the brand's name. Without it, brands are listed by name. |
limit | query | integer | Items per page, 1 to 100 (default 20). 1 to 100, default 20 |
cursor | query | string | The next_cursor of the previous page. Send it with the same filters; it is valid for 24 hours. |
Response 200
| Field | Type | Description |
|---|---|---|
data | object[] | |
data[].brand_key | string | |
data[].name | string | |
data[].logo_url | string or null | A signed media link (21 days). |
data[].website | string or null | |
data[].ad_platforms | string[] | The ad libraries the brand runs ads in: meta, google. |
data[].industry | string or null | |
data[].creative_count | integer or null | |
data[].social | object or null | The brand's collected TikTok and YouTube accounts, or null. |
has_more | boolean | |
next_cursor | string or null | Send it as cursor, with the same filters, for the next page. |
total | integer or null | |
social_only_brands | object[] | |
social_only_brands[].brand_key | string | |
social_only_brands[].name | string or null | |
social_only_brands[].social | object | |
social_only_brands[].accounts | object[] | |
billing | object | What the request charged. Partner keys get it on every answer, free ones too. Optional. |
billing.credits_charged | integer | Credits this request charged: always 0 on Enterprise, which has no credit count. On a partner key, the credits the partner bills: each new item read, and reports and new collections at their price. -9007199254740991 to 9007199254740991 |
billing.usd_micros | integer | Partner keys only: what the partner bills, in micro-dollars. -9007199254740991 to 9007199254740991 Optional. |
billing.operation_id | string or null | Partner keys only: the settled operation, for reconciliation; null when nothing was settled. Optional. |
billing.replayed | boolean | Partner keys only: true when the answer replays an earlier request, billed then. Optional. |
billing.price_version | string | Partner keys only: the version of the partner prices applied. Optional. |
Errors
400 invalid_request, 400 invalid_cursor, 401 unauthorized, 403 enterprise_required, 403 insufficient_scope, 403 forbidden, 429 rate_limited, 500 internal_error, 503 service_unavailable
Get a brand
GET/api/v1/brands/{brand_key}
One brand: its name, website, ad platforms, industry, creative count and collected social accounts. Needs the read permission.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
brand_key | path | string | The brand's key, from GET /v1/brands. Required. |
Response 200
| Field | Type | Description |
|---|---|---|
brand_key | string | |
name | string | |
logo_url | string or null | A signed media link (21 days). |
website | string or null | |
ad_platforms | string[] | The ad libraries the brand runs ads in: meta, google. |
industry | string or null | |
creative_count | integer or null | |
social | object or null | The brand's collected TikTok and YouTube accounts, or null. |
social.platforms | "tiktok" | "youtube"[] | |
social.posts | integer or null | Posts Adspy holds for these accounts; null when unknown or when it would include Instagram. |
billing | object | What the request charged. Partner keys get it on every answer, free ones too. Optional. |
billing.credits_charged | integer | Credits this request charged: always 0 on Enterprise, which has no credit count. On a partner key, the credits the partner bills: each new item read, and reports and new collections at their price. -9007199254740991 to 9007199254740991 |
billing.usd_micros | integer | Partner keys only: what the partner bills, in micro-dollars. -9007199254740991 to 9007199254740991 Optional. |
billing.operation_id | string or null | Partner keys only: the settled operation, for reconciliation; null when nothing was settled. Optional. |
billing.replayed | boolean | Partner keys only: true when the answer replays an earlier request, billed then. Optional. |
billing.price_version | string | Partner keys only: the version of the partner prices applied. Optional. |
Errors
400 invalid_request, 401 unauthorized, 402 partner_key_cap_reached, 402 partner_tenant_cap_reached, 403 enterprise_required, 403 insufficient_scope, 403 forbidden, 404 not_found, 429 rate_limited, 429 partner_fair_use, 500 internal_error, 503 service_unavailable
List a brand's creatives
GET/api/v1/brands/{brand_key}/creatives
The brand's creatives with the creative search filters. Pages can be shorter than limit: follow has_more. Needs the read permission.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
brand_key | path | string | The brand's key, from GET /v1/brands. Required. |
query | query | string | Words to find, in the scope chosen. |
scope | query | "all" | "ad_copy" | "content_transcript" | "visual_analysis" | "all_keywords" | "hooks" | Where query is matched (default all). default "all" |
platform | query | "all" | "meta" | "google" | The ad library: meta (Facebook, Instagram and Messenger placements) or google (Search, YouTube, Display). |
format | query | "all" | "image" | "video" | "carousel" | |
status | query | "all" | "active" | "inactive" | Whether the library last saw the ad running. |
sort | query | "newest" | "oldest" | "longest" | newest or oldest first sighting, or longest running (default newest). default "newest" |
tags | query | string | AI tags the creative must all carry, comma-separated, e.g. hook_type:Question. |
language | query | string | |
min_days_active | query | integer | Only creatives seen running for at least this many days. 0 to 36500 |
limit | query | integer | Items per page, 1 to 100 (default 20). 1 to 100, default 20 |
cursor | query | string | The next_cursor of the previous page. Send it with the same filters; it is valid for 24 hours. |
Response 200
| Field | Type | Description |
|---|---|---|
data | object[] | |
data[].id | string | The creative's id (its media hash). |
data[].brand_key | string or null | |
data[].brand_name | string or null | |
data[].brand_logo_url | string or null | |
data[].platform | string or null | meta or google. |
data[].format | string or null | image, video or carousel. |
data[].media_url | string or null | The creative's media: a signed link, valid 21 days. |
data[].poster_url | string or null | |
data[].media_urls | string[] | |
data[].external_watch_url | string or null | A YouTube link for Google video ads, when the file is not stored. |
data[].title | string or null | |
data[].body | string or null | |
data[].first_seen | string or null | |
data[].last_seen | string or null | |
data[].status | string or null | active, inactive or unknown. |
data[].days_active | integer or null | |
data[].ads_count | integer or null | Source ads that run this creative. |
data[].tags | string[] | |
data[].language | string or null | |
data[].media_availability | string or null | |
data[].media_unavailable_reason | string or null | |
data[].transcript | string or null | |
has_more | boolean | |
next_cursor | string or null | Send it as cursor, with the same filters, for the next page. |
total | integer or null | |
billing | object | What the request charged. Partner keys get it on every answer, free ones too. Optional. |
billing.credits_charged | integer | Credits this request charged: always 0 on Enterprise, which has no credit count. On a partner key, the credits the partner bills: each new item read, and reports and new collections at their price. -9007199254740991 to 9007199254740991 |
billing.usd_micros | integer | Partner keys only: what the partner bills, in micro-dollars. -9007199254740991 to 9007199254740991 Optional. |
billing.operation_id | string or null | Partner keys only: the settled operation, for reconciliation; null when nothing was settled. Optional. |
billing.replayed | boolean | Partner keys only: true when the answer replays an earlier request, billed then. Optional. |
billing.price_version | string | Partner keys only: the version of the partner prices applied. Optional. |
Errors
400 invalid_request, 400 invalid_cursor, 401 unauthorized, 402 partner_key_cap_reached, 402 partner_tenant_cap_reached, 403 enterprise_required, 403 insufficient_scope, 403 forbidden, 404 not_found, 429 rate_limited, 429 partner_fair_use, 500 internal_error, 503 service_unavailable, 504 timeout
Reports
Get a brand's X-Ray
GET/api/v1/brands/{brand_key}/xray
The brand's X-Ray: the observed creative strategy (formats, hooks, funnel, longevity, audience estimates, destinations, changes) over a range, from public creatives. Evidence, not ad performance. A report is reused for 24 hours. Needs the actions permission.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
brand_key | path | string | The brand's key, from GET /v1/brands. Required. |
range | query | "30d" | "90d" | "180d" | "all" | The window of first sightings the report covers (default 90d). default "90d" |
Response 200
| Field | Type | Description |
|---|---|---|
instagram_excluded | boolean | Optional. |
billing | object | What the request charged. Partner keys get it on every answer, free ones too. Optional. |
billing.credits_charged | integer | Credits this request charged: always 0 on Enterprise, which has no credit count. On a partner key, the credits the partner bills: each new item read, and reports and new collections at their price. -9007199254740991 to 9007199254740991 |
billing.usd_micros | integer | Partner keys only: what the partner bills, in micro-dollars. -9007199254740991 to 9007199254740991 Optional. |
billing.operation_id | string or null | Partner keys only: the settled operation, for reconciliation; null when nothing was settled. Optional. |
billing.replayed | boolean | Partner keys only: true when the answer replays an earlier request, billed then. Optional. |
billing.price_version | string | Partner keys only: the version of the partner prices applied. Optional. |
Errors
400 invalid_request, 401 unauthorized, 402 partner_key_cap_reached, 402 partner_tenant_cap_reached, 402 payment_required, 403 enterprise_required, 403 insufficient_scope, 403 forbidden, 404 not_found, 429 rate_limited, 429 partner_fair_use, 500 internal_error, 503 service_unavailable, 504 timeout
Get a brand's social report
GET/api/v1/brands/{brand_key}/social
The brand's organic TikTok and YouTube report: accounts, cadence, views and engagement per view with confidence intervals, breakouts, paid reach (listed apart from organic numbers) and posts run as ads. Instagram is left out; aggregates over all platforms are null when the brand also has Instagram (instagram_excluded). Needs the actions permission.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
brand_key | path | string | The brand's key, from GET /v1/brands. Required. |
range | query | "30d" | "90d" | The statistics window: the last 30 or 90 days (default 90d). default "90d" |
Response 200
| Field | Type | Description |
|---|---|---|
instagram_excluded | boolean | Optional. |
billing | object | What the request charged. Partner keys get it on every answer, free ones too. Optional. |
billing.credits_charged | integer | Credits this request charged: always 0 on Enterprise, which has no credit count. On a partner key, the credits the partner bills: each new item read, and reports and new collections at their price. -9007199254740991 to 9007199254740991 |
billing.usd_micros | integer | Partner keys only: what the partner bills, in micro-dollars. -9007199254740991 to 9007199254740991 Optional. |
billing.operation_id | string or null | Partner keys only: the settled operation, for reconciliation; null when nothing was settled. Optional. |
billing.replayed | boolean | Partner keys only: true when the answer replays an earlier request, billed then. Optional. |
billing.price_version | string | Partner keys only: the version of the partner prices applied. Optional. |
Errors
400 invalid_request, 401 unauthorized, 402 partner_key_cap_reached, 402 partner_tenant_cap_reached, 402 payment_required, 403 enterprise_required, 403 insufficient_scope, 403 forbidden, 404 not_found, 429 rate_limited, 429 partner_fair_use, 500 internal_error, 503 service_unavailable
Run a brand's Full Analysis
POST/api/v1/brands/{brand_key}/full-analysis
The Brand Full Analysis: the ads, the organic posts and the links between them, with every number's n, confidence interval and test, multiple-testing corrected. Evidence from public data, never spend or results. Reused for 24 hours. When the brand has Instagram, Instagram is left out and the cross-platform aggregates are withheld (instagram_excluded). Needs the actions permission.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
brand_key | path | string | The brand's key, from GET /v1/brands. Required. |
Idempotency-Key | header | string | Required. A unique key per new request; the same key on retries. |
Request body
| Field | Type | Description |
|---|---|---|
range | "30d" | "90d" | "180d" | "all" | The ads' mix, hooks and destinations cover this range; each finding states its own window (default 90d). default "90d" Optional. |
Response 200
| Field | Type | Description |
|---|---|---|
instagram_excluded | boolean | Optional. |
billing | object | What the request charged. Partner keys get it on every answer, free ones too. Optional. |
billing.credits_charged | integer | Credits this request charged: always 0 on Enterprise, which has no credit count. On a partner key, the credits the partner bills: each new item read, and reports and new collections at their price. -9007199254740991 to 9007199254740991 |
billing.usd_micros | integer | Partner keys only: what the partner bills, in micro-dollars. -9007199254740991 to 9007199254740991 Optional. |
billing.operation_id | string or null | Partner keys only: the settled operation, for reconciliation; null when nothing was settled. Optional. |
billing.replayed | boolean | Partner keys only: true when the answer replays an earlier request, billed then. Optional. |
billing.price_version | string | Partner keys only: the version of the partner prices applied. Optional. |
Errors
400 invalid_request, 400 idempotency_key_required, 401 unauthorized, 402 partner_key_cap_reached, 402 partner_tenant_cap_reached, 402 payment_required, 403 enterprise_required, 403 insufficient_scope, 403 forbidden, 404 not_found, 409 idempotency_conflict, 409 operation_in_progress, 413 payload_too_large, 415 unsupported_media_type, 429 rate_limited, 429 partner_fair_use, 500 internal_error, 503 service_unavailable, 504 timeout
Compare brands
POST/api/v1/compare/brands
The X-Rays of 2 to 5 brands over one range, side by side. Each brand's report is reused for 24 hours. Needs the actions permission.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
Idempotency-Key | header | string | Required. A unique key per new request; the same key on retries. |
Request body
| Field | Type | Description |
|---|---|---|
brand_keys | string[] | 2 to 5 brand keys. |
range | "30d" | "90d" | "180d" | "all" | The window of first sightings the report covers (default 90d). default "90d" Optional. |
Response 200
| Field | Type | Description |
|---|---|---|
reports | object[] | |
reports[].instagram_excluded | boolean | Optional. |
missing | object[] | |
missing[].brand_key | string | |
missing[].reason | string | |
billing | object | What the request charged. Partner keys get it on every answer, free ones too. |
billing.credits_charged | integer | Credits this request charged: always 0 on Enterprise, which has no credit count. On a partner key, the credits the partner bills: each new item read, and reports and new collections at their price. -9007199254740991 to 9007199254740991 |
billing.usd_micros | integer | Partner keys only: what the partner bills, in micro-dollars. -9007199254740991 to 9007199254740991 Optional. |
billing.operation_id | string or null | Partner keys only: the settled operation, for reconciliation; null when nothing was settled. Optional. |
billing.replayed | boolean | Partner keys only: true when the answer replays an earlier request, billed then. Optional. |
billing.price_version | string | Partner keys only: the version of the partner prices applied. Optional. |
Errors
400 invalid_request, 400 idempotency_key_required, 401 unauthorized, 402 partner_key_cap_reached, 402 partner_tenant_cap_reached, 402 payment_required, 403 enterprise_required, 403 insufficient_scope, 403 forbidden, 409 idempotency_conflict, 409 operation_in_progress, 413 payload_too_large, 415 unsupported_media_type, 429 rate_limited, 429 partner_fair_use, 500 internal_error, 503 service_unavailable, 504 timeout
Compare brands on TikTok or YouTube
POST/api/v1/compare/social
2 to 5 brands' organic posts on one platform: engagement per view and views per post, each brand's median against its peers with a stratified bootstrap, cadence, breakouts and paid reach. Needs the actions permission.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
Idempotency-Key | header | string | Required. A unique key per new request; the same key on retries. |
Request body
| Field | Type | Description |
|---|---|---|
brand_keys | string[] | 2 to 5 brand keys. |
platform | "tiktok" | "youtube" | tiktok or youtube. Instagram is not available in the API. |
range | "30d" | "90d" | The statistics window: the last 30 or 90 days (default 90d). default "90d" Optional. |
Response 200
| Field | Type | Description |
|---|---|---|
instagram_excluded | boolean | Optional. |
billing | object | What the request charged. Partner keys get it on every answer, free ones too. Optional. |
billing.credits_charged | integer | Credits this request charged: always 0 on Enterprise, which has no credit count. On a partner key, the credits the partner bills: each new item read, and reports and new collections at their price. -9007199254740991 to 9007199254740991 |
billing.usd_micros | integer | Partner keys only: what the partner bills, in micro-dollars. -9007199254740991 to 9007199254740991 Optional. |
billing.operation_id | string or null | Partner keys only: the settled operation, for reconciliation; null when nothing was settled. Optional. |
billing.replayed | boolean | Partner keys only: true when the answer replays an earlier request, billed then. Optional. |
billing.price_version | string | Partner keys only: the version of the partner prices applied. Optional. |
Errors
400 invalid_request, 400 idempotency_key_required, 401 unauthorized, 402 partner_key_cap_reached, 402 partner_tenant_cap_reached, 402 payment_required, 403 enterprise_required, 403 insufficient_scope, 403 forbidden, 409 idempotency_conflict, 409 operation_in_progress, 413 payload_too_large, 415 unsupported_media_type, 422 instagram_not_in_api, 429 rate_limited, 429 partner_fair_use, 500 internal_error, 503 service_unavailable
Social
List a brand's posts run as ads
GET/api/v1/brands/{brand_key}/posts-run-as-ads
Pairs of a brand's organic post and the ad cut from it (or the ad later posted organically), matched by media. Instagram pairs are left out; without platform, summary is null when the brand also has Instagram. Needs the read permission.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
brand_key | path | string | The brand's key, from GET /v1/brands. Required. |
range | query | "30d" | "90d" | "180d" | "all" | Posts published in this window (default 90d). default "90d" |
platform | query | "tiktok" | "youtube" | tiktok or youtube. Instagram is not available in the API. |
direction | query | "organic_to_paid" | "paid_to_organic" | "all" | organic_to_paid: posts later run as ads. paid_to_organic: ads later posted organically. default "organic_to_paid" |
limit | query | integer | Items per page, 1 to 100 (default 20). 1 to 100, default 20 |
cursor | query | string | The next_cursor of the previous page. Send it with the same filters; it is valid for 24 hours. |
Response 200
| Field | Type | Description |
|---|---|---|
data | object[] | |
data[].pair_id | string | |
data[].direction | string | |
data[].lag_days | number or null | |
data[].match | string or null | |
data[].post | object | |
data[].ad | object | The ad: creative_id, source, ad_type, ad_first_seen, in_library, creative. |
has_more | boolean | |
next_cursor | string or null | Send it as cursor, with the same filters, for the next page. |
summary | object or null | |
accounts | object[] | |
accounts[].account_id | string | |
accounts[].platform | "tiktok" | "youtube" | tiktok or youtube. Instagram is not available in the API. |
accounts[].handle | string or null | |
accounts[].display_name | string or null | |
accounts[].profile_url | string or null | |
accounts[].verified | boolean or null | |
accounts[].followers | integer or null | |
accounts[].followers_rounded | boolean or null | |
accounts[].posts_count | integer or null | |
accounts[].history_complete | boolean or null | |
accounts[].last_success_at | string or null | |
accounts[].status | string or null | |
matching | object or null | |
instagram_excluded | boolean | Optional. |
billing | object | What the request charged. Partner keys get it on every answer, free ones too. Optional. |
billing.credits_charged | integer | Credits this request charged: always 0 on Enterprise, which has no credit count. On a partner key, the credits the partner bills: each new item read, and reports and new collections at their price. -9007199254740991 to 9007199254740991 |
billing.usd_micros | integer | Partner keys only: what the partner bills, in micro-dollars. -9007199254740991 to 9007199254740991 Optional. |
billing.operation_id | string or null | Partner keys only: the settled operation, for reconciliation; null when nothing was settled. Optional. |
billing.replayed | boolean | Partner keys only: true when the answer replays an earlier request, billed then. Optional. |
billing.price_version | string | Partner keys only: the version of the partner prices applied. Optional. |
Errors
400 invalid_request, 400 invalid_cursor, 401 unauthorized, 402 partner_key_cap_reached, 402 partner_tenant_cap_reached, 403 enterprise_required, 403 insufficient_scope, 403 forbidden, 404 not_found, 422 instagram_not_in_api, 429 rate_limited, 429 partner_fair_use, 500 internal_error, 503 service_unavailable
Search social accounts
GET/api/v1/social/accounts
TikTok or YouTube accounts for a brand or a handle: the ones Adspy collects, then the platform's own search. official is true only with proof that the account is the brand's. Needs the read permission.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
query | query | string | A brand name or a handle. Required. |
platform | query | "tiktok" | "youtube" | tiktok or youtube. Instagram is not available in the API. Required. |
brand_key | query | string | The Adspy brand, when known: its linked accounts and website are used as proof. |
Response 200
| Field | Type | Description |
|---|---|---|
data | object[] | |
data[].platform | "tiktok" | "youtube" | tiktok or youtube. Instagram is not available in the API. |
data[].handle | string or null | |
data[].url | string or null | |
data[].display_name | string or null | |
data[].verified | boolean or null | |
data[].followers | integer or null | |
data[].official | boolean or null | True only with proof that the account is the brand's. |
data[].label | string or null | |
data[].tracked | boolean or null | Adspy already collects it: reading it is free. |
data[].account_id | string or null | |
data[].brand_key | string or null | |
status | string or null | found, not_found, search_unavailable, … |
reason | string or null | |
retry_after_seconds | integer or null | |
billing | object | What the request charged. Partner keys get it on every answer, free ones too. Optional. |
billing.credits_charged | integer | Credits this request charged: always 0 on Enterprise, which has no credit count. On a partner key, the credits the partner bills: each new item read, and reports and new collections at their price. -9007199254740991 to 9007199254740991 |
billing.usd_micros | integer | Partner keys only: what the partner bills, in micro-dollars. -9007199254740991 to 9007199254740991 Optional. |
billing.operation_id | string or null | Partner keys only: the settled operation, for reconciliation; null when nothing was settled. Optional. |
billing.replayed | boolean | Partner keys only: true when the answer replays an earlier request, billed then. Optional. |
billing.price_version | string | Partner keys only: the version of the partner prices applied. Optional. |
Errors
400 invalid_request, 401 unauthorized, 403 enterprise_required, 403 insufficient_scope, 403 forbidden, 422 instagram_not_in_api, 429 rate_limited, 500 internal_error, 503 service_unavailable
Collect a social account
POST/api/v1/social/fetches
Asks Adspy to collect a TikTok or YouTube account's posts. An account Adspy already collects is returned at once (state existing), and one already being collected answers its running job: neither counts. New collections count toward the contract's monthly quota, shared with the organization's MCP connections. Follow the job with GET /v1/fetches/{id}. Needs the actions permission.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
Idempotency-Key | header | string | Required. A unique key per new request; the same key on retries. |
Request body
| Field | Type | Description |
|---|---|---|
platform | "tiktok" | "youtube" | tiktok or youtube. Instagram is not available in the API. |
url | string | The profile link, e.g. tiktok.com/@handle. Give url or handle. Optional. |
handle | string | The @handle. Optional. |
brand_key | string | The brand the account belongs to: it is linked on proof only. Optional. |
Response 202
| Field | Type | Description |
|---|---|---|
job_id | string | |
kind | "brand_fetch" | "social_fetch" | |
state | string | existing (Adspy already had it: read it now), queued, pending, submitting, processing, waiting (social: retried automatically at retry_at), completed or failed. |
is_complete | boolean | The only signal that the collection is done; never infer it from progress. |
is_terminal | boolean | |
poll_after_seconds | integer or null | When to read the job again; null once terminal. |
brand_key | string or null | |
created_at | string or null | |
updated_at | string or null | |
source | "meta" | "google" or null | Brand fetches: the ad library. |
business_id | string or null | Brand fetches: the advertiser's id in that library. |
brand_name | string or null | |
total_ads | integer or null | |
processed_ads | integer or null | |
remaining_ads | integer or null | |
result_cap | integer or null | |
source_coverage | object or null | Brand fetches: how much of the advertiser's library was collected, when known. |
source_coverage.status | string or null | |
source_coverage.expected_ads_estimate | integer or null | |
source_coverage.observed_valid_ads | integer or null | |
source_coverage.low_confidence | boolean or null | |
source_coverage.reasons | string[] | |
source_coverage.last_scraped_at | string or null | |
platform | "tiktok" | "youtube" or null | Social fetches. |
account_id | string or null | |
handle | string or null | |
display_name | string or null | |
url | string or null | |
total_posts | integer or null | |
processed_posts | integer or null | |
remaining_posts | integer or null | |
new_posts | integer or null | |
posts_count | integer or null | |
history_complete | boolean or null | |
history_days | integer or null | |
retry_at | string or null | |
progress_percent | number or null | |
error_code | string or null | |
billing | object | What the request charged. Partner keys get it on every answer, free ones too. Optional. |
billing.credits_charged | integer | Credits this request charged: always 0 on Enterprise, which has no credit count. On a partner key, the credits the partner bills: each new item read, and reports and new collections at their price. -9007199254740991 to 9007199254740991 |
billing.usd_micros | integer | Partner keys only: what the partner bills, in micro-dollars. -9007199254740991 to 9007199254740991 Optional. |
billing.operation_id | string or null | Partner keys only: the settled operation, for reconciliation; null when nothing was settled. Optional. |
billing.replayed | boolean | Partner keys only: true when the answer replays an earlier request, billed then. Optional. |
billing.price_version | string | Partner keys only: the version of the partner prices applied. Optional. |
Errors
400 invalid_request, 400 idempotency_key_required, 401 unauthorized, 402 partner_key_cap_reached, 402 partner_tenant_cap_reached, 402 payment_required, 403 enterprise_required, 403 insufficient_scope, 403 forbidden, 409 idempotency_conflict, 409 operation_in_progress, 413 payload_too_large, 415 unsupported_media_type, 422 instagram_not_in_api, 429 rate_limited, 429 partner_fair_use, 429 fetch_quota_exceeded, 429 fetch_limited, 500 internal_error, 503 service_unavailable
List social posts
GET/api/v1/social/posts
A brand's (or one account's) organic TikTok and YouTube posts with their public counts. Instagram posts are left out, so a page can hold fewer posts than limit: follow has_more. Needs the read permission.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
brand_key | query | string | The brand; give brand_key or account_id. |
account_id | query | string | An account id, e.g. social:tiktok:6643891469239320582. |
platform | query | "tiktok" | "youtube" | tiktok or youtube. Instagram is not available in the API. |
format | query | "video" | "short" | "live" | "carousel" | "image" | TikTok: video, carousel (photo post), live. YouTube: video, short, live. |
since | query | string | Posts published on or after this date (YYYY-MM-DD). |
sort | query | "recent" | "engagement" | "breakouts" | recent: newest first. engagement: highest engagement per view first. breakouts: the posts far above the account's usual views (90-day statistics). default "recent" |
limit | query | integer | Items per page, 1 to 100 (default 20). 1 to 100, default 20 |
cursor | query | string | The next_cursor of the previous page. Send it with the same filters; it is valid for 24 hours. |
Response 200
| Field | Type | Description |
|---|---|---|
data | object[] | |
data[].id | string | |
data[].platform | "tiktok" | "youtube" | tiktok or youtube. Instagram is not available in the API. |
data[].post_id | string | |
data[].account_id | string or null | |
data[].handle | string or null | |
data[].brand_key | string or null | |
data[].permalink | string or null | |
data[].published_at | string or null | |
data[].published_at_approx | boolean or null | |
data[].format | string or null | |
data[].title | string or null | |
data[].caption | string or null | |
data[].hashtags | string[] | |
data[].duration_sec | number or null | |
data[].thumb_url | string or null | |
data[].counts | object | Public counts; null when the platform does not show one (never zero). |
data[].counts_rounded | boolean or null | |
data[].counts_at | string or null | |
data[].engagement_rate | number or null | Engagement per view (posts with 50+ views). |
data[].reach | string or null | breakout, paid_reach or null (90-day statistics). |
data[].ran_as_ad | boolean or null | |
data[].promoted_flag | boolean or null | |
data[].pinned | boolean or null | |
data[].deleted_at | string or null | |
has_more | boolean | |
next_cursor | string or null | Send it as cursor, with the same filters, for the next page. |
accounts | object[] | |
accounts[].account_id | string | |
accounts[].platform | "tiktok" | "youtube" | tiktok or youtube. Instagram is not available in the API. |
accounts[].handle | string or null | |
accounts[].display_name | string or null | |
accounts[].profile_url | string or null | |
accounts[].verified | boolean or null | |
accounts[].followers | integer or null | |
accounts[].followers_rounded | boolean or null | |
accounts[].posts_count | integer or null | |
accounts[].history_complete | boolean or null | |
accounts[].last_success_at | string or null | |
accounts[].status | string or null | |
reach_labels | object or null | |
analysis | object or null | |
billing | object | What the request charged. Partner keys get it on every answer, free ones too. Optional. |
billing.credits_charged | integer | Credits this request charged: always 0 on Enterprise, which has no credit count. On a partner key, the credits the partner bills: each new item read, and reports and new collections at their price. -9007199254740991 to 9007199254740991 |
billing.usd_micros | integer | Partner keys only: what the partner bills, in micro-dollars. -9007199254740991 to 9007199254740991 Optional. |
billing.operation_id | string or null | Partner keys only: the settled operation, for reconciliation; null when nothing was settled. Optional. |
billing.replayed | boolean | Partner keys only: true when the answer replays an earlier request, billed then. Optional. |
billing.price_version | string | Partner keys only: the version of the partner prices applied. Optional. |
Errors
400 invalid_request, 400 invalid_cursor, 401 unauthorized, 402 partner_key_cap_reached, 402 partner_tenant_cap_reached, 403 enterprise_required, 403 insufficient_scope, 403 forbidden, 422 instagram_not_in_api, 429 rate_limited, 429 partner_fair_use, 500 internal_error, 503 service_unavailable
Get a social post
GET/api/v1/social/posts/{id}
One TikTok or YouTube post with its count snapshots, ad links, pre-ad counts and, on request, its AI tags. Needs the read permission.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
id | path | string | A post id, platform:native id, e.g. tiktok:7675005480867073311. Required. |
include_analysis | query | "true" | "false" | true adds the post's AI tags (default false). |
Response 200
| Field | Type | Description |
|---|---|---|
id | string | |
platform | "tiktok" | "youtube" | tiktok or youtube. Instagram is not available in the API. |
post_id | string | |
account_id | string or null | |
handle | string or null | |
brand_key | string or null | |
permalink | string or null | |
published_at | string or null | |
published_at_approx | boolean or null | |
format | string or null | |
title | string or null | |
caption | string or null | |
hashtags | string[] | |
duration_sec | number or null | |
thumb_url | string or null | |
counts | object | Public counts; null when the platform does not show one (never zero). |
counts.views | integer or null | |
counts.likes | integer or null | |
counts.comments | integer or null | |
counts.shares | integer or null | |
counts.saves | integer or null | |
counts_rounded | boolean or null | |
counts_at | string or null | |
engagement_rate | number or null | Engagement per view (posts with 50+ views). |
reach | string or null | breakout, paid_reach or null (90-day statistics). |
ran_as_ad | boolean or null | |
promoted_flag | boolean or null | |
pinned | boolean or null | |
deleted_at | string or null | |
billing | object | What the request charged. Partner keys get it on every answer, free ones too. Optional. |
billing.credits_charged | integer | Credits this request charged: always 0 on Enterprise, which has no credit count. On a partner key, the credits the partner bills: each new item read, and reports and new collections at their price. -9007199254740991 to 9007199254740991 |
billing.usd_micros | integer | Partner keys only: what the partner bills, in micro-dollars. -9007199254740991 to 9007199254740991 Optional. |
billing.operation_id | string or null | Partner keys only: the settled operation, for reconciliation; null when nothing was settled. Optional. |
billing.replayed | boolean | Partner keys only: true when the answer replays an earlier request, billed then. Optional. |
billing.price_version | string | Partner keys only: the version of the partner prices applied. Optional. |
Errors
400 invalid_request, 401 unauthorized, 402 partner_key_cap_reached, 402 partner_tenant_cap_reached, 403 enterprise_required, 403 insufficient_scope, 403 forbidden, 404 not_found, 422 instagram_not_in_api, 429 rate_limited, 429 partner_fair_use, 500 internal_error, 503 service_unavailable
Creatives
Search creatives
GET/api/v1/creatives
Meta and Google creatives in Adspy's library, with filters. Live offset pages, not a fixed snapshot: a page can repeat or skip an item when the library changes between pages. Needs the read permission.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
query | query | string | Words to find, in the scope chosen. |
scope | query | "all" | "ad_copy" | "content_transcript" | "visual_analysis" | "all_keywords" | "hooks" | Where query is matched (default all). default "all" |
platform | query | "all" | "meta" | "google" | The ad library: meta (Facebook, Instagram and Messenger placements) or google (Search, YouTube, Display). |
format | query | "all" | "image" | "video" | "carousel" | |
status | query | "all" | "active" | "inactive" | Whether the library last saw the ad running. |
sort | query | "newest" | "oldest" | "longest" | newest or oldest first sighting, or longest running (default newest). default "newest" |
tags | query | string | AI tags the creative must all carry, comma-separated, e.g. hook_type:Question. |
language | query | string | |
min_days_active | query | integer | Only creatives seen running for at least this many days. 0 to 36500 |
brand_key | query | string | Only this brand's creatives. |
brand_keys | query | string | Only these brands' creatives, comma-separated (up to 100). |
limit | query | integer | Items per page, 1 to 100 (default 20). 1 to 100, default 20 |
cursor | query | string | The next_cursor of the previous page. Send it with the same filters; it is valid for 24 hours. |
Response 200
| Field | Type | Description |
|---|---|---|
data | object[] | |
data[].id | string | The creative's id (its media hash). |
data[].brand_key | string or null | |
data[].brand_name | string or null | |
data[].brand_logo_url | string or null | |
data[].platform | string or null | meta or google. |
data[].format | string or null | image, video or carousel. |
data[].media_url | string or null | The creative's media: a signed link, valid 21 days. |
data[].poster_url | string or null | |
data[].media_urls | string[] | |
data[].external_watch_url | string or null | A YouTube link for Google video ads, when the file is not stored. |
data[].title | string or null | |
data[].body | string or null | |
data[].first_seen | string or null | |
data[].last_seen | string or null | |
data[].status | string or null | active, inactive or unknown. |
data[].days_active | integer or null | |
data[].ads_count | integer or null | Source ads that run this creative. |
data[].tags | string[] | |
data[].language | string or null | |
data[].media_availability | string or null | |
data[].media_unavailable_reason | string or null | |
data[].transcript | string or null | |
has_more | boolean | |
next_cursor | string or null | Send it as cursor, with the same filters, for the next page. |
total | integer or null | |
billing | object | What the request charged. Partner keys get it on every answer, free ones too. Optional. |
billing.credits_charged | integer | Credits this request charged: always 0 on Enterprise, which has no credit count. On a partner key, the credits the partner bills: each new item read, and reports and new collections at their price. -9007199254740991 to 9007199254740991 |
billing.usd_micros | integer | Partner keys only: what the partner bills, in micro-dollars. -9007199254740991 to 9007199254740991 Optional. |
billing.operation_id | string or null | Partner keys only: the settled operation, for reconciliation; null when nothing was settled. Optional. |
billing.replayed | boolean | Partner keys only: true when the answer replays an earlier request, billed then. Optional. |
billing.price_version | string | Partner keys only: the version of the partner prices applied. Optional. |
Errors
400 invalid_request, 400 invalid_cursor, 401 unauthorized, 402 partner_key_cap_reached, 402 partner_tenant_cap_reached, 403 enterprise_required, 403 insufficient_scope, 403 forbidden, 429 rate_limited, 429 partner_fair_use, 500 internal_error, 503 service_unavailable, 504 timeout
Search creatives by meaning
GET/api/v1/creatives/by-meaning
Creatives whose transcript says what you describe, closest meaning first, in any language and even with other words. A creative without a transcript is never found here: use the creative search for exact words, ad copy or a brand's full list. Filters apply before ordering. Status, tags and days active are not offered here. Needs the read permission.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
query | query | string | What the ads should say, in plain words and any language: an idea, an angle, a pain point. Required. |
brand_key | query | string | Only this brand's creatives. |
brand_keys | query | string | Only these brands' creatives, comma-separated (up to 100). |
platform | query | "all" | "meta" | "google" | The ad library: meta (Facebook, Instagram and Messenger placements) or google (Search, YouTube, Display). |
format | query | "all" | "image" | "video" | "carousel" | |
language | query | string | |
since | query | string | Only creatives first seen on or after this day, e.g. 2026-09-01. |
limit | query | integer | Items per page, 1 to 100 (default 20). 1 to 100, default 20 |
cursor | query | string | The next_cursor of the previous page. Send it with the same filters; it is valid for 24 hours. |
Response 200
| Field | Type | Description |
|---|---|---|
data | object[] | |
data[].id | string | The creative's id (its media hash). |
data[].brand_key | string or null | |
data[].brand_name | string or null | |
data[].brand_logo_url | string or null | |
data[].platform | string or null | meta or google. |
data[].format | string or null | image, video or carousel. |
data[].media_url | string or null | The creative's media: a signed link, valid 21 days. |
data[].poster_url | string or null | |
data[].media_urls | string[] | |
data[].external_watch_url | string or null | A YouTube link for Google video ads, when the file is not stored. |
data[].title | string or null | |
data[].body | string or null | |
data[].first_seen | string or null | |
data[].last_seen | string or null | |
data[].status | string or null | active, inactive or unknown. |
data[].days_active | integer or null | |
data[].ads_count | integer or null | Source ads that run this creative. |
data[].tags | string[] | |
data[].language | string or null | |
data[].media_availability | string or null | |
data[].media_unavailable_reason | string or null | |
data[].transcript | string or null | |
data[].match_score | number | How close the meaning is, from 0 to 1. Never a measure of results. |
has_more | boolean | |
next_cursor | string or null | Send it as cursor, with the same filters, for the next page. |
total | integer or null | |
billing | object | What the request charged. Partner keys get it on every answer, free ones too. Optional. |
billing.credits_charged | integer | Credits this request charged: always 0 on Enterprise, which has no credit count. On a partner key, the credits the partner bills: each new item read, and reports and new collections at their price. -9007199254740991 to 9007199254740991 |
billing.usd_micros | integer | Partner keys only: what the partner bills, in micro-dollars. -9007199254740991 to 9007199254740991 Optional. |
billing.operation_id | string or null | Partner keys only: the settled operation, for reconciliation; null when nothing was settled. Optional. |
billing.replayed | boolean | Partner keys only: true when the answer replays an earlier request, billed then. Optional. |
billing.price_version | string | Partner keys only: the version of the partner prices applied. Optional. |
Errors
400 invalid_request, 400 invalid_cursor, 401 unauthorized, 402 partner_key_cap_reached, 402 partner_tenant_cap_reached, 403 enterprise_required, 403 insufficient_scope, 403 forbidden, 429 rate_limited, 429 partner_fair_use, 500 internal_error, 503 service_unavailable, 504 timeout
Get a creative
GET/api/v1/creatives/{id}
One creative with its transcript, source ads (variants), hook, AI tags, CTA and landing pages. Needs the read permission.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
id | path | string | The creative id. Required. |
Response 200
| Field | Type | Description |
|---|---|---|
id | string | The creative's id (its media hash). |
brand_key | string or null | |
brand_name | string or null | |
brand_logo_url | string or null | |
platform | string or null | meta or google. |
format | string or null | image, video or carousel. |
media_url | string or null | The creative's media: a signed link, valid 21 days. |
poster_url | string or null | |
media_urls | string[] | |
external_watch_url | string or null | A YouTube link for Google video ads, when the file is not stored. |
title | string or null | |
body | string or null | |
first_seen | string or null | |
last_seen | string or null | |
status | string or null | active, inactive or unknown. |
days_active | integer or null | |
ads_count | integer or null | Source ads that run this creative. |
tags | string[] | |
language | string or null | |
media_availability | string or null | |
media_unavailable_reason | string or null | |
transcript | string or null | |
transcript_status | string or null | |
transcript_parts | object[] | |
transcript_parts[].kind | string | |
transcript_parts[].label | string | |
transcript_parts[].text | string | |
variants | object[] | The source ads that run this creative, newest first. |
variants_limited | boolean | |
variants_count | integer or null | |
active_variants_count | integer or null | |
hook | object or null | |
ai_tags | object[] | |
ai_tags[].id | string | |
ai_tags[].label | string | |
ai_tags[].tags | object[] | |
cta | string or null | |
landing_page_url | string or null | |
overview | object or null | |
billing | object | What the request charged. Partner keys get it on every answer, free ones too. Optional. |
billing.credits_charged | integer | Credits this request charged: always 0 on Enterprise, which has no credit count. On a partner key, the credits the partner bills: each new item read, and reports and new collections at their price. -9007199254740991 to 9007199254740991 |
billing.usd_micros | integer | Partner keys only: what the partner bills, in micro-dollars. -9007199254740991 to 9007199254740991 Optional. |
billing.operation_id | string or null | Partner keys only: the settled operation, for reconciliation; null when nothing was settled. Optional. |
billing.replayed | boolean | Partner keys only: true when the answer replays an earlier request, billed then. Optional. |
billing.price_version | string | Partner keys only: the version of the partner prices applied. Optional. |
Errors
400 invalid_request, 401 unauthorized, 402 partner_key_cap_reached, 402 partner_tenant_cap_reached, 403 enterprise_required, 403 insufficient_scope, 403 forbidden, 404 not_found, 429 rate_limited, 429 partner_fair_use, 500 internal_error, 503 service_unavailable
Get a creative's AI analysis
GET/api/v1/creatives/{id}/analysis
The creative's record with its AI analysis: scores (an AI reading of the execution, not measured performance), objective, timed moments and the full analysis document. Needs the read permission.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
id | path | string | The creative id. Required. |
Response 200
| Field | Type | Description |
|---|---|---|
id | string | The creative's id (its media hash). |
brand_key | string or null | |
brand_name | string or null | |
brand_logo_url | string or null | |
platform | string or null | meta or google. |
format | string or null | image, video or carousel. |
media_url | string or null | The creative's media: a signed link, valid 21 days. |
poster_url | string or null | |
media_urls | string[] | |
external_watch_url | string or null | A YouTube link for Google video ads, when the file is not stored. |
title | string or null | |
body | string or null | |
first_seen | string or null | |
last_seen | string or null | |
status | string or null | active, inactive or unknown. |
days_active | integer or null | |
ads_count | integer or null | Source ads that run this creative. |
tags | string[] | |
language | string or null | |
media_availability | string or null | |
media_unavailable_reason | string or null | |
transcript | string or null | |
transcript_status | string or null | |
transcript_parts | object[] | |
transcript_parts[].kind | string | |
transcript_parts[].label | string | |
transcript_parts[].text | string | |
variants | object[] | The source ads that run this creative, newest first. |
variants_limited | boolean | |
variants_count | integer or null | |
active_variants_count | integer or null | |
hook | object or null | |
ai_tags | object[] | |
ai_tags[].id | string | |
ai_tags[].label | string | |
ai_tags[].tags | object[] | |
cta | string or null | |
landing_page_url | string or null | |
overview | object or null | |
scores | object[] | AI reading of the creative's execution, not measured ad performance. |
scores[].id | string | |
scores[].label | string | |
scores[].value | number or null | |
scores[].out_of | number or null | |
scores[].meaning | string or null | |
objective | string or null | |
moments | object[] | |
analysis | object or null | |
analysis_status | string or null | |
billing | object | What the request charged. Partner keys get it on every answer, free ones too. Optional. |
billing.credits_charged | integer | Credits this request charged: always 0 on Enterprise, which has no credit count. On a partner key, the credits the partner bills: each new item read, and reports and new collections at their price. -9007199254740991 to 9007199254740991 |
billing.usd_micros | integer | Partner keys only: what the partner bills, in micro-dollars. -9007199254740991 to 9007199254740991 Optional. |
billing.operation_id | string or null | Partner keys only: the settled operation, for reconciliation; null when nothing was settled. Optional. |
billing.replayed | boolean | Partner keys only: true when the answer replays an earlier request, billed then. Optional. |
billing.price_version | string | Partner keys only: the version of the partner prices applied. Optional. |
Errors
400 invalid_request, 401 unauthorized, 402 partner_key_cap_reached, 402 partner_tenant_cap_reached, 403 enterprise_required, 403 insufficient_scope, 403 forbidden, 404 not_found, 429 rate_limited, 429 partner_fair_use, 500 internal_error, 503 service_unavailable
List similar creatives
GET/api/v1/creatives/{id}/similar
Creatives of other brands that share the creative's execution and topic tags, ranked. Needs the read permission.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
id | path | string | The creative id. Required. |
limit | query | integer | Matches to return, 1 to 100 (default 20). 1 to 100, default 20 |
Response 200
| Field | Type | Description |
|---|---|---|
data | object[] | |
data[].creative | object | |
candidates_reviewed | integer or null | |
candidate_limit | integer or null | |
candidate_pool_limited | boolean or null | |
method | string or null | |
billing | object | What the request charged. Partner keys get it on every answer, free ones too. Optional. |
billing.credits_charged | integer | Credits this request charged: always 0 on Enterprise, which has no credit count. On a partner key, the credits the partner bills: each new item read, and reports and new collections at their price. -9007199254740991 to 9007199254740991 |
billing.usd_micros | integer | Partner keys only: what the partner bills, in micro-dollars. -9007199254740991 to 9007199254740991 Optional. |
billing.operation_id | string or null | Partner keys only: the settled operation, for reconciliation; null when nothing was settled. Optional. |
billing.replayed | boolean | Partner keys only: true when the answer replays an earlier request, billed then. Optional. |
billing.price_version | string | Partner keys only: the version of the partner prices applied. Optional. |
Errors
400 invalid_request, 401 unauthorized, 402 partner_key_cap_reached, 402 partner_tenant_cap_reached, 403 enterprise_required, 403 insufficient_scope, 403 forbidden, 404 not_found, 429 rate_limited, 429 partner_fair_use, 500 internal_error, 503 service_unavailable
Fetches
Search advertisers in public ad libraries
GET/api/v1/advertisers
Advertisers on the Meta Ad Library or Google Ads Transparency, for a brand Adspy does not have yet. Give the chosen one's url to POST /v1/fetches. Needs the read permission.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
query | query | string | The advertiser's name. Required. |
source | query | "meta" | "google" | The public ad library to search: Meta Ad Library or Google Ads Transparency. Required. |
Response 200
| Field | Type | Description |
|---|---|---|
data | object[] | |
data[].source | string | |
data[].business_id | string | |
data[].name | string or null | |
data[].logo_url | string or null | |
data[].ad_count | integer or null | |
data[].country | string or null | |
data[].url | string | Give it to POST /v1/fetches. |
billing | object | What the request charged. Partner keys get it on every answer, free ones too. Optional. |
billing.credits_charged | integer | Credits this request charged: always 0 on Enterprise, which has no credit count. On a partner key, the credits the partner bills: each new item read, and reports and new collections at their price. -9007199254740991 to 9007199254740991 |
billing.usd_micros | integer | Partner keys only: what the partner bills, in micro-dollars. -9007199254740991 to 9007199254740991 Optional. |
billing.operation_id | string or null | Partner keys only: the settled operation, for reconciliation; null when nothing was settled. Optional. |
billing.replayed | boolean | Partner keys only: true when the answer replays an earlier request, billed then. Optional. |
billing.price_version | string | Partner keys only: the version of the partner prices applied. Optional. |
Errors
400 invalid_request, 401 unauthorized, 403 enterprise_required, 403 insufficient_scope, 403 forbidden, 429 rate_limited, 500 internal_error, 503 service_unavailable
Collect a new brand
POST/api/v1/fetches
Asks Adspy to collect an advertiser's ads. A brand Adspy already has is returned at once (state existing), and one already being collected answers its running job: neither counts. New collections count toward the contract's monthly quota, shared with the organization's MCP connections. Follow the job with GET /v1/fetches/{id}. Needs the actions permission.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
Idempotency-Key | header | string | Required. A unique key per new request; the same key on retries. |
Request body
| Field | Type | Description |
|---|---|---|
url | string | The advertiser's page in the Meta Ad Library (view_all_page_id) or Google Ads Transparency, from GET /v1/advertisers. |
name | string | The brand's name. |
result_cap | integer | Suggested page size for reading the new creatives later; not an ingestion limit. 1 to 100, default 20 Optional. |
Response 202
| Field | Type | Description |
|---|---|---|
job_id | string | |
kind | "brand_fetch" | "social_fetch" | |
state | string | existing (Adspy already had it: read it now), queued, pending, submitting, processing, waiting (social: retried automatically at retry_at), completed or failed. |
is_complete | boolean | The only signal that the collection is done; never infer it from progress. |
is_terminal | boolean | |
poll_after_seconds | integer or null | When to read the job again; null once terminal. |
brand_key | string or null | |
created_at | string or null | |
updated_at | string or null | |
source | "meta" | "google" or null | Brand fetches: the ad library. |
business_id | string or null | Brand fetches: the advertiser's id in that library. |
brand_name | string or null | |
total_ads | integer or null | |
processed_ads | integer or null | |
remaining_ads | integer or null | |
result_cap | integer or null | |
source_coverage | object or null | Brand fetches: how much of the advertiser's library was collected, when known. |
source_coverage.status | string or null | |
source_coverage.expected_ads_estimate | integer or null | |
source_coverage.observed_valid_ads | integer or null | |
source_coverage.low_confidence | boolean or null | |
source_coverage.reasons | string[] | |
source_coverage.last_scraped_at | string or null | |
platform | "tiktok" | "youtube" or null | Social fetches. |
account_id | string or null | |
handle | string or null | |
display_name | string or null | |
url | string or null | |
total_posts | integer or null | |
processed_posts | integer or null | |
remaining_posts | integer or null | |
new_posts | integer or null | |
posts_count | integer or null | |
history_complete | boolean or null | |
history_days | integer or null | |
retry_at | string or null | |
progress_percent | number or null | |
error_code | string or null | |
billing | object | What the request charged. Partner keys get it on every answer, free ones too. Optional. |
billing.credits_charged | integer | Credits this request charged: always 0 on Enterprise, which has no credit count. On a partner key, the credits the partner bills: each new item read, and reports and new collections at their price. -9007199254740991 to 9007199254740991 |
billing.usd_micros | integer | Partner keys only: what the partner bills, in micro-dollars. -9007199254740991 to 9007199254740991 Optional. |
billing.operation_id | string or null | Partner keys only: the settled operation, for reconciliation; null when nothing was settled. Optional. |
billing.replayed | boolean | Partner keys only: true when the answer replays an earlier request, billed then. Optional. |
billing.price_version | string | Partner keys only: the version of the partner prices applied. Optional. |
Errors
400 invalid_request, 400 idempotency_key_required, 401 unauthorized, 402 partner_key_cap_reached, 402 partner_tenant_cap_reached, 402 payment_required, 403 enterprise_required, 403 insufficient_scope, 403 forbidden, 409 idempotency_conflict, 409 operation_in_progress, 409 conflict, 413 payload_too_large, 415 unsupported_media_type, 429 rate_limited, 429 partner_fair_use, 429 fetch_quota_exceeded, 429 fetch_limited, 500 internal_error, 503 service_unavailable
Get a fetch job
GET/api/v1/fetches/{id}
A brand or social account collection: its state and progress. A job is complete only when is_complete is true; then read the brand's creatives (GET /v1/brands/{brand_key}/creatives) or the account's posts (GET /v1/social/posts). Needs the actions permission.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
id | path | string | The fetch job id. Required. |
Response 200
| Field | Type | Description |
|---|---|---|
job_id | string | |
kind | "brand_fetch" | "social_fetch" | |
state | string | existing (Adspy already had it: read it now), queued, pending, submitting, processing, waiting (social: retried automatically at retry_at), completed or failed. |
is_complete | boolean | The only signal that the collection is done; never infer it from progress. |
is_terminal | boolean | |
poll_after_seconds | integer or null | When to read the job again; null once terminal. |
brand_key | string or null | |
created_at | string or null | |
updated_at | string or null | |
source | "meta" | "google" or null | Brand fetches: the ad library. |
business_id | string or null | Brand fetches: the advertiser's id in that library. |
brand_name | string or null | |
total_ads | integer or null | |
processed_ads | integer or null | |
remaining_ads | integer or null | |
result_cap | integer or null | |
source_coverage | object or null | Brand fetches: how much of the advertiser's library was collected, when known. |
source_coverage.status | string or null | |
source_coverage.expected_ads_estimate | integer or null | |
source_coverage.observed_valid_ads | integer or null | |
source_coverage.low_confidence | boolean or null | |
source_coverage.reasons | string[] | |
source_coverage.last_scraped_at | string or null | |
platform | "tiktok" | "youtube" or null | Social fetches. |
account_id | string or null | |
handle | string or null | |
display_name | string or null | |
url | string or null | |
total_posts | integer or null | |
processed_posts | integer or null | |
remaining_posts | integer or null | |
new_posts | integer or null | |
posts_count | integer or null | |
history_complete | boolean or null | |
history_days | integer or null | |
retry_at | string or null | |
progress_percent | number or null | |
error_code | string or null | |
billing | object | What the request charged. Partner keys get it on every answer, free ones too. Optional. |
billing.credits_charged | integer | Credits this request charged: always 0 on Enterprise, which has no credit count. On a partner key, the credits the partner bills: each new item read, and reports and new collections at their price. -9007199254740991 to 9007199254740991 |
billing.usd_micros | integer | Partner keys only: what the partner bills, in micro-dollars. -9007199254740991 to 9007199254740991 Optional. |
billing.operation_id | string or null | Partner keys only: the settled operation, for reconciliation; null when nothing was settled. Optional. |
billing.replayed | boolean | Partner keys only: true when the answer replays an earlier request, billed then. Optional. |
billing.price_version | string | Partner keys only: the version of the partner prices applied. Optional. |
Errors
400 invalid_request, 401 unauthorized, 403 enterprise_required, 403 insufficient_scope, 403 forbidden, 404 not_found, 429 rate_limited, 500 internal_error, 503 service_unavailable
Collections
List collections
GET/api/v1/collections
The workspace's collections of saved creatives, 100 per page. Needs the read permission.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
cursor | query | string | The next_cursor of the previous page. Send it with the same filters; it is valid for 24 hours. |
Response 200
| Field | Type | Description |
|---|---|---|
data | object[] | |
data[].id | string | |
data[].name | string | |
data[].description | string or null | |
data[].count | integer or null | |
has_more | boolean | |
next_cursor | string or null | Send it as cursor, with the same filters, for the next page. |
billing | object | What the request charged. Partner keys get it on every answer, free ones too. Optional. |
billing.credits_charged | integer | Credits this request charged: always 0 on Enterprise, which has no credit count. On a partner key, the credits the partner bills: each new item read, and reports and new collections at their price. -9007199254740991 to 9007199254740991 |
billing.usd_micros | integer | Partner keys only: what the partner bills, in micro-dollars. -9007199254740991 to 9007199254740991 Optional. |
billing.operation_id | string or null | Partner keys only: the settled operation, for reconciliation; null when nothing was settled. Optional. |
billing.replayed | boolean | Partner keys only: true when the answer replays an earlier request, billed then. Optional. |
billing.price_version | string | Partner keys only: the version of the partner prices applied. Optional. |
Errors
400 invalid_request, 400 invalid_cursor, 401 unauthorized, 403 enterprise_required, 403 insufficient_scope, 403 forbidden, 429 rate_limited, 500 internal_error, 503 service_unavailable
Save creatives to a new collection
POST/api/v1/collections
Creates a collection with these creatives, or adds them to your collection that already has this name. Creatives the library does not hold are left out and listed in not_saved; when none is held, nothing is created (404). Needs the actions permission.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
Idempotency-Key | header | string | Required. A unique key per new request; the same key on retries. |
Request body
| Field | Type | Description |
|---|---|---|
name | string | The collection's name. An existing collection of yours with this name is reused. |
creative_ids | string[] | 1 to 100 creative ids. |
Response 201
| Field | Type | Description |
|---|---|---|
collection_id | string | |
updated | boolean | |
not_saved | string[] | Creative ids the library does not hold, left out of the save. Optional. |
billing | object | What the request charged. Partner keys get it on every answer, free ones too. Optional. |
billing.credits_charged | integer | Credits this request charged: always 0 on Enterprise, which has no credit count. On a partner key, the credits the partner bills: each new item read, and reports and new collections at their price. -9007199254740991 to 9007199254740991 |
billing.usd_micros | integer | Partner keys only: what the partner bills, in micro-dollars. -9007199254740991 to 9007199254740991 Optional. |
billing.operation_id | string or null | Partner keys only: the settled operation, for reconciliation; null when nothing was settled. Optional. |
billing.replayed | boolean | Partner keys only: true when the answer replays an earlier request, billed then. Optional. |
billing.price_version | string | Partner keys only: the version of the partner prices applied. Optional. |
Errors
400 invalid_request, 400 idempotency_key_required, 401 unauthorized, 403 enterprise_required, 403 insufficient_scope, 403 forbidden, 404 not_found, 409 idempotency_conflict, 409 operation_in_progress, 413 payload_too_large, 415 unsupported_media_type, 429 rate_limited, 500 internal_error, 503 service_unavailable
Get a collection
GET/api/v1/collections/{id}
A collection and its creatives with their notes. expand=true adds each creative's record. Needs the read permission.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
id | path | string | The collection id. Required. |
expand | query | "true" | "false" | true adds each creative's record (default false). |
limit | query | integer | Items per page, 1 to 100 (default 20). 1 to 100, default 20 |
cursor | query | string | The next_cursor of the previous page. Send it with the same filters; it is valid for 24 hours. |
Response 200
| Field | Type | Description |
|---|---|---|
data | object[] | |
data[].creative_id | string | |
data[].note | string | |
data[].added_at | string or null | |
data[].creative | object | Optional. |
has_more | boolean | |
next_cursor | string or null | Send it as cursor, with the same filters, for the next page. |
collection | object | |
collection.id | string | |
collection.name | string | |
collection.description | string or null | |
collection.color | string or null | |
billing | object | What the request charged. Partner keys get it on every answer, free ones too. Optional. |
billing.credits_charged | integer | Credits this request charged: always 0 on Enterprise, which has no credit count. On a partner key, the credits the partner bills: each new item read, and reports and new collections at their price. -9007199254740991 to 9007199254740991 |
billing.usd_micros | integer | Partner keys only: what the partner bills, in micro-dollars. -9007199254740991 to 9007199254740991 Optional. |
billing.operation_id | string or null | Partner keys only: the settled operation, for reconciliation; null when nothing was settled. Optional. |
billing.replayed | boolean | Partner keys only: true when the answer replays an earlier request, billed then. Optional. |
billing.price_version | string | Partner keys only: the version of the partner prices applied. Optional. |
Errors
400 invalid_request, 400 invalid_cursor, 401 unauthorized, 402 partner_key_cap_reached, 402 partner_tenant_cap_reached, 403 enterprise_required, 403 insufficient_scope, 403 forbidden, 404 not_found, 429 rate_limited, 429 partner_fair_use, 500 internal_error, 503 service_unavailable
Add creatives to a collection
POST/api/v1/collections/{id}/creatives
Adds creatives to the collection. A creative already in it keeps its note. Creatives the library does not hold are left out and listed in not_saved; when none is held, nothing is added (404). Needs the actions permission.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
id | path | string | The collection id. Required. |
Idempotency-Key | header | string | Required. A unique key per new request; the same key on retries. |
Request body
| Field | Type | Description |
|---|---|---|
creative_ids | string[] | 1 to 100 creative ids. |
Response 200
| Field | Type | Description |
|---|---|---|
collection_id | string | |
updated | boolean | |
not_saved | string[] | Creative ids the library does not hold, left out of the save. Optional. |
billing | object | What the request charged. Partner keys get it on every answer, free ones too. Optional. |
billing.credits_charged | integer | Credits this request charged: always 0 on Enterprise, which has no credit count. On a partner key, the credits the partner bills: each new item read, and reports and new collections at their price. -9007199254740991 to 9007199254740991 |
billing.usd_micros | integer | Partner keys only: what the partner bills, in micro-dollars. -9007199254740991 to 9007199254740991 Optional. |
billing.operation_id | string or null | Partner keys only: the settled operation, for reconciliation; null when nothing was settled. Optional. |
billing.replayed | boolean | Partner keys only: true when the answer replays an earlier request, billed then. Optional. |
billing.price_version | string | Partner keys only: the version of the partner prices applied. Optional. |
Errors
400 invalid_request, 400 idempotency_key_required, 401 unauthorized, 403 enterprise_required, 403 insufficient_scope, 403 forbidden, 404 not_found, 409 idempotency_conflict, 409 operation_in_progress, 413 payload_too_large, 415 unsupported_media_type, 429 rate_limited, 500 internal_error, 503 service_unavailable
Set a creative's note
PATCH/api/v1/collections/{id}/creatives/{creative_id}
Sets the note of a creative in the collection. Sending the same note again changes nothing. Needs the actions permission.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
id | path | string | The collection id. Required. |
creative_id | path | string | The creative id. Required. |
Request body
| Field | Type | Description |
|---|---|---|
note | string | The note; an empty string clears it. |
Response 200
| Field | Type | Description |
|---|---|---|
collection_id | string | |
creative_id | string | |
note | string | |
billing | object | What the request charged. Partner keys get it on every answer, free ones too. Optional. |
billing.credits_charged | integer | Credits this request charged: always 0 on Enterprise, which has no credit count. On a partner key, the credits the partner bills: each new item read, and reports and new collections at their price. -9007199254740991 to 9007199254740991 |
billing.usd_micros | integer | Partner keys only: what the partner bills, in micro-dollars. -9007199254740991 to 9007199254740991 Optional. |
billing.operation_id | string or null | Partner keys only: the settled operation, for reconciliation; null when nothing was settled. Optional. |
billing.replayed | boolean | Partner keys only: true when the answer replays an earlier request, billed then. Optional. |
billing.price_version | string | Partner keys only: the version of the partner prices applied. Optional. |
Errors
400 invalid_request, 401 unauthorized, 403 enterprise_required, 403 insufficient_scope, 403 forbidden, 404 not_found, 413 payload_too_large, 415 unsupported_media_type, 429 rate_limited, 500 internal_error, 503 service_unavailable
Exports
Create an export
POST/api/v1/exports
Exports up to 10,000 items as CSV, Excel, JSON, ZIP (with media), PDF, Markdown or HTML. The file is built in the background: follow the job with GET /v1/exports/{id}. Files are kept 7 days. Social exports take platform tiktok or youtube. Needs the export permission.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
Idempotency-Key | header | string | Required. A unique key per new request; the same key on retries. |
Request body
| Field | Type | Description |
|---|---|---|
source | object | |
format | object | csv: one table. xlsx: sheets with an About sheet. json: everything with a manifest. zip: CSV + JSON + media files. pdf: reports, X-Rays and comparisons. markdown and html: creatives only. |
include | object | Optional. |
include.analysis | boolean | Add analyses or AI tags. default false Optional. |
include.transcripts | boolean | Add creative transcripts. Optional. |
include.media | "none" | "thumbnails" | "originals" | zip only: thumbnails (default, up to 2,000 files) or originals (up to 200 files and 2 GB). Optional. |
Response 202
| Field | Type | Description |
|---|---|---|
job_id | string | |
state | "pending" | "running" | "partial" | "completed" | "failed" | |
title | string or null | A short name of what is exported, such as "120 ads of Northstar". |
source | object or null | What is exported: its kind (creatives, creative_ids, collection, social_posts, post_ad_pairs, social_comparison, brand_xray) and size. |
source.kind | string | |
format | string or null | |
completed_items | integer or null | |
requested_items | integer or null | |
missing_count | integer or null | |
bytes | integer or null | |
filename | string or null | |
created_at | string or null | |
expires_at | string or null | |
error_code | string or null | |
download_url | string or null | A link valid 5 minutes, when the file is ready. Read the job again for a new one. |
billing | object | What the request charged. Partner keys get it on every answer, free ones too. Optional. |
billing.credits_charged | integer | Credits this request charged: always 0 on Enterprise, which has no credit count. On a partner key, the credits the partner bills: each new item read, and reports and new collections at their price. -9007199254740991 to 9007199254740991 |
billing.usd_micros | integer | Partner keys only: what the partner bills, in micro-dollars. -9007199254740991 to 9007199254740991 Optional. |
billing.operation_id | string or null | Partner keys only: the settled operation, for reconciliation; null when nothing was settled. Optional. |
billing.replayed | boolean | Partner keys only: true when the answer replays an earlier request, billed then. Optional. |
billing.price_version | string | Partner keys only: the version of the partner prices applied. Optional. |
Errors
400 invalid_request, 400 idempotency_key_required, 401 unauthorized, 402 payment_required, 403 enterprise_required, 403 insufficient_scope, 403 forbidden, 403 not_offered_to_partner, 409 idempotency_conflict, 409 operation_in_progress, 413 payload_too_large, 415 unsupported_media_type, 422 instagram_not_in_api, 429 rate_limited, 500 internal_error, 503 service_unavailable
List exports
GET/api/v1/exports
The exports the key's user made in its workspace in the last 7 days, newest first, through the API or in Adspy. Exports of a source the API does not offer (Instagram among them) are left out, so a page can hold fewer than limit: follow has_more. Needs the export permission.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
state | query | "pending" | "running" | "completed" | "partial" | "failed" | |
limit | query | integer | Items per page, 1 to 50 (default 20). 1 to 50, default 20 |
cursor | query | string | The next_cursor of the previous page. Send it with the same filters; it is valid for 24 hours. |
Response 200
| Field | Type | Description |
|---|---|---|
data | object[] | |
data[].job_id | string | |
data[].state | "pending" | "running" | "partial" | "completed" | "failed" | |
data[].title | string or null | A short name of what is exported, such as "120 ads of Northstar". |
data[].source | object or null | What is exported: its kind (creatives, creative_ids, collection, social_posts, post_ad_pairs, social_comparison, brand_xray) and size. |
data[].format | string or null | |
data[].completed_items | integer or null | |
data[].requested_items | integer or null | |
data[].missing_count | integer or null | |
data[].bytes | integer or null | |
data[].filename | string or null | |
data[].created_at | string or null | |
data[].expires_at | string or null | |
data[].error_code | string or null | |
data[].download_url | string or null | A link valid 5 minutes, when the file is ready. Read the job again for a new one. |
has_more | boolean | |
next_cursor | string or null | Send it as cursor, with the same filters, for the next page. |
billing | object | What the request charged. Partner keys get it on every answer, free ones too. Optional. |
billing.credits_charged | integer | Credits this request charged: always 0 on Enterprise, which has no credit count. On a partner key, the credits the partner bills: each new item read, and reports and new collections at their price. -9007199254740991 to 9007199254740991 |
billing.usd_micros | integer | Partner keys only: what the partner bills, in micro-dollars. -9007199254740991 to 9007199254740991 Optional. |
billing.operation_id | string or null | Partner keys only: the settled operation, for reconciliation; null when nothing was settled. Optional. |
billing.replayed | boolean | Partner keys only: true when the answer replays an earlier request, billed then. Optional. |
billing.price_version | string | Partner keys only: the version of the partner prices applied. Optional. |
Errors
400 invalid_request, 400 invalid_cursor, 401 unauthorized, 403 enterprise_required, 403 insufficient_scope, 403 forbidden, 403 not_offered_to_partner, 429 rate_limited, 500 internal_error, 503 service_unavailable
Get an export
GET/api/v1/exports/{id}
An export job and, when the file is ready, a download link valid 5 minutes. An export of a source the API does not offer, made in Adspy, is not available here. Needs the export permission.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
id | path | string | The export job id. Required. |
Response 200
| Field | Type | Description |
|---|---|---|
job_id | string | |
state | "pending" | "running" | "partial" | "completed" | "failed" | |
title | string or null | A short name of what is exported, such as "120 ads of Northstar". |
source | object or null | What is exported: its kind (creatives, creative_ids, collection, social_posts, post_ad_pairs, social_comparison, brand_xray) and size. |
source.kind | string | |
format | string or null | |
completed_items | integer or null | |
requested_items | integer or null | |
missing_count | integer or null | |
bytes | integer or null | |
filename | string or null | |
created_at | string or null | |
expires_at | string or null | |
error_code | string or null | |
download_url | string or null | A link valid 5 minutes, when the file is ready. Read the job again for a new one. |
billing | object | What the request charged. Partner keys get it on every answer, free ones too. Optional. |
billing.credits_charged | integer | Credits this request charged: always 0 on Enterprise, which has no credit count. On a partner key, the credits the partner bills: each new item read, and reports and new collections at their price. -9007199254740991 to 9007199254740991 |
billing.usd_micros | integer | Partner keys only: what the partner bills, in micro-dollars. -9007199254740991 to 9007199254740991 Optional. |
billing.operation_id | string or null | Partner keys only: the settled operation, for reconciliation; null when nothing was settled. Optional. |
billing.replayed | boolean | Partner keys only: true when the answer replays an earlier request, billed then. Optional. |
billing.price_version | string | Partner keys only: the version of the partner prices applied. Optional. |
Errors
400 invalid_request, 401 unauthorized, 403 enterprise_required, 403 insufficient_scope, 403 forbidden, 403 not_offered_to_partner, 404 not_found, 422 instagram_not_in_api, 429 rate_limited, 500 internal_error, 503 service_unavailable
Usage
Get usage
GET/api/v1/usage
The organization's plan, the contract's limits, this month's new collections and the operations of the last 30 days. Enterprise has no credit count: its credit fields are null or 0. Needs the read permission.
Response 200
| Field | Type | Description |
|---|---|---|
plan | string or null | The organization's plan: Enterprise. |
unlimited | boolean | True on Enterprise: there is no credit count. |
credits | object | Its fields are null on Enterprise, which has no credit count. |
credits.available | number or null | |
credits.used_this_month | number or null | |
credits.renews_at | string or null | |
limits | object | |
limits.requests_per_minute | integer | Requests a minute for this key, set by the contract. -9007199254740991 to 9007199254740991 |
limits.fetches_per_month | integer | New brand or account collections a month for the organization, set by the contract. -9007199254740991 to 9007199254740991 |
limits.fetches_this_month | integer | New collections the organization started this month (UTC), from its API keys and its MCP connections: the count fetch_quota_exceeded checks. -9007199254740991 to 9007199254740991 |
spent | object | |
spent.days | integer | -9007199254740991 to 9007199254740991 |
spent.by_operation | object[] | |
billing | object | What the request charged. Partner keys get it on every answer, free ones too. Optional. |
billing.credits_charged | integer | Credits this request charged: always 0 on Enterprise, which has no credit count. On a partner key, the credits the partner bills: each new item read, and reports and new collections at their price. -9007199254740991 to 9007199254740991 |
billing.usd_micros | integer | Partner keys only: what the partner bills, in micro-dollars. -9007199254740991 to 9007199254740991 Optional. |
billing.operation_id | string or null | Partner keys only: the settled operation, for reconciliation; null when nothing was settled. Optional. |
billing.replayed | boolean | Partner keys only: true when the answer replays an earlier request, billed then. Optional. |
billing.price_version | string | Partner keys only: the version of the partner prices applied. Optional. |
Errors
400 invalid_request, 401 unauthorized, 403 enterprise_required, 403 insufficient_scope, 403 forbidden, 403 not_offered_to_partner, 429 rate_limited, 500 internal_error, 503 service_unavailable