Follow this guide to understand limits and quotas when working with the
Data Manager API.

## Project limits

You need a Google Cloud project in order to use the
Data Manager API. The Google Cloud project provides the OAuth
client and credentials that you use to [authenticate API
requests](https://developers.google.com/data-manager/api/devguides/quickstart/set-up-access#setup-auth).

The Data Manager API enforces rate limits on each Google Cloud
project, separated by service and operation type (read versus mutate):

| Service | Operation | Requests per day | Requests per minute |
|---|---|---|---|
| [`IngestionService`](https://developers.google.com/data-manager/api/reference/rpc/google.ads.datamanager.v1#ingestionservice) | Mutate (write) | 100,000 | 300 |
| [`IngestionService`](https://developers.google.com/data-manager/api/reference/rpc/google.ads.datamanager.v1#ingestionservice) | Read | 100,000 | 300 |
| All other services *combined* | Mutate (write) | 50,000 | 300 |
| All other services *combined* | Read | 50,000 | 300 |

Requests that exceed the limits are rejected with the error `RESOURCE_EXHAUSTED`
and HTTP status `429 Too Many Requests`.

You can take control of your app and mitigate rate limits by both actively
[reducing the number of requests](https://developers.google.com/data-manager/api/devguides/concepts/best-practices#optimize) and throttling QPS from the
client side. You can also [set up quota alerts and monitoring](https://cloud.google.com/docs/quotas/set-up-quota-alerts) in
the Google Cloud console to receive notifications before your
application reaches its limits.

### Quota names

Each limit corresponds to a quota limit name and metric in
Google Cloud. When a request exceeds a limit, the Data Manager API
returns the quota limit name in the [`ErrorInfo`](https://developers.google.com/data-manager/api/devguides/concepts/understand-errors#error-info) standard detail
payload under `metadata.quota_limit`:

| Quota limit name | Service | Operation | Window | Limit |
|---|---|---|---|---|
| `IngestionMutateRequestsPerDayPerProject` | `IngestionService` | Mutate | Day | 100,000 |
| `IngestionMutateRequestsPerMinutePerProject` | `IngestionService` | Mutate | Minute | 300 |
| `IngestionReadRequestsPerDayPerProject` | `IngestionService` | Read | Day | 100,000 |
| `IngestionReadRequestsPerMinutePerProject` | `IngestionService` | Read | Minute | 300 |
| `ManagementMutateRequestsPerDayPerProject` | All other services | Mutate | Day | 50,000 |
| `ManagementMutateRequestsPerMinutePerProject` | All other services | Mutate | Minute | 300 |
| `ManagementReadRequestsPerDayPerProject` | All other services | Read | Day | 50,000 |
| `ManagementReadRequestsPerMinutePerProject` | All other services | Read | Minute | 300 |

Inspect `metadata.quota_limit` in the [`ErrorInfo`](https://developers.google.com/data-manager/api/devguides/concepts/understand-errors#error-info) payload to
distinguish between daily and per-minute limit errors and determine whether to
pause temporarily and retry with backoff, or pause until the daily quota resets.
For details, see [Quota and rate limit errors](https://developers.google.com/data-manager/api/devguides/concepts/understand-errors#quota-errors).

### Handle rate limits and concurrency

To maximize throughput without exceeding project quotas, follow these
guidelines:

- **Batch records per request** : Include as many records as possible in each
  request up to the [request limits](https://developers.google.com/data-manager/api/devguides/limits#request_limits) (up to 10,000
  `AudienceMember` resources or 2,000 `Event` resources per request).

- **Send up to 10 concurrent requests** : To reduce total ingestion time
  without exceeding the 300 requests per minute limit,
  [send up to 10 concurrent requests](https://developers.google.com/data-manager/api/devguides/concepts/best-practices#concurrent) to
  [`IngestionService`](https://developers.google.com/data-manager/api/reference/rpc/google.ads.datamanager.v1#ingestionservice).

- **Retry per-minute rate limits with backoff** : If a request fails with
  `RESOURCE_EXHAUSTED` (HTTP `429`) and `metadata.quota_limit` indicates a
  per-minute limit (such as `IngestionMutateRequestsPerMinutePerProject`),
  [retry using exponential backoff with jitter](https://developers.google.com/data-manager/api/devguides/concepts/understand-errors#retry-strategy) (for example,
  waiting 1s, 2s, and 4s between retries).

- **Pause on daily quota exhaustion** : If `metadata.quota_limit` indicates a
  daily limit (such as `IngestionMutateRequestsPerDayPerProject`), don't
  retry immediately. Pause requests until the daily quota resets at midnight
  Pacific Time.

## Request limits

Here are the limits for specific requests:

- [`IngestAudienceMembersRequest`](https://developers.google.com/data-manager/api/reference/rpc/google.ads.datamanager.v1#ingestaudiencemembersrequest) and
  [`RemoveAudienceMembersRequest`](https://developers.google.com/data-manager/api/reference/rpc/google.ads.datamanager.v1#removeaudiencemembersrequest):

  - 10,000 `AudienceMember` resources in the `audience_members` list

  - 10 user identifiers in the `UserData` for an `AudienceMember`

  - 10 `Destination` resources in the `destinations` list

- [`RemoveAllAudienceMembersRequest`](https://developers.google.com/data-manager/api/reference/rpc/google.ads.datamanager.v1#removeallaudiencemembersrequest):

  - 10 `Destination` resources in the `destinations` list
- [`IngestEventsRequest`](https://developers.google.com/data-manager/api/reference/rpc/google.ads.datamanager.v1#ingesteventsrequest):

  - 2,000 `Event` resources in the `events` list

  - 10 user identifiers in the `UserData` for an `Event`

  - 10 `Destination` resources in the `destinations` list