Create Ads
Boost a TikTok video as a Spark Ad, create a standalone or website conversion campaign, boost another creator with a Spark Code, and set the bid strategy.
Spark Ads (boost)
Call POST /v1/ads/boost with postId, accountId, adAccountId, goal and budget. Spark Ads keep the creator's identity, organic engagement signals and follower handle.
import Zernio from '@zernio/node';
const zernio = new Zernio();
const { data: boosted } = await zernio.adcampaigns.boostPost({
body: {
postId: '65f1c0a9e2b5af0012ab34cd',
accountId: '66b2e19d8c3f5a7e9d0b1c2d',
adAccountId: '7123456789012345678',
name: 'Boost viral video',
goal: 'traffic',
budget: { amount: 50, type: 'daily' },
schedule: { startDate: '2027-01-04T09:00:00Z', endDate: '2027-01-11T23:59:00Z' },
targeting: { countries: ['US'] },
linkUrl: 'https://example.com/landing',
callToAction: 'SHOP_NOW',
bidStrategy: 'COST_CAP',
bidAmount: 0.5
}
});
console.log(boosted.ad._id);Response (201):
{
"ad": {
"_id": "66f0a1b2c3d4e5f6a7b8c9d0",
"name": "Boost viral video",
"platform": "tiktok",
"status": "pending_review",
"adType": "boost",
"goal": "traffic",
"budget": { "amount": 50, "type": "daily" },
"bidStrategy": "COST_CAP",
"bidAmount": 0.5,
"platformAdId": "1802345678901234567",
"platformCampaignId": "1802345678901234001",
"platformAdSetId": "1802345678901234002"
},
"message": "Ad created"
}linkUrl and callToAction are the Spark Ad creative overrides. They map to landing_page_url and call_to_action on TikTok's /v2/ad/create/.
Pass them for traffic and conversion goals. Without linkUrl, the Spark Ad has no clickable destination distinct from the organic video.
targeting.countries is required on TikTok boosts (the ad group needs location_ids).
bidStrategy and bidAmount are optional Cost Cap bidding (Bid strategy).
Every sample on this page reuses the zernio and client constructors from this one.
Standalone campaign
Call POST /v1/ads/create. TikTok's ads endpoint is video-only, so:
- the video URL goes in
imageUrl(the field keeps its name for cross-platform consistency) bodyis the video captionheadlineis ignored, because TikTok creatives have no headline slot
Valid goal values are engagement, traffic, awareness, video_views, lead_generation, conversions and app_promotion.
const { data: created } = await zernio.adcampaigns.createStandaloneAd({
body: {
accountId: '66b2e19d8c3f5a7e9d0b1c2d',
adAccountId: '7123456789012345678',
name: 'Spring launch',
goal: 'traffic',
budgetAmount: 100,
budgetType: 'daily',
body: 'Spring drop is live',
linkUrl: 'https://example.com/spring',
imageUrl: 'https://cdn.example.com/launch.mp4',
callToAction: 'SHOP_NOW',
countries: ['US'],
ageMin: 18,
ageMax: 34
}
});
console.log(created.ad.platformAdSetId);Response (201), same shape as the boost with "adType": "standalone":
{
"ad": {
"_id": "66f0a1b2c3d4e5f6a7b8c9d1",
"name": "Spring launch",
"platform": "tiktok",
"status": "pending_review",
"adType": "standalone",
"goal": "traffic",
"platformAdId": "1802345678901234568",
"platformCampaignId": "1802345678901234003",
"platformAdSetId": "1802345678901234004"
},
"message": "Ad created"
}platformAdSetId is the new TikTok ad group.
Conversion campaigns
A website-conversion campaign needs a TikTok Pixel. Zernio maps goal: "conversions" to a CONVERSIONS objective with a WEBSITE / CONVERT ad group.
Without a pixel, TikTok rejects the ad group with 40002: Please select a pixel.
Pass the pixel through promotedObject, the same cross-platform field Meta uses:
promotedObject field | Maps to TikTok | Required |
|---|---|---|
pixelId | ad group pixel_id (numeric) | Yes |
customEventType | ad group optimization_event (the pixel event to optimise for) | No (auto-bid CONVERT works without it) |
customEventType takes a TikTok optimization_event code, or the exact event name shown in TikTok Events Manager.
Codes are TikTok's own UPPER_SNAKE codes, not Meta's PURCHASE or LEAD vocabulary and not PascalCase.
The value must be one of the events your pixel is configured to track. Common website codes:
| Code | Pixel event |
|---|---|
ON_WEB_ORDER | Complete Payment |
INITIATE_ORDER | Place an Order |
ON_WEB_CART | Add to Cart |
ON_WEB_REGISTER | Complete Registration |
ON_WEB_DETAIL | View Content |
FORM | Submit Form |
ON_WEB_SEARCH | Search |
ON_WEB_ADD_TO_WISHLIST | Add to Wishlist |
LANDING_PAGE_VIEW | Landing Page View |
pixelId must be the numeric TikTok Pixel id, not the alphanumeric Pixel Code shown in Events Manager (for example D00IKHRC77UE0J0RTNHG). TikTok's ad-group API rejects the code with 40002: pixel_id ... is not a valid integer string.
The numeric id is the pixel_id that TikTok's GET /pixel/list/ returns.
If Ads Manager only shows the alphanumeric code for your pixel, list your pixels. Each tag's id is the numeric id, and siteTagId is the code.
Find the pixel and the events it tracks in TikTok Ads Manager under Assets, then Events.
The request is the standalone create plus promotedObject:
{
"accountId": "66b2e19d8c3f5a7e9d0b1c2d",
"adAccountId": "7123456789012345678",
"name": "Spring launch, purchases",
"goal": "conversions",
"budgetAmount": 100,
"budgetType": "daily",
"body": "Spring drop is live",
"linkUrl": "https://example.com/spring",
"imageUrl": "https://cdn.example.com/launch.mp4",
"callToAction": "SHOP_NOW",
"countries": ["US"],
"ageMin": 18,
"ageMax": 34,
"promotedObject": { "pixelId": "7987654321098765432", "customEventType": "ON_WEB_ORDER" }
}Existing conversion ad group. If one exists in TikTok Ads Manager with the pixel and event configured, pass its id as adSetId on POST /v1/ads/create instead.
The new creative inherits the pixel and optimization_event from the parent ad group, so promotedObject is not needed (Attach to an existing ad group).
Spark Code for cross-creator boosts
To boost a creator's organic video from a different TikTok account than the one running the ads, you need a Spark Code.
The creator generates it in their TikTok app's Promote settings and shares it with the advertiser.
Pass it as sparkAuthCode on POST /v1/ads/boost, with the creator's video as platformPostId:
{
"platformPostId": "7310234567890123456",
"accountId": "66b2e19d8c3f5a7e9d0b1c2d",
"adAccountId": "7123456789012345678",
"name": "Cross-creator boost",
"goal": "traffic",
"budget": { "amount": 50, "type": "daily" },
"targeting": { "countries": ["US"] },
"linkUrl": "https://example.com",
"callToAction": "SHOP_NOW",
"sparkAuthCode": "BCAQAAAA..."
}Without sparkAuthCode, boosts are limited to videos owned by the same TikTok account that runs the ads.
The value maps to auth_code on TikTok's AdcreateCreatives.
Bid strategy
Pass bidStrategy (the cross-platform Meta enum) on POST /v1/ads/boost, POST /v1/ads/create or PUT /v1/ads/ad-sets/{adSetId}.
Zernio maps it to TikTok's bid_type, bid_price and deep_bid_type:
bidStrategy | Maps to TikTok | Required field |
|---|---|---|
LOWEST_COST_WITHOUT_CAP (default) | bid_type: BID_TYPE_NO_BID | none |
LOWEST_COST_WITH_BID_CAP | bid_type: BID_TYPE_CUSTOM plus bid_price | bidAmount |
COST_CAP | bid_type: BID_TYPE_CUSTOM plus bid_price | bidAmount |
LOWEST_COST_WITH_MIN_ROAS | bid_type: BID_TYPE_NO_BID plus deep_bid_type: MIN_ROAS | roasAverageFloor (the account must be value-optimization-enabled) |
bidAmount is in whole currency units of the ad account (USD: 5 is $5.00).
On reads (GET /v1/ads/tree, GET /v1/ads/campaigns), TikTok's native bid_type is normalized back to the same enum. Cross-platform consumers see one shape regardless of source platform.
Media requirements
| 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 |
Videos are fetched from the URL you pass. The media uploads guide covers hosting them on Zernio.