---
title: "Upload enhanced Google Ads conversions"
method: POST
path: "/api/apps/{app_id}/google-ads/conversions/upload-enhanced"
---

# Upload enhanced Google Ads conversions

`POST /api/apps/{app_id}/google-ads/conversions/upload-enhanced`

<Info>This API is in beta. Endpoints, fields, and behavior may still change, so avoid depending on it in production.</Info>

Adds hashed buyer details to conversions you have already reported, so Google can match more of them to a click.

Use it when you learn who the buyer was after the conversion was reported, for example a form submitted after checkout. Each adjustment finds its conversion by the `order_id` you sent originally, so it only works for a conversion you reported with one. It changes the details on an existing conversion and never creates a new one, so [Upload conversions](/api-reference/upload-google-ads-conversions) has to run first.

Hash each value yourself with SHA-256 over the lowercased, trimmed input and send lowercase hex. Base44 forwards what you send without hashing or normalizing it, so an unhashed or differently formatted value simply fails to match and reports as accepted.

Read the outcome from `total_uploaded` rather than `status`, which reports `success` as soon as one adjustment lands.

<Note>There is no cap on how many rows you can send and no rate limit on this endpoint. Base44 sends them to Google in batches of 2,000, one batch after another, while your request stays open, so a very large list means a very long request. Keep each call to a few thousand rows and send several calls instead.</Note>

<Warning>A 409 means the request to Google timed out after it was sent, so the adjustments may or may not have landed. Unlike [Upload conversions](/api-reference/upload-google-ads-conversions), this endpoint keeps no record of what it has sent, so a retry can apply the same adjustment twice. Check the conversion in Google Ads before retrying.</Warning>

<Note>This endpoint accepts a personal API key. Workspace API keys are not authorized for it and are rejected with a 403.</Note>

## Path parameters

- `app_id` string, required — ID of the app whose Google Ads conversion tracking you want to manage.

## Request body

- object
  - `adjustments` object[] — The adjustments to apply. An empty list is accepted and changes nothing.
    - `conversion_action_id` string, required — Google Ads' own ID for the goal the original conversion counted towards, as returned in `google_action_id` by [List conversion actions](/api-reference/list-google-ads-conversion-actions).
    - `order_id` string, required — The `order_id` you sent on the original conversion. It is how Google finds the conversion to enhance, so an adjustment without it cannot be matched.
    - `adjustment_date_time` string, required — When you are making the adjustment, as `YYYY-MM-DD HH:MM:SS+HH:MM` including the offset. Google rejects any other format with a 400.
    - `user_identifiers` object, required — Hashed details of the buyer to add to the conversion. Hash every value yourself, because Base44 sends them as given. An adjustment that ends up with no usable identifier is dropped before Google sees it.
      - `hashed_email` string — The buyer's email address, lowercased, trimmed, and SHA-256 hashed to lowercase hex.
      - `hashed_phone_number` string — The buyer's phone number in E.164 form, SHA-256 hashed to lowercase hex.
      - `hashed_first_name` string — The buyer's first name, lowercased and SHA-256 hashed to lowercase hex. Base44 only sends it together with `hashed_last_name`, so one without the other is dropped and has no effect.
      - `hashed_last_name` string — The buyer's last name, lowercased and SHA-256 hashed to lowercase hex. Send it together with `hashed_first_name`, because one without the other is dropped.
    - `user_agent` string — The browser user agent from the original conversion, which helps Google match it. Leave it out when you do not have it.

## Response `200`

What happened to the batch of adjustments.

- EnhancedConversionUploadResult — What happened to a batch of enhanced-conversion adjustments.
  - `status` string, required — Whether anything reached Google. The value is `success` when at least one adjustment landed and `no_rows_uploaded` when none did, so it does not tell you the whole batch landed.
  - `total_submitted` integer, required — How many adjustments you sent.
  - `total_uploaded` integer, required — How many adjustments Google accepted. Anything short of `total_submitted` is made up of adjustments dropped for carrying no usable hashed identifier and adjustments Google rejected one by one, and the response does not separate the two.

## Other responses

- `400` — Google Ads rejected the whole request, for example a malformed `conversion_date_time` or a `conversion_action_id` that is not on the account. The response message carries Google's reason.
- `401` — Missing or invalid credentials.
- `403` — You don't have access to this app, the app does not exist, or you used a workspace API key. A missing app and an app you cannot reach are deliberately the same answer.
- `404` — The app has no connected Google Ads account.
- `409` — The request to Google Ads timed out after being sent, so the adjustments may or may not have landed. Check the conversion in Google Ads before retrying, because a retry can apply the same adjustment twice.
- `422` — Validation Error
- `429` — Google Ads is rate limiting the account. Retry later.

---

[API](https://skmtc.dev/adexad/apis/base44-app-management-api.md) · [All operations](https://skmtc.dev/adexad/apis/base44-app-management-api/llms.txt) · [OpenAPI document](https://skmtc-service-production.skmtc.workers.dev/v1/apis/adexad/base44-app-management-api/revisions/6ad855bf424f/schema)
