Create Campaigns
Create and submit an ad campaign to Meta (Facebook & Instagram) or TikTok with a single call. You send one unified campaignInput; Symphony translates it into the platform-specific campaign behind the scenes.
Endpoint: POST https://api.symphonyos.co/api/sym/v2/campaigns
curl -X POST https://api.symphonyos.co/api/sym/v2/campaigns \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d @campaign.jsonRequest body
| Field | Type | Required | Description |
|---|---|---|---|
adPlatform | string | yes | "meta" or "tiktok". |
brandId | integer | no | Brand to create under. Defaults to your API key's default brand. |
campaignInput | object | yes | The campaign definition — see below. |
campaignInput
campaignInput| Field | Type | Required | Description |
|---|---|---|---|
name | string | no | Human-friendly campaign name. |
startDate | string | yes | ISO-8601 datetime the campaign should start. |
endDate | string | yes | ISO-8601 datetime the campaign should end. |
budget | number | yes | Total lifetime budget (positive), in currency. |
currency | string | yes | ISO currency code, e.g. "USD". |
promotedLink | string | yes | The URL being promoted (must be a valid URL). |
captions | string[] | no | Ad caption/copy variants. |
callToAction | string | yes | LEARN_MORE, LISTEN_NOW, or VIEW_NOW. |
targetingConfig | object | yes | Audience targeting — see below. |
conversionConfig | object | no | { "pixelId": string, "conversionEvent": string } — see Conversions API. |
targetingConfig
targetingConfig| Field | Type | Description |
|---|---|---|
geographies | GeographyTargeting[] | { id, type, name, percentage } (percentage 0–100). |
audiences | Audience[] | { id, type, name } — interest/hashtag audiences. |
languages | Locale[] | { id, name }. |
genders | string[] | Any of "MALE", "FEMALE". |
Populate the id/type/name values from the targeting search endpoints
(/geography-search, /interest-search, /language-search) — see the
Integration Guide.
Meta vs. TikTok
The campaignInput schema is shared, with two platform differences:
- Meta additionally requires
minAgeandmaxAgeinsidetargetingConfig
(integers 13–65, withminAge <= maxAge). - TikTok ignores the inbound
callToAction— the CTA is derived server-side
from the campaign type. All other fields behave identically.
Example — Meta
{
"adPlatform": "meta",
"brandId": 12345,
"campaignInput": {
"name": "Summer Single Launch",
"startDate": "2026-08-01T00:00:00.000Z",
"endDate": "2026-08-14T00:00:00.000Z",
"budget": 500,
"currency": "USD",
"promotedLink": "https://open.spotify.com/track/xxxx",
"captions": ["Out now 🎧", "Stream the new single"],
"callToAction": "LISTEN_NOW",
"targetingConfig": {
"geographies": [
{ "id": "US", "type": "country", "name": "United States", "percentage": 100 }
],
"audiences": [
{ "id": "6003139266461", "type": "InterestAudience", "name": "Hip hop music" }
],
"languages": [{ "id": "6", "name": "English" }],
"genders": ["MALE", "FEMALE"],
"minAge": 18,
"maxAge": 45
}
}
}Example — TikTok
{
"adPlatform": "tiktok",
"brandId": 12345,
"campaignInput": {
"name": "Summer Single Launch (TikTok)",
"startDate": "2026-08-01T00:00:00.000Z",
"endDate": "2026-08-14T00:00:00.000Z",
"budget": 300,
"currency": "USD",
"promotedLink": "https://vm.tiktok.com/xxxx",
"captions": ["New single out now"],
"callToAction": "LISTEN_NOW",
"targetingConfig": {
"geographies": [
{ "id": "US", "type": "country", "name": "United States", "percentage": 100 }
],
"audiences": [
{ "id": "12345678", "type": "HashtagAudience", "name": "#newmusic" }
],
"languages": [{ "id": "en", "name": "English" }],
"genders": ["MALE", "FEMALE"]
}
}
}Response
{
"success": true,
"data": {
"id": 98765,
"name": "Summer Single Launch",
"platform": "meta",
"status": "SUBMITTED",
"startDate": "2026-08-01T00:00:00.000Z",
"endDate": "2026-08-14T00:00:00.000Z",
"budget": 500
}
}Campaign creation is asynchronous. The API returns immediately with the
campaign record, but submission to Meta/TikTok happens in the background. Track
progress by pollingGET /sym/v2/campaigns/:campaignIdor by registering a
webhook.
Possible status values: DRAFT, PUBLISHED, SUBMITTED, ACTIVE,
STOPPED, FINALIZING, PAUSED, AWAITING_PAYMENT, ERROR, IN_REVIEW,
WITH_ISSUES, DENIED, TO_RETRY, FINISHED, SCHEDULED.
Managing a campaign
Update budget, end date, or pause state with PUT /sym/v2/campaigns/:campaignId:
curl -X PUT https://api.symphonyos.co/api/sym/v2/campaigns/98765 \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "budget": 750, "paused": false }'Any subset of budget, endDate, and paused may be supplied. Each applied
change fires a campaign.updated webhook event.
Updated about 1 month ago
