Observed since 20 Oct, 19:54 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
Machine-readable view of the Google Ad Manager API version list, with a CLI for humans and AI agents
Machine-readable view of the Google Ad Manager API version list, with a CLI built for both humans and AI agents.
Google only publishes which Ad Manager (formerly DoubleClick for Publishers)
API versions are supported on a human-readable page:
https://ads.google.com/apis/ads/publisher. Versions rotate several times a
year, get marked deprecated, and then disappear. adspub turns that page into
JSON, caches it locally, and answers two questions reliably:

Status rules:
| Status | Meaning |
|---|---|
active | Listed on the page without a deprecation marker. Safe to use. |
deprecated | Listed with the "Deprecated" marker. Still callable, migrate soon. |
unlisted | Not on the page at all. Assumed sunset and no longer callable. |
uv tool install adspub # as a global CLI tool
uvx adspub latest # or run without installing
pip install adspub # or into a project
Supports Python 3.11 through 3.15.
adspub latest # v202608
adspub list # table of all versions with status
adspub check v202602 # active, deprecated or unlisted
adspub check v202511 v202602 # several at once; worst status sets the exit code
adspub services v202608 # SOAP services and WSDL/doc links in a version
adspub dump -o catalog.json # full catalog as JSON
adspub cache info # where the cache is and how old
adspub cache clear
Global options go before the command:
adspub --json latest # JSON output, every command supports it
adspub --refresh list # ignore the cache and fetch now
adspub --offline check v202602 # never touch the network
adspub --max-age 3600 latest # reuse the cache for at most one hour
Example:
$ adspub check v202511 v202602 v202608 v202405
deprecated v202511 is deprecated and will be removed; migrate to v202608.
active v202602 is active but not the latest; v202608 is newer.
active v202608 is the latest active version.
unlisted v202405 is not listed and is assumed to be sunset; migrate to v202608.
$ echo $?
20
Results are cached as a single JSON file for 24 hours by default:
~/.cache/adspub/catalog.json~/Library/Caches/adspub/catalog.json%LOCALAPPDATA%\adspub\adspub\Cache\catalog.jsonOverride the location with --cache-dir or the ADSPUB_CACHE_DIR environment
variable. If the network is down and a cache exists, the stale cache is used
and a warning is printed to stderr. JSON output always reports where the data
came from (network, cache or stale-cache) and when it was fetched.
Fail a build when the pinned version is no longer active:
adspub check "$AD_MANAGER_API_VERSION"
Exit code 0 means active, 10 deprecated, 20 unlisted. Use
|| [ $? -eq 10 ] if you want deprecated to warn rather than fail.
The CLI is designed so an agent can call it without parsing prose:
--json gives structured output on every command.0 active, 10 deprecated, 20 unlisted,
1 runtime error (network or parse), 2 usage error.meta block with source and fetched_at so the agent
can decide whether to re-run with --refresh.adspub schema prints the JSON Schema of the catalog document.adspub parse page.html parses a saved copy with no network or cache.Paste this into your agent's instructions file (CLAUDE.md, AGENTS.md,
a system prompt, or a tool description):
## Google Ad Manager API versions
Use the `adspub` CLI (install: `uv tool install adspub`, or run `uvx adspub`)
to find out which Ad Manager API versions are valid. Never guess a version.
- Latest version: `adspub --json latest`
- Check a pinned version: `adspub --json check v202602`
- All versions: `adspub --json list`
- Force a fresh fetch: add `--refresh` before the command
Exit codes for `check`: 0 active, 10 deprecated, 20 unlisted (assume removed).
Read `.results[].status`, `.results[].latest` and `.results[].newer_versions`
from the JSON. If `.meta.source` is `stale-cache`, retry with `--refresh`.
Example JSON from adspub --json check v202511:
{
"ok": false,
"exit_code": 10,
"latest": "v202608",
"results": [
{
"version": "v202511",
"status": "deprecated",
"is_latest": false,
"latest": "v202608",
"newer_versions": ["v202602", "v202605", "v202608"],
"message": "v202511 is deprecated and will be removed; migrate to v202608."
}
],
"meta": {
"source": "cache",
"fetched_at": "2026-10-09T09:47:14.401329+00:00",
"cache_age_seconds": 0.7,
"source_url": "https://ads.google.com/apis/ads/publisher",
"warning": null
}
}
A minimal tool definition that wraps the CLI:
{
"name": "ad_manager_api_version_check",
"description": "Check whether a Google Ad Manager API version (vYYYYMM) is active, deprecated or unlisted, and get the latest version. Runs `adspub --json check <version>`.",
"input_schema": {
"type": "object",
"properties": {
"version": { "type": "string", "description": "Version such as v202602" }
},
"required": ["version"]
}
}
The tool handler runs adspub --json check <version> and returns stdout
verbatim.
Everything is async. The CLI is a thin layer over these functions.
import asyncio
from adspub import load_catalog
async def main() -> None:
result = await load_catalog() # cache-aware; fetches when stale
catalog = result.catalog
print(result.source) # network | cache | stale-cache
print(catalog.latest.version) # v202608
print([v.version for v in catalog.deprecated])
check = catalog.check("v202511")
print(check.status, check.newer_versions, check.message)
asyncio.run(main())
Other entry points:
from adspub import fetch_catalog, parse_catalog
catalog = await fetch_catalog() # no cache
catalog = parse_catalog(html, source_url="https://...") # from a string
load_catalog accepts refresh, offline, max_age (seconds), cache_dir,
allow_stale, timeout, and an optional httpx.AsyncClient for connection
reuse or testing with httpx.MockTransport.
All models are Pydantic v2 (Catalog, ApiVersion, Service,
VersionCheck), so model_dump_json() and model_json_schema() work as
expected.
git clone https://github.com/eivl/adspub && cd adspub
uv sync # creates .venv with dev dependencies
uv run pre-commit install # ruff, mypy, uv lock check on commit
uv run pytest # tests
uv run pytest --cov # with coverage
uv run ruff check . && uv run ruff format . && uv run mypy
uv run --python 3.11 pytest # any supported interpreter
The demo GIF in this README is rendered from demo/demo.tape with
VHS: run vhs demo/demo.tape locally, or
trigger the "Render demo" workflow, which commits the updated GIF.
Tests never touch the network. The parser is tested against
tests/fixtures/publisher.html, a saved copy of the real page. A weekly GitHub
Actions job parses the live page and warns when the fixture falls behind.
Releases publish to PyPI via GitHub Actions trusted publishing when a v* tag
is pushed:
uv version --bump minor
git commit -am "Release v$(uv version --short)"
git tag "v$(uv version --short)"
git push && git push --tags
One-time setup: on PyPI, add a trusted publisher for this repository with
workflow publish.yml and environment pypi, and create a pypi environment
in the GitHub repository settings.
MIT
Download counts and popularity will appear here as the collector receives them.
| Version | Published | Direct dependencies | Open version |
|---|---|---|---|
| 0.1.1 | 9 Oct 2026 | 4 |
This describes our collected data; it is not a security assessment.
Observed since 20 Oct, 19:54 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
package:e1ef09ec8e9b62256b1e70284955982cf08a13869dd9eaabf48f1f2d5dc286e7