AdCP discovery files
adagents.json is the file a publisher or data provider hosts at /.well-known/adagents.json to declare which agents may sell its inventory or resell its signals; brand.json, at /.well-known/brand.json, is the buy-side half.
Publisher domains host an adagents.json for their properties, data provider domains host
one for their signals, and brands host brand.json. The consumer is a buyer's agent
checking that whoever offered it the inventory is allowed to sell it, which is why the
declaration sits on the domain that owns the thing rather than in the offer.
The ads.txt and sellers.json equivalents
The mapping is AdCP's own: adagents.json takes the ads.txt role, and brand.json's properties
take the sellers.json role, each property carrying a relationship. direct, delegated and ad_network appear on both sides with the same meaning.
Where the two files sit in the registry
AdCP, the Ad Context Protocol, is governed by AgenticAdvertising.org and ships as one versioned
schema registry. 2 schemas in it carry a file_location: the annotation
marking a document that is fetched from a fixed path on a domain rather than passed inside an
API call. Those two are adagents.json, hosted by the owner of the inventory or the
data, and brand.json, hosted by the owner of the brand.
AdCP names three further well-known paths that have no schema in the registry, all three
specified in prose only: /.well-known/jwks.json, which publishes an agent's own
signing keys and which the signing_keys pin overrides; /.well-known/adcp-ownership.txt, which carries the ownership challenge; and /.well-known/governance-revocations.json. Verification rules for those three paths are prose and have no schema in the registry.
adagents.json
Declaration of authorized agents for advertising inventory and data signals.
Fetched from https://<domain>/.well-known/adagents.json
The 2 branches of adagents.json
Variant 1
URL reference variant - points to the authoritative location of the adagents.json file
| Field | Type | Required | Description |
|---|---|---|---|
$schema | string | JSON Schema identifier for this adagents.json file | |
authoritative_location | string | required | HTTPS URL of the authoritative adagents.json file. |
last_updated | string | ISO 8601 timestamp indicating when this reference was last updated |
Variant 2
Inline structure variant - contains full agent authorization data
adagents.json — Variant 2 — 16 fields, 1 required
| Field | Type | Required | Description |
|---|---|---|---|
$schema | string | JSON Schema identifier for this adagents.json file | |
contact | object | Contact information for the entity managing this adagents.json file (may be publisher or third-party operator) | |
catalog_etag | string | Opaque publisher-controlled cache validator for the public catalog portions of this file (`properties[]`, `collections[]`, `placements[]`, `formats[]`, `signals[]`, and tag metadata). | |
properties | property[] | Array of all properties covered by this adagents.json file. | |
revoked_publisher_domains | object[] | Publisher domains explicitly removed from this managed network. | |
collections | collection[] | Collections produced or distributed by this publisher. | |
placements | placement-definition[] | Canonical placement definitions for properties in this file. | |
formats | any[] | Publisher-authoritative format catalog. | |
superseded_by | string | Optional pointer indicating this adagents.json file has been superseded by another adagents.json at a different URL. | |
tags | object | Metadata for each tag referenced by properties. | |
placement_tags | object | Metadata for each tag referenced by placements. | |
authorized_agents | any[] | required | Array of sales agents authorized to make inventory from this file available to buyers. |
last_updated | string | ISO 8601 timestamp indicating when this file was last updated | |
property_features | object[] | [AdCP 3.0] Optional list of agents that provide property feature data (certifications, scores, compliance status). | |
signals | signal-definition[] | Signal definitions published by this domain. | |
signal_tags | object | Metadata for each tag referenced by signals. |
{
"$schema": "/schemas/3.1.13/adagents.json",
"authoritative_location": "https://cdn.example.com/adagents/v2/adagents.json",
"last_updated": "2025-01-15T10:00:00Z"
} brand.json
Brand identity and discovery file.
Fetched from https://<domain>/.well-known/brand.json
The 5 branches of brand.json
Authoritative Location Redirect
Redirects to a hosted brand.json file at another URL
| Field | Type | Required | Description |
|---|---|---|---|
$schema | string | ||
authoritative_location | string | required | HTTPS URL of the authoritative brand.json file |
redirect_reason | string | Optional structured signal indicating why this redirect was put in place. One of: acquisition, divestiture, rebrand, regional, legacy, consolidation, other. | |
redirect_effective_at | string | Optional timestamp when this redirect became effective. | |
note | string | Optional human-readable rationale for the redirect. | |
last_updated | string |
House Redirect
Redirects to the house domain that contains the full brand portfolio
| Field | Type | Required | Description |
|---|---|---|---|
$schema | string | ||
house | domain | required | House domain to fetch brand portfolio from |
region | string | ISO 3166-1 alpha-2 country code if this is a regional domain | |
redirect_reason | string | Optional structured signal indicating why this redirect was put in place. One of: acquisition, divestiture, rebrand, regional, legacy, consolidation, other. | |
redirect_effective_at | string | Optional timestamp when this redirect became effective. | |
note | string | Optional human-readable rationale for the redirect. | |
last_updated | string |
Brand Agent
Brand represented by agents that provide brand info via MCP
| Field | Type | Required | Description |
|---|---|---|---|
$schema | string | ||
version | string | ||
agents | agents | ||
brand_agent | brand_agent | ||
contact | contact | ||
data_subject_contestation | data_subject_contestation | ||
last_updated | string |
House Portfolio
Full house/brand portfolio with hierarchy, creative assets, and properties.
| Field | Type | Required | Description |
|---|---|---|---|
$schema | string | ||
version | string | ||
house | house | required | |
brands | brand[] | Inline brands owned by this house (parent-owned data). | |
brand_refs | portfolio_entry[] | Portfolio entries for brands owned by this house that publish their own canonical brand.json elsewhere (child-owned data). | |
contact | contact | ||
authorized_operators | authorized_operator[] | Entities authorized to represent brands from this house. | |
trademarks | trademark[] | House-level (corporate) registered trademarks. | |
last_updated | string |
Brand Canonical Document
Self-published brand document where the brand owns its own identity attributes.
| Field | Type | Required | Description |
|---|---|---|---|
$schema | string | ||
version | string | ||
house_domain | domain | Optional pointer to the corporate house this brand belongs to. | |
last_updated | string |
{
"$schema": "/schemas/3.1.13/brand.json",
"authoritative_location": "https://adcontextprotocol.org/brand/abc123/brand.json"
} Authenticity guarantees
Control of the domain is the only guarantee. The document carries no signature and the registry
defines no schema for one. The only assertion a consumer can verify is that the file was served
by the host it speaks for. AdCP does define an ownership challenge: a single-use nonce published
either as a DNS TXT record at _adcp-owner.{domain} or as a file at /.well-known/adcp-ownership.txt, expiring fifteen minutes after issue. That challenge gates writes to AdCP's registry index.
It does not gate the file on the publisher's own domain.
signing_keys pins the publisher-attested public keys an authorized agent is allowed to
sign with. A verifier that finds a pin must reject any signature whose key is outside it, whatever
the agent's own JWKS advertises. The field sits in core/authorized-agent-base.json next
to url and authorized_for, and unlike those two it is not in required. The docs make it a MUST for any agent whose delegated scopes include mutating operations: create_media_buy, update_media_buy, sync_creatives and update_performance_index.
Two rules that reject a well-formed file
Both files are oneOf unions with overlapping branches: $schema and last_updated appear in all of them, and a document must satisfy exactly one branch. The first rule follows from
that. A document carrying both authoritative_location and authorized_agents validates against both branches, which fails the oneOf under a draft-07 validator.
The schema defines no pointer-with-inline-fallback shape.
The second is emptiness. authorized_agents may be empty, but only in a file that publishes
something else. The inline branch wraps an anyOf over six arrays (authorized_agents, formats, properties, placements, collections, signals) and asks for one of them to be non-empty. The $comment on that
anyOf
says why: "a file with neither sales authorization nor non-empty catalog content is rejected." The
authorized_agents description names the case it protects: a catalog-only community mirror,
publishing a platform's formats and properties for a platform that has not adopted AdCP, where there
is no sales agent to authorize. An empty array there asserts no sales authorization, and the schema
tells validators not to read it as deny-all, authorize-all or a revocation.
Following authoritative_location
authoritative_location is an indirection: the well-known path holds a pointer and the
real file lives at the URL it names. The rules for dereferencing it sit in the field description rather
than in any schema keyword. Validators must refuse redirects on it and keep timeouts short. On a transient
5xx they serve the previously cached file. The size cap comes in two tiers, the smaller of them the
general server-side request forgery (SSRF) cap: "pointer files served at /.well-known/adagents.json
use the general 5 MB SSRF cap; dereferenced authoritative files (this URL's response, after the indirection)
use a recommended 20 MB cap because the origin has explicitly opted in to fanning out across a publisher
network." The 20 MB tier is sized for one file covering every property on a publisher network rather
than one domain.
additionalProperties in adagents.json and brand.json
Both adagents.json branches set additionalProperties to true, and so do all six authorized_agents entry shapes. An agent entry whose key is misspelled — delegatoin_type in place of
delegation_type — validates clean and has no effect. The correctly spelled key with an
invalid value, delegation_type of "reseller", fails validation. The value is enum-constrained;
the key name is not checked. Validation of a generated adagents.json therefore has to check key names
against the six authorized_agents entry shapes rather than rely on a draft-07 pass.
brand.json, in the same release and the same registry, sets additionalProperties to false
on four of its five branches: Authoritative Location Redirect, House Redirect, Brand Agent and House
Portfolio. The identical misspelling in a House Portfolio file is therefore a hard error. The fifth
branch, Brand Canonical Document, sets no additionalProperties and stays open. The release
notes do not mention the difference.
Required fields inherited through allOf
Every authorized_agents entry requires url and authorized_for, and neither appears in the branch's own required list. Both are inherited through
an allOf onto core/authorized-agent-base.json. A validator reports the
two as missing against core/authorized-agent-base.json, not against the branch.
brand.json inherits required fields the same way. Its Brand Canonical Document branch is an allOf onto the shared brand definition, so id and names are required there even
though the branch names neither. Its Brand Agent branch goes further: an empty required list plus an anyOf demanding agents or brand_agent.
authorization_type and the scope of a signal authorization
authorized_agents is a discriminated union on authorization_type. Four
values scope inventory (property_ids, property_tags, inline_properties, publisher_properties), and signal_ids and signal_tags are
the two that scope data. The four inventory branches carry delegation_type. On the
brand.json side, relationship takes a fourth value, owned, which the
schema describes as having no delegation_type counterpart.
The two data branches declare the discriminator and the selector only. countries, effective_from, effective_until and delegation_type are absent from both. Adding effective_until to a signal_tags entry still validates, because the object is open, and no consumer
built from this schema reads the field. A time-bounded or geo-bounded signal authorization has no
representation in the file.
A missing or malformed file
A 404 on the well-known path means the file is absent. Consumers proceed without verification;
absence is not a denial, and the docs state that it does not mean the agent is unauthorized. A
404 or an S3-style 403 AccessDenied may send a validator to the domain's ads.txt for a managerdomain line instead, one hop only and only on those two statuses. Otherwise the publisher is unverifiable.
Unparseable JSON, or a missing top-level authorized_agents, aborts processing for
that domain outright. A missing file does not. A single malformed property inside an
otherwise-valid file must not either: validators skip that entry, log it and continue. A
generation bug therefore causes a larger failure than hosting nothing, and the effect is largest
on a managed-network file covering hundreds of publisher domains.
Frequently asked
- What is adagents.json?
- A file at /.well-known/adagents.json naming the agents a publisher or data provider allows to sell its inventory or resell its signals. Each entry needs a url, an authorized_for label, and an authorization_type saying what the authorization covers.
- What is brand.json?
- The buy-side half of the pair, hosted at /.well-known/brand.json. It declares who the brand is, which agents speak for it, and which properties it owns or sells. AdCP's docs line it up against sellers.json.
- Can an adagents.json point at an authoritative copy and still list agents inline?
- No. Both branches match, and a oneOf needs exactly one.