This guide contains examples of calling the REST endpoints directly, without the use of a client library.
Prerequisites
All the samples below are meant to be copy-and-pasted into a bash shell using the curl command.
You also need a developer token, test account access is fine, and a Google Ads manager account containing at least one client account.
Environment variables
Enter account credentials and IDs below, and then copy-and-paste into your terminal to configure the environment variables used in the subsequent examples. The Authorization guide provides instructions for generating an OAuth 2.0 access token.
API_VERSION="17"
DEVELOPER_TOKEN="DEVELOPER_TOKEN"
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 below.
BUDGET_ID=BUDGET_ID
CAMPAIGN_ID=CAMPAIGN_ID
Otherwise, the two Mutates - Creates examples create a new budget and campaign.
Search
The 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 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
curl -f --request POST "https://googleads.googleapis.com/v${API_VERSION}/customers/${CUSTOMER_ID}/googleAds:search" \ --header "Content-Type: application/json" \ --header "developer-token: ${DEVELOPER_TOKEN}" \ --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
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
curl -f --request POST "https://googleads.googleapis.com/v${API_VERSION}/customers/${CUSTOMER_ID}/googleAds:searchStream" \ --header "Content-Type: application/json" \ --header "developer-token: ${DEVELOPER_TOKEN}" \ --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
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 "developer-token: ${DEVELOPER_TOKEN}" \ --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. The campaign created below
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 "developer-token: ${DEVELOPER_TOKEN}" \ --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 "developer-token: ${DEVELOPER_TOKEN}" \ --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 "developer-token: ${DEVELOPER_TOKEN}" \ --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 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 "developer-token: ${DEVELOPER_TOKEN}" \ --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 "developer-token: ${DEVELOPER_TOKEN}" \ --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
Creating 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 "developer-token: ${DEVELOPER_TOKEN}" \ --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' } }"
Listing 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 "developer-token: ${DEVELOPER_TOKEN}" \ --header "Authorization: Bearer ${OAUTH2_ACCESS_TOKEN}" \
Uploading binary assets
The assets:mutate
method is used for uploading and managing
Assets. 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)
to encode a 1-pixel GIF image.
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 "developer-token: ${DEVELOPER_TOKEN}" \ --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' } } } ] }"