> [!NOTE]
> **Note:** If you are new to the Google Ads API, we recommend reading the [Getting
> Started](https://developers.google.com/google-ads/api/docs/get-started/make-first-call) guide first, which covers how to set up your account and make your first API call. Make sure to follow the *curl* tab.

This guide contains examples of calling the REST endpoints directly, without the
use of a client library.

For more detailed code examples, check out the REST code examples [GitHub
repository](https://github.com/googleads/google-ads-rest).

To view the request and response bodies for each API method, refer to the
reference documentation for specific service endpoints.

For example, the [reference page](https://developers.google.com/google-ads/api/reference/rpc/v26/GoogleAdsService/Search?transport=rest) for `GoogleAdsService.Search`
shows the request and response bodies for the `Search` method.

## Prerequisites

All the samples shown here are meant to be copy-and-pasted into a
[bash shell](https://www.gnu.org/software/bash/) using the [curl](https://curl.se/) command.

You also need a [Google Cloud project](https://developers.google.com/google-ads/api/docs/get-started/make-first-call#console-project), [test account
access](https://developers.google.com/google-ads/api/docs/access-levels#test-account-access) is fine, and a Google Ads manager account containing at
least one client account.

> [!IMPORTANT]
> **Important:** In these examples, we assume that you're accessing a client account (`CUSTOMER_ID`) by a user that has administrative access to a manager account (`MANAGER_CUSTOMER_ID`) that directly manages the client account. If you're instead accessing an individual client account directly, omit the `login-customer-id` header or set it to the same value as `CUSTOMER_ID`. Note that some examples, like [Create accounts](https://developers.google.com/google-ads/api/rest/examples#create-accounts), require a manager account.

### Environment variables

Enter account credentials and IDs as shown, and then copy-and-paste into your
terminal to configure the environment variables used in the subsequent examples.
The [Authorization](https://developers.google.com/google-ads/api/rest/auth) guide provides instructions for generating an
OAuth 2.0 access token.

    API_VERSION="26"
    OAUTH2_ACCESS_TOKEN="OAUTH_ACCESS_TOKEN"
    MANAGER_CUSTOMER_ID="MANAGER_CUSTOMER_ID"
    CUSTOMER_ID="CUSTOMER_ID"

#### Additional optional object IDs

Some of the following examples work on pre-existing budgets or campaigns. If you
have IDs of existing objects to use with these examples, enter them as shown.

    BUDGET_ID=BUDGET_ID
    CAMPAIGN_ID=CAMPAIGN_ID

Otherwise, the two [Mutates - Creates examples](https://developers.google.com/google-ads/api/rest/examples#creates) create
a new budget and campaign.

## Search

The [Query Cookbook](https://developers.google.com/google-ads/api/docs/query/cookbook) guide contains many reporting samples that
correspond to some of the default Google Ads screens and work with the same
environment variables used in this guide. Our
[interactive query builder tool](https://developers.google.com/google-ads/api/fields/latest/overview_query_builder) is also a great
resource for building custom queries interactively.

### Paginated

The `search` method uses pagination, with a fixed page size of 10,000 items and
a `page_token` specified alongside the `query`.

### curl

```console
curl -f --request POST "https://googleads.googleapis.com/v${API_VERSION}/customers/${CUSTOMER_ID}/googleAds:search" \
--header "Content-Type: application/json" \
--header "login-customer-id: ${MANAGER_CUSTOMER_ID}" \
--header "Authorization: Bearer ${OAUTH2_ACCESS_TOKEN}" \
--data '{
"query": "
  SELECT campaign.name,
    campaign_budget.amount_micros,
    campaign.status,
    campaign.optimization_score,
    campaign.advertising_channel_type,
    metrics.clicks,
    metrics.impressions,
    metrics.ctr,
    metrics.average_cpc,
    metrics.cost_micros,
    campaign.bidding_strategy_type
  FROM campaign
  WHERE segments.date DURING LAST_7_DAYS
    AND campaign.status != 'REMOVED'
",
"page_token":"${PAGE_TOKEN}"
}'
```

### GAQL

```sql
SELECT campaign.name,
  campaign_budget.amount_micros,
  campaign.status,
  campaign.optimization_score,
  campaign.advertising_channel_type,
  metrics.clicks,
  metrics.impressions,
  metrics.ctr,
  metrics.average_cpc,
  metrics.cost_micros,
  campaign.bidding_strategy_type
FROM campaign
WHERE segments.date DURING LAST_7_DAYS
  AND campaign.status != 'REMOVED'
```

### Streaming

The `searchStream` method streams all results in a single response, thus, the
`pageSize` field is not supported.

### curl

```console
curl -f --request POST "https://googleads.googleapis.com/v${API_VERSION}/customers/${CUSTOMER_ID}/googleAds:searchStream" \
--header "Content-Type: application/json" \
--header "login-customer-id: ${MANAGER_CUSTOMER_ID}" \
--header "Authorization: Bearer ${OAUTH2_ACCESS_TOKEN}" \
--data '{
"query": "
  SELECT campaign.name,
    campaign_budget.amount_micros,
    campaign.status,
    campaign.optimization_score,
    campaign.advertising_channel_type,
    metrics.clicks,
    metrics.impressions,
    metrics.ctr,
    metrics.average_cpc,
    metrics.cost_micros,
    campaign.bidding_strategy_type
  FROM campaign
  WHERE segments.date DURING LAST_7_DAYS
    AND campaign.status != 'REMOVED'
"
}'
```

### GAQL

```sql
SELECT campaign.name,
  campaign_budget.amount_micros,
  campaign.status,
  campaign.optimization_score,
  campaign.advertising_channel_type,
  metrics.clicks,
  metrics.impressions,
  metrics.ctr,
  metrics.average_cpc,
  metrics.cost_micros,
  campaign.bidding_strategy_type
FROM campaign
WHERE segments.date DURING LAST_7_DAYS
  AND campaign.status != 'REMOVED'
```

## Mutates

Multiple mutate operations (`create`, `update`, or `remove`) can be sent in a
single JSON request body by populating the `operations` array.

### Creates

This example creates two shared campaign budgets in a single request.

```
curl -f --request POST "https://googleads.googleapis.com/v${API_VERSION}/customers/${CUSTOMER_ID}/campaignBudgets:mutate" \
--header "Content-Type: application/json" \
--header "login-customer-id: ${MANAGER_CUSTOMER_ID}" \
--header "Authorization: Bearer ${OAUTH2_ACCESS_TOKEN}" \
--data "{
'operations': [
  {
    'create': {
      'name': 'My Campaign Budget #${RANDOM}',
      'amountMicros': 500000,
    }
  },
  {
    'create': {
      'name': 'My Campaign Budget #${RANDOM}',
      'amountMicros': 500000,
    }
  }
]
}"
```

The next example uses a `BUDGET_ID` of an existing campaign budget; you can
copy-and-paste from the previous step's output.

    BUDGET_ID=BUDGET_ID

Resources that refer to other resources do so by [resource name](https://developers.google.com/google-ads/api/docs/rest/design/resource-names).
The campaign created in the following example refers to a `campaignBudget` by
its string-valued resource name.

```
curl -f --request POST "https://googleads.googleapis.com/v${API_VERSION}/customers/${CUSTOMER_ID}/campaigns:mutate" \
--header "Content-Type: application/json" \
--header "login-customer-id: ${MANAGER_CUSTOMER_ID}" \
--header "Authorization: Bearer ${OAUTH2_ACCESS_TOKEN}" \
--data "{
'operations': [
  {
    'create': {
      'status': 'PAUSED',
      'advertisingChannelType': 'SEARCH',
      'geoTargetTypeSetting': {
        'positiveGeoTargetType': 'PRESENCE_OR_INTEREST',
        'negativeGeoTargetType': 'PRESENCE_OR_INTEREST'
      },
      'name': 'My Search campaign #${RANDOM}',
      'campaignBudget': 'customers/${CUSTOMER_ID}/campaignBudgets/${BUDGET_ID}',
      'targetSpend': {}
    }
  }
]
}"
```

### Updates

Update attributes of existing objects using `update` operations. The next
example uses an existing campaign; you can copy-and-paste from the previous
step's output.

    CAMPAIGN_ID=CAMPAIGN_ID

All updates require an `updateMask` field, a comma-separated list of which JSON
attributes should be in the request, that should be applied as an update.
Attributes listed in the `updateMask` but not present in the request body are
cleared on an object. Attributes *not listed* in the `updateMask`, but present
in the request body, are ignored.

```
curl -f --request POST "https://googleads.googleapis.com/v${API_VERSION}/customers/${CUSTOMER_ID}/campaigns:mutate" \
--header "Content-Type: application/json" \
--header "login-customer-id: ${MANAGER_CUSTOMER_ID}" \
--header "Authorization: Bearer ${OAUTH2_ACCESS_TOKEN}" \
--data "{
'operations': [
  {
    'update': {
      'resourceName': 'customers/${CUSTOMER_ID}/campaigns/${CAMPAIGN_ID}',
      'name': 'A changed campaign name #${RANDOM}',
    },
    'updateMask': 'name'
  }
],
}"
```

### Removes

Objects are removed by specifying their resource name as a `remove` operation.

```
curl -f --request POST "https://googleads.googleapis.com/v${API_VERSION}/customers/${CUSTOMER_ID}/campaigns:mutate" \
--header "Content-Type: application/json" \
--header "login-customer-id: ${MANAGER_CUSTOMER_ID}" \
--header "Authorization: Bearer ${OAUTH2_ACCESS_TOKEN}" \
--data "{
'operations': [
  {
    'remove': 'customers/${CUSTOMER_ID}/campaigns/${CAMPAIGN_ID}'
  }
],
}"
```

## Partial failures

When multiple operations are in a single request, optionally specify
`partialFailure`. If `true`, successful operations are carried out and invalid
operations return errors. If `false`, all operations in the request succeed if
and only if they are all valid.

The next example uses an existing campaign; you can copy-and-paste from the
[**Creates** example](https://developers.google.com/google-ads/api/rest/examples#creates) output.

    CAMPAIGN_ID=CAMPAIGN_ID

The following request contains two operations. The first attempts to change the
bid strategy of the provided campaign, and the next one tries removing a
campaign with an invalid ID. Since the second operation results in an error (the
campaign ID is invalid) and because `partialFailure` is set to `false`, the
first operation also fails and the existing campaign's bid strategy is not
updated.

```
curl --request POST "https://googleads.googleapis.com/v${API_VERSION}/customers/${CUSTOMER_ID}/campaigns:mutate" \
--header "Content-Type: application/json" \
--header "login-customer-id: ${MANAGER_CUSTOMER_ID}" \
--header "Authorization: Bearer ${OAUTH2_ACCESS_TOKEN}" \
--data "{
'partialFailure': false,
'operations': [
  {
    'update': {
      'resourceName': 'customers/${CUSTOMER_ID}/campaigns/${CAMPAIGN_ID}',
      'manualCpc': {
        'enhancedCpcEnabled': false
      }
    },
    'updateMask': 'manual_cpc.enhanced_cpc_enabled'
  },
  {
    'remove': 'customers/${CUSTOMER_ID}/campaigns/INVALID_CAMPAIGN_ID'
  }
]
}"
```

## Grouped operations

The `googleAds:mutate` method supports sending groups of operations with
multiple types of resources. You can send many operations of different types to
chain together a sequence of operations that should be carried out as a group.
The set of operations succeeds if no operation fails or all fail if any single
operation fails.

This example demonstrates creating a campaign budget, campaign, ad group, and ad
together as a single set of actions. Each successive operation depends on the
previous one. If one fails, the entire group of operations fails.

Negative integers (`-1`, `-2`, `-3`) are used as placeholders in the resource
names and are filled dynamically at runtime with the results from the sequence
of operations.

```
curl -f --request POST "https://googleads.googleapis.com/v${API_VERSION}/customers/${CUSTOMER_ID}/googleAds:mutate" \
--header "Content-Type: application/json" \
--header "login-customer-id: ${MANAGER_CUSTOMER_ID}" \
--header "Authorization: Bearer ${OAUTH2_ACCESS_TOKEN}" \
--data "{
'mutateOperations': [
  {
    'campaignBudgetOperation': {
      'create': {
        'resourceName': 'customers/${CUSTOMER_ID}/campaignBudgets/-1',
        'name': 'My Campaign Budget #${RANDOM}',
        'deliveryMethod': 'STANDARD',
        'amountMicros': 500000,
        'explicitlyShared': false
      }
    }
  },
  {
    'campaignOperation': {
      'create': {
        'resourceName': 'customers/${CUSTOMER_ID}/campaigns/-2',
        'status': 'PAUSED',
        'advertisingChannelType': 'SEARCH',
        'geoTargetTypeSetting': {
          'positiveGeoTargetType': 'PRESENCE_OR_INTEREST',
          'negativeGeoTargetType': 'PRESENCE_OR_INTEREST'
        },
        'name': 'My Search campaign #${RANDOM}',
        'campaignBudget': 'customers/${CUSTOMER_ID}/campaignBudgets/-1',
        'targetSpend': {}
      }
    }
  },
  {
    'adGroupOperation': {
      'create': {
        'resourceName': 'customers/${CUSTOMER_ID}/adGroups/-3',
        'campaign': 'customers/${CUSTOMER_ID}/campaigns/-2',
        'name': 'My ad group #${RANDOM}',
        'status': 'PAUSED',
        'type': 'SEARCH_STANDARD'
      }
    }
  },
  {
    'adGroupAdOperation': {
      'create': {
        'adGroup': 'customers/${CUSTOMER_ID}/adGroups/-3',
        'status': 'PAUSED',
        'ad': {
          'responsiveSearchAd': {
            'headlines': [
              {
                'pinned_field': 'HEADLINE_1',
                'text': 'An example headline'
              },
              {
                'text': 'Another example headline'
              },
              {
                'text': 'Yet another headline'
              }
            ],
            'descriptions': [
              {
                'text': 'An example description'
              },
              {
                'text': 'Another example description'
              }
            ],
            'path1': 'all-inclusive',
            'path2': 'deals'
          },
          'finalUrls': ['https://www.example.com']
        }
      }
    }
  }
]
}"
```

## Account management

You can create accounts, list accessible accounts, and upload binary assets.

### Create accounts

Create new accounts using the `createCustomerClient` method. Note that the URL
requires a *manager account* ID instead of a client account ID. A new client
account is created under the manager account.

```
curl f --request POST "https://googleads.googleapis.com/v${API_VERSION}/customers/${MANAGER_CUSTOMER_ID}:createCustomerClient" \
--header "Content-Type: application/json" \
--header "login-customer-id: ${MANAGER_CUSTOMER_ID}" \
--header "Authorization: Bearer ${OAUTH2_ACCESS_TOKEN}" \
--data "{
'customerClient': {
  'descriptiveName': 'My Client #${RANDOM}',
  'currencyCode': 'USD',
  'timeZone': 'America/New_York'
}
}"
```

### List accessible accounts

Use a simple `GET` request to the `listAccessibleCustomers` method to get a list
of Google Ads accounts accessible with the given OAuth 2.0 access token. No manager
or client account IDs should be used in this request.

```
curl -f --request GET "https://googleads.googleapis.com/v${API_VERSION}/customers:listAccessibleCustomers" \
--header "Content-Type: application/json" \
--header "Authorization: Bearer ${OAUTH2_ACCESS_TOKEN}" \
```

## Upload binary assets

The `assets:mutate` method is used for uploading and managing [Assets](https://developers.google.com/google-ads/api/docs/assets/overview).
Binary data, such as an image, is encoded as a string using standard base64
encoding with padding. Either standard or URL-safe base64 encoding with or
without padding are accepted.

This example encodes a 1-pixel GIF to keep the sample concise. In practice, the
`data` payloads are much larger.

Use the `base64` command line utility (part of
[GNU core utilities](https://www.gnu.org/software/coreutils)) to encode a
[1-pixel GIF image](https://developers.google.com/static/google-ads/api/images/1pixel.gif).

```
base64 1pixel.gif
```

The base64-encoded value is specified as the `data` attribute in an API request.

```
curl -f --request POST "https://googleads.googleapis.com/v${API_VERSION}/customers/${CUSTOMER_ID}/assets:mutate" \
--header "Content-Type: application/json" \
--header "login-customer-id: ${MANAGER_CUSTOMER_ID}" \
--header "Authorization: Bearer ${OAUTH2_ACCESS_TOKEN}" \
--data "{
'operations': [
  {
    'create': {
      'name': 'My image asset #${RANDOM}',
      'type': 'IMAGE',
      'imageAsset': {
        'data': 'R0lGODlhAQABAAAAACH5BAEAAAAALAAAAAABAAEAAAIA'
      }
    }
  }
]
}"
```