User-defined report schedules
After creating User-defined report templates, you must create schedules for those templates before you can generate one-time or recurring reports.
You can use the GraphQL and REST APIs to manage report schedules. The following table lists the report schedule tasks you can accomplish with these APIs.
| Report Schedule Task | GraphQL | REST |
|---|---|---|
| Create a report schedule. | Yes | Yes |
| Cancel a report being processed. | Yes | No |
| Rerun a report even if the recurring schedule is complete. | Yes | No |
| Delete a report schedule. | Yes | Yes |
| Update a current schedule. | Yes | No |
| Retrieve past report schedules. | Yes | Yes |
Here's what you need to know about report schedules regardless of which API you use:
- You can schedule reports for individual advertisers or for multiple advertisers.
- There is a limit of 100 report schedules per partner API account.
- To create a one-time or recurring report, you must first create a report template. For details, see User-defined report templates.
- After a report is finished processing, you can retrieve its download link and the status of the recurring schedule.
- You can retrieve a list of reports that you ran in the past.
Report schedules in GraphQL
NOTE: This section is intended for advertisers in The Trade Desk platform who want to manage report schedules using GraphQL. If you are a vendor providing reporting services on the advertiser's behalf, you must use the REST API to schedule reports.
The following table lists the tasks for retrieving and managing reports and their schedules.
| Task | Query or Mutation | Notes |
|---|---|---|
| Schedule a recurring report. | myReportsTemplateScheduleCreate |
You can schedule daily, weekly, monthly, and quarterly recurring reports. |
| Generate a one-time report. | myReportsTemplateScheduleCreate |
None. |
| Run a recurring report immediately. | myReportsReportScheduleCreate mutation |
All mutations require the report schedule ID that you can retrieve using the myReportsReportSchedules query. |
| Retrieve report and schedule details. | myReportsReportSchedules querymyReportsReportSchedule query |
Use these queries to retrieve report status, IDs, download links, and other details, and to apply filters as needed. |
| Update a recurring report schedule. | myReportsReportScheduleUpdate mutation |
Use this mutation to disable report schedules or to activate disabled ones. |
| Cancel a report in progress. | myReportsReportExecutionCancel mutation |
Use this mutation to cancel a report before it is processed. |
| Delete a recurring report schedule. | myReportsReportScheduleDelete mutation |
None. |
Schedule a recurring report
To schedule a recurring report, use the GraphQL myReportsTemplateScheduleCreate mutation. Include the report template ID and set the frequency value to define the cadence. The following example shows how to schedule a weekly report.
IMPORTANT: The download link requires an API token. To retrieve a regular link you can click to download the report without authentication, include the
emailsfield and send the report to an email address.
mutation {
myReportsTemplateScheduleCreate(
input: {
templateId: "4711075"
reportName: "REPORT_NAME_PLACEHOLDER"
startDate: "2025-10-10T00:00:00Z"
frequency: WEEKLY
dateRange: LAST14_DAYS
timezone: UTC
format: EXCEL
includeHeaders: true
dateFormat: US
numericFormat: US
emails: ["EMAIL_ADDRESS_PLACEHOLDER"]
reportFilters: [
{ reportType: "1", partnerIds: ["PARTNER_ID_PLACEHOLDER"] }
{ reportType: "10", partnerIds: ["PARTNER_ID_PLACEHOLDER"] }
]
conversionMetricOrdering: ALPHABETICALLY_BY_COLUMN_NAMES
tailAggregations: [{ columnId: 15, tailAggregation: NO_IMPRESSIONS }]
suppressTotals: false
suppressZeroMeasureRows: false
}
) {
data {
scheduleId
}
errors {
__typename
... on MutationError {
field
message
}
}
}
}
Generate a one-time report
To generate a one-time report, use the GraphQL myReportsTemplateScheduleCreate mutation. Include the report template ID and set the frequency value to SINGLE_RUN.
IMPORTANT: The download link requires an API token. To retrieve a regular link you can click to download the report without authentication, include the
emailsfield and send the report to an email address.
mutation {
myReportsTemplateScheduleCreate(
input: {
templateId: "4711075"
reportName: "REPORT_NAME_PLACEHOLDER"
startDate: "2025-10-10T00:00:00Z"
frequency: SINGLE_RUN
dateRange: LAST14_DAYS
timezone: UTC
format: EXCEL
includeHeaders: true
dateFormat: US
numericFormat: US
emails: ["EMAIL_ADDRESS_PLACEHOLDER"]
reportFilters: [
{ reportType: "1", partnerIds: ["PARTNER_ID_PLACEHOLDER"] }
{ reportType: "10", partnerIds: ["PARTNER_ID_PLACEHOLDER"] }
]
conversionMetricOrdering: ALPHABETICALLY_BY_COLUMN_NAMES
tailAggregations: [{ columnId: 15, tailAggregation: NO_IMPRESSIONS }]
suppressTotals: false
suppressZeroMeasureRows: false
}
) {
data {
scheduleId
}
errors {
__typename
... on MutationError {
field
message
}
}
}
}
Retrieve report and schedule details
To retrieve a list of reports and their schedules, processing statuses, and other details, use the GraphQL myReportsReportSchedules query. Here's what you need to know about this query:
- You can retrieve the status and the download link in the same query.
- There are multiple filters available at the partner, advertiser, campaign, and ad group level. For example, you can filter by name, last status change date, lookback window type, and so on.
- To retrieve the download link, include the
executions.delivery.downloadLinkfield. This download link requires an API token. - If the report is in the
COMPLETEDstate, you can retrieve the download link and view the report. - If needed, you can use the returned schedule ID in the
nodes.idfield from the query to perform additional tasks such as rerunning the report. - To check the status and retrieve the schedule of a single report, use the
myReportsReportSchedulequery and include the schedule ID. You can also include thescheduleIdvalue from when you scheduled the recurring report.
Here's an example of how to retrieve reports based on the last status change date. This also returns a list of schedule IDs in the nodes.id field.
query GetReportDetailsExample {
myReportsReportSchedules(
where: {
executions: { some: { lastStatusChangeDate: { gte: "2025-07-01" } } }
}
) {
nodes {
id
name
status
filters {
advertiserFilters {
name
}
partnerFilters {
name
}
}
timezone
executions {
nodes {
id
reportStartDateInclusive
reportEndDateExclusive
lastStatusChangeDate
state
delivery {
downloadLink
deliveredDate
}
}
}
}
pageInfo {
hasNextPage
endCursor
}
}
}
Here's an example of retrieving a single report with a schedule ID.
query GetSingleReportDetailsExample {
myReportsReportSchedule(id: "REPORT_SCHEDULE_ID_PLACEHOLDER") {
status
filters {
advertiserFilters {
name
}
partnerFilters {
name
}
}
executions {
nodes {
id
reportStartDateInclusive
reportEndDateExclusive
lastStatusChangeDate
state
delivery {
downloadLink
deliveredDate
}
}
}
}
}
Report statuses (states)
The following table lists the possible values for the state field.
| State Value | Description |
|---|---|
CANCELED |
The system or user stopped the report file from being generated. |
COMPLETED |
The report file generated successfully and is ready for download. |
FAILED |
The system could not generate the report due to an error. |
IN_PROGRESS |
The system is currently generating the report file. |
WAITING_FOR_DEPENDENCIES |
The report file is on hold while waiting for required data or other resources. |
WAITING_FOR_EXECUTION |
The report is queued and waiting to start generation. |
WAITING_FOR_FAILURE_HANDLING |
The report file failed to generate due to an error and is waiting for failure resolution. |
WAITING_FOR_RETRY_AFTER_FAILURE |
The report file failed to generate and is waiting to retry. |
Update a report schedule
To activate a disabled report or disable an active report, use the myReportsReportScheduleUpdate mutation, include the report ID, and set the status to either ACTIVE or DISABLED.
mutation GeneratedTabDisableSchedule {
myReportsReportScheduleUpdate(
input: { reportScheduleId: "REPORT_SCHEDULE_ID_PLACEHOLDER", status: DISABLED }
) {
data {
id
status
}
errors {
__typename
... on MutationError {
field
message
}
}
}
}
Cancel a report in progress
To cancel a report that is currently being processed by the system, use the myReportsReportExecutionCancel mutation and include the report schedule ID. For details about retrieving the schedule ID, see Retrieve report information.
mutation {
myReportsReportExecutionCancel(input: {
executionId: "REPORT_SCHEDULE_ID_PLACEHOLDER"
}) {
data {
isCancelled
}
errors {
__typename
... on MutationError {
field
message
}
}
}
}
Run an existing scheduled report
You might want to rerun a report for the following reasons:
- The download link expired.
- The report resulted in an error.
- You want the most up-to-date data outside the recurring schedule. For example, your weekly report runs on Mondays, but you need fresh data for a meeting on Thursday.
NOTE: If you make updates to a report schedule, you will create a new schedule.
To run a report from an existing schedule, use the myReportsReportScheduleCreate mutation and include the report ID you retrieved.
mutation {
myReportsReportScheduleCreate(
input: {
singleRunFromExistingScheduleInput: {
id: "REPORT_SCHEDULE_ID_PLACEHOLDER"
}
}
) {
data {
id
}
errors {
__typename
... on MutationError {
field
message
}
}
}
}
Delete a recurring schedule
To delete a recurring report schedule, use the myReportsReportScheduleDelete mutation and include the ID of the report you retrieved.
NOTE: If you delete a report schedule, you can still access the report.
mutation {
myReportsReportScheduleDelete(input: {
reportScheduleId: "REPORT_SCHEDULE_ID_PLACEHOLDER",
}) {
data {
isDeleted
}
errors {
__typename
... on MutationError {
field
message
}
}
}
}
Report schedules in REST
The following diagram describes the process of retrieving user-defined reports using the My Reports REST API.
For details on querying for template headers and scheduling reports, see Create and manage report schedules.
Create a report schedule
To create a report schedule, use the POST /myreports/reportschedule endpoint.
Best practices
Here's what you need to keep in mind when creating reports:
- For the most efficient workflow, create partner-level schedules and create schedules with a single-day lookback window. This ensures that completed reports contain the final report data, which is never updated after the report is complete.
- To retrieve all available data for a given date, create schedules with single-day lookback periods, but set the
ScheduleStartDatefield value to a date in the past. - To retrieve historical data, create a one-off schedule for a longer time frames, which you can set in the
ReportDateRangefield. - When setting your custom report start and end dates, be sure to select a valid data range. To get a full month's report on the first of the next month, set the
StartDateInclusiveandEndDateExclusivefields to span a full month. For details, see Best practices for custom report start and end dates.
Request
The following is a JSON example of a POST /myreports/reportschedule request.
{
"ReportScheduleName": "Adgroup Performance Report HD",
"RequestedByUserName": "jane.doe@companyemail.com",
"ReportTemplateId": 168005,
"IsCompleted": true,
"ReportScheduleStatus": "Disabled",
"ReportFileFormat": "TSV",
"PartnerFilters": [
"partner123abc"
],
"ReportDateRange": "LastXDays",
"TimeZone": "UTC",
"ReportDateFormat": "International",
"ReportNumericFormat": "US",
"IncludeHeaders": true,
"LookbackDays": 1,
"ReportFrequency": "Daily",
"ConversionPixelNames": [
{
"AdvertiserId": "adv890xyz",
"ConversionPixelName": "Generic Inc Friends Conversion",
"ConversionType": "abc123", // This is the tracking tag ID.
"CrossDeviceAttributionModelId": "IdentityAlliance"
},
{
"AdvertiserId": "adv890xyz",
"ConversionPixelName": "Landing Page Visit",
"ConversionType": "234def", // This is the tracking tag ID.
"CrossDeviceAttributionModelId": "IdentityAlliance"
},
{
"AdvertiserId": "adv890xyz",
"ConversionPixelName": "Inferred Brand Impact",
"ConversionType": "123abc", // This is the tracking tag ID.
"CrossDeviceAttributionModelId": "IdentityAlliance"
}
]
}
Response
The following is an example of a POST /myreports/reportschedule response with the newly created report schedule.
{
"ReportScheduleId":654321,
"ReportScheduleName":"PartnerID Adgroup Performance Report HD",
"ReportTemplateId":168005,
"ReportFileFormat":"TSV",
"PartnerFilters":[
"partner123abc"
],
"ReportDateRange":"LastXDays",
"TimeZone":"UTC",
"ReportDateFormat":"International",
"ReportNumericFormat":"US",
"IncludeHeaders":true,
"LookbackDays":1,
"ReportFrequency":"Daily",
"ConversionPixelNames":[
{
"AdvertiserId":"adv890xyz",
"ConversionPixelName":"Generic Inc Friends Conversion",
"ConversionType":"abc123",
"CrossDeviceAttributionModelId":"IdentityAlliance"
},
{
"AdvertiserId":"adv890xyz",
"ConversionPixelName":"Landing Page Visit",
"ConversionType":"234def",
"CrossDeviceAttributionModelId":"IdentityAlliance"
},
{
"AdvertiserId":"adv890xyz",
"ConversionPixelName":"Inferred Brand Impact",
"ConversionType":"123abc",
"CrossDeviceAttributionModelId":"IdentityAlliance"
}
]
}
Best practices for custom report start and end dates
When setting a custom date range for your report, ensure that the start and end dates that you specify cover the date range you want.
- Do not enter the same date in the
StartDateInclusiveandEndDateExclusivefields, or you'll get no data for your report. - Setting the
EndDateExclusivevalue to today is only meaningful when today is different from the date you specified in theStartDateInclusivefield. - To get a full month's report on the first of the next month, set the report start and end dates as follows:
- Set the
StartDateInclusivevalue to the first day of the previous month or at least 30 days before theEndDateExclusivedate. - Set the
EndDateExclusivevalue to the first day of the next month or one day after the last date you want to be included in your report, as theEndDateExclusivefield counts up to the last date in the range and excludes that date.
- Set the
The following table provides examples of different date ranges.
| Start Date Inclusive | End DAte Exclusinve | Date Range | Report Duration |
|---|---|---|---|
| May 1 | June 1 | May 1 - May 31 | Full month report. |
| May 1 | May 31 | May 1 - May 30 | Nearly a full month report but the last day is excluded since EndDateExclusive drops the last date in the range. |
| May 1 | May 1 | No data | Zero days. To get a one-day report for May 1, the date range should be May 1 - May 2. See also Best practices. |
The following sections describe the report execution and retrieval steps illustrated in the diagram.
Retrieve a report
Here's what you need to know when using the report execution endpoints:
- Be sure to use the correct endpoint for the report level you need:
- For partner-level reports, use POST /v3/myreports/reportexecution/query/partners.
- For advertiser-level reports, use POST /v3/myreports/reportexecution/query/advertisers.
- Do not include
Content-Typeheaders in the request when downloading a report using a GET call with the Amazon S3 download URL. - Verify that the link has not expired when you download a report using a GET call with the Amazon S3 download URL.
- Be sure to include a trailing period at the end of the URL.
TIP: Download a Python code sample that demonstrates recommended call patterns and best practices for this process. Use it as a starting point for testing in your sandbox environment.
To retrieve a report, complete the following steps.
| Step | Description | Endpoint |
|---|---|---|
| 1 | Retrieve a download URL for the report. | Depending on the report level, use one of the following endpoints:
|
| 2 | Download report data using the obtained download URL. | GET "REPORT_DOWNLOAD_URL_PLACEHOLDER" |
Retrieve a download URL for your report
The following is an example of a POST/v3/myreports/reportexecution/query/partners request with a placeholder for your API token. It retrieves any partner-wide reports for the given date.
curl -H "Content-Type: application/json" -H "TTD-Auth:API_TOKEN_PLACEHOLDER" -X POST "https://api.thetradedesk.com/v3/myreports/reportexecution/query/partners" -d '{"PartnerIds": ["PARTNER_ID_PLACEHOLDER"], "ExecutionStates": ["Complete"], "ExecutionSpansStartDate": "2019-06-20T00:00:00.4837693+00:00", "PageStartIndex": 0, "PageSize": 10}'
The following is an example of a POST /v3/myreports/reportexecution/query/partners response with the report download URL.
{
"Result":[
{
"ReportExecutionId":8247483,
"ReportExecutionState":"Complete",
"LastStateChangeUTC":"2019-06-21T03:32:33.073",
"DisabledReason":null,
"Timezone":"UTC",
"ReportStartDateInclusive":"2019-06-07T00:00:00",
"ReportEndDateExclusive":"2019-06-21T00:00:00",
"ReportScheduleName":"Daily Report",
"ReportDeliveries":[
{
"ReportDestination":"EmailedS3Link",
"DeliveredPath":"thetradedesk-useast-hdreports/scheduled/2019/06/07/SpotX_NGL - Daily Report_18323/Daily Report/ Daily Report NGL_2019-06-07_8247483.tsv",
"DeliveredUTC":"2019-06-21T03:32:33.027",
"DownloadURL":"api.thetradedesk.com/v3/reports/download/{EXECUTION_ID}/{DELIVERY_ID}?t={TIMESTAMP}&s={SIGNATURE}&src={SOURCE}", // The system will replace placeholders in curly braces with actual values.
"DownloadURLExpirationUTC":"2019-06-22T20:27:14.6448956Z"
}
]
}
],
"ResultCount":1,
"TotalFilteredCount":1
}
Download report data
Here's the request syntax for downloading reports with placeholders for your API token and the report download URL:
curl -H "TTD-Auth:API_TOKEN_PLACEHOLDER" -X GET "REPORT_DOWNLOAD_URL_PLACEHOLDER"
The following is an example of a request to view report data with a placeholder for your API token and the download URL returned in the preceding response example. The returned URL will have actual values instead of the placeholders shown in curly braces.
curl -H "TTD-Auth:API_TOKEN_PLACEHOLDER" -X GET "api.thetradedesk.com/v3/reports/download/{EXECUTION_ID}/{DELIVERY_ID}?t={TIMESTAMP}&s={SIGNATURE}&src={SOURCE}"
A successful response returns the contents of the report.
Report filtering
Based on the ReportExecutionStates, ReportScheduleIds, pagination, and other parameters that you specify in the My Reports execution endpoints, reports are filtered from the most general parameters like PageSize to more specific ones like ReportScheduleIds.
The following diagram illustrates the filtering process.
Report execution spans start and end dates
The following table provides guidelines and examples on setting the optional ExecutionSpansStartDate and ExecutionSpansEndDate values in the My Reports execution endpoints.
NOTE: The reporting range refers to the range of data included in a report.
| Property | Value Description | Example |
|---|---|---|
ExecutionSpansStartDate |
Any date prior to the end of the reporting range of your report request. | To pull a week-long report with data from August 1–7, set this parameter to any date on or prior to August 7. |
ExecutionSpansEndDate |
Any date after the start of the reporting range of your report request. | To pull a week-long report with data from August 1–7, set this parameter to any date on or after August 1. |
The following table provides more examples, which assume that you have a daily report set to deliver one day’s worth of data and that today is August 7.
| Data Wanted | Execution Span Start date | Execution Span End date |
|---|---|---|
| All reports that have been run with yesterday’s data (August 6) | August 6 | August 6 |
| Reports containing data for August 5, 6, and 7 | August 5 | August 7 |
| Reports containing data from before August 7 | August 7 | Do not specify |
| Reports containing all data from August 1 | Do not specify | August 1 |
| All reports for all date ranges | Do not specify | Do not specify |
FAQs
The following are frequently asked questions about report processing.
If I rerun a report for the last seven days, will it include data from the original time period or from the most recent seven days?
The regenerated report will use the most recent seven days and will end on the day you regenerated the report. For example, if you rerun a report on July 7 at 10:00 a.m., and the lookback window is 7 days, the report will include data from June 30 at 12:00 a.m. to July 7 at 12:00 a.m. based on the report’s time zone.
Can I cancel a report that is currently processing?
Yes. For details, see Cancel a report in progress.
Why was my report schedule automatically disabled?
The Trade Desk automatically disables a recurring report schedule in either of the following cases:
- The schedule hasn't produced any report data for more than two months.
- The reports generated by this schedule haven't been downloaded for more than 30 days.
In both cases, you receive a warning email two weeks before the schedule is disabled. To check whether a schedule was automatically disabled by the system, use the myReportsReportSchedules query and include the isAdminDisabled and disabledMessage fields. For details on how to reactivate a disabled schedule, see Update a report schedule.
Are all report schedules subject to being automatically disabled?
No. Here are the schedule types that do not get automatically disabled:
- Schedules delivered directly to your own S3 bucket.
- Schedules with exposure feeds, which use a separate expiration process.
If I lost the email that contains the download link for my report, how do I retrieve it?
Use the GraphQL myReportsReportSchedules query and include the downloadLink field. Note that this query returns an API download link, which requires an API token. To retrieve a regular link you can click to download the report without authentication, create a schedule and include an email address.
How do I get a new download link if my original one expired?
Use the myReportsReportScheduleCreate mutation to run the report immediately.
Can I search for campaigns based on the filters I create?
Yes. To retrieve a list of campaigns by the labels you created, use the advertiser query and include the customLabels field. The following is a GraphQL example for retrieving campaigns that have a specific custom label.
query Advertiser {
advertiser(id: "ADVERTISER_ID_PLACEHOLDER") {
campaigns {
edges {
node {
id
name
customLabels(
where: { id: { eq: "CUSTOM_LABEL_PLACEHOLDER" } }
) {
nodes {
id
name
}
}
}
}
}
}
}