---
title: "Create a Google Ads Search campaign (paused)"
method: POST
path: "/api/v1/tools/google_create_search_campaign/execute"
tags: ["Google Ads"]
---

# Create a Google Ads Search campaign (paused)

`POST /api/v1/tools/google_create_search_campaign/execute`

## Request

- Base URL: `https://adako.ai`
- URL: `https://adako.ai/api/v1/tools/google_create_search_campaign/execute`
- Auth: HTTP bearer

Creates a complete Search campaign in one atomic operation: daily budget, campaign, location and language targeting, ad groups, keywords, one responsive search ad per ad group and optional campaign-level negatives. Either everything is created or nothing is.
The campaign is created PAUSED and its ad groups and ads are created enabled inside it, so no money can be spent until the campaign is turned on, and turning it on launches everything. Say this explicitly when you report the result, with the two links the result gives (Google Ads and the campaign's page in Adako), and offer "enable all": google_resume_campaign turns the campaign on in one approval.
Use when: the user has agreed on a structure (budget, locations, ad groups, keywords, ad copy) and wants it built.
Do not use when: anything is still undecided. Resolve place names with google_resolve_locations first (free text is rejected), take language ids from google_list_languages, check ad copy with google_validate_ad_copy, and confirm the daily budget in the account currency. Call this once per campaign: on an error, read what exists with google_list_campaigns rather than retrying.
The preview runs Google's own dry run (validateOnly), so policy and structural rejections surface before anything is created. Search partners are off unless include_search_partners is true. Locations reach people in or regularly in those places (Presence) unless location_targeting is PRESENCE_OR_INTEREST, which also reaches people elsewhere who show interest in them. Leaving language_ids out sets no language criterion, so language does not restrict the campaign. Google Ads Help says that from September 2026 Search ads are matched on the language of the ad text and the campaign language setting is being removed for Search, so write the ads in the language the audience reads.
Dates are whole days in the account time zone: a start date before today is refused, and an end date stops the campaign at the end of that day. Budgets and bids are decimals in the account currency, never micros, rounded to the smallest amount Google bills in that currency (whole units for JPY, KRW and a few others); the preview shows the rounded amounts. Ids are strings.
Political advertising is not supported: every campaign is declared as containing no EU political advertising. If the user wants to run political ads, tell them to create the campaign in the Google Ads interface.
If you are unsure which account, campaign or period the user means, ask them — do not guess ids or dates.

## Headers

- `Idempotency-Key` string

## Request body

- object
  - `arguments` object, required
    - `customer_id` string: Google Ads customer id (10 digits, dashes optional). Omit to use the primary account; list_connected_accounts shows the valid ids.
    - `campaign_name` string, required: Campaign name. Must not already exist in the account.
    - `daily_budget` number: Average daily budget as a decimal in the account currency (for example 50 for $50/day). Never micros. Give this or budget_id, never both.
    - `budget_id` string: Join a budget that already exists instead of creating one: the `budget_id` of any campaign in google_list_campaigns. Use it for a shared budget, where several campaigns draw on one amount — the campaigns then compete for it, and changing the amount later moves all of them at once.
    - `bidding_strategy` 'MAXIMIZE_CLICKS' | 'MAXIMIZE_CONVERSIONS' | 'TARGET_CPA' | 'TARGET_ROAS' | 'MANUAL_CPC': How Google should bid. TARGET_CPA needs target_cpa; TARGET_ROAS needs target_roas. Give this or portfolio_strategy_id, never both.
    - `portfolio_strategy_id` string: Run the campaign on a portfolio (shared) bidding strategy that already exists, from google_list_bidding_strategies. The strategy then decides the bidding for every campaign on it, so target_cpa and target_roas belong to it and are not set here.
    - `target_cpa` number: Target cost per conversion, decimal in the account currency.
    - `target_roas` number: Target return on ad spend as a ratio, e.g. 4 for 400%.
    - `location_ids` string[], required: Geo target constant ids from google_resolve_locations. Place names are rejected.
    - `location_targeting` 'PRESENCE' | 'PRESENCE_OR_INTEREST': Who the locations reach. PRESENCE (the default here): people in or regularly in those places. PRESENCE_OR_INTEREST (Google’s own default): also people elsewhere who show interest in them, e.g. someone abroad planning a trip. Choose it only when the user wants that wider reach.
    - `language_ids` string[]: Language constant ids from google_list_languages, e.g. ["1000"] for English. Omit to set no language criterion, which leaves the campaign unrestricted by language.
    - `include_search_partners` boolean: Show on Google Search partner sites too. Default false: partner traffic converts differently and is hard to segment.
    - `start_date` string: First day the campaign may run (YYYY-MM-DD), in the account time zone. Today or later; omit to start whenever it is enabled.
    - `end_date` string: Last day the campaign may run (YYYY-MM-DD), in the account time zone; it stops at the end of that day.
    - `ad_groups` object[], required: One to ten ad groups, each with keywords and one responsive search ad.
      - `name` string, required: Ad group name, unique within the campaign.
      - `default_bid` number: Default max CPC for the ad group, decimal in the account currency.
      - `keywords` object[], required: Keywords for this ad group.
        - `text` string, required: Keyword text, without match-type punctuation.
        - `match_type` 'EXACT' | 'PHRASE' | 'BROAD', required: EXACT, PHRASE or BROAD.
        - `cpc_bid` number: Optional max CPC for this keyword, decimal in the account currency.
      - `headlines` string[], required: Between 3 and 15 headlines, each at most 30 characters.
      - `descriptions` string[], required: Between 2 and 4 descriptions, each at most 90 characters.
      - `path1` string: First display path segment.
      - `path2` string: Second display path segment; needs path1.
      - `final_url` string, uri, required: Landing page for this ad group, including https://.
    - `negative_keywords` object[]: Campaign-level negative keywords applied to every ad group.
      - `text` string, required
      - `match_type` 'EXACT' | 'PHRASE' | 'BROAD', required
    - `idempotency_key` string: Optional caller-supplied key; identical keys never execute twice.

## Response `200`

The tool ran. A write returns proposal_id and approve_url while the change waits for approval.

- SuccessEnvelope
  - `success` unknown, required
  - `tool` string, required
  - `data` object, required: Machine-readable result.
  - `markdown` string, required: The same result written for a person or a model.
  - `quota` Quota: Task usage for the current billing period.
    - `plan` string
    - `used` integer
    - `limit` integer
    - `period_end` string
    - `upgrade_url` string
  - `proposal_id` string: Present for writes. Nothing changes on the ad platform until it is approved.
  - `approve_url` string: Where a person approves the proposal.
  - `request_id` string, required

## Other responses

- `400`: Invalid arguments, or the ad account could not be resolved.
- `401`: Missing, invalid, revoked or expired API key.
- `402`: Monthly task quota used up, or the plan does not include this tool.
- `403`: The connected ad account lacks the access level this tool needs.
- `404`: Unknown tool name.
- `409`: Not connected, reconnect needed, confirmation required, a proposal already pending or no longer pending, an identical create that failed earlier today (proposal_failed_before), a create that duplicates an approved one (duplicate_create), the ad-account limit of the plan reached (account_limit), or an Idempotency-Key reused with different arguments.
- `429`: Rate limited by Adako or by the ad platform. See Retry-After.
- `500`: Unexpected error inside Adako.
- `502`: The ad platform returned an error.

---

[API](https://skmtc.dev/adako/apis/adako-rest-api.md) · [All operations](https://skmtc.dev/adako/apis/adako-rest-api/llms.txt) · [OpenAPI document](https://skmtc.dev/adako/apis/adako-rest-api/revisions/59ee60d48a56?raw)
