Requests to send events or audience members are processed asynchronously.
A successful ingestion response returns a `request_id` and indicates that the
request satisfied all requirements and was accepted for processing. However,
it doesn't indicate whether the records in the request were successfully
processed.

Use the returned `request_id` with [`RetrieveRequestStatus`](https://developers.google.com/data-manager/api/reference/rpc/google.ads.datamanager.v1#retrieverequeststatusrequest) to
check the status of your upload and review diagnostics.

Here's the recommended workflow to check the status of your requests and verify
the health of your event and audience uploads:

1. Issue requests to send [events](https://developers.google.com/data-manager/api/devguides/events) or send or remove
   [audience members](https://developers.google.com/data-manager/api/devguides/audiences).

2. Check the overall status of each ingestion request. A successful request has
   a [`Status`](https://github.com/googleapis/googleapis/blob/master/google/rpc/status.proto) with `code` equal to `0` (enum value `OK`, HTTP
   response `200 OK`), and returns a
   [`IngestEventsResponse`](https://developers.google.com/data-manager/api/reference/rpc/google.ads.datamanager.v1#ingesteventsresponse),
   [`IngestAudienceMembersResponse`](https://developers.google.com/data-manager/api/reference/rpc/google.ads.datamanager.v1#ingestaudiencemembersresponse), or
   [`RemoveAudienceMembersResponse`](https://developers.google.com/data-manager/api/reference/rpc/google.ads.datamanager.v1#removeaudiencemembersresponse).

   If a request isn't successful, modify the request to address the error
   and send the request again.

   If a request succeeds, capture the response's `request_id` so you can use
   it to check the processing status in the next step.

   > [!NOTE]
   > **Note:** You can only check status and retrieve diagnostics for requests that succeed and don't have `validate_only` set to `true`.

3. Wait for 30 minutes, then send a
   [`RetrieveRequestStatus`](https://developers.google.com/data-manager/api/reference/rpc/google.ads.datamanager.v1#retrieverequeststatusrequest) request for each successful
   `request_id`.

   A [`RetrieveRequestStatusRequest`](https://developers.google.com/data-manager/api/reference/rpc/google.ads.datamanager.v1#retrieverequeststatusrequest) requires a single
   `request_id` value. Send a separate status request for each request ID you
   captured from a successful ingestion request.

   > [!TIP]
   > **Tip:** [Try a request in your browser using the API Explorer](https://developers.google.com/data-manager/api/reference/rest/v1/requestStatus/retrieve?apix=true).

   Periodically repeat this step for each `request_id` until the
   [destination status](https://developers.google.com/data-manager/api/devguides/diagnostics#destination_status) for each destination reaches
   `SUCCESS`, `PARTIAL_SUCCESS`, or `FAILED`. Follow the recommended
   [polling strategy](https://developers.google.com/data-manager/api/devguides/diagnostics#polling_strategy) to wait between each request.
4. Review each [`RetrieveRequestStatusResponse`](https://developers.google.com/data-manager/api/reference/rpc/google.ads.datamanager.v1#retrieverequeststatusresponse) to confirm
   your uploads are working properly and identify any issues with your data.

5. Correct data issues.

6. Go back to step 1 and repeat until you've addressed all issues with your
   uploads.

## Check overall destination status

The `request_status_per_destination` in a
[`RetrieveRequestStatusResponse`](https://developers.google.com/data-manager/api/reference/rpc/google.ads.datamanager.v1#retrieverequeststatusresponse) contains a separate entry for
each destination in the corresponding ingestion request.

For example, if your [`IngestAudienceMembersRequest`](https://developers.google.com/data-manager/api/reference/rpc/google.ads.datamanager.v1#ingestaudiencemembersrequest)
contained 3 entries in the `destinations` list to send data to 3 different
audiences, the status response contains 3 entries in
`request_status_per_destination` (one entry per audience).

Check the `request_status` field on each
[`RequestStatusPerDestination`](https://developers.google.com/data-manager/api/reference/rpc/google.ads.datamanager.v1#requeststatusperdestination) to determine if the
Data Manager API has finished processing the data for that destination.

Here are the possible values of [`request_status`](https://developers.google.com/data-manager/api/reference/rpc/google.ads.datamanager.v1#requeststatus):

- `PROCESSING`: The data for the destination is still being processed. The
  [warnings and errors](https://developers.google.com/data-manager/api/devguides/diagnostics#warnings_errors) aren't populated for the destination
  at this stage. Continue polling until the status reaches a terminal state.

- `SUCCESS`: Request processing for the destination completed without any
  errors. [Check for warnings](https://developers.google.com/data-manager/api/devguides/diagnostics#warnings_errors) flagged during processing.

- `FAILED`: All of the records for the destination failed due to errors.
  [Check for warnings and errors](https://developers.google.com/data-manager/api/devguides/diagnostics#warnings_errors) to determine why all
  records failed. Also check for warnings flagged during processing.

- `PARTIAL_SUCCESS`: Some of the records for the destination succeeded, but
  others failed due to errors. [Check for errors](https://developers.google.com/data-manager/api/devguides/diagnostics#warnings_errors) to
  determine why some records failed. Also check for warnings flagged during
  processing.

## Review diagnostics

Once the `request_status` for a destination reaches `SUCCESS`, `FAILED`, or
`PARTIAL_SUCCESS`, review the detailed diagnostics in the response to verify
counts and troubleshoot issues.

### Check event or audience status per destination

Inspect the status field that corresponds to the type of ingestion request. Only
*one* of the following fields is set on each `RequestStatusPerDestination`:

- [`events_ingestion_status`](https://developers.google.com/data-manager/api/devguides/diagnostics#send_events_status)

- [`audience_members_ingestion_status`](https://developers.google.com/data-manager/api/devguides/diagnostics#send_audiences_status)

- [`audience_members_removal_status`](https://developers.google.com/data-manager/api/devguides/diagnostics#remove_audiences_status)

#### Events ingestion status

The `events_ingestion_status` field is populated if the request was an
[`IngestEventsRequest`](https://developers.google.com/data-manager/api/reference/rpc/google.ads.datamanager.v1#ingesteventsrequest).

Check the `record_count` of the [`IngestEventStatus`](https://developers.google.com/data-manager/api/reference/rpc/google.ads.datamanager.v1#ingesteventsstatus)
to confirm that the total number of records received matches your
expectations. The `record_count` includes both successful and failed
records.

#### Audience members ingestion status

The `audience_members_ingestion_status` field is populated if the request was an
[`IngestAudienceMembersRequest`](https://developers.google.com/data-manager/api/reference/rpc/google.ads.datamanager.v1#ingestaudiencemembersrequest). Here's the
[`IngestAudienceMembersStatus`](https://developers.google.com/data-manager/api/reference/rpc/google.ads.datamanager.v1#ingestaudiencemembersstatus) field to check for
each type of audience data. Only *one* of these fields is set.

`composite_data_ingestion_status`

:   Check the `record_count` of the
    [`IngestCompositeDataStatus`](https://developers.google.com/data-manager/api/reference/rpc/google.ads.datamanager.v1#ingestcompositedatastatus) to confirm that the
    total number of records received matches your expectations. The
    `record_count` includes both successful and failed records.

    Check the `data_type_counts` to confirm that the number of identifiers
    matches your expectations. This list provides a breakdown of all
    identifiers received (such as email address, phone number, physical
    address, and IP address) by [`DataType`](https://developers.google.com/data-manager/api/reference/rpc/google.ads.datamanager.v1#datatype).

    If the request had a sufficient number of records, the
    `upload_match_rate_range` contains the [match rate
    range](https://developers.google.com/data-manager/api/reference/rpc/google.ads.datamanager.v1#matchraterange) for records in the request.

`google_user_id_data_ingestion_status`

:   Check the `record_count` of the
    [`IngestGoogleUserIdDataStatus`](https://developers.google.com/data-manager/api/reference/rpc/google.ads.datamanager.v1#ingestgoogleuseriddatastatus) to confirm that
    the total number of records received matches your expectations. The
    `record_count` includes both successful and failed records.

    Check the `google_user_id_count` to confirm the number of Google user IDs
    received matches your expectations.

`mobile_data_ingestion_status`

:   Check the `record_count` of the
    [`IngestMobileDataStatus`](https://developers.google.com/data-manager/api/reference/rpc/google.ads.datamanager.v1#ingestmobiledatastatus) to confirm that the
    total number of records received matches your expectations. The
    `record_count` includes both successful and failed records.

    Check the `mobile_id_count` to confirm the number of mobile IDs received
    matches your expectations.

`pair_data_ingestion_status`

:   Check the `record_count` of the
    [`IngestPairDataStatus`](https://developers.google.com/data-manager/api/reference/rpc/google.ads.datamanager.v1#ingestpairdatastatus) to confirm that the total
    number of records received matches your expectations. The `record_count`
    includes both successful and failed records.

    Check the `pair_id_count` to confirm the number of PAIR IDs received
    matches your expectations.

`partner_provided_id_data_ingestion_status`

:   Check the `record_count` of the
    [`IngestPartnerProvidedIdDataStatus`](https://developers.google.com/data-manager/api/reference/rpc/google.ads.datamanager.v1#ingestpartnerprovidediddatastatus) to
    confirm that the total number of records received matches your expectations.
    The `record_count` includes both successful and failed records.

    Check the `partner_provided_id_count` to confirm the number of partner
    provided IDs received matches your expectations.

`ppid_data_ingestion_status`

:   Check the `record_count` of the
    [`IngestPpidDataStatus`](https://developers.google.com/data-manager/api/reference/rpc/google.ads.datamanager.v1#ingestppiddatastatus) to confirm that the total
    number of records received matches your expectations. The `record_count`
    includes both successful and failed records.

    Check the `ppid_count` to confirm the number of PPIDs received
    matches your expectations.

`user_data_ingestion_status`

:   Check the `record_count` of the
    [`IngestUserDataStatus`](https://developers.google.com/data-manager/api/reference/rpc/google.ads.datamanager.v1#ingestuserdatastatus) to confirm that the total
    number of records received matches your expectations. The `record_count`
    includes both successful and failed records.

    Check the `user_identifier_count` to confirm the number of
    [user identifiers](https://developers.google.com/data-manager/api/reference/rpc/google.ads.datamanager.v1#useridentifier) received matches your
    expectations.

    If the request had a sufficient number of records, the
    `upload_match_rate_range` contains the [match rate
    range](https://developers.google.com/data-manager/api/reference/rpc/google.ads.datamanager.v1#matchraterange) for records in the request.

`user_id_data_ingestion_status`

:   Check the `record_count` of the
    [`IngestUserIdDataStatus`](https://developers.google.com/data-manager/api/reference/rpc/google.ads.datamanager.v1#ingestuseriddatastatus) to confirm that the total
    number of records received matches your expectations. The `record_count`
    includes both successful and failed records.

    Check the `user_id_count` to confirm the number of user IDs received
    matches your expectations.

#### Audience members removal status

The `audience_members_removal_status` field is populated if the request was a
[`RemoveAudienceMembersRequest`](https://developers.google.com/data-manager/api/reference/rpc/google.ads.datamanager.v1#removeaudiencemembersrequest). Here's the
[`RemoveAudienceMembersStatus`](https://developers.google.com/data-manager/api/reference/rpc/google.ads.datamanager.v1#removeaudiencemembersstatus) field to check for each
type of audience data. Only *one* of these fields is set.

`composite_data_removal_status`
:   Removal status for [Composite data](https://developers.google.com/data-manager/api/reference/rpc/google.ads.datamanager.v1#compositedata)

`google_user_id_data_removal_status`
:   Removal status for [Google user ID data](https://developers.google.com/data-manager/api/reference/rpc/google.ads.datamanager.v1#googleuseriddata)

`mobile_data_removal_status`
:   Removal status for [mobile data](https://developers.google.com/data-manager/api/reference/rpc/google.ads.datamanager.v1#mobiledata).

`pair_data_removal_status`
:   Removal status for [PAIR data](https://developers.google.com/data-manager/api/reference/rpc/google.ads.datamanager.v1#pairdata).

`partner_provided_id_data_removal_status`
:   Removal status for [Partner provided ID data](https://developers.google.com/data-manager/api/reference/rpc/google.ads.datamanager.v1#partnerprovidediddata)

`ppid_data_removal_status`
:   Removal status for [PPID data](https://developers.google.com/data-manager/api/reference/rpc/google.ads.datamanager.v1#ppiddata).

`user_data_removal_status`
:   Removal status for [user data](https://developers.google.com/data-manager/api/reference/rpc/google.ads.datamanager.v1#userdata).

`user_id_data_removal_status`
:   Removal status for [User ID data](https://developers.google.com/data-manager/api/reference/rpc/google.ads.datamanager.v1#useriddata)

Check the `record_count` to confirm that the total number of records
received matches your expectations. The `record_count` includes both
successful and failed records.

In addition, check the `user_identifier_count`, `mobile_id_count`,
`pair_id_count`, `ppid_count`, `user_id_count`, `google_user_id_count`, or
`partner_provided_id_count` to confirm the total count of
identifiers received.

For composite data, check the `data_type_counts` to confirm that the number of
identifiers matches your expectations. This list provides a breakdown of all
identifiers received (such as email address, phone number, physical address, and
IP address) by [`DataType`](https://developers.google.com/data-manager/api/reference/rpc/google.ads.datamanager.v1#datatype).

### Check warnings and errors

In addition to the status fields for the destination and request type, the
[`RetrieveRequestStatusResponse`](https://developers.google.com/data-manager/api/reference/rpc/google.ads.datamanager.v1#retrieverequeststatusresponse) contains a breakdown of
warnings and errors for the request.

- An error indicates that the API completely rejected the record.

- A warning indicates that the API didn't reject the record, but it had to
  ignore portions of the record's data.

For example, if an `Event` contains encrypted
[`UserIdentifier`](https://developers.google.com/data-manager/api/reference/rpc/google.ads.datamanager.v1#useridentifier) data and
[`AdIdentifiers`](https://developers.google.com/data-manager/api/reference/rpc/google.ads.datamanager.v1#adidentifiers) such as `gclid`, and the
`UserIdentifier` data can't be decrypted, the Data Manager API still processes the
record using the `AdIdentifiers` but returns the warning
`PROCESSING_WARNING_REASON_USER_IDENTIFIER_DECRYPTION_ERROR`.

However, if the `Event` doesn't contain `AdIdentifiers` and the `UserIdentifier`
data can't be decrypted, the Data Manager API rejects the entire record and
reports the error `PROCESSING_ERROR_REASON_USER_IDENTIFIER_DECRYPTION_ERROR`
because a valid `Event` must have at least one of `ad_identifiers` or
`user_data`.

Here are the response fields that contain warning and error information. These
fields are populated when the [overall destination status](https://developers.google.com/data-manager/api/devguides/diagnostics#destination_status)
reaches `SUCCESS`, `PARTIAL_SUCCESS`, or `FAILED`.

`warning_info`

:   A [`WarningInfo`](https://developers.google.com/data-manager/api/reference/rpc/google.ads.datamanager.v1#warninginfo) object. Its `warning_counts` field contains a
    list of [`WarningCount`](https://developers.google.com/data-manager/api/reference/rpc/google.ads.datamanager.v1#warningcount) objects. Each `WarningCount` contains:

    - `reason`: The type of warning.

    - `record_count`: The number of records that had that type of warning.

    - `record_indices`: The indexes of the records in the original request
      that had that type of warning. See
      [Check affected records](https://developers.google.com/data-manager/api/devguides/diagnostics#record_indices).

    Check the `warning_info` even if the [overall destination
    status](https://developers.google.com/data-manager/api/devguides/diagnostics#destination_status) is `SUCCESS`.

`error_info`

:   An [`ErrorInfo`](https://developers.google.com/data-manager/api/reference/rpc/google.ads.datamanager.v1#errorinfo) object. Its `error_counts` field contains a list
    of [`ErrorCount`](https://developers.google.com/data-manager/api/reference/rpc/google.ads.datamanager.v1#errorcount) objects. Each `ErrorCount` contains:

    - `reason`: The type of error.

    - `record_count`: The number of records that failed due to that type of
      error.

    - `record_indices`: The indexes of the records in the original request
      that failed due to that type of error. See
      [Check affected records](https://developers.google.com/data-manager/api/devguides/diagnostics#record_indices).

### Check affected records

Use the `record_indices` of each `WarningCount` and `ErrorCount` to identify
the exact records in your ingestion request that had warnings or errors.

Each value in `record_indices` is the 0-based position of a record in the
original request:

- For an [`IngestEventsRequest`](https://developers.google.com/data-manager/api/reference/rpc/google.ads.datamanager.v1#ingesteventsrequest), the index refers to the
  position of the event in the request's `events` list.

- For an [`IngestAudienceMembersRequest`](https://developers.google.com/data-manager/api/reference/rpc/google.ads.datamanager.v1#ingestaudiencemembersrequest), the index refers
  to the position of the audience member in the request's `audience_members`
  list.

For example, a `record_indices` value of `0` refers to the first event or
audience member in the request.

Keep the following in mind when you analyze `record_indices`:

- **Indexes are reported per destination.** If your request had multiple
  destinations, each `RequestStatusPerDestination` reports the indexes of the
  records with warnings or errors for that destination. The same record can
  appear in more than one `RequestStatusPerDestination`.

- **A record can appear under more than one reason.** For example, a record
  can have both an error and a warning, or more than one type of warning. To
  find all of the issues for a given record, check every `WarningCount` and
  `ErrorCount` for the destination.

Here's a sample `RetrieveRequestStatusResponse` for an
`IngestEventsRequest` with five events and one destination. The first event
(index `0`) and the fourth event (index `3`) failed because the
transaction ID was already uploaded, and the third event (index `2`) was
processed but had a custom variable value that isn't predefined.

    {
      "requestStatusPerDestination": [
        {
          "destination": {
            "operatingAccount": {
              "accountType": "GOOGLE_ADS",
              "accountId": "1234567890"
            },
            "productDestinationId": "123456789"
          },
          "requestStatus": "PARTIAL_SUCCESS",
          "eventsIngestionStatus": {
            "recordCount": "5"
          },
          "errorInfo": {
            "errorCounts": [
              {
                "recordCount": "2",
                "reason": "PROCESSING_ERROR_REASON_DUPLICATE_TRANSACTION_ID",
                "recordIndices": [0, 3]
              }
            ]
          },
          "warningInfo": {
            "warningCounts": [
              {
                "recordCount": "1",
                "reason": "PROCESSING_WARNING_REASON_CUSTOM_VARIABLE_NOT_PREDEFINED",
                "recordIndices": [2]
              }
            ]
          }
        }
      ]
    }

To correct the records:

1. For each `ErrorCount` and `WarningCount`, use the `record_indices` to look
   up the corresponding records in your original request.

2. Use the `reason` to determine how to fix each record. For descriptions of
   each reason, see [`ProcessingErrorReason`](https://developers.google.com/data-manager/api/reference/rpc/google.ads.datamanager.v1#processingerrorreason) and
   [`ProcessingWarningReason`](https://developers.google.com/data-manager/api/reference/rpc/google.ads.datamanager.v1#processingwarningreason).

3. Send a new ingestion request that contains only the corrected records. Don't
   resend records that succeeded, as that may result in duplicate data or
   additional errors.

## Polling strategy

Periodically send the [`RetrieveRequestStatusRequest`](https://developers.google.com/data-manager/api/reference/rpc/google.ads.datamanager.v1#retrieverequeststatusrequest)
using an [exponential backoff algorithm](https://en.wikipedia.org/wiki/Exponential_backoff) until the `request_status` reaches
`SUCCESS`, `FAILED`, or `PARTIAL_SUCCESS` for every destination in the original
request. This may take up to 24 hours, although the Data Manager API may finish
processing some requests in as little as 30 minutes.

Here's an example of a reasonable initial wait time and retry configuration
that balances liveness and quota usage:

| Setting | Value |
|---|---|
| Wait time before first diagnostics request (minutes) | `30` |
| Backoff multiplier | `1.3` |
| Maximum backoff (minutes) | `60` (1 hour) |
| Maximum total time (minutes) | `1440` (24 hours) |

Here's a sequence of requests and elapsed time with this configuration:

### Graph

![Polling Strategy](https://developers.google.com/static/data-manager/api/images/diagnostics-polling-timeline.png)

### Data

| Attempt | Time Since Ingestion Request (hh:mm) | Delay Before Attempt | Notes |
|---|---|---|---|
| 1 | 00:30 | 30.0 min | First check for status availability |
| 2 | 01:09 | 39.0 min |   |
| 3 | 01:59 | 50.7 min |   |
| 4 | 02:59 | 60.0 min | Delay is now capped at 1 hour |
| 5 | 03:59 | 60.0 min |   |
| 6 | 04:59 | 60.0 min |   |
| 7 | 05:59 | 60.0 min |   |
| 8 | 06:59 | 60.0 min |   |
| 9 | 07:59 | 60.0 min |   |
| 10 | 08:59 | 60.0 min |   |
| 11 | 09:59 | 60.0 min |   |
| 12 | 10:59 | 60.0 min |   |
| 13 | 11:59 | 60.0 min | 12-hour mark |
| 14 | 12:59 | 60.0 min |   |
| 15 | 13:59 | 60.0 min |   |
| 16 | 14:59 | 60.0 min |   |
| 17 | 15:59 | 60.0 min |   |
| 18 | 16:59 | 60.0 min |   |
| 19 | 17:59 | 60.0 min |   |
| 20 | 18:59 | 60.0 min |   |
| 21 | 19:59 | 60.0 min |   |
| 22 | 20:59 | 60.0 min |   |
| 23 | 21:59 | 60.0 min |   |
| 24 | 22:59 | 60.0 min |   |
| 25 | 23:59 | 60.0 min | Last request before the 24 hour maximum total time |

Add a small random amount of
[jitter](https://docs.cloud.google.com/java/docs/client-retries#jitter) to the backoff
delays to prevent the "thundering herd" problem where many clients retry
simultaneously.

## Authorization requirements

A [`RetrieveRequestStatusRequest`](https://developers.google.com/data-manager/api/reference/rpc/google.ads.datamanager.v1#retrieverequeststatusrequest) doesn't accept destination
accounts or request headers. Instead, the Data Manager API identifies the
destinations from the original ingestion request associated with the
`request_id` and verifies that the caller has access to the `operating_account`
on each [`Destination`](https://developers.google.com/data-manager/api/devguides/concepts/destinations).

To check the status of a request, the credentials used in a
[`RetrieveRequestStatusRequest`](https://developers.google.com/data-manager/api/reference/rpc/google.ads.datamanager.v1#retrieverequeststatusrequest) must satisfy the following
requirements for the `operating_account` of each destination from the original
ingestion request:

- **Identical access path** : The credentials must have access to each
  `operating_account` using the *exact same access path* specified in the
  original ingestion request.

  For example, if an ingestion request for a Google Ads `operating_account`
  specified a parent manager account as the `login_account`, the
  credentials must also have access to the `operating_account` through
  that same manager account. Even if the Google Account associated
  with the credentials has direct access to the child `operating_account`,
  the request fails with a `PERMISSION_DENIED` error if that account lacks
  access through the `login_account` manager account specified during
  ingestion.
- **Sufficient access level** : The Google Account associated with the
  credentials must have an access level or role with permission to ingest
  data into the `operating_account`.

  For example, in Google Ads, the Google Account must have the
  **Admin** or **Standard** [access level](https://support.google.com/google-ads/answer/9978556).
  A request with credentials for an account with the **Read-only**
  access level fails with a `PERMISSION_DENIED` error.