Video campaign management


๐Ÿ“

Video campaigns (aka brand video) require a special Taboola account.

Overview

The video-campaigns API allows you to manage video advertising campaigns (aka brand video) on the Taboola platform. This documentation focuses on managed campaigns.

Authentication

All API requests require authentication using OAuth 2.0 client credentials. See Client Credentials Flow for detailed authentication instructions.

Business Models

Video campaigns support 3 business models:

Model

Description

CPM

Cost Per Mille (1,000 Impressions) The amount you pay per one thousand impressions of your campaign items.

VCPM

Viewable Cost Per Mille (1,000 Viewable Impressions) Calculated by dividing the amount spent by the number of viewable impressions multiplied by 1,000.

CPCV

Cost Per Completed View Your campaign will be optimized to achieve a CPCV of X. This metric is based on Realize Completion.

Endpoints and examples

List video campaigns

Retrieve all video campaigns for a given account.

๐Ÿ“˜

Guidelines

  1. The base endpoint retrieves basic campaign details only.
  2. To return all video campaigns across your network, pass your network account.
  3. You can apply optional filters and params, including paging.
๐Ÿšง

Take note

  1. The base endpoint uses different field names to the other endpoints.
  2. The base endpoint uses the general video-campaigns path, not the video-campaigns/managed path

Basic example

GET /backstage/api/1.0/{account_id}/video-campaigns/base
Authorization: Bearer {access_token}
Content-Type: application/json
{
  "results": [
    {
      "id": 12345678,
      "advertiser_id": 987654,
      "advertiser_name": "acme-advertising",
      "advertiser_description": "ACME Advertising",
      "name": "Summer Video Campaign 2024",
      "branding_text": "",
      "policy_state": null,
      "status": "RUNNING",
      "create_time": 1721529600000,
      "total_spent": 125.50,
      "type": "PAID",
      "marketing_objective": null,
      "campaign_groups": null,
      "bid_strategy": null,
      "is_creative_library_campaign": null,
      "business_model": "CPM"
    },
    {
      "id": 87654321,
      "advertiser_id": 987654,
      "advertiser_name": "acme-advertising",
      "advertiser_description": "ACME Advertising",
      "name": "Holiday Promotion Campaign",
      "branding_text": "",
      "policy_state": null,
      "status": "PAUSED",
      "create_time": 1699747200000,
      "total_spent": 0.0,
      "type": "PAID",
      "marketing_objective": null,
      "campaign_groups": null,
      "bid_strategy": null,
      "is_creative_library_campaign": null,
      "business_model": "VCPM"
    }
  ]
}

Additional examples

Examples with filters

Status

Fetch all video campaigns that are running:

GET /backstage/api/1.0/{account_id}/video-campaigns/base?status=RUNNING

Fetch all video campaigns that are paused:

GET /backstage/api/1.0/{account_id}/video-campaigns/base?status=PAUSED

Fetch all campaigns that are running or paused:

GET /backstage/api/1.0/{account_id}/video-campaigns/base?status=RUNNING,PAUSED
๐Ÿ“˜

Guidelines

  1. To filter on multiple statuses, pass a comma-delimited list (see example above).
  2. If you do not pass a status filter, the base endpoint will return all campaigns - regardless of status.
  3. Video campaigns support these status values: RUNNING, PAUSED, DELETED, EXPIRED.

Text Search

Return all video campaigns with an ID that contains '12345':

GET /backstage/api/1.0/{account_id}/video-campaigns/base?search_text=12345
{
    "results": [
        {
            "id": 12345678,
            "advertiser_id": 987654,
            "advertiser_name": "acme-advertising",
            "advertiser_description": "ACME Advertising",
            "name": "Summer Video Campaign 2024",
            "branding_text": "",
            "policy_state": null,
            "status": "RUNNING",
            "create_time": 1721529600000,
            "total_spent": 125.50,
            "type": "PAID",
            "marketing_objective": null,
            "campaign_groups": null,
            "bid_strategy": null,
            "is_creative_library_campaign": null,
            "business_model": "CPM"
        }
    ]
}

Return all video campaigns that contain 'Video' in their name:

GET /backstage/api/1.0/{account_id}/video-campaigns/base?search_text=Video
{
    "results": [
        {
            "id": 12345678,
            "advertiser_id": 987654,
            "advertiser_name": "acme-advertising",
            "advertiser_description": "ACME Advertising",
            "name": "Summer Video Campaign 2024",
            "branding_text": "",
            "policy_state": null,
            "status": "RUNNING",
            "create_time": 1721529600000,
            "total_spent": 125.50,
            "type": "PAID",
            "marketing_objective": null,
            "campaign_groups": null,
            "bid_strategy": null,
            "is_creative_library_campaign": null,
            "business_model": "CPM"
        },
        {
            "id": 87654321,
            "advertiser_id": 987654,
            "advertiser_name": "acme-advertising",
            "advertiser_description": "ACME Advertising",
            "name": "Holiday Video Promotion",
            "branding_text": "",
            "policy_state": null,
            "status": "PAUSED",
            "create_time": 1699747200000,
            "total_spent": 0.0,
            "type": "PAID",
            "marketing_objective": null,
            "campaign_groups": null,
            "bid_strategy": null,
            "is_creative_library_campaign": null,
            "business_model": "VCPM"
        }
    ]
}
๐Ÿ“˜

The search_text filter looks for matches on Campaign ID or Name.

Filtering on a specific Campaign ID will typically return that campaign only.

Combining filters

Return all video campaigns that are running and contain 'Video' in their name:

GET /backstage/api/1.0/{account_id}/video-campaigns/base?status=RUNNING&search_text=Video
๐Ÿšง

Combining filters

  • You can combine different filters - e.g. status=RUNNING&search_text=Video.
  • You cannot repeat the same filter twice.

No matching campaigns

If there are no video campaigns that match the requested filter, a 404 status is returned:

{
    "http_status": 404,
    "message": "No matching campaigns found",
    "message_code": "api.action.resource_not_found"
}

Paging

Use a page size of 100 - and fetch page 1:

GET /backstage/api/1.0/{account_id}/video-campaigns/base?page_size=100&page=1
{
    "results": [
        {
            "id": 12345678,
            "advertiser_id": 987654,
            "advertiser_name": "acme-advertising",
            "advertiser_description": "ACME Advertising",
            "name": "Summer Video Campaign 2024",
            "branding_text": "",
            "policy_state": null,
            "status": "RUNNING",
            "create_time": 1721529600000,
            "total_spent": 125.50,
            "type": "PAID",
            "marketing_objective": null,
            "campaign_groups": null,
            "bid_strategy": null,
            "is_creative_library_campaign": null,
            "business_model": "CPM"
        },
        {
            "id": 87654321,
            "advertiser_id": 987654,
            "advertiser_name": "acme-advertising",
            "advertiser_description": "ACME Advertising",
            "name": "Holiday Video Promotion",
            "branding_text": "",
            "policy_state": null,
            "status": "PAUSED",
            "create_time": 1699747200000,
            "total_spent": 0.0,
            "type": "PAID",
            "marketing_objective": null,
            "campaign_groups": null,
            "bid_strategy": null,
            "is_creative_library_campaign": null,
            "business_model": "VCPM"
        }
    ]
}
๐Ÿšง

The page_size and page query params are always passed together.

Get a single video campaign

Retrieve detailed information for a specific video campaign.

GET /backstage/api/1.0/{account_id}/video-campaigns/managed/{campaign_id}
Authorization: Bearer {access_token}
Content-Type: application/json
{
  "id": 12345678,
  "publisher_id": 987654,
  "cipid": 123456,
  "origin_id": 789,
  "campaign_name": "Summer Video Campaign 2024",
  "rate": 5.50,
  "start_date": "2024-06-01",
  "end_date": "2024-08-31",
  "start_date_in_utc": "2024-06-01 04:00:00",
  "end_date_in_utc": "2024-08-31 04:00:00",
  "active": true,
  "status": "RUNNING",
  "ad_adjacency": false,
  "business_model": "CPM",
  "targeting": {
    "country_targeting": {
      "type": "INCLUDE",
      "value": ["US", "CA"],
      "href": null
    },
    ...
  },
  "budget": 10000.0,
  "pacing": "BALANCED",
  "daily_cap": null,
  "activity_schedule": {
    "mode": "ALWAYS",
    "rules": null,
    "time_zone": null
  }
}

Create a video campaign

Create a new video campaign with the specified business model.

Create a CPM campaign

POST /backstage/api/1.0/{account_id}/video-campaigns/managed
Authorization: Bearer {access_token}
Content-Type: application/json
{
  "campaign_name": "Holiday Video Campaign CPM",
  "rate": 7.0,
  "start_date": "2024-12-01",
  "end_date": "2024-12-31",
  "active": false,
  "business_model": "CPM",
  "targeting": {
    "country_targeting": {
      "type": "INCLUDE",
      "value": ["US"]
    }
  },
  "budget": 5000.0,
  "pacing": "BALANCED"
}
{
  "id": 87654321,
  "publisher_id": 987654,
  "cipid": 123456,
  "origin_id": 789,
  "campaign_name": "Holiday Video Campaign CPM",
  "rate": 7.0,
  "start_date": "2024-12-01",
  "end_date": "2024-12-31",
  "start_date_in_utc": "2024-12-01 05:00:00",
  "end_date_in_utc": "2024-12-31 05:00:00",
  "active": false,
  "status": "PAUSED",
  "ad_adjacency": false,
  "business_model": "CPM",
  "targeting": {
    "country_targeting": {
      "type": "INCLUDE",
      "value": ["US"],
      "href": null
    },
    ...
  },
  "budget": 5000.0,
  "pacing": "BALANCED",
  "daily_cap": null,
  "activity_schedule": {
    "mode": "ALWAYS",
    "rules": null,
    "time_zone": null
  }
}

Create a VCPM campaign

POST /backstage/api/1.0/{account_id}/video-campaigns/managed
Authorization: Bearer {access_token}
Content-Type: application/json
{
  "campaign_name": "Brand Awareness Video Campaign",
  "rate": 8.5,
  "start_date": "2024-11-15",
  "end_date": "2024-12-15",
  "active": false,
  "business_model": "VCPM",
  "targeting": {
    "country_targeting": {
      "type": "INCLUDE",
      "value": ["US", "CA"]
    }
  },
  "budget": 7500.0,
  "pacing": "BALANCED"
}
{
  "id": 87654322,
  "publisher_id": 987654,
  "cipid": 123456,
  "origin_id": 789,
  "campaign_name": "Brand Awareness Video Campaign",
  "rate": 8.5,
  "start_date": "2024-11-15",
  "end_date": "2024-12-15",
  "start_date_in_utc": "2024-11-15 05:00:00",
  "end_date_in_utc": "2024-12-15 05:00:00",
  "active": false,
  "status": "PAUSED",
  "ad_adjacency": false,
  "business_model": "VCPM",
  "targeting": {
    "country_targeting": {
      "type": "INCLUDE",
      "value": ["US", "CA"],
      "href": null
    },
    ...
  },
  "budget": 7500.0,
  "pacing": "BALANCED",
  "daily_cap": null,
  "activity_schedule": {
    "mode": "ALWAYS",
    "rules": null,
    "time_zone": null
  }
}

Create a CPCV campaign

POST /backstage/api/1.0/{account_id}/video-campaigns/managed
Authorization: Bearer {access_token}
Content-Type: application/json
{
  "campaign_name": "Engagement Video Campaign",
  "rate": 0.25,
  "start_date": "2024-10-01",
  "end_date": "2024-10-31",
  "active": false,
  "business_model": "CPCV",
  "targeting": {
    "country_targeting": {
      "type": "INCLUDE",
      "value": ["US"]
    }
  },
  "budget": 3000.0,
  "pacing": "BALANCED"
}
{
  "id": 87654323,
  "publisher_id": 987654,
  "cipid": 123456,
  "origin_id": 789,
  "campaign_name": "Engagement Video Campaign",
  "rate": 0.25,
  "start_date": "2024-10-01",
  "end_date": "2024-10-31",
  "start_date_in_utc": "2024-10-01 04:00:00",
  "end_date_in_utc": "2024-10-31 04:00:00",
  "active": false,
  "status": "PAUSED",
  "ad_adjacency": false,
  "business_model": "CPCV",
  "targeting": {
    "country_targeting": {
      "type": "INCLUDE",
      "value": ["US"],
      "href": null
    },
    ...
  },
  "budget": 3000.0,
  "pacing": "BALANCED",
  "daily_cap": null,
  "activity_schedule": {
    "mode": "ALWAYS",
    "rules": null,
    "time_zone": null
  }
}

Update a video campaign

Update an existing video campaign. You can update individual fields or the entire campaign configuration.

Update a single field

POST /backstage/api/1.0/{account_id}/video-campaigns/managed/{campaign_id}
Authorization: Bearer {access_token}
Content-Type: application/json
{
  "rate": 6.5
}
{
  "id": 12345678,
  "publisher_id": 987654,
  "cipid": 123456,
  "origin_id": 789,
  "campaign_name": "Summer Video Campaign 2024",
  "rate": 6.5,
  "start_date": "2024-06-01",
  "end_date": "2024-08-31",
  "start_date_in_utc": "2024-06-01 04:00:00",
  "end_date_in_utc": "2024-08-31 04:00:00",
  "active": true,
  "status": "RUNNING",
  "ad_adjacency": false,
  "business_model": "CPM",
  "targeting": {
    "country_targeting": {
      "type": "INCLUDE",
      "value": ["US", "CA"],
      "href": null
    },
    ...
  },
  "budget": 10000.0,
  "pacing": "BALANCED",
  "daily_cap": null,
  "activity_schedule": {
    "mode": "ALWAYS",
    "rules": null,
    "time_zone": null
  }
}

Update multiple fields

POST /backstage/api/1.0/{account_id}/video-campaigns/managed/{campaign_id}
Authorization: Bearer {access_token}
Content-Type: application/json
{
  "rate": 8.0,
  "budget": 12000.0,
  "active": true,
  "end_date": "2024-12-31"
}
{
  "id": 12345678,
  "publisher_id": 987654,
  "cipid": 123456,
  "origin_id": 789,
  "campaign_name": "Summer Video Campaign 2024",
  "rate": 8.0,
  "start_date": "2024-06-01",
  "end_date": "2024-12-31",
  "start_date_in_utc": "2024-06-01 04:00:00",
  "end_date_in_utc": "2024-12-31 05:00:00",
  "active": true,
  "status": "RUNNING",
  "ad_adjacency": false,
  "business_model": "CPM",
  "targeting": {
    "country_targeting": {
      "type": "INCLUDE",
      "value": ["US", "CA"],
      "href": null
    },
    ...
  },
  "budget": 12000.0,
  "pacing": "BALANCED",
  "daily_cap": null,
  "activity_schedule": {
    "mode": "ALWAYS",
    "rules": null,
    "time_zone": null
  }
}

Pause a campaign

POST /backstage/api/1.0/{account_id}/video-campaigns/managed/{campaign_id}
Authorization: Bearer {access_token}
Content-Type: application/json
{
  "active": false
}
{
  "id": 12345678,
  "publisher_id": 987654,
  "cipid": 123456,
  "origin_id": 789,
  "campaign_name": "Summer Video Campaign 2024",
  "rate": 8.0,
  "start_date": "2024-06-01",
  "end_date": "2024-08-31",
  "start_date_in_utc": "2024-06-01 04:00:00",
  "end_date_in_utc": "2024-08-31 04:00:00",
  "active": false,
  "status": "PAUSED",
  "ad_adjacency": false,
  "business_model": "CPM",
  "targeting": {
    "country_targeting": {
      "type": "INCLUDE",
      "value": ["US", "CA"],
      "href": null
    },
    ...
  },
  "budget": 10000.0,
  "pacing": "BALANCED",
  "daily_cap": null,
  "activity_schedule": {
    "mode": "ALWAYS",
    "rules": null,
    "time_zone": null
  }
}

Resume a campaign

POST /backstage/api/1.0/{account_id}/video-campaigns/managed/{campaign_id}
Authorization: Bearer {access_token}
Content-Type: application/json
{
  "active": true
}
{
  "id": 12345678,
  "publisher_id": 987654,
  "cipid": 123456,
  "origin_id": 789,
  "campaign_name": "Summer Video Campaign 2024",
  "rate": 8.0,
  "start_date": "2024-06-01",
  "end_date": "2024-08-31",
  "start_date_in_utc": "2024-06-01 04:00:00",
  "end_date_in_utc": "2024-08-31 04:00:00",
  "active": true,
  "status": "RUNNING",
  "ad_adjacency": false,
  "business_model": "CPM",
  "targeting": {
    "country_targeting": {
      "type": "INCLUDE",
      "value": ["US", "CA"],
      "href": null
    },
    ...
  },
  "budget": 10000.0,
  "pacing": "BALANCED",
  "daily_cap": null,
  "activity_schedule": {
    "mode": "ALWAYS",
    "rules": null,
    "time_zone": null
  }
}

Update platform targeting

POST /backstage/api/1.0/{account_id}/video-campaigns/managed/{campaign_id}
Authorization: Bearer {access_token}
Content-Type: application/json
{
  "targeting": {
    "platform_targeting": {
      "type": "INCLUDE",
      "value": ["DESKTOP", "SMARTPHONE"]
    }
  }
}
{
  "id": 12345678,
  "publisher_id": 987654,
  "cipid": 123456,
  "origin_id": 789,
  "campaign_name": "Summer Video Campaign 2024",
  "rate": 5.50,
  "start_date": "2024-06-01",
  "end_date": "2024-08-31",
  "start_date_in_utc": "2024-06-01 04:00:00",
  "end_date_in_utc": "2024-08-31 04:00:00",
  "active": true,
  "status": "RUNNING",
  "ad_adjacency": false,
  "business_model": "CPM",
  "targeting": {
    "country_targeting": {
      "type": "INCLUDE",
      "value": ["US", "CA"],
      "href": null
    },
    ...
    "platform_targeting": {
      "type": "INCLUDE",
      "value": ["DESKTOP", "SMARTPHONE"],
      "href": null
    },
    ...
  },
  "budget": 10000.0,
  "pacing": "BALANCED",
  "daily_cap": null,
  "activity_schedule": {
    "mode": "ALWAYS",
    "rules": null,
    "time_zone": null
  }
}
๐Ÿ“˜

Guidelines

You can pass only the targeting fields that need to be updated.

Duplicate a video campaign

Create a copy of an existing video campaign with a " - Copy" suffix added to the campaign name.

POST /backstage/api/1.0/{account_id}/video-campaigns/managed/{campaign_id}/duplicate
Authorization: Bearer {access_token}
Content-Type: application/json
{
  "id": 98765432,
  "publisher_id": 987654,
  "cipid": 123456,
  "origin_id": 789,
  "campaign_name": "Summer Video Campaign 2024 - Copy",
  "rate": 5.50,
  "start_date": "2024-06-01",
  "end_date": "2024-08-31",
  "start_date_in_utc": "2024-06-01 04:00:00",
  "end_date_in_utc": "2024-08-31 04:00:00",
  "active": false,
  "status": "PAUSED",
  "ad_adjacency": false,
  "business_model": "CPM",
  "targeting": {
    "country_targeting": {
      "type": "INCLUDE",
      "value": ["US", "CA"],
      "href": null
    },
    ...
  },
  "budget": 10000.0,
  "pacing": "BALANCED",
  "daily_cap": null,
  "activity_schedule": {
    "mode": "ALWAYS",
    "rules": null,
    "time_zone": null
  }
}

Delete a video campaign

Permanently delete an existing video campaign.

DELETE /backstage/api/1.0/{account_id}/video-campaigns/managed/{campaign_id}
Authorization: Bearer {access_token}
Content-Type: application/json
{
  "id": 12345678,
  "publisher_id": 987654,
  "cipid": 123456,
  "origin_id": 789,
  "campaign_name": "Summer Video Campaign 2024",
  "rate": 5.50,
  "start_date": "2024-06-01",
  "end_date": "2024-08-31",
  "start_date_in_utc": "2024-06-01 04:00:00",
  "end_date_in_utc": "2024-08-31 04:00:00",
  "active": false,
  "status": "DELETED",
  "ad_adjacency": false,
  "business_model": "CPM",
  "targeting": {
    "country_targeting": {
      "type": "INCLUDE",
      "value": ["US", "CA"],
      "href": null
    },
    ...
  },
  "budget": 10000.0,
  "pacing": "BALANCED",
  "daily_cap": null,
  "activity_schedule": {
    "mode": "ALWAYS",
    "rules": null,
    "time_zone": null
  }
}
๐Ÿšง

Warning

The delete operation is irreversible.

Field Definitions

๐Ÿ“˜

Modifier Column

  • Required - field must be included when creating a new resource
  • Read-only - should never be sent to the server. Appears only when fetching a resource.
  • Final - set once when creating the resource. Thereafter, is read-only.

Campaign fields

FieldTypeModifiers and DefaultsDescription
campaign_namestringRequiredUnique name for the campaign
start_datestringRequiredCampaign start date (YYYY-MM-DD)
end_datestringDefault: nullCampaign end date (YYYY-MM-DD)
business_modelstringFinalCampaign pricing model (CPM, VCPM, or CPCV)
ratenumberRequiredBid amount (varies by business model)
budgetnumberRequiredCampaign budget amount
targetingobjectRequiredTargeting configuration (includes country, platform, etc.)
activebooleanDefault: falseWhether campaign is active
pacingstringDefault: "BALANCED"Budget pacing strategy (BALANCED, ACCELERATED)
daily_capnumberDefault: nullDaily spending limit
ad_adjacencybooleanDefault: falseWhether to enable ad adjacency
activity_scheduleobjectDefault: nullCampaign scheduling configuration
idnumberRead-onlyCampaign ID (auto-generated)
publisher_idnumberRead-onlyPublisher ID (auto-assigned)
cipidnumberRead-onlyContent provider ID (auto-assigned)
origin_idnumberRead-onlyOrigin ID (auto-assigned)
statusstringRead-onlyCampaign status (RUNNING, PAUSED, DELETED, EXPIRED)
start_date_in_utcstringRead-onlyStart date converted to UTC
end_date_in_utcstringRead-onlyEnd date converted to UTC

Business model values

ValueDescription
CPMCost Per Mille (per 1,000 impressions)
VCPMViewable Cost Per Mille (per 1,000 viewable impressions)
CPCVCost Per Completed View

Campaign status values

StatusDescription
RUNNINGCampaign is active and serving
PAUSEDCampaign is paused (not serving)
DELETEDCampaign has been deleted
EXPIREDCampaign has reached its end date

Targeting

Targeting options

All targeting fields support these operation types:

TypeDescription
INCLUDETarget only the specified values
EXCLUDEExclude the specified values from targeting
ALLTarget all available values (no restriction)

Targeting values reference

Platform targeting

Target users based on their device type.

ValueDescription
DESKTOPDesktop and laptop computers
SMARTPHONEMobile phones
TABLETTablet devices
IN_APPIn-app mobile placements

Country targeting

Target users by geographic location using ISO 3166-1 alpha-2 country codes.

Country CodeCountry Name
USUnited States
CACanada
GBUnited Kingdom
DEGermany
FRFrance
JPJapan
AUAustralia
MXMexico
BRBrazil
ILIsrael
๐Ÿ“˜

More countries

For a complete list of country codes, refer to the resources endpoint or ISO 3166-1.

Frequency capping periods

Control how often users see your campaign ads within specific time periods.

PeriodDescription
DAYLimit impressions per user per day
WEEKLimit impressions per user per week
MONTHLimit impressions per user per month
๐Ÿ“˜

Frequency capping

Combine with a threshold number (e.g. 3 impressions per DAY).

Viewability targeting

Viewability targeting ensures your video ads only serve in placements where a minimum percentage of the ad is visible to users.

ValueDescription
NONENo viewability requirement
OVER_40_PERCENTOnly serve where >40% of ad is viewable
OVER_45_PERCENTOnly serve where >45% of ad is viewable
OVER_50_PERCENTOnly serve where >50% of ad is viewable
OVER_55_PERCENTOnly serve where >55% of ad is viewable
OVER_60_PERCENTOnly serve where >60% of ad is viewable
OVER_65_PERCENTOnly serve where >65% of ad is viewable
OVER_70_PERCENTOnly serve where >70% of ad is viewable
OVER_75_PERCENTOnly serve where >75% of ad is viewable
OVER_80_PERCENTOnly serve where >80% of ad is viewable
๐Ÿ“˜

About viewability

Viewability measures how much of your video ad is actually visible to users.

Error Responses

400 Bad Request

{
  "error": "Bad Request",
  "message": "Invalid campaign data provided",
  "details": [
    {
      "field": "campaign_name",
      "message": "Campaign name is required"
    }
  ]
}

401 Unauthorized

{
  "error": "Unauthorized",
  "message": "Invalid or expired access token"
}

404 Not Found

{
  "error": "Not Found",
  "message": "Campaign not found",
  "campaign_id": "12345678"
}

409 Conflict

{
  "error": "Conflict",
  "message": "Campaign name already exists",
  "campaign_name": "Duplicate Campaign Name"
}

422 Unprocessable Entity

{
  "error": "Unprocessable Entity",
  "message": "Validation failed",
  "details": [
    {
      "field": "rate",
      "message": "Rate must be greater than 0"
    },
    {
      "field": "start_date",
      "message": "Start date must be in the future"
    }
  ]
}