Base URL
/.well-known/openapi.yaml.
Quick Start
Resolve a brand domain to its canonical identity:Response
Rate Limits
Rate-limited endpoints return
429 Too Many Requests when the limit is exceeded.
Endpoint Groups
Brand Resolution
Resolve domains to canonical brand identities, fetch brand.json files, and browse the brand registry.
Property Resolution
Resolve publisher domains to property information, validate adagents.json, and browse properties.
Agent Discovery
List, search, and filter agents by inventory profile. Browse publishers and view registry statistics.
Change Feed
Poll a cursor-based feed of registry changes for local sync.
Lookups & Authorization
Look up agents by domain, validate product authorization, and check property authorization in real time.
Lookups by entity
Three endpoints answer different questions about who is in the registry. They span two tag groups in the API reference, so use this table to pick the right lookup surface before diving into endpoint-specific parameters.GET /api/registry/agents — use this when you want to browse or filter the public agent population. See Registering an agent for how agents end up in this catalog. Reference: List agents endpoint under Agent Discovery.
GET /api/registry/operator?domain=X — use this when you have one entity in hand and want its agent footprint.
GET /api/registry/publisher?domain=X — use this when you have one publisher in hand and want its inventory and delegations.
Brand Resolution
These endpoints resolve domains to brand identities. Thesource field in the response indicates where the data came from:
All sources produce the same resolution response structure. To get full brand identity data (logos, colors, tone), use
/api/brands/enrich or look up the brand in the registry.
Property Resolution
Agent Discovery
Measurement-vendor discovery
To discover measurement vendors specifically (Adelaide-style attention, Scope3-style emissions, Nielsen DAR, IAS/DV custom quality, etc.), filter the agent list bytype=measurement:
get_adcp_capabilities.measurement.metrics[] — the canonical, vendor-controlled source of truth. AAO crawls each measurement agent’s get_adcp_capabilities on a TTL and stores the result; passing ?capabilities=true folds the catalog into the response next to creative_capabilities and signals_capabilities.
Filter parameters (all imply type=measurement when present; an explicit non-measurement type returns 400):
Change Feed
Lookups & Authorization
Authorization validation checks both sides: the publisher’s
adagents.json (does it authorize this agent with the claimed delegation_type?) and the operator’s brand.json (does it declare this property with a matching relationship?).
Validation Tools
Search
Agent Probing
Activity history
GET /api/brands/history?domain={domain} and GET /api/properties/history?domain={domain} return the edit history for a registry entry, newest first. These are public endpoints — no authentication required.
Response
editor_name: "system" were written by automated enrichment. When is_rollback is true, rolled_back_to contains the revision number that was restored. Pagination uses limit (max 100) and offset query parameters.
Anti-abuse and anti-homograph controls
Because/api/brands/save, /api/properties/save, and the adagents validation endpoints accept domain strings from authenticated member organizations, the hosted registry applies a layered floor of anti-abuse controls at save time. These are operational behaviors of the AgenticAdvertising.org registry in the 3.x era — not a new wire surface — and exist so that typosquats, confusable lookalikes, and drive-by brand hijacks cannot get written into the index by a single authenticated caller.
- Domain normalization (IDNA 2008 + confusable detection). Save endpoints SHOULD apply IDNA 2008 to normalize internationalized domain names to ASCII before persistence, and SHOULD then run Unicode confusable-detection (for example, ICU
uspoofor equivalent) against two corpora: (1) already-registered entries in the index, and (2) a curated high-value-brand deny list maintained by the registry operator. The deny list catches typosquats of well-known brands before those brands themselves are registered (e.g., ag00gle.comsubmission collides with the deny-list entry even if Google has not yet claimed an index row). Ambiguous submissions — mixed-script labels, homograph collisions, disallowed Unicode classes — SHOULD be rejected or flagged for human review rather than silently committed. - Ownership proof before commit. Save endpoints MUST require evidence of domain control before a new brand or property entry is committed to the index — this is the threat that motivates the control, since an attacker with a compromised member API key would otherwise be free to bulk-register fresh confusable variants that have no prior entry to conflict with. For revisions to an existing community-source entry by the same authenticated organization, re-proof SHOULD be required on a rolling basis (for example, once the prior proof is older than 90 days) but MAY be skipped within that window. Accepted proofs are either a DNS TXT record at
_adcp-owner.{domain}matching a server-issued nonce, or an HTTP challenge hosted at/.well-known/adcp-ownership.txton the domain. Nonces MUST be single-use, scoped to the(organization, domain)pair, and MUST expire within 15 minutes of issuance; verification MUST consume the nonce on success and invalidate it on failure. A leaked or unused nonce after expiry is dead. Revisions to an existing authoritative entry (i.e., one backed bybrand.json/adagents.json) continue to follow the 409 Conflict semantics in Save brand and Save property; ownership proof covers the community-source save path. - Per-organization rate limits on saves. In addition to the per-IP rate limits documented in Rate Limits, save endpoints SHOULD apply per-organization limits so that a single compromised API key cannot bulk-register confusable variants. The hosted implementation uses a burst-tolerant cap (indicative: tens of saves per hour per org, low-hundreds per day per org); callers exceeding the per-org bucket receive
429 Too Many Requests.
specs/registry-change-feed.md §Advisory identity material): the feed is change-detection, not a trust anchor, and the publisher’s own adagents.json pin remains the authoritative identity source (see adagents.json §signing_keys). Operators running an alternative registry implementation SHOULD apply equivalent save-time controls before accepting community-source writes.
Authentication
Public endpoints (resolution, discovery, search) require no authentication. Write endpoints accept either an organization API key (server-to-server) or a user JWT obtained via OAuth 2.1 (interactive / agent clients). Both are sent in theAuthorization: Bearer ... header.
Option A: Organization API key
Long-lived, org-scoped. Best for server-to-server integrations where no user is present.- Sign in at agenticadvertising.org/dashboard/api-keys
- Click Create key and copy the generated key
Authorization header:
Option B: User SSO via OAuth 2.1
Short-lived, user-scoped. Best for agent clients (MCP, AI assistants, custom apps) where a human is signing in to AAO. A single token works against both/mcp and the REST API.
Discovery follows RFC 8414 and RFC 9728:
- Authorization server metadata:
GET /.well-known/oauth-authorization-server - Protected-resource metadata (REST API):
GET /.well-known/oauth-protected-resource/api - Protected-resource metadata (MCP):
GET /.well-known/oauth-protected-resource/mcp
/register. Users authenticate via AuthKit; the token is a WorkOS-signed JWT.
403 if the authenticated user lacks the required standing.
Authenticated endpoints
These endpoints require a valid API key.Save brand
POST /api/brands/save
Save or update a community brand in the registry. For existing brands, creates a revision-tracked edit. Cannot edit authoritative brands managed via brand.json — those return 409 Conflict.
Request body:
domain and brand_name are required. brand_manifest (brand identity data) is optional. The brand’s source is set to "community" by the server. Domains are normalized (protocol stripped, lowercased).
Response (create)
Response (update)
Save property
POST /api/properties/save
Save or update a hosted property in the registry. For existing properties, creates a revision-tracked edit. Cannot edit authoritative properties managed via adagents.json — those return 409 Conflict.
This is an identity-only write surface: the stored document always carries authorized_agents: []. Sales authorization lives solely in the publisher’s own origin adagents.json — the community registry cannot mint or carry it — so any authorized_agents sent in the request body is ignored.
Request body:
publisher_domain is required. properties (each requiring type and name) and contact are optional. Domains are normalized (protocol stripped, lowercased).
Response (create)
Response (update)
Change feed
GET /api/registry/feed
Poll a cursor-based feed of registry changes. Use this to keep a local copy of the registry in sync without re-fetching the full dataset. Events are ordered by UUID v7 event_id, providing monotonic cursor progression. The feed retains events for 90 days — expired cursors return 410 Gone. Each response includes freshness metadata so consumers can measure feed lag for the requested type filter.
Schema: core/registry-feed-response.json wraps core/registry-event.json items.
Query parameters:
Event types:
Response
has_more is true, pass the returned cursor value in the next request to continue polling. When false, you’ve reached the end of the current feed — poll again later with the same cursor to pick up new events.
latest_event_created_at is the newest matching event currently visible to the feed. lag_seconds is computed against generated_at; alert on it according to your own mirror freshness target.
GET /api/registry/feed/stream provides the same feed pages over Server-Sent Events. Reconnect with your last persisted cursor after disconnects. The stream emits event: feed with the same JSON shape shown above and event: heartbeat while caught up. Cursors are tied to the same logical types subscription; changing filters while reusing a cursor can skip events that were filtered out previously. The stream carries the resume cursor in JSON data.cursor, not SSE id, so browser EventSource clients must reconnect with ?cursor=....
If the cursor has expired (older than 90 days or not found), the response is 410 Gone:
410 Gone
Agent search
GET /api/registry/agents/search
Search agents by inventory profile — channels, markets, content categories, property types, and more. Filters use AND across dimensions and OR within a dimension. Results are ranked by a relevance score based on filter match breadth, inventory depth, and TMP support.
Query parameters:
Each CSV parameter accepts up to 100 values.
Response
matched_filters array shows which filter dimensions matched, useful for understanding why a result was returned. The relevance_score combines filter match breadth, ln(property_count + 1) weighted at 0.1, and a 0.05 boost for TMP support.
Crawl request
POST /api/registry/crawl-request
Request an immediate re-crawl of a publisher domain. Use this after updating an adagents.json file so the registry picks up changes without waiting for the next scheduled crawl. The crawl runs asynchronously — the endpoint returns 202 Accepted immediately.
Rate-limited to one request per domain every 5 minutes and 30 requests per user per hour.
Request body:
domain is required. Domains are normalized (lowercased, trimmed). The endpoint validates the domain format and performs a DNS lookup to reject private/reserved IP addresses.
202 Accepted
429 Too Many Requests
retry_after is the number of seconds to wait before retrying.
Submit brand (legacy)
POST /api/brands/discovered/community
Submit a brand for review. This endpoint predates /api/brands/save — prefer the save endpoint for new integrations.
Error responses
Protocol vs REST API
The AdCP protocol defines MCP and A2A tasks for agent-to-agent communication (e.g.get_products, create_media_buy). The registry REST API is separate — it provides HTTP endpoints for looking up entities in the AgenticAdvertising.org registry.
Use the REST API for discovery and authorization:
- Resolve brand or property domains before making protocol calls
- Discover which agents exist and what they’re authorized for
- Validate authorization in real time during ad serving
- Build integrations that browse or search the registry
- Fetching products from a sales agent (
get_products) - Creating media buys (
create_media_buy) - Building creatives (
build_creative) - Getting signals (
get_signals)