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.json

Request body

FieldTypeRequiredDescription
adPlatformstringyes"meta" or "tiktok".
brandIdintegernoBrand to create under. Defaults to your API key's default brand.
campaignInputobjectyesThe campaign definition — see below.

campaignInput

FieldTypeRequiredDescription
namestringnoHuman-friendly campaign name.
startDatestringyesISO-8601 datetime the campaign should start.
endDatestringyesISO-8601 datetime the campaign should end.
budgetnumberyesTotal lifetime budget (positive), in currency.
currencystringyesISO currency code, e.g. "USD".
promotedLinkstringyesThe URL being promoted (must be a valid URL).
captionsstring[]noAd caption/copy variants.
callToActionstringyesLEARN_MORE, LISTEN_NOW, or VIEW_NOW.
targetingConfigobjectyesAudience targeting — see below.
conversionConfigobjectno{ "pixelId": string, "conversionEvent": string } — see Conversions API.

targetingConfig

FieldTypeDescription
geographiesGeographyTargeting[]{ id, type, name, percentage } (percentage 0–100).
audiencesAudience[]{ id, type, name } — interest/hashtag audiences.
languagesLocale[]{ id, name }.
gendersstring[]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 minAge and maxAge inside targetingConfig
    (integers 13–65, with minAge <= 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 polling GET /sym/v2/campaigns/:campaignId or 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.


Did this page help you?