Keep the following best practices in mind when using the Data Manager API.

## Send all user identifiers

Whether sending audience members or events with [`UserData`](https://developers.google.com/data-manager/api/reference/rpc/google.ads.datamanager.v1#userdata), include as many
`user_identifiers` as possible, including sending multiple identifiers of the
same type.

For example, if you have multiple email addresses for a user, include a separate
[`UserIdentifier`](https://developers.google.com/data-manager/api/reference/rpc/google.ads.datamanager.v1#useridentifier) for each email address. Similarly, if you have identifiers of
different types for a user, such as email addresses, phone numbers, and
addresses, add a separate `UserIdentifier` for each identifier, up to the
[maximum identifier count](https://developers.google.com/data-manager/api/devguides/limits#request_limits).

## Optimize requests

To reduce the likelihood of exceeding daily request limits, batch as many
items as possible in each request, up to the [per-request
limits](https://developers.google.com/data-manager/api/devguides/limits#request_limits).

For example, if you want to add 10,000 audience members to an audience, add all
10,000 members in the `audience_members` list in one
[`IngestAudienceMembersRequest`](https://developers.google.com/data-manager/api/reference/rpc/google.ads.datamanager.v1#ingestaudiencemembersrequest). Batching all 10,000
members in a single request is more efficient than sending a separate request to
add each audience member.

## Send concurrent requests

To reduce the overall time required to ingest data, send concurrent requests
to the [`IngestionService`](https://developers.google.com/data-manager/api/reference/rpc/google.ads.datamanager.v1#ingestionservice). We recommend sending up to 10
requests concurrently to reduce the likelihood of exceeding the [requests per
minute limit](https://developers.google.com/data-manager/api/devguides/limits#project_limits).

You can send concurrent requests even if the requests have the same
`destinations`.

## Validate data on the client side

The Data Manager API uses a [fast-fail model](https://developers.google.com/data-manager/api/devguides/concepts/understand-errors#fast-fail). If any record in a
request fails synchronous validation, the entire request fails and none of the
records are processed. In addition, the API validates requests in sequential
layers, so fixing one error might reveal an error from a subsequent validation
layer.

To avoid repeated round trips and rejected requests, validate and sanitize your
data before sending it:

- **Strip empty values before hashing:** Check fields such as `email_address`
  and `phone_number` for empty or whitespace-only strings before computing
  SHA-256 hashes. Hashing an empty string produces a valid hash that passes
  syntax checks but hurts match rates.

- **Drop incomplete compound objects:** Ensure compound objects have all
  required fields before adding them to a record. For example, if an
  [`AddressInfo`](https://developers.google.com/data-manager/api/reference/rpc/google.ads.datamanager.v1#addressinfo) object is missing any of its four required
  fields (`given_name`, `family_name`, `region_code`, or `postal_code`), drop
  the entire `address` identifier to avoid `REQUIRED_FIELD_MISSING` errors.

- **Validate encoding and plaintext fields:** Verify that hashed fields match
  the declared `encoding` rather than sending raw plaintext, and ensure
  fields that must remain plaintext (such as `mobile_ids`) aren't hashed.

- **Filter out-of-bounds timestamps:** Ensure timestamps aren't in the
  future or older than the destination's conversion lookback window.

  If you send requests using JSON, ensure timestamp strings use
  [RFC 3339 format](https://developers.google.com/data-manager/api/devguides/concepts/formatting#timestamp_format) with a timezone offset.
- **Clean phone numbers:** Verify that phone numbers include a country code
  and use [E.164 format](https://developers.google.com/data-manager/api/devguides/concepts/formatting) before hashing.

- **Prune empty or oversized records:** Cap `user_identifiers` at the
  [per-record limit](https://developers.google.com/data-manager/api/devguides/limits#request_limits) (10 identifiers), drop empty custom
  parameters, and omit any record that contains zero valid identifiers.

- **Verify use-case requirements:** Ensure each event includes all mandatory
  fields for its destination and use case (such as `transaction_id` for
  Google Ads online conversions). For a complete list of required fields by
  use case, see the send events guide for your destination in the
  [Events overview](https://developers.google.com/data-manager/api/devguides/events).

- **Use `validateOnly` to test requests:** Send requests with
  [`validateOnly`](https://developers.google.com/data-manager/api/devguides/concepts/understand-errors#validate-only) set to `true` to catch
  [fast-fail errors](https://developers.google.com/data-manager/api/devguides/concepts/understand-errors#fast-fail) without ingesting or removing data. A
  successful validation-only request doesn't guarantee there won't be
  errors during asynchronous processing, so continue to
  [check request status and diagnostics](https://developers.google.com/data-manager/api/devguides/concepts/best-practices#check-diagnostics) after sending a
  regular request.

For detailed normalization and hashing rules, see
[Format user data](https://developers.google.com/data-manager/api/devguides/concepts/formatting).

## Check request status and diagnostics

> [!IMPORTANT]
> **Important:** Check [request status and diagnostics](https://developers.google.com/data-manager/api/devguides/diagnostics) for each ingestion request to identify errors and warnings from audience or event processing.

Capture and collect the `request_id` from each
[`IngestAudienceMembersResponse`](https://developers.google.com/data-manager/api/reference/rpc/google.ads.datamanager.v1#ingestaudiencemembersresponse) or
[`IngestEventsResponse`](https://developers.google.com/data-manager/api/reference/rpc/google.ads.datamanager.v1#ingesteventsresponse), and use the request IDs to
check [request status and diagnostics](https://developers.google.com/data-manager/api/devguides/diagnostics).

## Monitor and alert on quotas

To avoid unexpected request rejections, [set up quota alerts and
monitoring](https://cloud.google.com/docs/quotas/set-up-quota-alerts) in the Google Cloud console.
Monitoring quota usage helps you track consumption patterns and optimize
request batching before your application reaches [daily or per-minute
limits](https://developers.google.com/data-manager/api/devguides/limits#project_limits).

## Deploy to production

When moving from local testing to production workloads, use
[Application Default Credentials](https://developers.google.com/data-manager/api/devguides/concepts/deploy) with an attached service
account or Workload Identity Federation to authenticate non-interactively and
securely.

For details on configuring authentication for different production
environments, see [Deploy to production](https://developers.google.com/data-manager/api/devguides/concepts/deploy).