Promoted Products

📝

Getting Started

  • A promoted product specifies the product that will be advertised on a line item.
  • Identify eligible products to promote by accessing your account catalog.
  • Each product can optionally be configured with a specific bid amount, allowing you to control how much you are willing to pay per click.
  • Each line item is limited to a maximum of 500 promoted products.

 

Endpoints

MethodEndpointDescription
GET/line-items/{lineItemId}/productsRetrieve all products associated with a specific line item.
POST/line-items/{lineItemId}/products/appendAdd products to a specific line item or update their bid override.
POST/line-items/{lineItemId}/products/deleteRemove products from a specific line item.
POST/line-items/{lineItemId}/products/pausePause products on a specific line item, preventing them from being advertised.
POST/line-items/{lineItemId}/products/unpauseReactivate paused products on a specific line item, allowing them to be advertised again.

 

Promoted Products Attributes

AttributeData TypeDescription
id*stringProduct ID, unique identifier at the Retailer catalog and obtained from the account Catalog

Accepted values: up to 500-chars string
Writeable? N / Nullable? N
lineItemId*stringLine Item ID, in which the product is to be promoted; required in the endpoints' path to define in which line item to perform the action

Accepted values: string of int64
Writeable? N / Nullable? N
bidOverridedecimalBid value for the specific product; overrides targetBid specified on the Line Item and must satisfy minBid from Catalog (input excludes platform fees)

Accepted values: bidOverride ≥ 0.0
Default: 0.0
Writeable? N / Nullable? Y
statusenumStatus of Promoted Product; can only be updated to active or paused using the endpoints below.
For more details about each state, check out Campaign, Line Item & Products Status

Returned values: active, paused, scheduled, ended, budgetHit, noFunds, draft, archived
Writeable? Y / Nullable? N

* Required

 

Get All Products on specific Line Item

This endpoint lists all products on the specified line item.

Results are paginated using offset and limit query parameters; if omitted, defaults to 0 and 500, respective - see API Response

Additional query parameter fields is supported to receive a comma-separated list of optional attributes to include in the response, to optimize response time and payload length

https://api.criteo.com/{version}/retail-media/line-items/{lineItemId}/products?offset={offset}&limit={limit}&fields={attributeList}

Sample Request

curl -X GET "https://api.criteo.com/{version}/retail-media/line-items/2465695028166499188/products?offset=0&limit=10&fields=bidOverride,status" \
    -H "Authorization: Bearer <MY_ACCESS_TOKEN>"
import requests

url = "https://api.criteo.com/{version}/retail-media/line-items/2465695028166499188/products?offset=0&limit=10&fields=bidOverride"

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/line-items/2465695028166499188/products?offset=0&limit=10&fields=bidOverride")
  .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/line-items/2465695028166499188/products?offset=0&limit=10&fields=bidOverride');
$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

🔵 HTTP code 200:

{
    "meta": {
        "offset": 0,
        "limit": 10,
        "count": 34,
        "responseCount": 34
    },
    "data": [
        {
            "id": "06d3049c3e1642ec92479dbeca1fc39f",
            "type": "RetailMediaPromotedProduct",
            "attributes": {
                "bidOverride": 0.70,
                "status": "active"
            }
        },
        // ...
        {
            "id": "926097",
            "type": "RetailMediaPromotedProduct",
            "attributes": {
                "bidOverride": 0.30,
                "status": "active"
            }
        }
    ]
}

Add Products to specific Line Item, or Update Bid Override

This endpoint adds one or more products to promote on the specified line item. If the product already exists, only its bid override will be updated.

https://api.criteo.com/{version}/retail-media/line-items/{lineItemId}/products/append

Sample Request

curl -L -X POST 'https://api.criteo.com/{version}/retail-media/line-items/2465695028166499188/products/append' \
    -H 'Accept: application/json' \
    -H 'Content-Type: application/json' \
    -H 'Authorization: Bearer <MY_ACCESS_TOKEN>' \
    -d '{
            "data": [
                {
                    "id": "492731",
                    "type": "RetailMediaPromotedProduct",
                    "attributes": {
                        "id": "492731",
                        "status": "paused",
                        "bidOverride": "0.0"
                    }
                }
            ]
        }'
import requests
import json

url = "https://api.criteo.com/{version}/retail-media/line-items/2465695028166499188/products/append"

payload = json.dumps({
    "data": [
        {
            "id": "492731",
            "type": "RetailMediaPromotedProduct",
            "attributes": {
                "id": "492731",
                "status": "paused",
                "bidOverride": "0.0"
            }
        }
    ]
})
headers = {
    'Accept': 'application/json',
    'Content-Type': 'application/json',
    'Authorization': 'Bearer <MY_ACCESS_TOKEN>'
}

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

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

MediaType mediaType = MediaType.parse("application/json");
RequestBody body = RequestBody.create("""
{
    "data": [
        {
            "id": "492731",
            "type": "RetailMediaPromotedProduct",
            "attributes": {
                "id": "492731",
                "status": "paused",
                "bidOverride": "0.0"
            }
        }
    ]
}
""", mediaType);

Request request = new Request.Builder()
    .url("https://api.criteo.com/{version}/retail-media/line-items/2465695028166499188/products/append")
    .post(body)
    .addHeader("Accept", "application/json")
    .addHeader("Content-Type", "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/line-items/2465695028166499188/products/append');
$request->setMethod(HTTP_Request2::METHOD_POST);
$request->setConfig(array(
    'follow_redirects' => TRUE
));
$request->setHeader(array(
    'Accept' => 'application/json',
    'Content-Type' => 'application/json',
    'Authorization' => 'Bearer <MY_ACCESS_TOKEN>'
));

$body = <<<JSON
{
    "data": [
        {
            "id": "492731",
            "type": "RetailMediaPromotedProduct",
            "attributes": {
                "id": "492731",
                "status": "paused",
                "bidOverride": "0.0"
            }
        }
    ]
}
JSON;
$request->setBody($body);

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

🔵 HTTP code 204 (no body content)


Remove Products from a specific Line Item

This endpoint removes one or more products from the specified line item. The resulting state of the line item is returned as a single page. Line items can be created without any promoted products, but once any products are added, at least one product must remain.

https://api.criteo.com/{version}/retail-media/line-items/{lineItemId}/products/delete

Sample Request

curl -X POST "https://api.criteo.com/{version}/retail-media/line-items/2465695028166499188/products/delete" \
    -H "Authorization: Bearer <MY_ACCESS_TOKEN>" \
    -H "Content-Type: application/json" \
    -d '{
            "data": [
                {
                    "id": "sku1",
                    "type": "RetailMediaPromotedProduct"
                }
            ]
        }'
import requests
import json

url = "https://api.criteo.com/{version}/retail-media/line-items/325713346766241792/products/delete"

payload = json.dumps({
  "data": [
    {
      "id": "be5a3dbc8eaf46608d58ce68107a5854",
      "type": "RetailMediaDeleteProduct",
      "attributes": {
        "bidOverride": "0.30"
      }
    }
  ]
})
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json',
  'Authorization': 'Bearer <MY_ACCESS_TOKEN>'
}

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

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

MediaType mediaType = MediaType.parse("application/json");

RequestBody body = RequestBody.create(mediaType, "{\n  \"data\": [\n    {\n      \"id\": \"be5a3dbc8eaf46608d58ce68107a5854\",\n      \"type\": \"RetailMediaDeleteProduct\",\n      \"attributes\": {\n        \"bidOverride\": \"0.30\"\n      }\n    }\n  ]\n}");

Request request = new Request.Builder()
  .url("https://api.criteo.com/{version}/retail-media/line-items/325713346766241792/products/delete")
  .method("POST", body)
  .addHeader("Content-Type", "application/json")
  .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/line-items/325713346766241792/products/delete');
$request->setMethod(HTTP_Request2::METHOD_POST);
$request->setConfig(array(
  'follow_redirects' => TRUE
));
$request->setHeader(array(
  'Content-Type' => 'application/json',
  'Accept' => 'application/json',
  'Authorization' => 'Bearer <MY_ACCESS_TOKEN>'
));

$request->setBody('{\n  "data": [\n    {\n      "id": "be5a3dbc8eaf46608d58ce68107a5854",\n      "type": "RetailMediaDeleteProduct",\n      "attributes": {\n        "bidOverride": "0.30"\n      }\n    }\n  ]\n}');
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

🔵 HTTP code 204 (no body content)


Pause Products on a specific Line Item

This endpoint allows reactivating one or multiple paused products on a line item:

https://api.criteo.com/{version}/retail-media/line-items/{lineItemId}/products/pause

Sample Request

curl -X POST 'https://api.criteo.com/{version}/retail-media/line-items/311990577399115776/products/pause' \
		-H 'Content-Type: application/json' \
		-H'Authorization: Bearer <MY_ACCESS_TOKEN>' \
    -d '{
          "data": [
            {
              "id": "4f5c49fce3c94542b5023e7cc1e1f5ca",
              "type": "RetailMediaPromotedProduct"
            }
         ]
    }'
import requests
import json

url = "https://api.criteo.com/{version}/retail-media/line-items/325713346766241792/products/pause"

payload = json.dumps({
  "data": [
    {
      "id": "be5a3dbc8eaf46608d58ce68107a5854",
      "type": "RetailMediaPausePromoteDProduct"
    }
  ]
})
headers = {
  'Content-Type': 'application/json',
  'Authorization': 'Bearer <MY_ACCESS_TOKEN>'
}

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

print(response.text)
<?php
require_once 'HTTP/Request2.php';
$request = new HTTP_Request2();
$request->setUrl('https://api.criteo.com/{version}/retail-media/line-items/325713346766241792/products/pause');
$request->setMethod(HTTP_Request2::METHOD_POST);
$request->setConfig(array(
  'follow_redirects' => TRUE
));

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

$request->setBody('{\n  "data": [\n    {\n      "id": "be5a3dbc8eaf46608d58ce68107a5854",\n      "type": "RetailMediaPausePromoteDProduct"\n    }\n  ]\n}');
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();
}
OkHttpClient client = new OkHttpClient().newBuilder()
  .build();

MediaType mediaType = MediaType.parse("application/json");

RequestBody body = RequestBody.create(mediaType, "{\n  \"data\": [\n    {\n      \"id\": \"be5a3dbc8eaf46608d58ce68107a5854\",\n      \"type\": \"RetailMediaPausePromoteDProduct\"\n    }\n  ]\n}");

Request request = new Request.Builder()
  .url("https://api.criteo.com/{version}/retail-media/line-items/325713346766241792/products/pause")
  .method("POST", body)
  .addHeader("Content-Type", "application/json")
  .addHeader("Authorization", "Bearer <MY_ACCESS_TOKEN>")
  .build();

Response response = client.newCall(request).execute();

Sample Response

🔵 HTTP code 204 (no body content)


Unpaused Products on a Specific Line Item

This endpoint allows unpausing one or multiple products on a line item:

https://api.criteo.com/{version}/retail-media/line-items/{lineItemId}/products/unpause

Sample Request

curl -L -X POST 'https://api.criteo.com/{version}/retail-media/line-items/311990577399115776/products/unpause' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer <MY_ACCESS_TOKEN>' \
-d '{
  "data": [
    {
      "id": "4f5c49fce3c94542b5023e7cc1e1f5ca",
      "type": "RetailMediaPromotedProduct"
    }
  ]
}'
import requests
import json

url = "https://api.criteo.com/{version}/retail-media/line-items/325713346766241792/products/unpause"

payload = json.dumps({
  "data": [
    {
      "id": "be5a3dbc8eaf46608d58ce68107a5854",
      "type": "RetailMediaPausePromoteDProduct"
    }
  ]
})
headers = {
  'Content-Type': 'application/json',
  'Authorization': 'Bearer <MY_ACCESS_TOKEN>'
}

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

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

MediaType mediaType = MediaType.parse("application/json");

RequestBody body = RequestBody.create(mediaType, "{\n  \"data\": [\n    {\n      \"id\": \"be5a3dbc8eaf46608d58ce68107a5854\",\n      \"type\": \"RetailMediaPausePromoteDProduct\"\n    }\n  ]\n}");

Request request = new Request.Builder()
  .url("https://api.criteo.com/{version}/retail-media/line-items/325713346766241792/products/unpause")
  .method("POST", body)
  .addHeader("Content-Type", "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/line-items/325713346766241792/products/unpause');
$request->setMethod(HTTP_Request2::METHOD_POST);
$request->setConfig(array(
  'follow_redirects' => TRUE
));
$request->setHeader(array(
  'Content-Type' => 'application/json',
  'Authorization' => 'Bearer <MY_ACCESS_TOKEN>'
));

$request->setBody('{\n  "data": [\n    {\n      "id": "be5a3dbc8eaf46608d58ce68107a5854",\n      "type": "RetailMediaPausePromoteDProduct"\n    }\n  ]\n}');
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

🔵 HTTP code 204 (no body content)


Responses

ResponseDescription
🟢 200Call completed with success
🟢 204Promoted product paused or un-paused with success (no body content returned)
🔴 400Bad Request - Common validation errors:

- Could not find the SKU ID used to append to the line item. Make sure the SKU exists in the retailer's catalog
- Product bid override less than the product min bid
- Invalid bid override: Cannot use bid override attribute for a product belonging to a preferred deals line item
- Pausing/Un-pausing promoted products: Only the ID is required; do not include BidOverride or Status attributes.
🔴 403API user does not have authorization to make requests for the account ID. For authorization, follow the authorization request steps.
🔴 404Line item ID not found