Third-party data usage and spend

The thirdPartyDataUsageReporting GraphQL query provides on-demand access to third-party data usage and spend across a partner's advertisers. This eliminates the wait for emailed reports (such as for billing) and gives you greater control through improved visibility and reduced complexity.

Intended use

You can use the thirdPartyDataUsageReporting query to do the following:

NOTE: Your existing API login is used for The Trade Desk platform authentication. No additional roles or permissions are required, and the thirdPartyDataUsageReporting GraphQL query accesses partner data using the existing tokens.

Behavior and limitations

Here's what you need to know about the thirdPartyDataUsageReporting query:

The following sections cover key concepts and provide a query example for checking usage reporting data from a third-party data provider as well as an advanced query example for looking up more than one million data segments at once. There is also a reference for the fields returned by this query.

Filter by date

The thirdPartyDataUsageReporting query supports date filtering through the where block. The date filter is optional. If not used, the API automatically applies a default 31-day window ending at the current date. When using date filters, be aware of the following limitations:

Limitation Description Notes
Lookback window Your start date must fall within the previous 60 days. Queries with a start date older than 60 days will return a validation error.
Maximum date range A single query can span a maximum of 31 days. If you need data covering a longer period, issue multiple queries in consecutive windows and combine the results.
Granularity Daily is the finest level of granularity available. Hourly breakdowns are not supported.

Here are additional tips for optimizing date filtering:

Dates are passed in the where block using the gte (greater than or equal to) and lt (less than) operators. To ensure your query covers the intended range, provide both bounds explicitly, as shown in the following snippet.

where: {
  date: {
    gte: "2026-03-01"
    lt:  "2026-04-01"
  }
}

NOTE: All dates are interpreted as UTC.

Define date ranges

To capture complete data with non-overlapping windows, use only the gte and lt fields, not gt or lte. Using lt for the end date captures the entire last day and keeps the query ranges clean. For example, to retrieve all of February 2026, use the following snippet:

where: {
  date: {
    gte: "2026-02-01"   # correct
    lt:  "2026-03-01"   # correct
  }
}

To cover March and April 2026 as two separate queries, use the following snippet:

# Query 1 — March
where: { date: { gte: "2026-03-01", lt: "2026-04-01" } }
 
# Query 2 — April
where: { date: { gte: "2026-04-01", lt: "2026-05-01" } }

Using lte: "2026-03-31" instead would match only up to the start of that day in UTC, meaning data for the remainder of March 31 could be missed. Using lt: "2026-04-01" is the explicit and reliable way to include all of March 31.

Query up to 60 days

To query the full 60-day window, split your request into two calls, one for days 60–30 and one for days 30–0, since each query is capped at 31 days. Paginate each call independently until the hasNextPage value is false, then sum the dataCostInUSD value and impressions across all nodes from both result sets.

NOTE: Update the following query examples each time you run the query, as hardcoded dates will eventually fall outside the 60-day lookback period. If you're automating this workflow, calculate date windows dynamically each run.

Here's an example of the ThirdPartyDataProviderWindowOne query for days 60-30.

query ThirdPartyDataProviderWindowOneExample {
  thirdPartyDataProvider(id: "3PD_PROVIDER_ID_PLACEHOLDER") {
    reporting {
      thirdPartyDataUsageReporting(
        where: {
          date: {
            gte: "2026-02-06"
            lt: "2026-03-08"
          }
        }
        first: 10000
        after: null
      ) {
        totalCount
        nodes {
          metrics {
            dataCostInUSD
            impressions
          }
          dimensions {
            thirdPartyDataBrand {
              name
              id
            }
          }
        }
        pageInfo {
          endCursor
          hasNextPage
        }
      }
    }
  }
}

And here's an example of the ThirdPartyDataProviderWindowTwo query for days 30 to today.

query ThirdPartyDataProviderWindowTwoExample {
  thirdPartyDataProvider(id: "3PD_PROVIDER_ID_PLACEHOLDER") {
    reporting {
      thirdPartyDataUsageReporting(
        where: {
          date: {
            gte: "2026-03-08"
            lt: "2026-04-07"
          }
        }
        first: 10000
        after: null
      ) {
        totalCount
        nodes {
          metrics {
            dataCostInUSD
            impressions
          }
          dimensions {
            thirdPartyDataBrand {
              name
              id
            }
          }
        }
        pageInfo {
          endCursor
          hasNextPage
        }
      }
    }
  }
}

Filter by brand ID

You can filter results to a specific third-party data brand using the brandId filter inside the where block. It accepts an eq (equals) operator with a string value matching the brand ID.

The brandId filter can be used on its own or combined with a date filter in the same where block, as shown in the following snippet.

NOTE: Passing an empty string or a value that parses incorrectly will return an error. See [Filter Input Errors]. Passing a valid but non-existent brand ID will return empty results with no error.

 thirdPartyDataUsageReporting(
  where: {
    brandId: { eq: "YOUR_BRAND_ID" }
    date: { gte: "2026-03-01", lt: "2026-04-01" }
  }
  first: 10000
  after: null
)

Paginate results

When using pagination (cursor-based), you can retrieve up to 10,000 pages in a single call. For example, set the first field to 10000 to return 10,000 pages.

IMPORTANT: Never assume a single call returns all data. Be sure to verify the hasNextPage field. If it is set to false, then all data has been returned.

To use pagination, do the following:

  1. In the first call, set the after field to null.
  2. In subsequent calls, pass the endCursor value from the pageInfo field as the after argument.
  3. Stop pagination when the hasNextPage field is set to false.

Look up data usage

Here's a thirdPartyDataUsageReporting query example for retrieving usage reporting data for a specific third-party data provider by the specified date range, limited to one node per page. It returns metrics like impressions and cost, as well as dimensions such as time, partner, advertiser, campaign, ad group, and data provider details.

query GetThirdPartyDataUsageExample {
  thirdPartyDataProvider(id: "3PD_PROVIDER_ID_PLACEHOLDER") {
    reporting {
      thirdPartyDataUsageReporting(
        after: "END_CURSOR_TOKEN"  # First call can be null. After that, pass in the value returned in the previous iteration.
        where: {
          date: {
            gte: "ISO_8601_START_DATE_PLACEHOLDER"
            lte: "ISO_8601_END_DATE_PLACEHOLDER"
          }
        }
        first: 10000
      ) {
        pageInfo {
          endCursor
          hasNextPage
        }
        totalCount
        nodes {
          dimensions {
            partnerBasicInfo {
              name
              id
            }
            advertiserBasicInfo {
              name
              id
            }
            campaignBasicInfo {
              name
              id
            }
            adGroupBasicInfo {
              name
              id
            }
            thirdPartyData {
              targetingData {
                id
              }
              fullPath
              providerElementId
            }
            thirdPartyDataBrand {
              name
              id
            }
          }
          metrics {
            impressions
            dataCostInUSD
          }
        }
      }
    }
  }
}

Look up large taxonomy (over one million segments)

If the provider has more than one million data segments, use the following workflow:

  1. Retrieve segment IDs only.
  2. Retrieve dimensions for the segment IDs.

Retrieve segment IDs only

Use the thirdPartyDataUsagePGIdsOnly query with the thirdPartyData.id field to retrieve segment IDs first, as shown in the following example:

query thirdPartyDataUsagePGIdsOnlyExample {
  thirdPartyDataProvider(id: "3PD_PROVIDER_ID_PLACEHOLDER") {
    reporting {
      thirdPartyDataUsageReporting(
        first: 10000
        where: {
          date: {
            gte: "2026-02-01"
            lt: "2026-03-01"
          }
        }
        after: "PREV_END_CURSOR_TOKEN"  # null on first call
      ) {
        pageInfo {
          endCursor
          hasNextPage
        }
        totalCount
        nodes {
          dimensions {
            thirdPartyData {
              id
            }
          }
        }
      }
    }
  }
}

Retrieve dimensions for segment IDs

To retrieve comprehensive dimensions and metrics, run the thirdPartyDataUsageReporting query and include the segment IDs obtained from the previous step in the thirdPartyDataIds filter. For best performance, group the IDs into batches of up to 1000 per request:

query thirdPartyDataUsageExample {
  thirdPartyDataProvider(id: "3PD_PROVIDER_ID_PLACEHOLDER") {
    reporting {
      thirdPartyDataUsageReporting(
        after: "END_CURSOR_TOKEN"  # First call can be null. After that, pass in the value returned in the previous iteration.
        where: {
          date: {
            gte: "ISO_8601_START_DATE_PLACEHOLDER"
            lte: "ISO_8601_END_DATE_PLACEHOLDER"
          },
          thirdPartyDataIds: {
            in: [
              "SEGMENT_ID_PLACEHOLDER_1",
              "SEGMENT_ID_PLACEHOLDER_2",
              "SEGMENT_ID_PLACEHOLDER_3",
              "SEGMENT_ID_PLACEHOLDER_4"  # Add more IDs here as needed. For best results, fetch up to 1000 IDs at a time.
            ]
          }
        }
        first: 10000
      ) {
        pageInfo {
          endCursor
          hasNextPage
        }
        totalCount
        nodes {
          dimensions {
            partnerBasicInfo {
              name
              id
            }
            advertiserBasicInfo {
              name
              id
            }
            campaignBasicInfo {
              name
              id
            }
            adGroupBasicInfo {
              name
              id
            }
            thirdPartyData {
             targetingData {
                id
              }
              fullPath
              providerElementId
            }
            thirdPartyDataBrand {
              name
              id
            }
          }
          metrics {
            impressions
            dataCostInUSD
          }
        }
      }
    }
  }
}

Field reference

The following table lists different fields that the thirdPartyDataUsageReporting query returns.

Field Name Description
partnerBasicInfo.name The name of the partner associated with the advertiser included in the data usage report.
partnerBasicInfo.id The ID of the partner.
advertiserBasicInfo.name The name of the advertiser included in the data usage report.
advertiserBasicInfo.id The ID of the advertiser.
campaignBasicInfo.name The name of the campaign included in the data usage report.
campaignBasicInfo.id The unique platform ID assigned to the campaign.
adGroupBasicInfo.name The name of the ad group within the campaign included in the data usage report.
adGroupBasicInfo.id The unique platform ID assigned to the ad group.
thirdPartyData.id The unique ID of the third-party data provider.
thirdPartyData.providerElementId The unique ID you (the third-party provider) assigned to the segment when designing your taxonomy. Also known as the segment ID, this ID is used to identify a data segment that you uploaded.
thirdPartyData.targetingData.id The advertiser targeting data ID from the targeting data group.
thirdPartyData.fullPath The full hierarchical path representing the data segment within the third-party data taxonomy.
thirdPartyDataBrand.name The name of the brand associated with the third-party data provider.
thirdPartyDataBrand.id The third-party data brand ID associated with the third party data ID in the targeting data group.
impressions The total number of ad impressions served.
dataCostInUSD The total cost of the data usage in U.S. dollars.

Error messages and codes

The following sections cover common errors, validation rules, and silent failure conditions you may encounter using the thirdPartyDataUsageReporting query.

Authorization

The API checks the Permission.General_Edit field on the ThirdPartyDataProvider entity. Dimensions and data values are not subject to separate permission checks. If you receive a "not found" error, confirm the following before escalating:

The following table describes "not found" error messages and their root cause.

Message Error
"The entity was not found." Provider ID not authorized
"At least one of the entities were not found." Bulk authorization failure

Date range

Keep the following limitations in mind when setting the date range for your query.

The following table describes date-range error messages and their root cause.

Message Error
"The requested time range exceeds the allowed limit. Start date must be on or after {date} UTC (up to 60 days prior to today)." Start date beyond 60-day lookback (no time dimension)
"The requested date range is too long. Limit daily aggregated queries to 31 days." Date range exceeds 31 days (no time dimension)
"The requested time range for daily reports exceeds the allowed limit..." Start date beyond lookback or range exceeds 31 days (with Day dimension)
"The requested time range for hourly reports exceeds the allowed limit..." Any hourly or datetime dimension query

Filter input

The following table describes filter-input error messages and their root cause.

NOTE: Date filters default to UTC if no timezone is specified.

Message Error
"Unable to parse value {value} as a datetime." Unparseable date in date filter
"Attempted to pass in a null or empty string for an eq operation." Empty string for brandId (eq)
"Attempted to pass in a null or empty list for an in operation." Empty list for thirdPartyDataIds (in)
"Attempted to pass in an invalid value for an eq operation." Invalid type for thirdPartyDataIds (eq)
"Attempted to pass in an invalid value in an in operation." Invalid type in thirdPartyDataIds list (in)
"Attempted to pass in an empty list for an in operation." Empty list after parsing thirdPartyDataIds (in)

Silent failures

Silent failures are the most dangerous errors. The query succeeds but returns incomplete or empty data with no indication that something is wrong.

The following table describes each silent failure scenario.

Error Description
Valid format but unrecognized thirdPartyDataIds or brandId values. Returns empty results with no error. Always verify IDs before querying.
Day dimension used without the required feature flag. The dimension is silently omitted from results rather than returning an error. If a provider reports missing time-breakdown data, confirm that the ReportingMetricsAccessThirdPartyDataReportingDataUsageTimeDimensionFeatureFlag flag is enabled for their account.