Campaigns Endpoints

View and manage all your campaigns

Endpoints

MethodEndpointDescription
POST/accounts/{accountId}/campaignsCreate a new campaign for the specified account.
GET/accounts/{accountId}/campaignsRetrieve all campaigns associated with the specified account.
GET/campaigns/{campaignId}Retrieve details of a specific campaign by its ID.
PUT/campaigns/{campaignId}Update details of a specific campaign by its ID.
📘

Create Operations:

  • When using the POST method to create a resource, all Required fields must be included. Any Optional fields that are omitted will be set to their default values.

Update Operations:

  • When using the PUT method to update a resource, all Write fields can be specified. Omitting any of these fields is treated as setting them to null, where applicable.

Campaign Attributes

Attribute

Data Type

Description

id

string

Campaign ID, generated internally by Criteo

Accepted values: int64
Writeable? N / Nullable? N

accountId*

string

Account ID associated with the campaign, generated internally by Criteo

Accepted values: int64
Writeable? N / Nullable? N

name*

string

Campaign name; must be unique within an Account

Accepted values: up to 255-chars string
Writeable? Y / Nullable? N

type

enum

Campaign type
If the attribute is passed in the call, a value must be specified

Accepted values: auction, preferred
Default: auction
Writeable? Y / Nullable? N

budget

decimal

Campaign lifetime spend cap; uncapped if omitted or set to null.
Note that preferred campaign types cannot have budgets as these campaign types must be uncapped

Accepted values: equals/greater than zero
Default: null
Writeable? Y / Nullable? Y

budgetSpent

decimal

Amount the campaign has already spent

Accepted values: equals/greater than zero
Default: 0.0
Writeable? N / Nullable? N

budgetRemaining

decimal

Amount the campaign has remaining until cap is hit; null if budget is uncapped

Accepted values: between zero and budget
Default: null
Writeable? N / Nullable? Y

promotedBrandIds

list<string>

List of brand IDs from promoted products in the campaign, originated from the retailer's Catalog - see also Brands

Accepted values: list of strings
Default: empty list
Writeable? N / Nullable? N

clickAttributionWindow*

enum

Post-click attribution window

Accepted values: 7D, 14D, 30D
Default: 30D
Writeable? Y / Nullable? N

viewAttributionWindow*

enum

Post-view attribution window

Accepted values: None,1D,7D, 14D, 30D
Default: None
Writeable? Y / Nullable? N

clickAttributionScope

enum

Post-click attribution scope

Accepted values: sameSku, sameSkuCategory, sameSkuCategoryBrand
Default: sameSkuCategory
Writeable? Y / Nullable? N

viewAttributionScope

enum

Post-view attribution scope

Accepted values: sameSku, sameSkuCategory, sameSkuCategoryBrand
Default: sameSku
Writeable? Y / Nullable? N

drawableBalanceIds

list<string>

List of Balances the campaign is able to draw from; at least one balance is required for a campaign to start

Accepted values: list of balanceId
Default: empty list
Writeable? N / Nullable? N

status

enum

Campaign status, derived from the status of Line Items it holds; active if at least one line item is active. To understand the conditions that will cause a status to change, check out Campaign & Line Item Status

Accepted values: active, inactive
Default: inactive
Writeable? N / Nullable? N

monthlyPacing

decimal

The maximum monthly spend allowed for the campaign in the currency of the account. The spend is constrained by remaining account balance and total budget of the campaign. Monthly budget spend reset monthly at the start of the month based on the account timezone

Accepted values: null or greater than zero
Default: null
Writeable? Y / Nullable? Y

dailyPacing

decimal

The maximum daily spend allowed for the campaign in the currency of the account, as long as not set to null and isAutoDailyPacing = false; otherwise no daily spend limit will be enforced

Accepted values: null or greater than zero
Default: null
Writeable? Y / Nullable? Y

isAutoDailyPacing

boolean

Auto daily pacing flag for the campaign budget. The daily pacing value is automatically calculated with respect to the days left in the month for the account. The campaign's remaining account balance, total budget, and monthly pacing value are constrained by account's timezone and the campaign status. If auto daily pacing is enabled, dailyPacing value should be left empty (null).
Note the value may be affected by budget override. Daily budget spend is reset daily at the start of the day based on the account timezone. To activate, either campaign's endDate and budget or monthlyPacing must be specified, overwriting dailyPacing with the new respective pace (if not set previously)

Accepted values: true, false
Writeable? Y / Nullable? N

startDate*

timestamp

Campaign start date. The campaign starts inactive if invalid start date is not today or end date is in previous day.

Accepted values: yyyy-mm-ddThh:mm:ss±hh:mm(in ISO-8601)
Default: creation timestamp
Writeable? Y / Nullable? Y

⚠️ Note: if time/timezone designators are not provided, the default value to be considered will be 00:00:00+00:00 (i.e., midnight in UTC - account timezone not taken in consideration here)

endDate*

timestamp

Campaign end date. The campaign starts inactive if invalid start date is not today or end date is in previous day

Accepted values: yyyy-mm-ddThh:mm:ss±hh:mm(in ISO-8601)
Default: null
Writeable? Y / Nullable? Y

⚠️ Note: if time/timezone designators are not provided, the default value to be considered will be 00:00:00+00:00 (i.e., midnight in UTC - account timezone not taken in consideration here)

createdAt

timestamp

Timestamp of campaign creation, in UTC

Accepted values: yyyy-mm-ddThh:mm:ss±hh:mm(in ISO-8601)
Writeable? N / Nullable? N

updatedAt

timestamp

Timestamp of last campaign update, in UTC

Accepted values: yyyy-mm-ddThh:mm:ss±hh:mm(in ISO-8601)
Writeable? N / Nullable? N

companyName

string

This optional field, exclusively accessible to marketplaces within the European Union (in compliance with the Digital Service Act - DSA), will display the name of the company associated with the advertisement.

Accepted values: up to 255-chars string
Writeable? Y / Nullable? Y

onBehalfCompanyName

string

This optional field, exclusively accessible to marketplaces within the European Union (in compliance with the Digital Service Act - DSA), will display the name of the company (on behalf of companyName) associated with the advertisement

Accepted values: up to 255-chars string
Writeable? Y / Nullable? Y

retailerId

string

The retailer this campaign is associated with.
Required when using a retailer budget balance.

Writeable? Y (at create) / Nullable? Y (for non-retailer-budget campaigns)

(*) Required for create operations

📑

Digital Service Act (DSA)

In compliance with the Digital Services Act (DSA), marketplaces within the European Union will receive information about the company name associated with each advertisement.


Create a Campaign

This endpoint creates a Sponsored Products (type: auction) or Onsite Display (type: preferred) campaign.

Retailer budget vs Criteo budget: Including retailerId in the request creates a retailer budget campaign. Omitting retailerId (or setting it to null) creates a standard Criteo budget campaign — retailerId will be null in the response.

Balance mapping at create time: You may optionally include drawableBalanceIds to map the campaign to one or more retailer budget balances at creation. All compatibility rules apply (same retailer, same billing type, same demand account). You can also map balances separately after creation using POST /balances/{balanceId}/campaigns/append.

⚠️

Note on 403 vs 400

A 403 on campaign create means the retailerId you set is not recognized as an authorized retailer for your account. A 400 with a specific mismatch code means the retailer is valid but incompatible with the balance you included (see Error responses).

Legacy version behavior (2025-10 and earlier): Returns 400 when attempting to create a retailer budget campaign.

⚠️

Retailer budgets campaigns

When creating a campaign for a retailer-budget balance, retailerId must be provided and must match the retailerId of the balance. Mismatched values will return a RetailerMismatchWithBalance error. Learn more about Retailer budgets here.

https://api.criteo.com/{version}/retail-media/accounts/{accountId}/campaigns

Sample Request

curl -L -X POST 'https://api.criteo.com/2026-01/retail-media/accounts/{accountId}/campaigns' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer <MY_ACCESS_TOKEN>' \
-d '{
  "data": {
    "type": "Campaign",
    "attributes": {
      "name": "My Retailer Budget Campaign",
      "type": "auction",
      "retailerId": "123",
      "drawableBalanceIds": ["100000000000000001"],
      "startDate": "2026-06-01T00:00:00+00:00",
      "clickAttributionWindow": "30D",
      "viewAttributionWindow": "none",
      "clickAttributionScope": "sameSkuCategory",
      "viewAttributionScope": "sameSkuCategory",
      "isAutoDailyPacing": false
    }
  }
}'

Sample Response

{
  "data": {
    "id": "100000000000000001",
    "type": "RetailMediaCampaignV202301",
    "attributes": {
      "accountId": "123",
      "promotedBrandIds": [],
      "budgetSpent": 0.0,
      "budgetRemaining": null,
      "status": "inactive",
      "createdAt": "2026-05-29T20:33:27+00:00",
      "updatedAt": "2026-05-29T20:33:27+00:00",
      "type": "auction",
      "drawableBalanceIds": ["100000000000000001"],
      "clickAttributionWindow": "30D",
      "viewAttributionWindow": "none",
      "retailerId": 123,
      "name": "My Retailer Budget Campaign",
      "budget": null,
      "monthlyPacing": null,
      "dailyPacing": null,
      "isAutoDailyPacing": false,
      "startDate": "2026-06-01T00:00:00+00:00",
      "endDate": null,
      "clickAttributionScope": "sameSkuCategory",
      "viewAttributionScope": "sameSkuCategory",
      "companyName": null,
      "onBehalfCompanyName": null
    }
  }
}

Get All Campaigns by Account ID

This endpoint returns all campaigns for an account.

⚠️

As of 2026-01, retailerId is included in each campaign's attributes. Use the retailerId query parameter to filter campaigns by retailer.

Legacy version behavior (2025-10 and earlier): Retailer budget campaigns are not returned; retailerId is not present in the attribute set.

Results are paginated using pageIndex and pageSize query parameters; if omitted, defaults to 0 and 25, respectively - see API Response

https://api.criteo.com/{version}/retail-media/accounts/{accountId}/campaigns?pageIndex={pageIndex}&pageSize={pageSize}

Sample Request

curl -L -X GET 'https://api.criteo.com/2026-01/retail-media/accounts/{accountId}/campaigns' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer <MY_ACCESS_TOKEN>'
import requests

url = "https://api.criteo.com/{version}/retail-media/accounts/4/campaigns?pageIndex=8&pageSize=2"

payload={}
headers = {
  'Accept': 'application/json',
  'Authorization': 'Bearer <MY_ACCESS_TOKEN>'
}

response = requests.request("GET", url, headers=headers, data=payload)

print(response.text)
OkHttpClient client = new OkHttpClient().newBuilder()
  .build();

MediaType mediaType = MediaType.parse("text/plain");

RequestBody body = RequestBody.create(mediaType, "");

Request request = new Request.Builder()
  .url("https://api.criteo.com/{version}/retail-media/accounts/4/campaigns?pageIndex=8&pageSize=2")
  .method("GET", body)
  .addHeader("Accept", "application/json")
  .addHeader("Authorization", "Bearer <MY_ACCESS_TOKEN>")
  .build();

Response response = client.newCall(request).execute();
<?php
require_once 'HTTP/Request2.php';
$request = new HTTP_Request2();
$request->setUrl('https://api.criteo.com/{version}/retail-media/accounts/4/campaigns?pageIndex=8&pageSize=2');
$request->setMethod(HTTP_Request2::METHOD_GET);
$request->setConfig(array(
  'follow_redirects' => TRUE
));

$request->setHeader(array(
  'Accept' => 'application/json',
  'Authorization' => 'Bearer <MY_ACCESS_TOKEN>'
));

try {
  $response = $request->send();
  if ($response->getStatus() == 200) {
    echo $response->getBody();
  }
  
  else {
    echo 'Unexpected HTTP status: ' . $response->getStatus() . ' ' .
    $response->getReasonPhrase();
  }
}

catch(HTTP_Request2_Exception $e) {
  echo 'Error: ' . $e->getMessage();
}

Sample Response

{
  "metadata": {
    "totalItemsAcrossAllPages": 2533,
    "currentPageSize": 25,
    "currentPageIndex": 0,
    "totalPages": 102
  },
  "data": [
    {
      "id": "100000000000000001",
      "type": "RetailMediaCampaignV202301",
      "attributes": {
        "accountId": "123",
        "promotedBrandIds": [],
        "budgetSpent": 0.0,
        "budgetRemaining": null,
        "status": "inactive",
        "createdAt": "2026-05-29T20:00:47+00:00",
        "updatedAt": "2026-05-29T20:00:47+00:00",
        "type": "auction",
        "drawableBalanceIds": ["100000000000000002"],
        "clickAttributionWindow": "30D",
        "viewAttributionWindow": "none",
        "retailerId": 123,
        "name": "Sample Name",
        "budget": null,
        "monthlyPacing": null,
        "dailyPacing": null,
        "isAutoDailyPacing": false,
        "startDate": "2026-06-01T00:00:00+00:00",
        "endDate": null,
        "clickAttributionScope": "sameSkuCategory",
        "viewAttributionScope": "sameSkuCategory",
        "companyName": null,
        "onBehalfCompanyName": null
      }
    }
  ]
}

Get a Specific Campaign

This endpoint retrieves the specified campaign.

⚠️

As of 2026-01, retailerId is included in the response attributes. Retailer budget campaigns also surface criteoPoNumber and retailerPoNumber from the mapped balance.

Legacy version behavior (2025-10 and earlier): Returns 400 for retailer budget campaigns.

https://api.criteo.com/{version}/retail-media/campaigns/{campaignId}

Sample Request

curl -L -X GET 'https://api.criteo.com/{version}/retail-media/campaigns/1240' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer <MY_ACCESS_TOKEN>'
import http.client

conn = http.client.HTTPSConnection("api.criteo.com")
payload = ''
headers = {
  'Accept': 'application/json',
  'Authorization': 'Bearer <MY_ACCESS_TOKEN>'
}
conn.request("GET", "/{version}/retail-media/campaigns/1240", payload, headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))
OkHttpClient client = new OkHttpClient().newBuilder()
  .build();
MediaType mediaType = MediaType.parse("text/plain");
RequestBody body = RequestBody.create(mediaType, "");
Request request = new Request.Builder()
  .url("https://api.criteo.com/{version}/retail-media/campaigns/1240")
  .method("GET", body)
  .addHeader("Accept", "application/json")
  .addHeader("Authorization", "Bearer <MY_ACCESS_TOKEN>")
  .build();
Response response = client.newCall(request).execute();
<?php
require_once 'HTTP/Request2.php';
$request = new HTTP_Request2();
$request->setUrl('https://api.criteo.com/{version}/retail-media/campaigns/1240');
$request->setMethod(HTTP_Request2::METHOD_GET);
$request->setConfig(array(
  'follow_redirects' => TRUE
));
$request->setHeader(array(
  'Accept' => 'application/json',
  'Authorization' => 'Bearer MY_ACCESS_TOKEN>'
));
try {
  $response = $request->send();
  if ($response->getStatus() == 200) {
    echo $response->getBody();
  }
  else {
    echo 'Unexpected HTTP status: ' . $response->getStatus() . ' ' .
    $response->getReasonPhrase();
  }
}
catch(HTTP_Request2_Exception $e) {
  echo 'Error: ' . $e->getMessage();
}

Sample Response

{
  "data": {
    "id": "100000000000000001",
    "type": "RetailMediaCampaignV202301",
    "attributes": {
      "accountId": "123",
      "promotedBrandIds": [],
      "budgetSpent": 0.0,
      "budgetRemaining": null,
      "status": "inactive",
      "createdAt": "2026-05-29T20:00:47+00:00",
      "updatedAt": "2026-05-29T20:00:47+00:00",
      "type": "auction",
      "drawableBalanceIds": ["100000000000000002"],
      "clickAttributionWindow": "30D",
      "viewAttributionWindow": "none",
      "retailerId": 123,
      "name": "Sample Name",
      "budget": null,
      "isAutoDailyPacing": false,
      "startDate": "2026-06-01T00:00:00+00:00",
      "endDate": null,
      "clickAttributionScope": "sameSkuCategory",
      "viewAttributionScope": "sameSkuCategory",
      "companyName": null,
      "onBehalfCompanyName": null
    }
  }
}

Update a Specific Campaign

This endpoint allows you to update a specified campaign. The following example demonstrates how to switch to an uncapped campaign budget and modify the post-view attribution window.

⚠️

Legacy version behavior (2025-10 and earlier): Returns 400 for retailer budget campaigns.

https://api.criteo.com/{version}/retail-media/campaigns/{campaignId}

Sample Request

curl -L -X PUT 'https://api.criteo.com/2026-01/retail-media/campaigns/{campaignId}' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer <MY_ACCESS_TOKEN>' \
-d '{
  "data": {
    "type": "Campaign",
    "attributes": {
      "name": "Updated Campaign Name",
      "endDate": "2026-12-31T23:59:59+00:00"
    }
  }
}'

Sample Response

{
  "data": {
    "id": "100000000000000001",
    "type": "RetailMediaCampaignV202301",
    "attributes": {
      "accountId": "123",
      "promotedBrandIds": [],
      "budgetSpent": 0.0,
      "budgetRemaining": null,
      "status": "inactive",
      "createdAt": "2026-05-29T20:00:47+00:00",
      "updatedAt": "2026-05-29T20:00:47+00:00",
      "type": "auction",
      "drawableBalanceIds": ["100000000000000002"],
      "clickAttributionWindow": "30D",
      "viewAttributionWindow": "none",
      "retailerId": 123,
      "name": "Sample Name",
      "budget": null,
      "isAutoDailyPacing": false,
      "startDate": "2026-06-01T00:00:00+00:00",
      "endDate": null,
      "clickAttributionScope": "sameSkuCategory",
      "viewAttributionScope": "sameSkuCategory",
      "companyName": null,
      "onBehalfCompanyName": null
    }
  }
}

Responses

📘

All validation errors on campaign create use code: "validation-error".

The error type is identified by a bracketed prefix in the title field.

StatusTitleDescription
🔴 400[retailer-id-mismatch]The retailerId on the campaign doesn't match the retailerId on one of the balances in drawableBalanceIds. Also returned when balances from multiple retailers are included. Full message: "Cannot map campaign {id} to insertion order {id}: they belong to different retailers."
🔴 400[balance-type-mismatch]Billing type mismatch — e.g. retailer budget campaign with a Criteo budget balance, or no-retailerId campaign with a retailer budget balance. Full message: "Cannot map campaign {id} to insertion order {id}: cannot map Criteo-budget balance to retailer-budget campaign".
🔴 400[account-mismatch]The balance in drawableBalanceIds belongs to a different demand account than the campaign being created.
🔴 403authorization-unknownThe retailerId in the request is not recognized as an authorized retailer for this account — either the retailer ID is invalid or the account has not been approved as an authorized buyer. Use GET /retailers/search to discover eligible retailers first. A 403 does not mean a retailer mismatch; it means the retailer is unknown to the account.
🔴 400Invalid isAutoDailyPacingCannot turn on IsAutoDailyPacing and add a DailyPacing value. IsAutoDailyPacing and Daily Pacing cannot be active at the same time.
🔴 400Invalid BudgetBudget is not allowed for the Preferred campaign.
🔴 400RetailerMismatchWithBalanceCampaign retailerId does not match the balance retailerId. Ensure the retailerId in campaign settings matches the retailerId on the balance you are associating.


Did anything feel unclear or missing on this page?