> ## Documentation Index
> Fetch the complete documentation index at: https://developers.criteo.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Partner Billing Report

export const EndpointBadge = ({method = "GET", children}) => {
  const METHOD_STYLES = {
    GET: {
      bg: "mint-bg-[#2AB673]"
    },
    POST: {
      bg: "mint-bg-[#3064E3]"
    },
    PUT: {
      bg: "mint-bg-[#C28C30]"
    },
    PATCH: {
      bg: "mint-bg-[#DA622B]"
    },
    DELETE: {
      bg: "mint-bg-[#CB3A32]"
    },
    API: {
      bg: "mint-bg-black"
    }
  };
  const key = method.toUpperCase();
  const styles = METHOD_STYLES[key] ?? METHOD_STYLES.API;
  return <div className="relative mt-7">
      <span className={`absolute -top-2 -left-2 z-10 ${styles.bg} text-white px-2.5 py-0.5 rounded-full text-xs font-bold tracking-wide`}>
        {key}
      </span>
      {children}
    </div>;
};

## Introduction

The Partner Billing Report (PBR) enables retailers to generate a billing report automatically through the API with custom date ranges and should contain data applicable for the specified retailer identified through the supply account.

***

## Endpoints

The report generation uses an asynchronous endpoint that is used to receive the report creation request (using a POST request); then, using the `reportId` generated, it's possible to check the report status and download the output results using the following GET endpoint requests.

<table>
  <thead>
    <tr>
      <th>
        <p>
          Verb
        </p>
      </th>

      <th>
        <p>
          Endpoint
        </p>
      </th>

      <th>
        <p>
          Description
        </p>
      </th>
    </tr>
  </thead>

  <tbody>
    <tr>
      <td>
        <p>
          <b>
            POST
          </b>
        </p>
      </td>

      <td>
        <p>
          <code>
            /billing/partner-report
          </code>
        </p>
      </td>

      <td>
        <p>
          Request a partner billing report creation
        </p>
      </td>
    </tr>

    <tr>
      <td>
        <p>
          <b>
            GET
          </b>
        </p>
      </td>

      <td>
        <p>
          <code>
            /billing/partner-report/\{reportId}/status
          </code>
        </p>
      </td>

      <td>
        <p>
          Get status of a specific report
        </p>
      </td>
    </tr>

    <tr>
      <td>
        <p>
          <b>
            GET
          </b>
        </p>
      </td>

      <td>
        <p>
          <code>
            /billing/partner-report/\{reportId}/output
          </code>
        </p>
      </td>

      <td>
        <p>
          Download output of a specific report
        </p>
      </td>
    </tr>
  </tbody>
</table>

***

## Report Request Attributes

<table>
  <thead>
    <tr>
      <th>
        <p>
          Attribute
        </p>
      </th>

      <th>
        <p>
          Data Type
        </p>
      </th>

      <th>
        <p>
          Description
        </p>
      </th>
    </tr>
  </thead>

  <tbody>
    <tr>
      <td>
        <p>
          <code>
            accountIds
          </code>
        </p>
      </td>

      <td>
        <p>
          list
        </p>
      </td>

      <td>
        <p>
          Account IDs (currently supports only Supply Account IDs)
        </p>

        <p>
          Accepted values: array of strings/int64
        </p>

        <p>
          Writeable? N / Nullable? N
        </p>
      </td>
    </tr>

    <tr>
      <td>
        <p>
          <code>
            retailerIds
          </code>
        </p>
      </td>

      <td>
        <p>
          list
        </p>
      </td>

      <td>
        <p>
          <a href="/retail-media/v2025.10/docs/retailers">
            Retailer
          </a>

          IDs
        </p>

        <p>
          Accepted values: array of strings/int64
        </p>

        <p>
          Writeable? N / Nullable? N
        </p>
      </td>
    </tr>

    <tr>
      <td>
        <p>
          <code>
            startDate
          </code>

          <span>\*</span>
        </p>
      </td>

      <td>
        <p>
          date
        </p>
      </td>

      <td>
        <p>
          Start date of the report (inclusive)
        </p>

        <p>
          Accepted values:

          <code>
            yyyy-mm-dd
          </code>
        </p>

        <p>
          Writeable? N / Nullable? N
        </p>
      </td>
    </tr>

    <tr>
      <td>
        <p>
          <code>
            endDate
          </code>

          <span>\*</span>
        </p>
      </td>

      <td>
        <p>
          date
        </p>
      </td>

      <td>
        <p>
          End date of the report (inclusive)
        </p>

        <p>
          Accepted values:

          <code>
            yyyy-mm-dd
          </code>
        </p>

        <p>
          Writeable? N / Nullable? N
        </p>
      </td>
    </tr>

    <tr>
      <td>
        <p>
          <code>
            format
          </code>
        </p>
      </td>

      <td>
        <p>
          enum
        </p>
      </td>

      <td>
        <p>
          The format type the report should return results
        </p>

        <p>
          Accepted values:

          <code>
            json
          </code>

          ,

          <code>
            csv
          </code>
        </p>

        <p>
          Default:

          <code>
            json
          </code>
        </p>

        <p>
          Writeable? N / Nullable? N
        </p>
      </td>
    </tr>
  </tbody>
</table>

*\* Required*

<Info>
  **Field Definitions**

  * **Writeable (Y/N)**: Indicates if the field can be modified in requests.
  * **Nullable (Y/N)**: Indicates if the field can accept null/empty values.
  * **Primary Key**: A unique, immutable identifier of the entity, generated internally by Criteo. Primary keys are typically ID fields (e.g., `retailerId`, `campaignId`, `lineItemId`) and are usually required in the URL path.
</Info>

<Info>
  **Reporting Asynchronous Workflow: Step 1/3**

  * First, create a request for Partner Billing Report with the desired attributes
  * This generates a `reportId` representing the report
</Info>

***

## Create a Partner Billing Report request

This endpoint receives requests to create Partner Billing Reports and returns a report `id` (to be used in the next steps) in case the request was successfully created; otherwise, it will expose errors details about the request issues

<EndpointBadge method="post">
  ```http theme={null}
  https://api.criteo.com/{version}/retail-media/billing/partner-report
  ```
</EndpointBadge>

**Sample Request**

<CodeGroup>
  ```bash cURL theme={null}
  curl -L -X POST 'https://api.criteo.com/{version}/retail-media/billing/partner-report' \
      -H 'Content-Type: application/json' \
      -H 'Accept: application/json' \
      -H 'Authorization: Bearer <MY_ACCESS_TOKEN>' \
      -d '{
              "data": {
                  "type": "PartnerBillingReportRequest",
                  "attributes": {
                      "accountIds": [
                          "4257354123567401216"
                      ],
                      "retailerIds": [
                          "1234",
                          "5678"
                      ],
                      "startDate": "2025-01-01",
                      "endDate": "2025-01-31",
                      "format": "json"
                  }
              }
          }'
  ```

  ```python Python expandable theme={null}
  import requests
  import json

  url = "https://api.criteo.com/{version}/retail-media/billing/partner-report"

  payload = json.dumps({
      "data": {
          "type": "<string>",
          "attributes": {
              "accountIds": [
                  "4257354123567401216"
              ],
              "retailerIds": [
                  "1234",
                  "5678"
              ],
              "startDate": "2025-01-01",
              "endDate": "2025-01-31",
              "format": "json"
          }
      }
  })
  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)
  ```

  ```java Java theme={null}
  OkHttpClient client = new OkHttpClient().newBuilder()
    .build();

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

  RequestBody body = RequestBody.create(mediaType, "{\"data\":{\"type\":\"<string>\",\"attributes\":{\"accountIds\":[\"4257354123567401216\"],\"retailerIds\":[\"1234\",\"5678\"],\"startDate\":\"2025-01-01\",\"endDate\":\"2025-01-31\",\"format\":\"json\"}}}");

  Request request = new Request.Builder()
    .url("https://api.criteo.com/{version}/retail-media/billing/partner-report")
    .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 PHP theme={null}
  <?php
  require_once 'HTTP/Request2.php';
  $request = new HTTP_Request2();
  $request->setUrl('https://api.criteo.com/{version}/retail-media/billing/partner-report');
  $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('{"data":{"type":"<string>","attributes":{"accountIds":["4257354123567401216"],"retailerIds":["1234","5678"],"startDate":"2025-01-01","endDate":"2025-01-31","format":"json"}}}');
  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();
  }
  ```
</CodeGroup>

**Sample Response**: Report request successfully created (response status 🟢 `200`)

```json theme={null}
{
    "data": {
        "id": "c19ed799-6747-4815-aa09-d3e04898xxxx",
        "type": "PartnerBillingReportStatusV1",
        "attributes": {
            "status": "success",
            "errorMessage": null,
            "createdAt": "2025-03-27T14:43:28.3788206+00:00"
        }
    },
    "warnings": [],
    "errors": []
}
```

<Info>
  **Reporting Asynchronous Workflow: Step 2/3**

  * Next, use the `reportId` to pull the report status endpoint until one is successfully computed
</Info>

**Sample Response**: Validation error when creating report request (response status 🔴 `400`)

```json theme={null}
{
    "warnings": [],
    "errors": [
        {
            "traceId": "c19ed799-6747-4815-aa09-d3e04898xxxx",
            "type": "validation",
            "code": "model-validation-error",
            "title": "Model validation error",
            "detail": "data.attributes.endDate value is invalid"
        }
    ]
}
```

***

## Get status of specific report

This endpoint retrieves the status of a specific report creation.  Status can be `pending`, `success`, `failure`, or `expired`

<EndpointBadge method="get">
  ```http theme={null}
  https://api.criteo.com/{version}/retail-media/billing/partner-report/{reportId}/status
  ```
</EndpointBadge>

**Sample Request**

```bash theme={null}
curl -L -X GET 'https://api.criteo.com/{version}/retail-media/billing/partner-report/c19ed799-6747-4815-aa09-d3e04898xxxx/status' \
    -H 'Accept: application/json' \
    -H 'Authorization: Bearer <MY_ACCESS_TOKEN>'
```

**Sample Response**

```json theme={null}
{
    "data": {
        "id": "c19ed799-6747-4815-aa09-d3e04898xxxx",
        "type": "PartnerBillingReportStatusV1",
        "attributes": {
            "status": "pending",
            "errorMessage": null,
            "createdAt": "2025-03-27T14:43:28.3788206+00:00"
        }
    },
    "warnings": [],
    "errors": []
}
```

<Info>
  **Reporting Asynchronous Workflow: Step 3/3**

  * Finally, download the report using the report output endpoint
  * Report outputs are cached for at least 1 hour before expiration
</Info>

***

## Download output of specific report

Once the report creation is completed (`"status": "success"` in response above), the report output will be available to download in this endpoint.

The metrics definition of the Partner Billing Report is available in [PBR Metrics](/retail-media/v2025.10/docs/pbr-metrics)

<EndpointBadge method="get">
  ```http theme={null}
  https://api.criteo.com/{version}/retail-media/billing/partner-report/{reportId}/output
  ```
</EndpointBadge>

**Sample Request**

```bash theme={null}
curl -L -X GET "https://api.criteo.com/{version}/retail-media/reports/2e733b8c-9983-4237-aab9-17a4xxxxxx/output" \
    -H 'Accept: application/json' \
    -H "Authorization: Bearer <MY_ACCESS_TOKEN>"
```

**Sample Responses**

```json expandable theme={null}
[
    {
        "AccountName": "Brand A US",
        "AccountExternalId": "525404033764731234",
        "IsUnbillable": "No",
        "AccountCategory": "Network Demand",
        "RetailerName": "My Retailer Shop",
        "AccountService": null,
        "AccountCurrencyCode": "USD",
        "ExternalBalanceId": "525746374845021111",
        "BalanceName": null,
        "PurchaseOrder": null,
        "BalanceStartDate": null,
        "PrivateMarketPaymentOption": null,
        "CampaignExternalId": null,
        "CampaignName": "Brand A - Campaign Jan2025",
        "CampaignType": "SponsoredProducts",
        "BuyType": "Auction",
        "LineItemId": 530088677885964287,
        "LineItemName": "Brand A - My Retailer Shop - Jan2025",
        "WorkingMediaSpend": 100.72000000,
        "CreditSpend": 0.00000000,
        "ValueAddSpend": 0.00000000,
        "Clicks": 394,
        "Impressions": 0,
        "SupplyFeeAmount": 20.14400000,
        "RetailerManagedFeeRate": 0.0,
        "RetailerManagedFeeAmount": 0.0,
        "RetailerAudienceDataFeeAmount": null,
        "CriteoRetailerDataFeeAmount": null,
        "UtcOffset": "-05:00"
    },
    // ...
    {
        "AccountName": "Brand B US",
        "AccountExternalId": "137955447513525678",
        "IsUnbillable": "No",
        "AccountCategory": "Network Demand",
        "RetailerName": "My Retailer Shop",
        "AccountService": null,
        "AccountCurrencyCode": "USD",
        "ExternalBalanceId": "390893529643232222",
        "BalanceName": null,
        "PurchaseOrder": null,
        "BalanceStartDate": null,
        "PrivateMarketPaymentOption": null,
        "CampaignExternalId": null,
        "CampaignName": "Brand B - Auction 2025",
        "CampaignType": "SponsoredProducts",
        "BuyType": "Auction",
        "LineItemId": 592048399992061951,
        "LineItemName": "Brand B - My Retailer Shop - Jan2025",
        "WorkingMediaSpend": 1497.28125424,
        "CreditSpend": 0.00000000,
        "ValueAddSpend": 0.00000000,
        "Clicks": 5312,
        "Impressions": 0,
        "SupplyFeeAmount": 299.45625082,
        "RetailerManagedFeeRate": 0.0,
        "RetailerManagedFeeAmount": 0.0,
        "RetailerAudienceDataFeeAmount": null,
        "CriteoRetailerDataFeeAmount": null,
        "UtcOffset": "-05:00"
    }
]
```

***

## Responses

<table>
  <thead>
    <tr>
      <th>
        <p>
          Response
        </p>
      </th>

      <th>
        <p>
          Title
        </p>
      </th>

      <th>
        <p>
          Detail
        </p>
      </th>

      <th>
        <p>
          Troubleshooting
        </p>
      </th>
    </tr>
  </thead>

  <tbody>
    <tr>
      <td>
        <p>
          🟢

          <code>
            200
          </code>
        </p>
      </td>

      <td />

      <td />

      <td>
        <p>
          Call executed with success
        </p>
      </td>
    </tr>

    <tr>
      <td>
        <p>
          🟢

          <code>
            201
          </code>
        </p>
      </td>

      <td />

      <td />

      <td>
        <p>
          Report request created with success
        </p>
      </td>
    </tr>

    <tr>
      <td>
        <p>
          🔴

          <code>
            400
          </code>
        </p>
      </td>

      <td>
        <p>
          <b>
            Validation error
          </b>
        </p>
      </td>

      <td>
        <p>
          Invalid date range. Maximum allowed is 31 days.
        </p>
      </td>

      <td>
        <p>
          Review the

          <code>
            startDate
          </code>

          and

          <code>
            endDate
          </code>

          provided, ensuring their maximum interval of 31 days
        </p>
      </td>
    </tr>

    <tr>
      <td>
        <p>
          🔴

          <code>
            400
          </code>
        </p>
      </td>

      <td>
        <p>
          <b>
            Model Validation error
          </b>
        </p>
      </td>

      <td>
        <p>
          <code>
            data.atributes.xxx
          </code>

          value is invalid.
        </p>
      </td>

      <td>
        <p>
          Review the value of respective field provided, ensuring it was informed with a valid format
        </p>
      </td>
    </tr>

    <tr>
      <td>
        <p>
          🔴

          <code>
            403
          </code>
        </p>
      </td>

      <td>
        <p>
          <b>
            The scope Billing is missing
          </b>
        </p>
      </td>

      <td>
        <p>
          The scope Billing is required to access this endpoint and is missing from the provided token
        </p>
      </td>

      <td>
        <p>
          The respective API app doesn't have access to the domain/scope Billing. Review the Types of Permissions in

          <a href="/retail-media/v2025.10/docs/authorization-requests">
            Authorization Requests
          </a>
        </p>
      </td>
    </tr>

    <tr>
      <td>
        <p>
          🔴

          <code>
            403
          </code>
        </p>
      </td>

      <td>
        <p>
          <b>
            Authorization error
          </b>
        </p>
      </td>

      <td>
        <p>
          Resource access forbidden: all the accounts/retailers are not accessible.
        </p>
      </td>

      <td>
        <p>
          Review the Account/Retailer ID(s) provided in the report request
        </p>
      </td>
    </tr>
  </tbody>
</table>

## What's next

* [PBR Metrics](/retail-media/v2025.10/docs/pbr-metrics)
