You can create and schedule reports using the Google Display \& Video 360 UI or the
API. For example, end users can set up a daily report showing yesterday's
impressions, or a monthly report showing total spend.

> [!NOTE]
> **Note:** Accessing reports using this approach only allows for read-only retrieval of reports that have already been set up in the Display \& Video 360 UI; it does not provide any opportunity to modify existing reports or create new reports.

## Create Scheduled Reports

Create a new scheduled report in the Display \& Video 360 reporting interface or
with the [`queries.create`](https://developers.google.com/bid-manager/reference/rest/v2/queries/create) API method. Full details on
Display \& Video 360's reporting functionality and how to create new reports can be
found in the [Display \& Video 360 support site](https://support.google.com/displayvideo/answer/6375151).

Reports can be scheduled at creation using the `Repeats` field in the UI and the
[`schedule`](https://developers.google.com/bid-manager/reference/rest/v2/queries#Query.FIELDS.schedule) field in the API. These fields should be set to an
appropriate time interval.

After the proper field has been set, this report will run at that schedule and
the generated reports will then be available for download.

## Access Scheduled Reports

Scheduled reports are generated as simple CSV files and are stored automatically
and securely in Google Cloud Storage. It isn't possible, however, to access the
Google Cloud Storage buckets which contain these files directly. Instead, the
files may be manually downloaded from the Display \& Video 360 UI or retrieved
programmatically using [pre-authorized URLs](https://developers.google.com/bid-manager/reference/rest/v2/queries.reports#ReportMetadata.FIELDS.google_cloud_storage_path) obtained from
the API.

An example of using the API to download a report file is provided below. In this
example, [`queries.reports.list`](https://developers.google.com/bid-manager/reference/rest/v2/queries.reports/list) is used with the
[`orderBy`](https://developers.google.com/bid-manager/reference/rest/v2/queries.reports/list#body.QUERY_PARAMETERS.order_by) parameter to retrieve the most recent report
under a query. Then the
[`Report.reportMetadata.googleCloudStoragePath`](https://developers.google.com/bid-manager/reference/rest/v2/queries.reports#ReportMetadata.FIELDS.google_cloud_storage_path) field is
used to locate the report file and download its contents to a local CSV file.

### Java

Required imports:

```java
import com.google.api.client.googleapis.media.MediaHttpDownloader;
import com.google.api.client.googleapis.util.Utils;
import com.google.api.client.http.GenericUrl;
import com.google.api.services.doubleclickbidmanager.DoubleClickBidManager;
import com.google.api.services.doubleclickbidmanager.model.ListReportsResponse;
import com.google.api.services.doubleclickbidmanager.model.Report;
import java.io.FileOutputStream;
import java.io.OutputStream;
```

Code example:

```java
long queryId = query-id;

// Call the API, listing the reports under the given queryId from most to
// least recent.
ListReportsResponse reportListResponse =
    service
        .queries()
        .reports()
        .list(queryId)
        .setOrderBy("key.reportId desc")
        .execute();

// Iterate over returned reports, stopping once finding a report that
// finished generating successfully.
Report mostRecentReport = null;
if (reportListResponse.getReports() != null) {
  for (Report report : reportListResponse.getReports()) {
    if (report.getMetadata().getStatus().getState().equals("DONE")) {
      mostRecentReport = report;
      break;
    }
  }
} else {
  System.out.format("No reports exist for query Id %s.\n", queryId);
}

// Download report file of most recent finished report found.
if (mostRecentReport != null) {
  // Retrieve GCS URL from report object.
  GenericUrl reportUrl =
      new GenericUrl(mostRecentReport.getMetadata().getGoogleCloudStoragePath());

  // Build filename.
  String filename =
      mostRecentReport.getKey().getQueryId() + "_"
          + mostRecentReport.getKey().getReportId() + ".csv";

  // Download the report file.
  try (OutputStream output = new FileOutputStream(filename)) {
    MediaHttpDownloader downloader =
        new MediaHttpDownloader(Utils.getDefaultTransport(), null);
    downloader.download(reportUrl, output);
  }
  System.out.format("Download of file %s complete.\n", filename);
} else {
  System.out.format(
      "There are no completed report files to download for query Id %s.\n",
      queryId);
}
```

### Python

Required imports:

```python
from contextlib import closing
from six.moves.urllib.request import urlopen
```

Code example:

```python
query_id = query-id

# Call the API, listing the reports under the given queryId from most to
# least recent.
response = service.queries().reports().list(queryId=query_id, orderBy="key.reportId desc").execute()

# Iterate over returned reports, stopping once finding a report that
# finished generating successfully.
most_recent_report = None
if response['reports']:
  for report in response['reports']:
    if report['metadata']['status']['state'] == 'DONE':
      most_recent_report = report
      break
else:
  print('No reports exist for query Id %s.' % query_id)

# Download report file of most recent finished report found.
if most_recent_report != None:
  # Retrieve GCS URL from report object.
  report_url = most_recent_report['metadata']['googleCloudStoragePath']

  # Build filename.
  output_file = '%s_%s.csv' % (report['key']['queryId'], report['key']['reportId'])

  # Download the report file.
  with open(output_file, 'wb') as output:
    with closing(urlopen(report_url)) as url:
      output.write(url.read())
  print('Download of file %s complete.' % output_file)
else:
  print('There are no completed report files to download for query Id %s.' % query_id)
```

### PHP

```php
$queryId = query-id;

// Call the API, listing the reports under the given queryId from most to
// least recent.
$optParams = array('orderBy' => "key.reportId desc");
$response = $service->queries_reports->listQueriesReports($queryId, $optParams);

// Iterate over returned reports, stopping once finding a report that
// finished generating successfully.
$mostRecentReport = null;
if (!empty($response->getReports())) {
  foreach ($response->getReports() as $report) {
    if ($report->metadata->status->state == "DONE") {
      $mostRecentReport = $report;
      break;
    }
  }
} else {
  printf('<p>No reports exist for query ID %s.</p>', $queryId);
}

// Download report file of most recent finished report found.
if ($mostRecentReport != null) {
  // Build filename.
  $filename = $mostRecentReport->key->queryId . '_' . $mostRecentReport->key->reportId . '.csv';

  // Download the report file.
  file_put_contents($filename, fopen($mostRecentReport->metadata->googleCloudStoragePath, 'r'));
  printf('<p>Download of file %s complete.</p>', $filename);
} else {
  printf('<p>There are no completed report files to download for query Id %s.</p>', $queryId);
}
```