Ads

TikTok Ads

Boost TikTok videos as Spark Ads, create video campaigns with pixel conversions, manage ad comments and run live TikTok reports.

A tiktokads connection runs TikTok's Business API: Spark Ads that promote organic videos, standalone video campaigns, website conversion campaigns on a TikTok pixel, customer list audiences, ad comment moderation and live reports with de-duplicated reach. Agencies get every advertiser under their Business Centers from one connection.

#Connect

Call GET /v1/connect/tiktok/ads with the profileId. TikTok Ads is a separate OAuth from TikTok posting, and TikTok grants its permissions at the app level, so there is no scope list to pick. You do not need your own TikTok developer onboarding.

Connect with What you get
accountId of a connected TikTok posting account The ads connection links to it. Spark Ads and standalone ads can run as the real @username.
No accountId (ads-only) Standalone ads run under a brand identity you configure. Spark Ads need the creator's Spark Code.

Set the ads-only brand identity once with PATCH /v1/connect/tiktok-ads, or per ad with brandIdentity: { displayName, imageUrl } on the create. GET /v1/ads/tiktok-identities lists the identities an advertiser can run ads as.

GET /v1/ads/accounts?accountId=... returns every advertiser the connection reaches, including all advertisers under the Business Centers the user owns. GET /v1/ads/business-centers lists the Business Centers themselves with an advertiser count each, for an agency picker. The advertiser list is cached for an hour.

#Create a video campaign

TikTok's ad creative is video. On POST /v1/ads/create, the video URL goes in imageUrl (the field keeps its name across networks), body is the caption, and headline is ignored because TikTok ads have no headline slot.

curl -X POST https://api.pozy.ai/v1/ads/create \
  -H "Authorization: Bearer $POZY_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: tt-summer-drop-1" \
  -d '{
    "accountId": "66b2e19d8c3f5a7e9d0b1c4f",
    "adAccountId": "7301234567890123456",
    "name": "Summer drop - US 18-34",
    "goal": "traffic",
    "budgetAmount": 50,
    "budgetType": "daily",
    "body": "The summer drop is live. Link in bio, or tap below.",
    "imageUrl": "https://cdn.example.com/summer-drop-9x16.mp4",
    "linkUrl": "https://shop.example.com/summer",
    "callToAction": "SHOP_NOW",
    "countries": ["US"],
    "ageMin": 18,
    "ageMax": 34
  }'

goal takes engagement, traffic, awareness, video_views, lead_generation, conversions or app_promotion. TikTok's minimum budget is $20 per ad group. smartPlus: true builds a Smart+ campaign; check each creative's review with GET /v1/ads/{adId}/tiktok-smart-plus-review and per-creative results with GET /v1/ads/tiktok-smart-plus-materials.

lead_generation sends the click to your own form on linkUrl. TikTok instant forms are not supported.

#Conversion campaigns

A website conversion campaign needs a TikTok pixel. Pass it in promotedObject, the same field Meta uses:

Conversion fields
{
  "goal": "conversions",
  "promotedObject": { "pixelId": "7212345678901234567", "customEventType": "ON_WEB_ORDER" }
}
Field Meaning
pixelId The numeric pixel id, not the alphanumeric pixel code shown in Events Manager. List your pixels on Pixels and tags to find it.
customEventType The event to optimize for, in TikTok's codes: ON_WEB_ORDER (complete payment), INITIATE_ORDER, ON_WEB_CART, ON_WEB_REGISTER, ON_WEB_DETAIL, FORM, ON_WEB_SEARCH, ON_WEB_ADD_TO_WISHLIST, LANDING_PAGE_VIEW. Optional for auto-bid.

If a conversion ad group already exists in TikTok Ads Manager, pass its id as adSetId instead: the new ad inherits the pixel and event.

#Spark Ads

A Spark Ad promotes a published TikTok video and keeps the creator's handle, likes and comments. Call POST /v1/ads/boost:

Boost a TikTok video
{
  "postId": "65f1c0a9e2b5af0012ab34cd",
  "accountId": "66b2e19d8c3f5a7e9d0b1c4f",
  "adAccountId": "7301234567890123456",
  "name": "Spark - summer drop",
  "goal": "traffic",
  "budget": { "amount": 30, "type": "daily" },
  "targeting": { "countries": ["US", "CA"] },
  "linkUrl": "https://shop.example.com/summer",
  "callToAction": "SHOP_NOW"
}
  • targeting.countries is required, unless you attach to an existing Smart+ ad group with adSetId.
  • linkUrl and callToAction add a clickable destination. Without them the Spark Ad has no destination beyond the video itself.
  • To promote another creator's video, ask them for a Spark Code from the TikTok app's promote settings. Send it as sparkAuthCode with their video id in platformPostId. Several creators at once go in sparkPosts[].
  • On an ads-only connection, sparkAuthCode and platformPostId are always required, because the connection has no TikTok identity of its own.

More boost options across networks are on Boost posts.

#Bidding

bidStrategy uses the shared names and maps to TikTok's bid types:

bidStrategy Needs TikTok bid type
LOWEST_COST_WITHOUT_CAP (default) No bid, maximum delivery
LOWEST_COST_WITH_BID_CAP bidAmount Custom bid
COST_CAP bidAmount Custom bid (cost cap)
LOWEST_COST_WITH_MIN_ROAS roasAverageFloor Minimum ROAS (value-optimized accounts only)

It works on create, boost and PUT /v1/ads/ad-sets/{adSetId}. Reads normalize TikTok's bid type back to these names.

#Media

Type Format Max size Notes
Video MP4, MOV, MPEG 500 MB 9:16 vertical, 720p or better, 5 to 60 seconds
Image JPEG, PNG 30 MB 1080 x 1920 for full screen

The video transfers in one request, so stay under 500 MB. URLs must be public.

#Manage running ads

Job Call
Pause or resume PUT /v1/ads/campaigns/{campaignId}/status, /ad-sets/{adSetId}/status or /{adId}/status with platform: "tiktok"
Add an ad to an ad group built in TikTok Ads Manager POST /v1/ads/create with adSetId (budget, targeting and goal are inherited)
Swap the creative PUT /v1/ads/{adId} with creative: body becomes the ad text, linkUrl the landing page, videoUrl uploads a new video
Change targeting PUT /v1/ads/{adId} with targeting
Duplicate a campaign POST /v1/ads/campaigns/{campaignId}/duplicate with platform: "tiktok". The copy is created paused and keeps Spark Ad links.
Change budget or bid PUT /v1/ads/ad-sets/{adSetId}

Creating an ad group on its own is not available on TikTok. Use the create or boost calls, or attach to an existing ad group.

#Ad comments

GET /v1/ads/{adId}/comments reads comments on a TikTok ad, Spark Ads and dark posts included. TikTok also supports moderation from the same endpoints:

  • POST /v1/ads/{adId}/comments/{commentId}/reply with text
  • POST /v1/ads/{adId}/comments/{commentId}/hide with hidden: true or false
  • DELETE /v1/ads/{adId}/comments/{commentId} for your own comments

TikTok only looks for comments inside a date range of 30 days or less; without one you get the past 30 days. Give the range as since and until in YYYY-MM-DD, and reuse it when you reply to or hide a comment close to either end. Every comment says what you may do with it through canReply, canDelete and canHide. Pages can come back empty with pagination.hasMore still true, so follow the cursor until it is not.

#Targeting

Countries, regions, cities, ZIP codes and metros (create only), age, gender, languages, interests, behaviors, income tier and customer list audiences. Behaviors such as video:1913101 (watched or engaged with videos in a category in the last 15 days) or creator:24001 (followed creators in a category) restrict delivery to the TikTok placement. PUT /v1/ads/{adId} with targeting updates the ad group; sending a location replaces both location and ZIP targeting. More on Targeting.

#Reporting

  • GET /v1/ads/{adId}/analytics returns spend, impressions, clicks, CTR, CPM and video metrics. breakdowns takes gender, age, country_code, platform, ac (network type) and language.
  • GET /v1/ads/tree adds those metrics up for each campaign and ad group.
  • GET /v1/ads/insights asks TikTok for a report on the spot. Send adAccountId, a dataLevel (AUCTION_ADVERTISER, AUCTION_CAMPAIGN, AUCTION_ADGROUP or AUCTION_AD), between 1 and 4 dimensions, the metrics, and dates spanning 365 days or less. reportType takes BASIC or AUDIENCE.

To count each person once across several campaigns, filter the set and group by country_code:

De-duplicated reach for two campaigns
curl -G https://api.pozy.ai/v1/ads/insights \
  -H "Authorization: Bearer $POZY_API_KEY" \
  --data-urlencode "accountId=66b2e19d8c3f5a7e9d0b1c4f" \
  --data-urlencode "adAccountId=7301234567890123456" \
  --data-urlencode "dataLevel=AUCTION_CAMPAIGN" \
  --data-urlencode "dimensions=country_code" \
  --data-urlencode "metrics=reach,impressions,spend" \
  --data-urlencode 'filtering=[{"field":"campaign_ids","operator":"IN","value":["1790000000000001","1790000000000002"]}]' \
  --data-urlencode "fromDate=2026-09-01" \
  --data-urlencode "toDate=2026-09-30"

Rows come back as TikTok returns them, with metric values as strings. A filter finer than dataLevel (such as ad_ids at campaign level) returns 400. Pozy imports the last 90 days of metrics when an account connects. Async report runs are Meta only.

#Limits and errors

Not available on TikTok: catalog and TikTok Shop ads, instant forms, chunked video upload, standalone ad group creation, and the Meta-only tools (previews, creative library, reach and frequency, studies, async reports).

Error Cause Fix
422 ads_connection_required The profile has no tiktokads account, or the TikTok user has not been authorized as an identity of the advertiser Connect TikTok Ads, or authorize that identity in TikTok Ads Manager.
40002: Please select a pixel A conversions goal with no promotedObject.pixelId Add the pixel's numeric id.
40002: pixel_id ... is not a valid integer string You sent the pixel code, not its number Send the numeric id of the pixel.
422 invalid_field_value on targeting.countries A boost without a country Send at least one country.
400 missing_required_field on sparkAuthCode An ads-only connection boosting without a Spark Code Send sparkAuthCode, or connect the TikTok account.
Budget rejected Below $20 per ad group Raise the budget.
Audience not applied A new customer list takes up to 48 hours to process Wait, then target it.

#Endpoints

Endpoint What it does
GET /v1/connect/{platform}/ads Connect ads for a platform
PATCH /v1/connect/tiktok-ads Set TikTok brand identity
GET /v1/ads/accounts List ad accounts
GET /v1/ads/business-centers List TikTok Business Centers
GET /v1/ads/tiktok-identities List TikTok ad identities
POST /v1/ads/create Create standalone ad
POST /v1/ads/boost Boost post as ad
GET /v1/ads/tree Get campaign tree
PUT /v1/ads/{adId} Update ad
PUT /v1/ads/{adId}/status Pause or resume a single ad
PUT /v1/ads/ad-sets/{adSetId} Update an ad set
PUT /v1/ads/campaigns/{campaignId}/status Pause or resume a campaign
POST /v1/ads/campaigns/{campaignId}/duplicate Duplicate a campaign
GET /v1/ads/{adId}/comments List comments on an ad
POST /v1/ads/{adId}/comments/{commentId}/reply Reply to an ad comment
POST /v1/ads/{adId}/comments/{commentId}/hide Hide or unhide an ad comment
DELETE /v1/ads/{adId}/comments/{commentId} Delete an ad comment
GET /v1/ads/{adId}/tiktok-smart-plus-review Review status of each creative in a TikTok Smart+ ad
GET /v1/ads/tiktok-smart-plus-reviews Review status of every TikTok Smart+ ad of an advertiser
GET /v1/ads/tiktok-smart-plus-materials Per-creative performance inside TikTok Smart+ ads
GET /v1/ads/pixels List TikTok ad pixels
GET /v1/ads/{adId}/analytics Get ad analytics
GET /v1/ads/insights Flexible live insights query