---
name: google-ads-oauth-app
description: >-
  Google Ads API credentials, on top of the shared
  `google-cloud-console-oauth` skill — read that one first for the Cloud
  project, consent app, client, redirect URIs and verification. This file
  covers only what Google Ads adds: the API access level that replaced the
  developer token at the 9 September 2026 sunset, the Test / Explorer / Basic
  / Standard ladder, brand verification, the manager (MCC) account and its
  Terms of Service, the single `adwords` scope, the `login-customer-id`
  header, and the 2SV and passkey mandates. Use when asked for Google Ads API
  credentials, a developer token, a manager account, Basic or Standard access,
  or when a Google Ads connector fails with `DEVELOPER_TOKEN_NOT_APPROVED`,
  `CLOUD_PROJECT_NOT_APPROVED_FOR_PRODUCTION`, `USER_PERMISSION_DENIED` or
  `TWO_STEP_VERIFICATION_NOT_ENROLLED`. A client that authorizes fine still
  cannot read a production ad account without a reviewed access level.
---

# Google Ads API OAuth2 App Registration

Get a Google Ads API client that can actually read a customer's live ad accounts: an OAuth2 client ID and secret, an
approved **API access level** for the Cloud project that owns them, a Google Ads manager account, and the
`login-customer-id` header wired into the calls.

The thing that makes Google Ads different from plain Google OAuth is that **the OAuth client is only half the
credential**. The other half is an access level Google grants after reviewing your tool — historically issued as a
22-character *developer token* from a Google Ads manager account, and since 9 September 2026 attached to the Google
Cloud project instead. The two halves come from two different consoles owned by two different Google products, and a
perfectly valid OAuth client whose project sits at **Test** access can authorize every customer in the world and then
fail every single API call against a real ad account. Budget for the review, not the clicking.

## Built on: `google-cloud-console-oauth`

**Read that skill first.** It is the whole registration mechanic; this file is the Ads delta and assumes it. What it
covers, and what you will be missing if you load only this file:

- Picking or creating the **Cloud project**, enabling APIs, permissions, and the Google Auth Platform page layout.
- Creating the OAuth client: **Web application** is the type that yields a usable client secret; the others do not.
- **Redirect URI** rules — exact match, HTTPS only, no wildcards, propagation delay — and the Unified.to callback list.
- **Declaring every scope** on the Data Access page, and how scope tiers drive review.
- The **one-time client secret** (hashed; full value shown only at creation) and add-then-disable rotation.
- **Testing vs In production**, the seven-day refresh-token expiry, the 100-user caps, and OAuth app verification.

Where this file and the base ever disagree, the base wins.

## Inputs to collect before you start

The base skill's input list applies in full. These are the extra ones Google Ads needs. Ask in one batch; never invent.

| Input | Notes |
| --- | --- |
| **Which Google Cloud project** owns, or will own, the OAuth client | This is the credential that now carries API access (§1, §2, §5) |
| **Existing developer token**, if any, and the manager account it came from | Determines reuse vs. re-application (§1, §5) |
| **Manager (MCC) account** that will sit at the root, and its 10-digit customer ID | Needed for `login-customer-id` and for test hierarchies (§2, §7) |
| **Tool profile**: full-service, reporting-only, or internal | Decides the access level you need and whether RMF applies (§5) |
| **Expected daily operation volume** | Decides Explorer vs. Basic vs. Standard (§5) |
| **Google account** that will own the project, with 2SV/passkey already enabled | Blocking for generating refresh tokens (§4) |

## Quick Start

1. Reuse the existing **project** if you can — a new one starts back at Test access, with no way to carry the old
   approval across (§1).
2. Create or select the Google Ads **manager account**, plus a **test manager account** if you are below Explorer, and
   enable the Google Ads API in the project — that grants **Test** access automatically (§2).
3. Run the base skill's consent-app and Web-application-client steps with the Ads overrides: External, In production,
   complete branding (§3).
4. Request the single `https://www.googleapis.com/auth/adwords` scope with `access_type=offline` (§4).
5. Work the **access level** ladder — Test → Explorer → Basic → Standard, brand verification included. The long pole (§5).
6. Capture all three credentials: client ID, client secret, and the developer token / access-level state (§6).
7. Verify against a **test** account first, then a production one (§7), and hand off (§8).

## Platform state (verified 2026-09-20 — re-verify before trusting)

This area changed eleven days ago. Anything written before September 2026 — including parts of Google's own docs —
describes a process that no longer exists.

- **Developer tokens were sunset on 9 September 2026.** API access levels now attach to the **Google Cloud project**
  that owns your OAuth client ID and secret (or your service account), not to a token. You may still send the
  `developer-token` header; it is accepted and ignored, so existing code keeps working. Google says it will start
  **rejecting** developer tokens in a future major API version.
- **Access levels were migrated automatically**, based on the last 90 days of API call logs: every Cloud project seen
  using an approved developer token inherited that token's level. A token that was approved but never used, or unused
  for 90 days, transferred **nothing** — those projects sit at Test.
- **You can no longer re-associate an approved developer token with a new Cloud project.** Google supported this
  case-by-case until the sunset; it does not any more. A new project must apply for access on its own merits.
- **Sign-up moved to the Google Cloud Console.** Applications started from the Google Ads manager account's **API
  Center** are no longer processed. API Center still exists for historical lookup and will be retired. The one
  exception Google calls out: the **App Conversion Tracking API** still issues developer tokens from API Center.
- **There are now four access levels, not three**: Test, **Explorer**, Basic, Standard. Explorer is new and is the
  first rung that touches production accounts.
- **Brand verification is a prerequisite for Basic access** on new applications. Basic is then reviewed
  automatically, within minutes. Standard is still a manual audit.
- **2-Step Verification has been required since 21 April 2026** for users generating new refresh tokens, and from
  **5 August 2026** Google began requiring **passkeys** for some Google Ads API users. Existing refresh tokens are
  unaffected either way.
- **Known issue, open as of this date**: projects on the Google Cloud **Free Trial**, or with a suspended or disabled
  billing account, get rejected for Explorer and Basic even after brand verification, with a rejection email blaming
  brand verification or eligibility. Workarounds: upgrade the project to a paid tier, remove billing from the project
  entirely, or use a different brand-verified project.
- **Second known issue**: projects whose level was upgraded from Test *after* 9 September 2026 may still get
  `AUTHORIZATION_ERROR` on production calls while test-account calls succeed. Google has a fix rolling out; the
  interim workaround is a brand-new Cloud project applying for Explorer.
- **Current API version is v25** (released 22 July 2026, sunset tentatively August 2027). v22 sunsets around October
  2026. Versions sunset on a published cadence, so the version in your URL path is a maintenance commitment, not a
  one-time choice.

If either console does not look like this, stop and report what you actually see rather than clicking on.

## 1. Reuse the project, or start new

The base skill covers reusing versus replacing the **OAuth client**. Google Ads adds a second, independent decision
that people conflate with it: the **Cloud project**, which is what now holds the approved access level.

**Reuse the Cloud project** unless you have a specific reason not to. Spinning up a fresh one to "start clean"
silently demotes you to Test access and puts you back at the bottom of the review ladder, with no way to carry the old
approval across. The only good reasons to start new: deliberately separating deployment tiers (Google's own policy
requires separate projects for development, staging and production), or the current project is stuck behind the Free
Trial billing defect above. Say which path you are taking, and why, before you touch anything.

## 2. Accounts: Cloud project and Google Ads manager account

You need both. They are different products with different sign-ins, and the most common failure mode here is setting
up one and assuming the other came with it.

**Google Cloud project** — created or selected per the base skill. Billing is optional for the Google Ads API itself
(there is no charge for the API), but see the Free Trial defect above before deciding to leave a trial billing account
attached. Enable the API at
`https://console.cloud.google.com/flows/enableapi?apiid=googleads.googleapis.com`. Enabling it grants the project
**Test** access automatically.

**Google Ads manager account (MCC)** — the account type that sits above client ad accounts and is what
`login-customer-id` names. Create one at `https://ads.google.com/home/tools/manager-accounts/`. You still need a
manager account even though it no longer issues your access level: it is where customer accounts get linked, where
the Google Ads API Terms of Service are signed (the `MISSING_TOS` error points at
`https://ads.google.com/aw/apicenter`), and it is the root of any test hierarchy.

**Test manager account** — separate, and required for development below Explorer access. Create it at
`https://ads.google.com/nav/selectaccount?sf=mt`, signed in with a Google Account **not** linked to your production
manager account. Test and production accounts cannot interact at all, so a test account cannot live under a
production manager. Any client account created under a test manager is automatically a test account; they show as
*cancelled* in the UI with a red **Test account** label, serve no ads, and return empty metrics. Limits worth
knowing: no bid simulations, no conversion uploads, no billing, roughly 50 accounts per hierarchy, and Google
permanently deletes test accounts after one year with no API activity or logins.

Ads-specific steps only a human can do: signing the Google Ads API Terms of Service on the manager account, 2SV and
passkey enrollment, and entering payment details. When you hand a user a click path, have them report back both the
client ID **and** the access level shown on the Google Ads API Overview page — the second decides whether anything
works at all.

## 3. Consent screen: the Google Ads overrides

Configure the consent app and create the **Web application** client exactly as the base skill describes, with two
Ads-specific deviations:

- **Publish the app, even if it is internal.** Set the audience to **External** and the publishing status to **In
  production**. Workspace users will land on **Internal** by default and must click **Make external** first. Google
  Ads' own documentation explicitly overrides the general Cloud guidance here, and a Basic access application from a
  project still in **Testing** will not pass. (Testing also caps refresh-token lifetime at seven days — see the base
  skill; with the `adwords` scope you are squarely in that trap.)
- **Fill in *all* branding before you go further.** App name, logo, home page, privacy policy, terms of service.
  Half-filled branding is the usual reason **brand verification** — the prerequisite for Basic access (§5) — fails.

## 4. The `adwords` scope and the authentication mandates

The Google Ads API has exactly **one** scope, and it covers both reading and writing:

```
https://www.googleapis.com/auth/adwords
```

There is no read-only variant, no per-object split, and no way to request a narrower grant. Say that plainly to a
customer security team that asks for least privilege — the narrowing happens through Google Ads *user roles* on the
authorizing account, not through OAuth scopes. Identity scopes (`openid`, `profile`, `email`) are for sign-in only
and grant no ads access.

Request it with `access_type=offline` (see the base skill for the refresh-token rules). The Google Ads API does not
support hybrid simultaneous sign-in, and **does not support domain-wide delegation (2LO)** — so the service-account
shortcut that works for some Workspace APIs is not available here.

**The authentication mandates are customer-side and blocking.** Since 21 April 2026 the Google Ads API requires
2-Step Verification for any user generating a new refresh token; from 5 August 2026 Google began requiring a
**passkey** for some users, and for those users passwords, TOTP and SMS codes are disallowed outright. Separately, a
manager account administrator can mandate 2SV across owned sub-accounts — in that case existing refresh tokens keep
working for everything *except* the Google Ads API, which fails with `TWO_STEP_VERIFICATION_NOT_ENROLLED` until the
user enrolls. Note also that a new passkey may carry a **7-day security delay** before it is trusted, so "just add a
passkey" is not a same-day fix. None of this is something you can register your way around; it belongs in your
customer onboarding instructions.

**Product fact.** As of 2026-09-20, Unified.to's Google Ads connector requests the single
`https://www.googleapis.com/auth/adwords` scope for every ads object it supports — organizations, campaigns, groups,
ads, creatives, assets, targets, promoted items and reports, read and write alike — plus `openid`, `profile` and
`email` for the login/identity flow. Its authorize request carries `access_type` and `prompt` so that offline refresh
tokens are issued; token exchange and refresh are form-encoded POSTs sending client ID and client secret in the body,
and access tokens are presented as bearer tokens. It also requires **a second, non-OAuth credential alongside the
client ID and secret — a developer-token-style value that it labels "Developer Token" and sends as a request header
on every API call** — so a run that produces only a client ID and secret is incomplete for this connector even though
Google now ignores that header. Confirm all of this with the connector's owner before relying on it; it is a snapshot
of one day's configuration, not a contract.

## 5. The access level and the API access application

This section is the reason Google Ads takes days instead of an afternoon.

**What a developer token was.** A 22-character alphanumeric string issued from the **API Center** page of a Google Ads
manager account, sent as the `developer-token` HTTP header on every call, and carrying an access level that decided
how many operations you could run per day and whether you could touch production accounts at all.

**What replaced it.** Since 9 September 2026 the access level lives on the **Google Cloud project** that owns your
OAuth credentials. You apply, check status and upgrade from the **Google Ads API Overview** page in the Cloud
Console: `https://console.cloud.google.com/google/ads-apis/overview`. The header is now optional and ignored. If you
already hold an approved token, you still want to open that page and confirm your project inherited the level you
expect — the migration only covered projects that had actually made calls with the token in the preceding 90 days.

**The four levels**, in order. You climb them one at a time; each application asks you to confirm the *next* level is
what is offered before you click:

| Level | Can call | Daily operation limit | How you get it | Review |
| --- | --- | --- | --- | --- |
| **Test** | Test accounts only | 15,000/day | Automatic when you enable the API | none |
| **Explorer** | Test **and** production | 2,880/day production, 15,000/day test | Apply from the Overview page | usually automatic |
| **Basic** | Test and production | 15,000/day both | Brand verification, then apply | automated, minutes |
| **Standard** | Test and production | Unlimited | Apply from the Overview page | manual audit, ~10 business days |

"Per day" is a sliding 24-hour window over the requests the project made, and all levels remain subject to per-service
rate limits and quotas on top of these numbers.

**Explorer is restricted, not merely small.** Even with production access, an Explorer project cannot call account
creation (`CustomerService.CreateCustomerClient`), user management (`CustomerUserAccessService`,
`CustomerUserAccessInvitationService`), planning (`KeywordPlanService`, `KeywordPlanIdeaService`, the other
`KeywordPlan*` services, `AudienceInsightsService`, `ReachPlanService`), or billing and payments
(`PaymentsAccountService`, `BillingSetupService`, `AccountBudgetProposalService`, `InvoiceService`). If your connector
exposes keyword planning or invoices, Explorer will not do and you need Basic or Standard.

**Brand verification** is the prerequisite for Basic, and it is a lighter-weight cousin of full OAuth app
verification. Having done §3 — External user type, In production publishing status, complete Branding tab — go back
to **Branding**, click **Verify Branding**, wait the few minutes it takes, fix anything it flags, then click
**Publish branding**. If you already completed brand verification for this project as part of OAuth app verification,
you can skip it.

**The Standard application** is a manual compliance audit, not a form. Expect questions about what your tool does and
who uses it, and expect to provide **demo sign-in access** if external users use it. Your tool must comply with
**Required Minimum Functionality** (RMF) — a published list of features a tool must offer, scoped by whether you are
a full-service tool, reporting-only, or internal-use-only. RMF applies only to projects at Standard. Standard also
carries a **permissible use** designation that decides which parts of the API you may call: *Ad creation /
management* (everything), *Reporting* (only `GoogleAdsService.Search` / `SearchStream` and other read-only calls), or
*Researching keywords and recommendations*. Google's Compliance team runs the review over email; slow replies stall
it. **Do not answer compliance, legal or volume questions on the user's behalf** — draft them, hand them over, and
say so.

**Test access cannot touch production, ever.** On v25 the error is `CLOUD_PROJECT_NOT_APPROVED_FOR_PRODUCTION`; on
older versions it surfaces as `ACTION_NOT_PERMITTED`. There is no header, flag or retry that works around it. Two
related traps: access is **revoked after 90 days of inactivity**, and an approved-but-never-used legacy token
transferred no access to anything, so its owner is now at Test and must apply fresh.

Finally: historically a project could use only **one** developer token, while one token could serve many projects.
Post-sunset the practical shape is the reverse — you can hold several Cloud projects at **different** access levels
at once, for example one at Basic and one at Standard, and pick per deployment tier.

## 6. Capture the credentials — all three

The base skill covers the client ID and the one-time client secret, including rotation. Google Ads needs a third
value and a set of Ads-specific facts recorded alongside them:

**Developer token**, if the platform still requires one as a configured credential — the 22-character string from
`https://ads.google.com/aw/apicenter` on the manager account. Google ignores it now, but a connector that treats it
as a required field still needs a value. **If no token exists and none can be issued**, that is a finding to report,
not something to invent: say so and ask whether the field can be made optional.

Also record, because the run is not reproducible without them:

- The **Google Cloud project ID** that owns the client, and its **current API access level** and permissible use.
- The **manager account's 10-digit customer ID**, hyphens stripped — this is the `login-customer-id` value.
- The API base `https://googleads.googleapis.com/v25/…` and that version's sunset date. The `v3` in some older Google
  token-endpoint examples is an OAuth endpoint version and has nothing to do with the Google Ads API version.
- Whether this is a production or test hierarchy.

## 7. Verify end-to-end

The base skill's round trip applies. These are the Ads-specific steps layered on it:

1. If the project is at **Test**, verify against a **test client account** under the test manager first. Use the
   production project's OAuth credentials — a Test-level project can still call test accounts.
2. Call `CustomerService.ListAccessibleCustomers` — `GET /v25/customers:listAccessibleCustomers` — to enumerate the
   accounts that user reaches directly. Those IDs are the valid `login-customer-id` values.
3. Run one real read against a client account under the manager, sending `login-customer-id` as the manager's CID
   with hyphens stripped, and `Authorization: Bearer <access token>`. Repeat it with a refreshed access token.
4. Only then repeat against a **production** account, which is also the first moment the access level is tested for
   real.

| Symptom | Cause |
| --- | --- |
| `CLOUD_PROJECT_NOT_APPROVED_FOR_PRODUCTION` | The project owning the OAuth client is at Test access — apply for Explorer or above (§5) |
| `ACTION_NOT_PERMITTED` on an older API version | Same as above, under the pre-v25 error name (§5) |
| `DEVELOPER_TOKEN_NOT_APPROVED` | Legacy form of the same problem: the credential is approved for test accounts only |
| `DEVELOPER_TOKEN_PROHIBITED` | The token is not allowed with the Cloud project in the request — the pairing the sunset removed |
| `USER_PERMISSION_DENIED` | The authorizing user has no access to that customer, **or** you are calling a client account without setting `login-customer-id` to the manager's CID (§2, §7) |
| `INVALID_LOGIN_CUSTOMER_ID_SERVING_CUSTOMER_ID_COMBINATION` | The manager named in `login-customer-id` does not reach the target account |
| `TWO_STEP_VERIFICATION_NOT_ENROLLED` | The authorizing Google account has no 2SV, or an admin mandated it on the hierarchy (§4) |
| `MISSING_TOS` | The Google Ads API Terms of Service have not been signed on the manager account at API Center (§2) |
| `NOT_ADS_USER` | The Google account that authorized has no Google Ads account attached at all |
| `CUSTOMER_NOT_ENABLED` | The target ad account is not activated or has been deactivated — customer-side |
| `METRIC_ACCESS_DENIED` | Permissible use restricts the metrics queried (Standard access only) (§5) |
| `AUTHORIZATION_ERROR` on production only, right after an upgrade | Known Google-side defect for projects upgraded after 9 Sept 2026 (see **Platform state**) |
| Basic/Explorer application rejected despite brand verification | Cloud Free Trial or suspended billing on the project (see **Platform state**) |
| Auth works, every call 404s or errors on version | The API version in the URL path has been sunset; upgrade (see **Platform state**) |
| Works for one customer, fails for another with identical config | Almost always the customer's Google Ads user role, account hierarchy, or 2SV state — not the app |

## 8. Hand off

Follow the base skill's handoff rules, with one addition: the **developer token is a secret on the same terms as the
client secret** and never goes into source control, a ticket, a PR body or a chat channel.

Close with everything recorded in §6 — project ID, access level and permissible use, developer-token status, manager
CID, hierarchy type, API version and its sunset date — plus any access application still pending and what it is
waiting on, and the customer-facing **2SV and passkey** requirements, which the user must put into their onboarding
instructions.

## Stop and ask

The base skill's stop-and-ask list applies. Additionally, hand back to a human when: a Standard access application
asks for compliance, legal, volume or RMF commitments, or wants demo sign-in credentials for the product; the access
level needed depends on a business decision about what the connector will offer (keyword planning and invoices push
you past Explorer); a new Cloud project would be required and you would lose an existing approval; the project is
blocked by the Free Trial billing defect and removing billing would affect other services; a customer cannot connect
because of 2SV, passkey or Google Ads user-role requirements on their side; the platform requires a developer token
field that can no longer be populated; or either console does not match the **Platform state** section above.

## References

Google Ads specific. The generic Google OAuth, consent-screen and verification references are in the base skill.
Every link below verified to return 200 on 2026-09-20.

- Developer token sunset, migration and FAQ — https://developers.google.com/google-ads/api/docs/api-policy/developer-token
- Access levels and permissible use — https://developers.google.com/google-ads/api/docs/api-policy/access-levels
- Brand verification — https://developers.google.com/google-ads/api/docs/api-policy/brand-verification
- Required Minimum Functionality — https://developers.google.com/google-ads/api/docs/api-policy/rmf
- Google Ads API Terms and Conditions — https://developers.google.com/google-ads/api/docs/api-policy/terms
- OAuth 2.0 overview for the Google Ads API — https://developers.google.com/google-ads/api/docs/oauth/overview
- Multi-user authentication workflow — https://developers.google.com/google-ads/api/docs/oauth/multi-user-authentication
- Set up a Cloud project for authorization — https://developers.google.com/google-ads/api/docs/oauth/cloud-project
- OAuth 2.0 internals (scope, offline access, headers) — https://developers.google.com/google-ads/api/docs/oauth/internals
- Security requirements (2SV and passkeys) — https://developers.google.com/google-ads/api/docs/oauth/security-requirements
- Google Ads access model and `login-customer-id` — https://developers.google.com/google-ads/api/docs/oauth/access-model
- Credential management — https://developers.google.com/google-ads/api/docs/oauth/credential-management
- REST auth and request headers — https://developers.google.com/google-ads/api/docs/rest/auth
- API call structure — https://developers.google.com/google-ads/api/docs/concepts/call-structure
- Test accounts — https://developers.google.com/google-ads/api/docs/best-practices/test-accounts
- Make your first API call — https://developers.google.com/google-ads/api/docs/get-started/make-first-call
- API versions, deprecation and sunset dates — https://developers.google.com/google-ads/api/docs/sunset-dates
- `AuthorizationError` enum — https://developers.google.com/google-ads/api/reference/rpc/v25/AuthorizationErrorEnum.AuthorizationError
- `AuthenticationError` enum — https://developers.google.com/google-ads/api/reference/rpc/v25/AuthenticationErrorEnum.AuthenticationError
- Google Ads API Overview page (Cloud Console) — https://console.cloud.google.com/google/ads-apis/overview
- Enable the Google Ads API — https://console.cloud.google.com/flows/enableapi?apiid=googleads.googleapis.com
- Create a Google Ads manager account — https://ads.google.com/home/tools/manager-accounts/
- Create a test manager account — https://ads.google.com/nav/selectaccount?sf=mt
- Google Ads API Center (historical developer token lookup) — https://ads.google.com/aw/apicenter
