ad_groups[] (each with its ads[]) in one request, and Thrad creates the whole tree, charges a deposit, and submits it for review.
All paths on this page are relative to the base URL https://api.thrad.ai/v1. Every request must send Authorization: Bearer ak_... — see Authentication.
Money on campaign resources is expressed in integer micros, where
$1 = 1,000,000. So budget.lifetime_spend_limit_micros: 5000000 is $5.00. This is different from the Insights API, which returns dollar floats. State the unit you mean — micros here, dollars there.The campaign object
Unique campaign identifier (UUID).
Campaign name (3–100 characters).
Free-text description, or
null if none was set.Read-only moderation state:
in_review | approved | rejected. A freshly created campaign is in_review. See Review status.Campaign start, as a Unix timestamp in seconds. Always present — if you omit
start_time on create, Thrad sets it to roughly two days in the future (the earliest allowed launch window), so a read response is never null here.Campaign end, as a Unix timestamp in seconds.
null means open-ended — the campaign spends until the budget is exhausted.Spend cadence:
daily | weekly | monthly | quarterly | yearly.Bidding basis:
cpm (cost per thousand impressions) or cpc (cost per click).Creation time, as a Unix timestamp in seconds.
Last-modified time, as a Unix timestamp in seconds.
Review status
Every campaign created through this API is submitted to Thrad for human review. The two status fields are independent:statusis the lifecycle state you control:active|paused|archived.review_statusis the moderation verdict you do not control:in_review|approved|rejected.
status: "paused", review_status: "in_review". It cannot serve or be activated until Thrad approves it. Once approved, review_status becomes approved and you can activate it. If it is rejected, review_status becomes rejected.
Approval (the
in_review → approved transition) is performed by Thrad, not through this API. Until a campaign is approved, /activate returns 400 campaign_not_approved.List campaigns
Returns a paginated list of campaigns for your organization, newest first by default.Restrict the list to a single ad account (UUID). Omit to list across all ad accounts in your organization.
Number of campaigns to return,
1–500.Sort direction by creation time:
asc or desc.Cursor for the previous page — pass a prior response’s
first_id. Mutually exclusive with after.Cursor for the next page — pass a prior response’s
last_id. Mutually exclusive with before.Create a campaign
Creates a campaign together with its ad groups and ads in a single nested request, then submits the campaign for review.Validate billing
Your organization must have a default card on file. If it does not, the request fails with
400 billing_not_configured and nothing is created.Create the tree
The campaign, its
ad_groups[], and each ad group’s ads[] are created together. Each ad’s creative image becomes a stored asset.Charge the deposit
A $10 deposit is charged off-session on your default card. A card decline returns
402 card_declined and the campaign is removed (no lingering draft); a provider outage returns 502 payment_provider_error.A client-generated key (e.g. a UUID) that makes retries safe. The same key replays the first response indefinitely (there is no expiry window), so a retried create never charges twice. Reusing the same key with a different body returns
409 idempotency_key_reused.Campaign name, 3–100 characters.
One or more ad groups, each with at least one ad. All ads within a single ad group must share one creative type (all
chat_card or all poll).Free-text description.
Campaign start, as a Unix timestamp in seconds. Omit to default to roughly two days in the future (the earliest allowed launch window) — the response then comes back with that computed timestamp, never
null.Campaign end, as a Unix timestamp in seconds. Omit for an open-ended campaign that spends until the budget is exhausted.
Spend cadence:
daily | weekly | monthly | quarterly | yearly.Bidding basis:
cpm or cpc.The ad account to create the campaign under (UUID). Defaults to your organization’s default ad account.
Retrieve a campaign
Fetches a single campaign by ID.The campaign UUID. An unknown or cross-organization ID returns
404.Update a campaign
Updates the mutable fields of a campaign. Only the fields you send are changed.name, description, budget, targeting, start_time, and end_time. Numeric values are re-validated exactly as on create: budget.lifetime_spend_limit_micros must still be >= 990000, and any start_time / end_time must be an integer Unix timestamp. An out-of-range or non-integer value returns 400 invalid_value.
The campaign UUID.
New campaign name, 3–100 characters.
New description.
New geo targeting. Same shape as on create —
locations.include[] with country_code per entry.New start, as a Unix timestamp in seconds.
New end, as a Unix timestamp in seconds.
Activate a campaign
Resumes a previously paused campaign. The campaign must already be approved.- If the campaign is paused and approved, it transitions to
active. - If the campaign is already running, this is a no-op and returns
200with the unchanged campaign. - If the campaign is not yet approved (still
in_review, or rejected), it returns400 campaign_not_approved.
The campaign UUID.
Pause a campaign
Pauses a running campaign so it stops serving.active) campaign can be paused. Any other state returns 400 campaign_not_running.
The campaign UUID.
Archive a campaign
Ends a campaign permanently. An archived campaign cannot be reactivated.400 cannot_archive. Archiving sets status to archived.
The campaign UUID.
Error codes
| HTTP | code | When |
|---|---|---|
400 | required | A required field (name, budget.lifetime_spend_limit_micros, ad_groups, an ad group’s ads) is missing. |
400 | invalid_value | A field is the wrong type or out of range — e.g. budget below 990000, max_bid_micros outside 1–100000000, a non-integer timestamp, or mixed creative types in one ad group. |
400 | use_status_action | status was sent in an update body. Use /activate, /pause, or /archive. |
400 | billing_not_configured | The organization has no default card; set one up before creating a campaign. |
400 | campaign_not_approved | /activate was called on a campaign that is not approved and paused. |
400 | campaign_not_running | /pause was called on a campaign that is not running. |
400 | cannot_archive | /archive was called on a campaign that is not running or paused. |
400 | no_ad_account | No ad_account_id was supplied and the organization has zero ad accounts. A supplied-but-unknown ad_account_id returns 404 not_found instead. |
401 | auth_required | The Authorization header is missing entirely. |
401 | invalid_api_key | The key is malformed, unknown, or revoked. |
402 | card_declined | The $10 deposit charge was declined. Nothing is created. |
404 | not_found | The campaign_id is unknown or belongs to another organization. |
409 | idempotency_key_reused | The same Idempotency-Key was reused with a different request body. |
409 | name_conflict | A campaign with that name already exists. |
429 | rate_limit_exceeded | The 1000/hour key limit (or the 60/hour create limit) was exceeded. |
502 | payment_provider_error | The payment provider was unavailable. Nothing is created; retry later. |
