Catalog Endpoints
Generate and download a copy of retailer's inventory
Endpoints
Method | Endpoint | Description |
---|---|---|
POST | /accounts/{accountId}/catalogs | Create a catalog request to generate a new catalog for Brand account |
POST | /accounts/{accountId}/catalogs/sellers | Create a catalog request to generate a new catalog for Seller account |
GET | /catalogs/{catalogId}/status | Retrieve the status of a specific catalog request. |
GET | /catalogs/{catalogId}/output | Download the output of a specific catalog once it's ready. |
Catalog Creation Request Attributes (for Brand accounts)
Attribute | Data Type | Description |
---|---|---|
format | enum | Format of the catalog data returned Accepted values: json-newline Default: json-newline Writeable? N / Nullable? Y |
brandIdFilter | list | Brand ID(s) used to filter down catalog results based on specified brands Accepted values: list of string/int64 Writeable? N / Nullable? N |
Catalog Creation Request Attributes (for Seller accounts)
Attribute | Data Type | Description |
---|---|---|
sellers | list | List of required seller pairs retailerId and sellerId associated with the catalog to be generatedParameters: * retailerId : Retailer ID, generated internally by Criteo* sellerId : seller ID in the respective retailer's catalog, used to filter down catalog products |
Catalog Status Response Attributes
Attribute | Data Type | Description |
---|---|---|
id | string | ID of the catalog creation request, to be used to retrieve its status and output (using other endpoints below - async) Accepted values: string of int64 Writeable? N / Nullable? N |
status | enum | Possible status of respective catalog creation Accepted values: pending , success , failure , expired , unknown Default: pending Writeable? N / Nullable? N |
currency | enum | Currency of the products in the catalog Accepted values: 3-chars currency code (in ISO-4217 ; e.g. USD , EUR )Writeable? N / Nullable? Y |
rowCount | integer | Number of products available in the catalog (available when reach success status)Accepted values: int32 Writeable? N / Nullable? Y |
fileSizeBytes | integer | File size of catalog, in bytes (available when reach success status)Accepted values: int32 Writeable? N / Nullable? Y |
md5Checksum | string | MD5 checksum of catalog's content (available when reach success status)Accepted values: 32-char alpha-numeric strings Writeable? N / Nullable? Y |
createdAt | timestamp | Timestamp of catalog creation, in UTC Accepted values: yyyy-mm-ddThh:mm:ss±hh:mm (in ISO-8601)Writeable? N / Nullable? N |
message | string | Optional informative message, for developer consumption Accepted values: string Writeable? N / Nullable? Y |
Catalog Output Response Attributes
Attribute | Data Type | Description |
---|---|---|
id | string | Product ID, defined by the retailer Accepted values: up to 500-chars string Writeable? N / Nullable? N |
name | string | Product name, defined by the retailer Accepted values: up to 1000-chars string Writeable? N / Nullable? N |
category | string | Product category, defined by the retailer Accepted values: up to 1000-chars string Writeable? N / Nullable? Y |
brandName | string | Brand name of the product; brands are standardized across retailers Accepted values: up to 120-chars string Writeable? N / Nullable? Y |
retailerId | string | Retailer ID that contains the product offer Accepted values: string of int64 Writeable? N / Nullable? N |
retailerName | string | Retailer name that contains the product offer Accepted values: up to 100-chars string Writeable? N / Nullable? N |
price | decimal | Current product price in the respective retailer Accepted values: price ≥ 0.0Writeable? N / Nullable? Y |
isInStock | boolean | Flag defining if product is currently in stock or not Accepted values: true , false Writeable? N / Nullable? N |
minBid | decimal | Minimum Cost-Per-Click (CPC) an advertiser must bid for the product, established by the retailer Any Line Item with this product must have its targetBid satisfying this valueAccepted values: minBid > 0.0Writeable? N / Nullable? Y |
gtin | string | Global Trade Item Number (GTIN), if available; also known as European Article Number (EAN) or Universal Product Code (UPC) Accepted values: up to 14-chars numeric string Writeable? N / Nullable? Y |
mpn | string | Manufacturer Part Number (MPN), if available Accepted values: up to 70-chars string Writeable? N / Nullable? Y |
imageUrl | string | HTTP URL of the product image provided by the retailer Accepted values: string Writeable? N / Nullable? N |
updatedAt | timestamp | Timestamp of last product info update in retailer's catalog, in UTC Accepted values: yyyy-mm-ddThh:mm:ss±hh:mm (in ISO-8601 )Writeable? N / Nullable? N |
Catalog Asynchronous Workflow: Step 1 of 3
- Create a request for the latest catalog of the specified account using the appropriate endpoint.
- This action generates a
catalogId
that represents the account's catalog.- Catalog requests are cached for 1 hour, meaning repeated requests within this timeframe will return the same
catalogId
and output.
Create a Catalog Request for Brand account
This endpoint creates a request for the latest available catalog for a specific account

https://api.criteo.com/{version}/retail-media/accounts/{accountId}/catalogs
Best Practice Tip!
To speed up catalog downloads, you can narrow down the results by using the
brandIdFilter
body parameter. This allows you to filter the catalog by specific brands, helping to return results faster.
Sample Request
curl -L -X POST 'https://api.criteo.com/{version}/retail-media/accounts/18446744073709551616/catalogs' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer <MY_ACCESS_TOKEN>' \
--data-raw '{
"data": {
"type": "RetailMediaCatalogStatus",
"attributes": {
"format": "json-newline",
"brandIdFilter": [
"40115",
"9092"
]
}
}
}'
import requests
import json
url = "https://api.criteo.com/{version}/retail-media/accounts/18446744073709551616/catalogs"
payload = json.dumps({
"data": {
"type": "RetailMediaCatalogStatus",
"attributes": {
"format": "json-newline",
"brandIdFilter": [
"4768"
]
}
}
})
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 \"type\": \"RetailMediaCatalogStatus\",\n \"attributes\": {\n \"format\": \"json-newline\",\n \"brandIdFilter\": [\n \"4768\"\n ]\n }\n }\n}");
Request request = new Request.Builder()
.url("https://api.criteo.com/{version}/retail-media/accounts/18446744073709551616/catalogs")
.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/accounts/18446744073709551616/catalogs');
$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 "type": "RetailMediaCatalogStatus",\n "attributes": {\n "format": "json-newline",\n "brandIdFilter": [\n "4768"\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
{
"data": {
"id": "1122850670915847014",
"type": "RetailMediaCatalogStatus",
"attributes": {
"status": "pending",
"currency": null,
"rowCount": null,
"fileSizeBytes": null,
"md5Checksum": null,
"createdAt": "2024-04-06T05:11:41.351+00:00",
"message": null
}
}
}
Catalog Asynchronous Workflow: Step 2 of 3
After generating a
catalogId
, use it to poll the catalog status endpoint to check the progress. Continue polling until the catalog is successfully created and ready for download.
Create a Catalog Request for Seller account
This endpoint creates catalog for a particular Seller account:

https://api.criteo.com/{version}/retail-media/accounts/{accountId}/catalogs/sellers
Sample Request
curl --location 'https://api.criteo.com/{version}/retail-media/accounts/18446744073709551616/catalogs/sellers' \
--header 'Content-Type: application/json' \
--header 'Accept: text/plain' \
--header 'Authorization: Bearer <TOKEN>' \
--data '{
"data": {
"type": "RetailMediaCatalogStatus",
"attributes": {
"sellers": [
{
"retailerId": "123",
"sellerId": "60axxxxxxxxxxxxxxxx"
}
]
}
}
}'
import requests
import json
url = "https://api.criteo.com/{version}/retail-media/accounts/18446744073709551616/catalogs/sellers"
payload = json.dumps({
"data": {
"type": "RetailMediaCatalogStatus",
"attributes": {
"sellers": [
{
"retailerId": "123",
"sellerId": "60axxxxxxxxxxxxxxxx"
}
]
}
}
})
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 \"type\": \"RetailMediaCatalogStatus\",\n \"attributes\": {\n \"sellers\": [\n {\n \"retailerId\": \"123\",\n \"sellerId\": \"60axxxxxxxxxxxxxxxx\"\n }\n ]\n }\n }\n}");
Request request = new Request.Builder()
.url("https://api.criteo.com/{version}/retail-media/accounts/18446744073709551616/catalogs/sellers")
.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/accounts/18446744073709551616/catalogs/sellers');
$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 "type": "RetailMediaCatalogStatus",\n "attributes": {\n "sellers": [\n {\n "retailerId": "123",\n "sellerId": "60axxxxxxxxxxxxxxxx"\n }\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
{
"data": {
"id": "1122850670915847014",
"type": "RetailMediaCatalogStatus",
"attributes": {
"status": "success",
"currency": "USD",
"rowCount": 369318,
"fileSizeBytes": 216634050,
"md5Checksum": "713f2d3c0ed718125a1acdef05224df5",
"createdAt": "2025-01-17T22:45:11.44+00:00",
"message": null
}
}
}
Get Status of a Specific Catalog
This endpoint retrieves the status of a specific catalog. Status can be pending
, success
, failure
, or expired

https://api.criteo.com/{version}/retail-media/catalogs/{catalogId}/status
Sample Request
curl -X GET "https://api.criteo.com/{version}/retail-media/catalogs/1122850670915847014/status" \
-H "Authorization: Bearer <MY_ACCESS_TOKEN>"
import requests
url = "https://api.criteo.com/{version}/retail-media/catalogs/357957813719011328/status"
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/catalogs/357957813719011328/status")
.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/catalogs/357957813719011328/status');
$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": "1122850670915847014",
"type": "RetailMediaCatalogStatus",
"attributes": {
"status": "success",
"currency": "USD",
"rowCount": 1001,
"fileSizeBytes": 353293,
"md5Checksum": "2c15b77740028435ca476823df7fb4f8",
"createdAt": "2020-04-06T05:11:41.351+00:00",
"message": null
}
}
}
Catalog Asynchronous Workflow: Step 3 of 3
Once the catalog is successfully created, use the catalog output endpoint to download the collection of catalog products. Note that catalog outputs are typically available for 72 hours before they expire, so be sure to download them within this time frame.
Download Output of a Specific Catalog
This endpoint returns the products in a specific catalog as a newline-delimited JSON byte stream

https://api.criteo.com/{version}/retail-media/catalogs/{catalogId}/output
Sample Request
curl -X GET "https://api.criteo.com/{version}/retail-media/catalogs/1122850670915847014/output" \
-H "Authorization: Bearer <MY_ACCESS_TOKEN>"
import http.client
conn = http.client.HTTPSConnection("api.criteo.com")
payload = ''
headers = {
'Accept': 'application/x-json-stream',
'Authorization': 'Bearer <MY_ACCESS_TOKEN>'
}
conn.request("GET", "/{version}/retail-media/catalogs/357957813719011328/output", 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/catalogs/357957813719011328/output")
.method("GET", body)
.addHeader("Accept", "application/x-json-stream")
.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/catalogs/357957813719011328/output');
$request->setMethod(HTTP_Request2::METHOD_GET);
$request->setConfig(array(
'follow_redirects' => TRUE
));
$request->setHeader(array(
'Accept' => 'application/x-json-stream',
'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 - Brand Catalog
{ \
"id": "sku1", \
"name": "Product One", \
"category": "category1", \
"brandId": "7672171780147256541", \
"brandName": "Brand 123", \
"retailerId": "3239117063738827231", \
"retailerName": "Retailer 123", \
"price": 1.00, \
"isInStock": true, \
"minBid": 0.30, \
"gtin": "abc123", \
"mpn": "789xyz", \
"imageUrl": "/image1.jpg", \
"updatedAt": "2020-04-06T02:23:07Z" \
}
// ... newline-delimited, no comma
{ \
"id": "product-1001", \
"name": "Product One Thousand and One", \
"category": "category2", \
"brandId": "7672171780147256541", \
"brandName": "Brand 123", \
"retailerId": "18159942378514859684", \
"retailerName": "Retailer 789", \
"price": 5.00, \
"isInStock": false, \
"minBid": 0.45, \
"gtin": "none", \
"mpn": "none", \
"imageUrl": "/image1001.jpg", \
"updatedAt": "2020-04-06T01:07:23Z" \
}
Sample Response - Seller Catalog
{ \
"id": "86833674", \
"name": "Flat Front Short 46 x 10.5\" - Black", \
"category": "clothing, shoes & accessories|men’s clothing|bottoms|shorts", \
"categoryId": "3051218", \
"brandId": "40095", \
"brandName": "Test Brand", \
"retailerId": "131", \
"retailerName": "Retailer Name", \
"price": 39.99, \
"isInStock": true, \
"minBid": 0.4000, \
"gtin": "1234567890", \
"mpn": null, \
"imageUrl": "https://example.com/is/image/a610-881aa9a71c93", \
"updatedAt": "2024-07-25T19:52:30Z", \
"sellerId": "60axxxxxxxxxxxxxxxx", \
"sellerName": "Test Seller" \
}
// ... newline-delimited, no comma
{ \
"id": "86833235", \
"name": "Pleated Front Short 52 x 10.5\" - String", \
"category": "clothing, shoes & accessories|men’s clothing|bottoms|shorts", \
"categoryId": "3051218", \
"brandId": "40095", \
"brandName": "Test Brand", \
"retailerId": "131", \
"retailerName": "Retailer Name", \
"price": 39.99, \
"isInStock": true, \
"minBid": 0.4000, \
"gtin": "1234567890", \
"mpn": null, \
"imageUrl": "https://example.com/is/image/a610-881aa9a71c93", \
"updatedAt": "2024-07-25T19:52:30Z", \
"sellerId": "60axxxxxxxxxxxxxxxx", \
"sellerName": "Test Seller" \
}
Responses
Response | Description |
---|---|
🟢200 | Success |
🔴 400 | The indicated catalog is not available for retrieval, wait for a success status |
🔴 403 | API user does not have the authorization to make requests to the account ID. For an authorization request, follow the authorization request steps |
Updated 3 days ago