Ad groups live under a campaign. Each ad group carries the context hints that steer where its ads serve and the max bid the auction may pay, and it holds one or more ads that all share a single creative type.
You can create ad groups inline when you create a campaign (see Campaigns ), or add them to an existing campaign with the endpoints below.
All paths are relative to the base URL https://api.thrad.ai/v1. Authenticate every request with Authorization: Bearer ak_.... See Authentication for how to create your key.
The ad group object
Unique identifier for the ad group (a UUID).
The parent campaign’s id.
Display name for the ad group.
The hints that tell Thrad which conversations this ad group’s ads are relevant to. Returned as an array of strings.
One of active, paused, or archived. Ad groups have no distinct archived state on Thrad, so an archived ad group reads back as paused. Change status with the dedicated /activate, /pause, and /archive actions, or by sending status in an update body.
Bidding settings for the ad group. Show bidding_config properties
The event you are billed on. Always impression.
The maximum bid in micros , where $1 = 1,000,000. For example, 700000 is $0.70. null when no max bid is set.
Unix timestamp (seconds) when the ad group was created.
Unix timestamp (seconds) when the ad group was last updated.
{
"id" : "9a1f2c3d-4e5f-6789-abcd-ef0123456789" ,
"campaign_id" : "1b2c3d4e-5f60-7182-93a4-b5c6d7e8f901" ,
"name" : "Runners — focus playlists" ,
"context_hints" : [
"marathon training" ,
"running shoes" ,
"endurance"
],
"status" : "active" ,
"bidding_config" : {
"billing_event_type" : "impression" ,
"max_bid_micros" : 700000
},
"created_at" : 1775088000 ,
"updated_at" : 1775174400
}
List ad groups
GET /v1/ad_groups
Returns the ad groups for one campaign, most recent first. campaign_id is required — listing across all campaigns is not supported.
The campaign whose ad groups to list.
Number of ad groups 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.
curl "https://api.thrad.ai/v1/ad_groups?campaign_id=1b2c3d4e-5f60-7182-93a4-b5c6d7e8f901&limit=20" \
-H "Authorization: Bearer $THRAD_ADS_API_KEY "
{
"object" : "list" ,
"data" : [
{
"id" : "9a1f2c3d-4e5f-6789-abcd-ef0123456789" ,
"campaign_id" : "1b2c3d4e-5f60-7182-93a4-b5c6d7e8f901" ,
"name" : "Runners — focus playlists" ,
"context_hints" : [ "marathon training" , "running shoes" ],
"status" : "active" ,
"bidding_config" : {
"billing_event_type" : "impression" ,
"max_bid_micros" : 700000
},
"created_at" : 1775088000 ,
"updated_at" : 1775174400
}
],
"count" : 1 ,
"first_id" : "9a1f2c3d-4e5f-6789-abcd-ef0123456789" ,
"last_id" : "9a1f2c3d-4e5f-6789-abcd-ef0123456789" ,
"has_more" : false
}
Create an ad group
POST /v1/ad_groups
Adds an ad group to an existing campaign. The ad group must include at least one ad, and all ads in the ad group must share one creative type (all chat_card, or all poll).
The campaign to add this ad group to.
Display name for the ad group. Max 255 characters.
Hints that steer where the ad group’s ads serve. Each array entry is one hint. Must be a non-empty array.
Bidding settings for the ad group. Show bidding_config properties
Maximum bid in micros ($1 = 1,000,000). Must be between 1 and 100000000 (0.000001 – 0.000001– 0.000001– 100). Omit to leave unset.
The ads in this ad group. At least one is required, and all ads must share one creative type. Display name for the ad. Falls back to the creative’s title when omitted.
When true, Thrad generates a chat_card title and body for you, so creative.title and creative.body become optional. Not available for polls.
The ad creative. See Ads for the full creative schema. chat_card (a standard card ad) or poll (a Thrad-only format). AI-generated polls are not allowed.
For chat_card: the headline (max 30 characters; optional when auto_generate is true). For poll: the poll question (required, max 120 characters).
chat_card only. The card description.
chat_card only. Call-to-action text.
chat_card only. A file_id from POST /v1/upload to use as the card image.
chat_card only. A public image URL to fetch and store as the card image.
poll only. The 2–4 answer options.
poll only. The advertiser URL the poll links to. Required for polls.
curl -X POST "https://api.thrad.ai/v1/ad_groups" \
-H "Authorization: Bearer $THRAD_ADS_API_KEY " \
-H "Content-Type: application/json" \
-d '{
"campaign_id": "1b2c3d4e-5f60-7182-93a4-b5c6d7e8f901",
"name": "Runners — focus playlists",
"context_hints": ["marathon training", "running shoes"],
"bidding_config": { "max_bid_micros": 700000 },
"ads": [
{
"name": "Marathon shoes card",
"creative": {
"type": "chat_card",
"title": "Premium Running Shoes",
"body": "Lightweight and built for marathon training.",
"cta": "Shop Now",
"image_url": "https://cdn.example.com/nike-shoes.jpg"
}
}
]
}'
{
"id" : "9a1f2c3d-4e5f-6789-abcd-ef0123456789" ,
"campaign_id" : "1b2c3d4e-5f60-7182-93a4-b5c6d7e8f901" ,
"name" : "Runners — focus playlists" ,
"context_hints" : [ "marathon training" , "running shoes" ],
"status" : "active" ,
"bidding_config" : {
"billing_event_type" : "impression" ,
"max_bid_micros" : 700000
},
"created_at" : 1775088000 ,
"updated_at" : 1775088000
}
Retrieve an ad group
GET /v1/ad_groups/{id}
curl "https://api.thrad.ai/v1/ad_groups/9a1f2c3d-4e5f-6789-abcd-ef0123456789" \
-H "Authorization: Bearer $THRAD_ADS_API_KEY "
{
"id" : "9a1f2c3d-4e5f-6789-abcd-ef0123456789" ,
"campaign_id" : "1b2c3d4e-5f60-7182-93a4-b5c6d7e8f901" ,
"name" : "Runners — focus playlists" ,
"context_hints" : [ "marathon training" , "running shoes" ],
"status" : "active" ,
"bidding_config" : {
"billing_event_type" : "impression" ,
"max_bid_micros" : 700000
},
"created_at" : 1775088000 ,
"updated_at" : 1775174400
}
Update an ad group
POST /v1/ad_groups/{id}
Patch the mutable fields. Only the fields you send are changed.
Replacement set of context hints.
Bidding settings. Send max_bid_micros to change the max bid. Show bidding_config properties
New maximum bid in micros ($1 = 1,000,000). Re-validated to 1–100000000 on update.
Optionally set active, paused, or archived directly. archived deactivates the ad group, so it reads back as paused. You can also use the dedicated /activate, /pause, and /archive actions below.
curl -X POST "https://api.thrad.ai/v1/ad_groups/9a1f2c3d-4e5f-6789-abcd-ef0123456789" \
-H "Authorization: Bearer $THRAD_ADS_API_KEY " \
-H "Content-Type: application/json" \
-d '{
"name": "Runners — focus playlists (v2)",
"bidding_config": { "max_bid_micros": 850000 }
}'
{
"id" : "9a1f2c3d-4e5f-6789-abcd-ef0123456789" ,
"campaign_id" : "1b2c3d4e-5f60-7182-93a4-b5c6d7e8f901" ,
"name" : "Runners — focus playlists (v2)" ,
"context_hints" : [ "marathon training" , "running shoes" ],
"status" : "active" ,
"bidding_config" : {
"billing_event_type" : "impression" ,
"max_bid_micros" : 850000
},
"created_at" : 1775088000 ,
"updated_at" : 1775260800
}
Activate, pause, or archive an ad group
POST /v1/ad_groups/{id}/activate
POST /v1/ad_groups/{id}/pause
POST /v1/ad_groups/{id}/archive
These are the recommended way to change an ad group’s status. Each returns the updated ad group object.
Status actions require the parent campaign to be approved . If the parent campaign is still pending approval, the action returns 400 campaign_pending_status_locked; if it has been completed or blocked, it returns 400 campaign_terminal.
Thrad ad groups have no separate archived state, so /archive deactivates the ad group and it reads back with status: "paused" — the same result as a PATCH with status: "archived". Use /activate to bring it back.
curl -X POST "https://api.thrad.ai/v1/ad_groups/9a1f2c3d-4e5f-6789-abcd-ef0123456789/pause" \
-H "Authorization: Bearer $THRAD_ADS_API_KEY "
{
"id" : "9a1f2c3d-4e5f-6789-abcd-ef0123456789" ,
"campaign_id" : "1b2c3d4e-5f60-7182-93a4-b5c6d7e8f901" ,
"name" : "Runners — focus playlists" ,
"context_hints" : [ "marathon training" , "running shoes" ],
"status" : "paused" ,
"bidding_config" : {
"billing_event_type" : "impression" ,
"max_bid_micros" : 700000
},
"created_at" : 1775088000 ,
"updated_at" : 1775347200
}
Errors
Errors use the bare error shape:
{
"error" : {
"message" : "`bidding_config.max_bid_micros` exceeds the allowed maximum." ,
"type" : "invalid_request_error" ,
"param" : "bidding_config.max_bid_micros" ,
"code" : "invalid_value"
}
}
Status codeWhen 400requiredcampaign_id, name, context_hints, ads, or another required field is missing or empty400invalid_valuemax_bid_micros is non-integer or outside 1–100000000, the ads do not share one creative type, or a creative is missing or not an object400string_too_longA creative title exceeds its limit (30 for cards, 120 for polls) 400poll_cannot_be_aiA poll ad was sent with auto_generate: true 400campaign_pending_status_lockedA status action was attempted while the parent campaign is still pending approval 400campaign_terminalA status action was attempted while the parent campaign is completed or blocked 401auth_requiredThe Authorization header is missing 401invalid_api_keyThe Authorization header is malformed, unknown, or revoked 404not_foundThe ad group or its campaign does not exist or belongs to another organization 429rate_limit_exceededPer-key rate limit (1000/hour) exceeded