Indexer by DependsiT

Google Indexing API Scopes and Permissions Explained

Indexing API scopes and permissions from OAuth scope to Search Console Owner access

Scopes and permissions decide whether an Indexing API call succeeds before Google ever looks at your URL. The scope states what the credential may do. Search Console ownership states which site it may act for. Cloud IAM states who may manage the credential itself. When all three align, publish returns 200. When any one is missing, you see 401, 403, or invalid scope errors that look like code bugs but are really access gaps. This guide is for owners, SEOs, and developers who want a plain explanation of each layer and a safe pattern to follow. The primary keyword is indexing api scopes, and every section maps that concept to a concrete check you can run.

You will learn the single OAuth scope the Indexing API needs, how service accounts use it with JWT signing, which Search Console roles actually allow publish, why verification must come first, which Cloud IAM roles are safe, and how to apply least privilege for teams and vendors. You will also see error patterns, rotation steps, and a quarterly audit checklist. By the end you will be able to grant, test, and revoke access without downtime. For the full project creation flow that precedes scopes, see the complete setup guide.

Key takeaways

  • The Indexing API uses one OAuth scope for publish and metadata calls, requested with a service account and JWT assertion.
  • The service account email must be Owner in Search Console on the exact property that contains the notified URLs.
  • Cloud IAM roles control who manages keys and projects, while Search Console roles control which sites the account may notify for.
  • Least privilege means separate accounts for prod and test, no broad Editor roles, and quarterly reviews of users and keys.
  • Google does not support IndexNow, and the Indexing API officially covers JobPosting and BroadcastEvent URLs with URL_UPDATED and URL_DELETED.

Indexing API scopes and permissions from OAuth scope to Search Console Owner access <!-- IMAGE-PROMPT cover: 1200x630, DependsIt brand, deep charcoal #121212 background, vibrant mint #22E3B0 accent glow, thin node-network line art, Clash Display style bold heading space on left, General Sans clean labels, subject: OAuth scope token and Search Console Owner permission flow for Indexing API, flat vector, high contrast, accessible, no photorealistic faces, no text smaller than 24px, no em dash in rendered text, export PNG then cwebp -q 82 to WEBP -->

How the three permission layers fit together

Three separate systems must agree before a publish succeeds. OAuth scopes define what the token may do. Search Console permissions define which site the identity may act for. Cloud IAM defines who may create, edit, or delete the credential and the project. Think of scopes as the key shape, Search Console as the list of rooms the key opens, and IAM as the record of who may copy the key. A correct key shape means nothing if the room list does not include your site. Access to the right room means nothing if the token requests the wrong scope.

In practice the flow is linear. Your code loads the service account JSON, requests an access token for the indexing scope, calls the publish endpoint with that token, and Google checks Search Console delegation for the notified URL. If the scope is missing or misspelled, token minting fails or the API returns an auth error. If delegation is missing, token minting succeeds but publish returns 403 permission denied. If IAM is misconfigured, you cannot create keys or view logs, but publish from an existing key may still work until rotation. That separation explains why debugging must follow the order: scope, then delegation, then IAM, not the reverse.

A concrete example helps. Suppose the service account email is indexing-publisher@example.iam.gserviceaccount.com. The code requests a token with the indexing scope. The token is valid for about an hour. The code posts a notification for https://example.com/jobs/123 with type URL_UPDATED. Google verifies the token signature, confirms the scope includes indexing, then checks whether indexing-publisher is Owner on the Search Console property that contains that URL. If yes, it records the notification and returns 200 with metadata. If no, it returns 403. No step can be skipped, and caching a token does not bypass delegation checks.

Teams often confuse these layers because consoles look similar. Cloud Console shows IAM members and service accounts. Search Console shows users and permissions per property. OAuth consent screens show scopes for user login flows, which service accounts do not use in the same way. Keep a one page diagram in your runbook with three boxes and arrows: code to token with scope, token plus URL to publish endpoint, endpoint to Search Console check. Label each box with where to verify it. That page resolves most handover questions in one minute.

LayerWhat it grantsWhere to verifyFailure signal
OAuth scopePermission to call indexing methodsCode config, token request401, invalid scope, invalid grant
Search Console rolePermission to notify for a propertyUsers and permissions per property403 permission denied
Cloud IAM rolePermission to manage project and keysIAM and Admin, IAM pageCannot create keys, cannot view quota
Key fileProof of service account identityJSON project_id and client_email401 invalid credentials
Property verificationProof you own the siteSearch Console settingsCannot delegate, cannot add users

By the end of this section you should be able to name the layer responsible for any auth error before opening code. That habit saves the most time in scope work, because most fixes are one console change plus a short wait, not a rewrite.

Many newcomers first meet these ideas through an indexing api oauth walkthrough that shows token minting end to end. The core lesson is simple and worth restating as api scope meaning in plain terms: the scope string declares what the token may call, nothing more. Teams that compare oauth scopes google publishes for different products quickly see why separation matters, because an Analytics token cannot call the Indexing endpoint even when Search Console delegation is perfect. Keep one constants file with the exact indexing scope, log the scope requested on every token fetch, and review mismatches before touching IAM or delegation.

Understanding indexing api scopes: the only OAuth scope you need

The Indexing API uses a single scope for both publish and metadata calls. In code you request the indexing scope URL with your service account credentials, Google returns an access token, and you send that token as a Bearer header on every API call. The scope string must be exact. A trailing slash, a changed path, or a substituted userinfo scope produces a token that the Indexing API will not accept. Copy the value from the official prerequisites page rather than typing it from memory, and store it as a constant in one place so all environments use the same string. For the canonical list, see the OAuth scopes for the Indexing API.

The scope is narrow by design. It allows urlNotifications publish and getMetadata for properties where the service account has Search Console access. It does not grant Analytics access, Search Console read access beyond what delegation allows, or admin control over the Cloud project. That narrowness is useful for least privilege reviews, because you can state plainly what a leaked token could and could not do within its one hour lifetime. It could attempt notifications against your quota for properties where the account is delegated. It could not change site settings, read unrelated projects, or manage billing. Rotation and delegation limits still matter, but the blast radius is bounded.

Request the scope at token time, not as a Cloud IAM role. A frequent misunderstanding is granting a broad IAM role such as Editor to fix a 403, when the real gap is Search Console delegation. IAM roles and OAuth scopes are different systems. IAM controls the console. Scopes control the API call. Adding Editor does not add Search Console ownership and does not change the token scope. The correct fix for publish 403 is Owner delegation in Search Console for the exact property, followed by a short wait for propagation, then a single retry.

Code should request the scope explicitly. In Python, pass scopes when loading credentials from the JSON file. In Node.js, pass scopes when constructing the JWT client. In PHP, set scopes on the client before fetching a token. In cURL manual flows, confirm the helper that mints the token was configured with the same scope. The examples below show the pattern without exposing secrets. Keep the scope string identical across languages so logs remain comparable.

# Python: request the indexing scope explicitly
from google.oauth2 import service_account
SCOPES = ["https://www.googleapis.com/auth/indexing"]
creds = service_account.Credentials.from_service_account_file(KEY_PATH, scopes=SCOPES)
// Node: same scope, JWT client
// const SCOPES = ["https://www.googleapis.com/auth/indexing"];
// const auth = new google.auth.JWT({ email: clientEmail, key: privateKey, scopes: SCOPES });
<?php
// PHP: set the indexing scope before token fetch
// $client->setScopes(["https://www.googleapis.com/auth/indexing"]);

Token lifetime is typically around 3600 seconds. Cache the token in memory and reuse it until near expiry, then refresh. Do not request a new token per URL in a bulk loop, because that adds latency and can trigger token rate limits without using publish quota efficiently. Log token fetch failures separately from publish failures so you can tell scope problems apart from delegation problems. A token failure points to key or scope config. A publish failure with a valid token points to delegation, URL, or quota.

QuestionAnswer
How many scopes for Indexing APIOne, the indexing scope
Where is it usedToken request, then Bearer header on publish and metadata
Does it grant site ownershipNo, Search Console delegation grants that separately
Does IAM Editor replace itNo, IAM and scopes are separate systems
How long does a token lastAbout one hour, then refresh

If you remember one line from this section, make it this: the scope states what the call may do, delegation states which site it may do it for. Both must be correct, and they are configured in different consoles.

Search Console roles that actually allow publish

Search Console has three practical roles: Owner, Full user, and Restricted user. Only Owner delegation allows reliable publish for the Indexing API. Full user can view most reports and run inspection, but publish calls from a Full user service account return 403 permission denied in practice. Restricted user can view limited data and cannot publish. When you add the service account email, select Owner. After saving, reopen Users and permissions and confirm the row shows Owner, not Pending. Pending means propagation is still in progress. Wait 10 to 15 minutes and refresh before testing again.

The property you choose matters as much as the role. Domain properties cover all URLs under the domain across protocols and subdomains. URL prefix properties cover only URLs under that exact prefix. If you delegate on the domain property, you may notify for any URL on that domain. If you delegate only on https://example.com/jobs/, you may only notify for URLs under that path. A common failure is delegating on http while notifying for https, or delegating on the root while notifying for a subdomain that lives under a separate prefix property. Use domain properties where possible to avoid prefix mismatches. Document which property you delegated and why.

Delegation must be repeated per property. Adding the account to example.com does not grant access to example.net or to a separate Search Console account for a client. Agencies should maintain a matrix of service account to property to role, with dates. Each row states the account email, the property, the role observed, who approved it, and when it was last verified. That matrix is the first page you open when a previously workingintegration returns 403 after a quiet period. Often the cause is a role change, a property move, or a verification lapse, not a code change.

Human ownership must come first. You cannot delegate access you do not have. The human who adds the service account must already be Owner on that property. If you see a message that you lack permission to add users, ask an existing Owner to add the service account or to promote you first. Do not create a duplicate property to work around roles, because the new property will not match your production URLs and publish will still fail. Keep a record of which human added which service account to which property and when. That line resolves handover and audit questions.

RoleCan view reportsCan publish via APIHow to confirm
OwnerYesYes, when property matches URLUsers page shows Owner
Full userYes, most reportsNo, expect 403 on publishUsers page shows Full
Restricted userLimitedNoUsers page shows Restricted
Pending inviteNoNo, wait and refreshStatus shows Pending
No entryNoNo, 403 permission deniedEmail absent from list

For step images and field level details of the add user flow, the service account setup steps show the exact clicks and the JSON fields to compare. Keep that guide open during your first delegation so you can match client_email character by character. One transposed character produces a clean looking but non functional delegation to the wrong identity.

To keep reviews concrete, document service account roles alongside property access in one matrix. List each account email, the properties it may notify for, and the observed search console user permissions value of Owner, Full or Restricted. That sheet becomes your indexing api access control record for audits, because it shows who approved each row and when it was last verified. When a previously working integration returns 403, open the matrix first and check for role changes, verification lapse or property moves before rebuilding code. Most late onset failures trace to access drift rather than software regression.

Why verification must come before delegation

Verification proves to Google that you control the site. Delegation grants a service account permission to act for that site. Google will not let you delegate for an unverified property, and it will not accept notifications for URLs outside the delegated property. The order is fixed: verify the property as a human Owner first, then add the service account as Owner. Skipping verification produces errors that look like scope problems but are really ownership gaps. If you inherited a property, confirm verification is still valid before debugging code. Expired DNS tokens and removed HTML files silently break the chain.

Choose a verification method you can maintain. DNS TXT records suit teams that control DNS and rarely change providers. HTML file upload suits single server sites with stable deploys. HTML tag suits CMS sites where theme changes are controlled. Google tag manager and Analytics linkage suit marketing teams that already manage those containers. All methods prove the same fact. The difference is maintenance. Pick the method whose token survives routine deploys and redesigns. A verification that breaks on every theme update will cause periodic 403s that look random but are really ownership lapses.

Domain versus prefix choice returns here. Domain verification via DNS covers the whole domain, including new subdomains you launch later. Prefix verification covers one protocol plus host plus path. If you plan to submit jobs on www and livestreams on a subdomain, domain verification avoids a second delegation round later. If you only manage one path on a shared domain, prefix verification with delegation on that prefix is safer and follows least privilege. Record the decision and the reason in one line so future teammates do not switch methods to save clicks and break coverage.

Verification health checks belong in your quarterly routine. Open Search Console settings for each property and confirm verification status shows verified. Confirm the service account still shows Owner. Confirm the test URL you used on day one still sits inside the property. If verification lapsed, re verify before rotating keys, because new keys cannot fix ownership. If you migrated DNS providers or rebuilt the site, re check verification the same day. That five minute check prevents a week of failed submissions that everyone blames on quota.

MethodBest forMaintenance risk
DNS TXTTeams with DNS control, many subdomainsLow, survives redesigns, check on DNS moves
HTML fileSingle server, stable deploysMedium, file can be deleted by cleanup
HTML tagCMS with controlled themeMedium, theme updates can remove tag
Tag ManagerSites with GTM alreadyLow, depends on container access
Analytics linkSites with Analytics adminLow, depends on Analytics permissions

Once verification and delegation both show healthy, run one publish and one metadata check on a safe URL. Success proves the chain end to end. Save the response and the timestamp. That baseline becomes the reference for every later scope question: if the same URL with the same key worked on that date, what changed since.

Cloud IAM roles that are safe for indexing

Cloud IAM controls who may manage the project, view quota, create keys, and change service accounts. It does not control whether publish succeeds for a given URL. That distinction keeps reviews honest. Grant IAM narrowly for admin tasks and grant Search Console Owner narrowly for publish rights. The service account that publishes does not need Editor, Owner, or Billing Admin on the Cloud project. It needs to exist, to have a valid key or workload attachment, and to be delegated in Search Console. Humans who operate the pipeline need just enough IAM to do their job and no more.

Practical role mapping for small teams: give one or two admins Owner on the indexing project so access survives departures. Give developers who deploy the pipeline Service Account User or a custom role that allows using the service account without managing keys. Give analysts who watch quota Viewer on the project so they can read graphs without changing config. Keep key creation limited to admins. Document who holds which role and why. When someone changes teams, remove IAM the same day. Dormant admin access is the most common finding in audits and the easiest to fix.

Avoid broad roles as shortcuts. Granting Editor to fix a publish 403 does not add Search Console ownership and expands what the identity may change in Cloud. Granting Owner to a vendor to save a delegation step gives that vendor control over billing linkage and IAM. Prefer narrow grants plus clear Search Console delegation. If organization policy blocks a grant, work with your admin to define an approved pattern once, then copy it per site. Shadow projects under personal accounts to bypass policy create ownership risk that outweighs any speed gain.

Workload attachment reduces key risk where available. On Google Cloud, attach the service account to Compute Engine, Cloud Run, GKE via Workload Identity, or Cloud Functions, so code obtains tokens without a downloaded JSON file. Outside Google Cloud, store the JSON in a secrets manager and load it at runtime. In both cases, IAM should allow only the workload to impersonate or use the account. Log IAM changes with audit logs and review them quarterly alongside Search Console users. The two lists together answer who can change credentials and which sites those credentials may notify for.

IAM roleWhat it allowsGive to whom
OwnerFull project control, IAM changesOne or two admins only
EditorModify most resources, not IAMAvoid for indexing-only work
ViewerRead config, quota, logsAnalysts who monitor
Service Account UserUse account for workloadsDeploy pipeline identity
Service Account Key AdminCreate and manage keysAdmins only, rarely granted
No IAM, only Search Console OwnerPublish for delegated propertyPublisher service account

For the click path to create the account and download the first key, follow the service account guide linked earlier. Keep IAM and Search Console reviews on the same calendar date so neither list drifts. That joint review takes 30 minutes and prevents most access incidents.

indexing api scopes separation showing token scope versus Search Console delegation <!-- IMAGE-PROMPT diagram-01: 1600px max, DependsIt brand mint #22E3B0 on charcoal #121212 or white, node-network line art, subject: OAuth scope versus IAM versus Search Console permission layers diagram, flat vector, accessible, no em dash, Clash Display and General Sans feel -->

Least privilege patterns for teams and vendors

Least privilege means each identity can do its job and nothing else. For indexing, that translates to separate service accounts for prod and test, separate Cloud projects where volume justifies it, Search Console Owner only on properties the account must notify for, and no standing access for vendors beyond what the task requires. A publisher account notifies for prod URLs. A tester account notifies for staging URLs. A monitor identity reads quota and logs but cannot publish. Humans hold narrow IAM plus Search Console roles that match their duties. Nothing is shared by email or chat.

Vendor access deserves explicit rules. Prefer that vendors operate within your project under a dedicated service account with delegation only to the properties in scope, rather than receiving a copy of your prod key. Define the scope of work, the properties covered, the quota budget, and the end date. Log every publish with service account email so vendor traffic is separable in reports. When the engagement ends, remove Search Console delegation, disable keys, and archive logs. If a vendor insists on holding keys in their own project, confirm in writing which properties they will access, how they store secrets, when they rotate, and how they delete on exit. Many teams prefer a bring your own key pattern where the vendor tool runs against the customer project, so control stays with the site owner.

Environment separation enforces least privilege without friction. Prod keys live only in prod secrets and prod servers. Test keys live only in test secrets and developer machines. CI injects the correct key per branch, so main branch deploys use prod and feature branches use test. Deploy pipelines submit only URLs that changed in that build, filtered to absolute public URLs inside the verified property. That filter is itself a privilege control, because it prevents a buggy build from notifying thousands of unrelated URLs and consuming quota.

Secrets handling completes the pattern. Store JSON keys in a manager, load at runtime, restrict file permissions where a file must exist, and never commit keys to Git. Record key ID, creation date, creator, purpose, and rotation date in your runbook, but never the private key. Rotate yearly or on staff changes, and test rotation in test first. The routine is create new key, deploy to secrets, verify one publish, disable old key, delete after a week of clean operation. Document each step with actor and timestamp. That record is the evidence auditors ask for.

PatternImplementationBenefit
Separate prod and test accountsTwo service accounts, two propertiesTest failures cannot consume prod quota
Narrow Search Console delegationOwner only on needed propertiesLeaked test key cannot notify prod
CI injected secretsBranch selects key, no repo filesNo accidental prod use from feature branch
Vendor dedicated accountOne account per vendor, time boxedTraffic separable, revocation is one click
Monitor only identityViewer on project, no publishAnalysts see quota without publish risk

Least privilege is not slower once documented. New teammates follow the matrix instead of guessing. New vendors receive the one page access sheet instead of a shared key. The quarterly audit confirms the matrix still matches reality. That steady discipline matters more than any single tool choice.

How the JWT flow works in plain terms

Service accounts authenticate with JWTs, which are signed statements that say who is calling and what scope is requested. Your client library builds that statement from the JSON key, signs it with the private key, sends it to Google token endpoint, and receives an access token good for about an hour. Your code then sends that token on publish and metadata calls. You do not handcraft JWTs in most stacks, because official clients handle signing and refresh. Understanding the steps still helps debugging, because each failure names the step that broke.

The four steps in order: load key, build and sign assertion with scope and expiry, exchange assertion for access token, call API with Bearer token. Key problems surface at step one as file not found or invalid key format. Scope problems surface at step two as invalid scope. Clock problems surface at step two or three as invalid grant, because the assertion carries issued at and expiry timestamps. Delegation problems surface at step four as 403, because the token is valid but the identity lacks rights for that URL. Reading errors in that order prevents rebuilding keys when the real issue is delegation.

Clock skew deserves emphasis because it mimics key failure. If server time is more than a few minutes off, Google rejects the assertion even with a perfect key and scope. Confirm NTP sync on servers, containers, and local machines. In containers, inherit host time rather than setting time manually. In CI, use standard images with NTP and log system time on auth failures. A one line time check in your health endpoint saves hours of key rotation that would not have helped.

Token reuse is both efficient and diagnostic. Cache the token in memory until near expiry and reuse it across publish calls. Log token fetch events separately from publish events. If token fetch fails for all URLs, the cause is key, scope, or clock. If token fetch succeeds but publish fails for one URL pattern, the cause is delegation, URL eligibility, or quota. That split narrows the search immediately. Do not log token values. Log token fetch status, expiry, and scope requested, plus publish status per URL.

# Pseudo flow with official client handling JWT details
# 1. Load JSON key from secrets, not from repo
# 2. Build credentials with indexing scope
# 3. Client signs JWT and fetches access token
# 4. Reuse token until near expiry, then refresh
# Diagnose clock skew quickly on any host
date -u
timedatectl status
StepWhat happensTypical error if broken
Load keyRead JSON, extract email and private keyFile not found, invalid key format
Sign assertionBuild JWT with scope and timestampsInvalid scope, invalid grant on time
Exchange for tokenPOST to token endpoint, receive BearerInvalid grant, unauthorized client
Call publishSend Bearer plus URL and type403 delegation, 429 quota, 404 URL

For the exact scope string and token endpoint values, rely on the official prerequisites and the OAuth 2.0 scopes documentation. Copy scope strings from docs rather than memory. One character difference is enough to fail token minting while everything else looks correct.

Scope and permission errors and what they mean

Errors in this area are precise if you read the full body. The numeric code tells the class, the message names the missing piece. Start with the message, confirm the layer from the earlier table, fix that layer once, wait for propagation where roles changed, then retry once. Hammering retries without a fix consumes quota and can turn a per minute 429 into a daily exhaustion. For a broader error catalog beyond scopes, the error fixes for 403 and JWT failures pairs well with this section.

401 unauthorized with invalid credentials points to key handling. Causes include an edited JSON file with broken private key line breaks, a deleted or disabled key, a revoked service account, or a token minted for the wrong project. Re download the key if you edited it, confirm project_id matches the enabled project, and confirm the service account still exists and is enabled. Check system time as well, because clock skew can surface as invalid grant rather than a clear time message.

403 permission denied points to Search Console delegation. Confirm the service account email is Owner on the exact property, confirm the URL sits inside that property, and confirm status shows Owner rather than Pending. Wait 15 minutes after any role change. Compare client_email in the JSON to the email in Search Console character by character. Teams often delegate one account while testing with another. If delegation looks correct but 403 persists, check whether verification lapsed. Expired DNS tokens and removed HTML files break delegation silently.

403 with service disabled or access not configured points to API enablement or scope mismatch. Confirm indexing.googleapis.com is enabled in the project whose ID appears in the JSON. Confirm the code requests the indexing scope exactly. Confirm you are not sending a token minted for a different API. If you use multiple Google APIs in one process, keep token caches separated by scope so an Analytics token is never sent to the Indexing endpoint.

429 and quota exceeded are not scope errors, but they appear during scope testing when teams retry aggressively. Pause, check the quota graph, and resume with throttling. Creating new projects or keys to dodge quota complicates audits and does not fix delegation. Scope work should use one or two test URLs, not bulk lists, so quota never becomes the blocker while you verify access.

Message patternLayerFix
401 invalid credentialsKey or tokenRe download key, confirm project_id, fix clock
401 invalid grantJWT or timeConfirm scope string, sync NTP, retest
403 permission deniedSearch Console delegationAdd as Owner, wait 15 min, retry once
403 service disabledAPI enablementEnable indexing API in correct project
403 access not configuredScope or enablementConfirm scope, confirm enabled service
404 not foundEndpoint or URL paramCorrect path, use absolute public URL

Log every failure with timestamp, URL, status, response body, project ID, key ID, and scope requested. That record turns the next identical error into a one line diagnosis. Add new messages to your runbook with the fix you used. Over a quarter, that table becomes the fastest page in your docs.

Grant test and revoke access safely

Safe changes follow the same routine every time: grant narrowly, test with one URL, observe, then expand or revoke. To grant, add the service account as Owner on the exact property, wait for propagation, then publish one URL_UPDATED for a safe test URL and check metadata for matching notifyTime. Save the response. If success, proceed to small batches with logging and throttling. If failure, read the message, fix the named layer once, and retry once. Do not grant broader IAM to work around a Search Console gap. Broader IAM does not add site rights and expands admin risk.

Testing should use the test project and test property where possible. Promote to prod only after test success with the same code path and scope string. In CI, gate promotion on the single URL test plus quota and log checks. That gate catches scope typos, wrong key injection, and property mismatches before they reach prod traffic. Keep the test URL stable so history is comparable across weeks. A changing test URL makes it hard to tell whether a new failure is access or content.

Revocation should be as practiced as granting. When a teammate leaves, remove their IAM and rotate any keys they could access. When a vendor engagement ends, remove Search Console delegation for their dedicated account, disable keys, and archive logs. When a site is retired, remove delegation, disable the project or delete keys, and retain logs per policy. Each revocation gets a runbook line with date, actor, account, property, and verification result. That record answers audit questions without searching chat history.

Rotation without downtime uses overlap. Create a new key for the same service account, deploy it to secrets, verify one publish with the new key, then disable the old key but do not delete it yet. Observe for a week. If no service still uses the old key, delete it. If errors appear, re enable briefly while you find the missed deployment, then disable again. Never delete the only working key on a Friday afternoon. Never rotate prod and test at the same hour. Stagger changes so one environment remains known good.

ActionStepsVerify
GrantAdd as Owner, wait 15 min, publish one URL200 plus matching metadata
Test promoteSame code and scope in prod, one URL200, quota increment by one
RotateNew key, deploy, verify, disable old, delete laterOne week clean before delete
Vendor exitRemove delegation, disable keys, archive logs403 expected on old key test
Staff exitRemove IAM, rotate exposed keysNew key works, old fails

Document the routine on one page and link it from onboarding. New operators follow the page instead of improvising. That consistency is the real safeguard, more than any single role choice.

Quarterly audit checklist you can run in 30 minutes

Audits prevent slow drift. Every quarter, open Cloud IAM and Search Console side by side and confirm the matrix still matches reality. List every service account, its purpose, its key age, and its last use. List every Search Console property, its verification status, and its Owner rows. List every human admin and their role. Remove anything dormant. Rotate anything old. The whole pass takes 30 minutes for a small estate and saves days of incident response later.

Checklist with owners and evidence:

  1. IAM members reviewed, dormant admins removed, evidence is IAM export with date.
  2. Service accounts listed with purpose, evidence is account list plus runbook purpose lines.
  3. Keys checked by age, old keys rotated via overlap routine, evidence is key IDs and dates.
  4. Search Console verification confirmed per property, evidence is settings screenshot or status note.
  5. Search Console Owners confirmed, expected service accounts present, ex vendors absent.
  6. Quota baseline compared to last quarter, spikes explained by deploys or imports.
  7. Logs retained 90 days, secrets absent from logs, evidence is retention check.
  8. Runbook updated with any role, key, or property change.

Record findings in one page per quarter with date, reviewer, changes made, and next review date. If nothing changed, record that explicitly. An empty audit with a date still proves control. If you find a vendor account still delegated after contract end, remove it the same day and note the delay cause so it does not repeat. If you find a key older than a year, schedule rotation within two weeks and test in non prod first.

Common findings and fixes: personal Gmail as sole Owner, fixed by adding a shared admin as second Owner. Test account delegated to prod property, fixed by narrowing delegation to test property only. Broad Editor grants for pipeline identities, fixed by replacing with Service Account User plus Viewer where needed. Missing log retention, fixed by enabling 90 day retention and scrubbing secrets. Each fix is small. Together they keep the access story clean enough to explain to an owner in two minutes.

FindingRiskFix this week
Sole Owner is personal accountLoss on departureAdd shared admin as second Owner
Old key over one yearHigher leak windowRotate via overlap routine
Vendor still delegatedUnneeded publish rightsRemove delegation, disable keys
Test key can notify prodQuota and content riskNarrow delegation to test property
No quarterly recordCannot prove controlWrite one page audit with date

Pair this audit with the project health routine from the setup guide so access and quota reviews happen together. One calendar event, two checklists, 30 minutes. That cadence keeps scopes boring, which is exactly what you want from access control.

Where scopes fit in a two engine workflow

Most sites need Google plus participating IndexNow engines. Scopes govern only the Google side. IndexNow uses a different proof: a key file hosted at your site root, not OAuth. The two systems share no credentials, quotas, or endpoints. Your Google path uses a service account, the indexing scope, Search Console delegation, and the urlNotifications endpoint. Your IndexNow path uses a generated key, a text file at root, and submission to IndexNow endpoints that fan out to Bing, Yandex, Naver, Seznam, and others listed on indexnow.org. Google does not support IndexNow, so do not send IndexNow pings to Google or expect Indexing API notifications to reach Bing.

Operationally, keep the two workflows separate but coordinated. Trigger both from the same CMS publish event, but queue them independently with separate logs, retries, and backoff. Google quota is per Cloud project with daily and per minute limits. IndexNow etiquette asks for honest submissions of changed URLs, batching up to 10000 URLs per request, and no spam. A shared deduplication filter helps both sides by ensuring only changed absolute public URLs enter either queue. Separate retry policies matter because 429 from Google and 429 or 422 from IndexNow mean different things and clear on different timelines.

Access reviews cover both sides on the same day but with different checklists. For Google, review IAM, service accounts, keys, scopes, and Search Console delegation. For IndexNow, review key file presence, content type, CDN caching, and submission logs. One calendar event, two pages. That pairing prevents the common gap where Google access is tidy but the IndexNow key file broke during a redesign and no one noticed for months.

indexing api scopes diagram: understanding indexing api scopes, verification must come before, least privilege patterns for <!-- IMAGE-PROMPT workflow-02: 1600px max, DependsIt brand, subject: two engine indexing workflow Google API plus IndexNow fanout diagram, flat vector, accessible, no em dash, mint #22E3B0 on charcoal #121212, node-network line art, Clash Display and General Sans feel -->

SideCredentialProof locationEndpoint family
Google Indexing APIService account JSON plus scopeSearch Console delegationurlNotifications publish and metadata
IndexNowGenerated key stringKey text file at site rootIndexNow submission endpoints

By keeping scopes on the Google side and key files on the IndexNow side, your runbook stays clear and your logs stay separable. That clarity is the whole point of explaining scopes carefully: fewer guesses, faster fixes, and access you can hand to the next teammate without a long meeting.

FAQ

Which scope does the Indexing API need?

It needs the single indexing OAuth scope, requested with a service account and sent as a Bearer token on publish and metadata calls. The identifier is documented as https www googleapis com auth indexing which appears in code as https://www.googleapis.com/auth/indexing with slashes and dots. Store it as a constant shared by all environments and copy it from the official prerequisites page rather than typing from memory. If token minting fails with invalid scope, compare your constant to the docs character by character before changing keys or roles, then test with one safe URL.

Why does publish return 403 when my token looks valid?

A valid token proves identity and scope, but publish also requires Search Console Owner delegation for the exact property that contains the URL. Confirm the service account email is Owner, not Full user, confirm the URL sits inside that property, and wait 15 minutes after role changes. Compare client_email in the JSON to the email in Users and permissions. Most 403s reflect a missing delegated access grant rather than code bugs, so verify the grant shows Owner and retest once with a safe URL before rotating keys or changing scopes.

Do I need to grant Editor or Owner in Cloud IAM to fix 403?

No. Cloud IAM controls project administration, not site publish rights, and that distinction is central to safe api authorization design. Granting Editor does not add Search Console ownership and expands admin risk without helping publish. The fix for publish 403 is Owner delegation in Search Console for the matching property. Keep Cloud IAM narrow with Owner for one or two admins, Viewer for monitors, Service Account User for deploy identities, and key management limited to admins. Review both consoles together each quarter to catch drift early.

How do service accounts differ from user OAuth logins?

Service accounts are machine identities with an email and a JSON key, designed for server to server calls without interactive login. They request tokens with a JWT assertion for a specific scope and run unattended in cron, CI and build hooks. User logins involve consent screens and refresh tokens tied to a person for console work. Indexing pipelines should use service accounts so production submission loops never depend on a personal session. Keep user logins for administration and verification, rotate machine keys on schedule, and log which identity sent each notification for clear audits.

How often should I rotate keys and review access?

Rotate keys yearly or on staff and vendor changes, and review access quarterly with evidence you can show auditors. Rotation should use overlap: create new key, deploy to secrets, verify one publish, disable old key, delete after a week of clean operation. Quarterly reviews cover IAM members, service accounts, key ages, Search Console verification, Owner rows, quota trends and log retention. Confirm verified property permissions still show verified plus Owner for each live property, and record each review on one page with date, reviewer and changes for continuity.

Does the same scope cover IndexNow?

No. IndexNow does not use OAuth scopes for access control. It uses a generated key string hosted as a text file at your site root for ownership proof, plus submission endpoints that fan out to participating engines. Google does not support IndexNow. Run the two workflows side by side from the same publish event but with separate queues, logs and retries. Review both on the same calendar date with separate checklists so Google delegation and IndexNow key health stay trustworthy without extra process overhead.

Sources

  • https://developers.google.com/search/apis/indexing-api/v3/prereqs
  • https://developers.google.com/identity/protocols/oauth2/scopes
  • https://support.google.com/webmasters/answer/9008080
  • https://developers.google.com/search/docs/monitoring-debug/search-console-start
  • https://www.indexnow.org/documentation

Further reading

Put this into practice. Indexer submits URLs to the Google Indexing API and IndexNow, audits coverage with Search Console, and shows exactly which pages are indexed. Start free or see how it works.