Poll and view completed reports

A report run operation executes asynchronously as a long-running operation, represented by the Operation object. To determine when a report run operation has completed, you can poll the Operation object with the agencies.reports.operations.get method.

You can view the results of a completed report run operation with the agencies.reports.results.fetchRows method. The output of a report run operation consists of report results based on the Report object.

This guide describes how you can use the Agencies & Brands API to get a report run operation to poll the operation's status and fetch the report results of the completed report run operation.

Before you begin

Before you continue, you must complete the following:

Poll status of a report run

To check the execution status of a report run operation, use the agencies.reports.operations.get method.

The following example makes a GET request to poll an operation:

REST

Request

curl \
  'https://agenciesandbrands.googleapis.com/v1/agencies/ACCOUNT_ID/reports/123456789/operations/10486370264' \
  --header 'Authorization: Bearer ACCESS_TOKEN' \
  --header 'Accept: application/json' \
  --compressed

Replace the following:

  • ACCOUNT_ID: your account ID.
  • ACCESS_TOKEN: your access token.

Response

If successful, the response is an Operation object with the done field set to the true value, and the response payload is populated with the reportResult resource name:

{
  "name": "agencies/ACCOUNT_ID/reports/123456789/operations/10486370264",
  "done": true,
  "metadata": {
    "@type": "type.googleapis.com/google.ads.agenciesandbrands.v1.RunReportMetadata",
    "percentComplete": 100
  },
  "response": {
    "@type": "type.googleapis.com/google.ads.agenciesandbrands.v1.RunReportResponse",
    "reportResult": "agencies/ACCOUNT_ID/reports/123456789/results/10486370264"
  }
}

Java

/*
 * Copyright (c) 2026 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
 * in compliance with the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License
 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing permissions and limitations under
 * the License.
 */

package com.google.api.services.samples.agenciesandbrands.v1.agencies.reports.operations;

import com.google.api.services.agenciesandbrands.v1.AgenciesAndBrands;
import com.google.api.services.agenciesandbrands.v1.model.Operation;
import com.google.api.services.samples.agenciesandbrands.v1.Utils;
import java.io.IOException;
import java.security.GeneralSecurityException;
import net.sourceforge.argparse4j.ArgumentParsers;
import net.sourceforge.argparse4j.inf.ArgumentParser;
import net.sourceforge.argparse4j.inf.ArgumentParserException;
import net.sourceforge.argparse4j.inf.Namespace;

public class GetReportOperation {

  /**
   * Executes the get operation for a report operation.
   *
   * @param agenciesAndBrandsClient the initialized Agencies & Brands API client.
   * @param accountId the account ID of the agency.
   * @param reportId the resource ID of the report.
   * @param operationId the resource ID of the report operation.
   * @throws IOException if the API returns an error.
   */
  public static void execute(
      AgenciesAndBrands agenciesAndBrandsClient,
      Long accountId,
      String reportId,
      String operationId)
      throws IOException {
    String name =
        String.format(
            "agencies/%s/reports/%s/operations/%s", accountId, reportId, operationId);

    System.out.printf("Getting report operation with name \"%s\".%n", name);

    // Get the status of the report operation.
    Operation operation =
        agenciesAndBrandsClient
            .agencies()
            .reports()
            .operations()
            .get(name)
            .execute();

    System.out.println("Successfully retrieved report operation:");
    Utils.jsonPrettyPrint(operation);
  }

  /**
   * Creates and configures the ArgumentParser for this sample.
   *
   * @return the configured ArgumentParser.
   */
  private static ArgumentParser createArgumentParser() {
    ArgumentParser parser =
        ArgumentParsers.newFor("GetReportOperation")
            .build()
            .defaultHelp(true)
            .description("Gets the status of a long-running report operation. If the " +
                "operation is done, you can view the report contents with the " +
                "`agencies.reports.results.fetchRows` method.");

    // Required arguments.
    parser
        .addArgument("-a", "--account_id")
        .help("The account ID of the agency.")
        .required(true)
        .type(Long.class);
    parser
        .addArgument("-r", "--report_id")
        .help("The resource ID of the report.")
        .required(true);
    parser
        .addArgument("-o", "--operation_id")
        .help("The resource ID of the report operation to retrieve.")
        .required(true);

    return parser;
  }

  public static void main(String[] args) {
    ArgumentParser parser = createArgumentParser();

    Namespace parsedArgs = null;
    try {
      parsedArgs = parser.parseArgs(args);
    } catch (ArgumentParserException ex) {
      parser.handleError(ex);
      System.exit(1);
    }

    AgenciesAndBrands client = null;
    try {
      client = Utils.getAgenciesAndBrandsClient();
    } catch (IOException ex) {
      System.out.printf("Unable to create Agencies & Brands API service:%n%s", ex);
      System.out.println("Did you specify a valid path to a service account key file?");
      System.exit(1);
    } catch (GeneralSecurityException ex) {
      System.out.printf("Unable to establish secure HttpTransport:%n%s", ex);
      System.exit(1);
    }

    try {
      execute(
          client,
          parsedArgs.getLong("account_id"),
          parsedArgs.getString("report_id"),
          parsedArgs.getString("operation_id"));
    } catch (IOException ex) {
      System.out.printf("Agencies & Brands API returned error response:%n%s", ex);
      System.exit(1);
    }
  }
}

The following describes how you can use the done field to poll the status of the operation:

  • If the done field in the response is the false value, the report run operation is still processing.
  • If the done field in the response is the true value, the report run operation is complete. The Operation object in the response body also contains either of the following fields:
    • response: Indicates that the report run operation succeeded. This field is an object populated with a @type field set to the type.googleapis.com/google.ads.agenciesandbrands.v1.RunReportResponse type. The RunReportResponse type is populated with a reportResult field containing the name of the corresponding report result.
    • error: Indicates that the report run operation failed. The error field is populated with a Status object describing why the report run failed.

Fetch rows from a completed report

You can retrieve the contents of a completed report run operation with the agencies.reports.results.fetchRows method. You must fill in the name path parameter for the report result, which is the resource name from the reportResult field of a complete report run operation.

The following example makes a GET request to fetch result rows:

REST

Request

curl \
  'https://agenciesandbrands.googleapis.com/v1/agencies/ACCOUNT_ID/reports/123456789/results/10486370264:fetchRows?pageSize=1' \
  --header 'Authorization: Bearer ACCESS_TOKEN' \
  --header 'Accept: application/json' \
  --compressed

Response

{
  "rows": [
    {
      "dimensionValues": [
        {
          "stringValue": "2026-08-01"
        },
        {
          "stringValue": "deal-1001"
        },
        {
          "stringValue": "creative-1001"
        }
      ],
      "metricValueGroups": [
        {
          "primaryValues": [
            {
              "intValue": "500000"
            },
            {
              "intValue": "450000"
            },
            {
              "intValue": "150000"
            },
            {
              "intValue": "150000"
            },
            {
              "intValue": "3200"
            },
            {
              "doubleValue": 450.75
            },
            {
              "doubleValue": 405.67
            }
          ]
        }
      ]
    }
  ],
  "runTime": "2026-08-05T12:00:00Z",
  "dateRanges": [
    {
      "startDate": {
        "year": 2026,
        "month": 7,
        "day": 6
      },
      "endDate": {
        "year": 2026,
        "month": 8,
        "day": 4
      }
    }
  ],
  "totalRowCount": 2,
  "nextPageToken": "QC7nzW91c2VTcGFubmVyQ29udGlubWF0aW6uVG9wZY45NP=="
}

Java

/*
 * Copyright (c) 2026 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
 * in compliance with the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License
 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing permissions and limitations under
 * the License.
 */

package com.google.api.services.samples.agenciesandbrands.v1.agencies.reports.results;

import com.google.api.services.agenciesandbrands.v1.AgenciesAndBrands;
import com.google.api.services.agenciesandbrands.v1.model.FetchReportResultRowsResponse;
import com.google.api.services.samples.agenciesandbrands.v1.Utils;
import java.io.IOException;
import java.security.GeneralSecurityException;
import net.sourceforge.argparse4j.ArgumentParsers;
import net.sourceforge.argparse4j.inf.ArgumentParser;
import net.sourceforge.argparse4j.inf.ArgumentParserException;
import net.sourceforge.argparse4j.inf.Namespace;

public class FetchReportResultRows {

  /**
   * Executes the fetchRows operation for report result rows.
   *
   * @param agenciesAndBrandsClient the initialized Agencies & Brands API client.
   * @param accountId the account ID of the agency.
   * @param reportId the resource ID of the report.
   * @param resultId the resource ID of the report result.
   * @param pageSize the maximum number of rows to return per page.
   * @param pageToken the page token from a previous response, if any.
   * @throws IOException if the API returns an error.
   */
  public static void execute(
      AgenciesAndBrands agenciesAndBrandsClient,
      Long accountId,
      String reportId,
      String resultId,
      Integer pageSize,
      String pageToken)
      throws IOException {
    String name = String.format("agencies/%s/reports/%s/results/%s", accountId, reportId, resultId);

    System.out.printf("Fetching report result rows for \"%s\".%n", name);

    AgenciesAndBrands.Agencies.Reports.Results.FetchRows request =
        agenciesAndBrandsClient.agencies().reports().results().fetchRows(name);

    if (pageSize != null) {
      request.setPageSize(pageSize);
    }
    if (pageToken != null) {
      request.setPageToken(pageToken);
    }

    FetchReportResultRowsResponse response = request.execute();

    System.out.println("Successfully fetched report result rows:");
    Utils.jsonPrettyPrint(response);
  }

  /**
   * Creates and configures the ArgumentParser for this sample.
   *
   * @return the configured ArgumentParser.
   */
  private static ArgumentParser createArgumentParser() {
    ArgumentParser parser =
        ArgumentParsers.newFor("FetchReportResultRows")
            .build()
            .defaultHelp(true)
            .description("Fetches rows for a completed report result.");

    // Required arguments.
    parser
        .addArgument("-a", "--account_id")
        .help("The account ID of the agency.")
        .required(true)
        .type(Long.class);
    parser
        .addArgument("-r", "--report_id")
        .help("The resource ID of the report.")
        .required(true);
    parser
        .addArgument("--result_id")
        .help("The resource ID of the report result. This is identical to the resource ID of " +
            "the corresponding report run operation.")
        .required(true);

    // Optional arguments.
    parser
        .addArgument("--page_size")
        .help("The maximum number of rows to return per page.")
        .type(Integer.class);
    parser
        .addArgument("--page_token")
        .help("A page token, received from a previous `FetchReportResultRows` call.");

    return parser;
  }

  public static void main(String[] args) {
    ArgumentParser parser = createArgumentParser();

    Namespace parsedArgs = null;
    try {
      parsedArgs = parser.parseArgs(args);
    } catch (ArgumentParserException ex) {
      parser.handleError(ex);
      System.exit(1);
    }

    AgenciesAndBrands client = null;
    try {
      client = Utils.getAgenciesAndBrandsClient();
    } catch (IOException ex) {
      System.out.printf("Unable to create Agencies & Brands API service:%n%s", ex);
      System.out.println("Did you specify a valid path to a service account key file?");
      System.exit(1);
    } catch (GeneralSecurityException ex) {
      System.out.printf("Unable to establish secure HttpTransport:%n%s", ex);
      System.exit(1);
    }

    try {
      execute(
          client,
          parsedArgs.getLong("account_id"),
          parsedArgs.getString("report_id"),
          parsedArgs.getString("result_id"),
          parsedArgs.getInt("page_size"),
          parsedArgs.getString("page_token"));
    } catch (IOException ex) {
      System.out.printf("Agencies & Brands API returned error response:%n%s", ex);
      System.exit(1);
    }
  }
}

You can specify the following query parameters:

  • pageSize: the maximum number of rows to return. The default is 1,000 rows, and the maximum is 10,000 rows.
  • pageToken: the page token returned in a previous fetchRows response to fetch the next batch of rows.

The response contains the following fields:

  • rows: An array of Row objects. Each row contains:
    • dimensionValues: Values for each requested dimension, ordered identically to the dimensions in the report definition.
    • metricValueGroups: Groups of metric values corresponding to the date ranges. Each group contains a primaryValues list ordered identically to the metrics in the report definition.
  • dateRanges: The computed fixed date ranges for the report. The dateRanges field is only included in the response body of the first page.
  • totalRowCount: The total number of rows in the report result. The totalRowCount field is only included in the response body of the first page.
  • nextPageToken: Token to pass in subsequent requests to retrieve the next page of rows. If no additional rows exist, the Agencies & Brands API omits this field from the response body.

In the agencies.reports.results.fetchRows REST example, each item in the rows field maps directly to the ReportDefinition configured in the report:

  • dimensionValues: contains values corresponding to each dimension in the reportDefinition.dimensions field in the exact order you specified. In the example, the first value, 2026-08-01, corresponds to the DATE dimension, the second value, deal-1001, corresponds to the DEAL_ID dimension, and the third value, creative-1001, corresponds to the CREATIVE_ID dimension.
  • metricValueGroups: contains metric values grouped in the report's date ranges. In each group, the primaryValues field contains the values corresponding to each metric in the reportDefinition.metrics field in the exact order you specified. In this example, the seven values correspond to the following Metric enum values:

    • BIDS: 500000
    • BIDS_IN_AUCTION: 450000
    • AUCTIONS_WON: 150000
    • IMPRESSIONS: 150000
    • CLICKS: 3200
    • SPEND: 450.75
    • SPEND_WITHOUT_CURATION_PARTNER_FEE: 405.67
  • dateRanges: contains the fixed date range that Google computed for the relative range, THIS_MONTH_TO_DATE, configured in the report definition.

Next steps