Skip to main content

Documentation Index

Fetch the complete documentation index at: https://agenticadvertisingorg-changeset-release-main.mintlify.app/llms.txt

Use this file to discover all available pages before exploring further.

The brand.json file provides a standardized way for brands to claim their identity and establish discoverable brand information. It supports five variants to accommodate different publishing models.
brand.json is the canonical source of brand identity data. The brand object defined here (logos, colors, tone, tagline) is the single brand definition used across AdCP. Tasks reference brands by domain and brand_id — the system resolves full identity from brand.json or the registry.

Motivation

Brand identity for a holdco could live in one brand.json owned by the parent — every child change requires editing the parent’s file. If Converse wants to update its logo, someone edits Nike, Inc.’s file. If a holdco runs 100 subsidiary brands, all 100 teams converge on the same monolithic document. Brand teams own their identity, but a monolithic shape forces a single ops choke point at the corporate parent. It also blocks independent brands from publishing at all — a brand listed in someone else’s portfolio has no protocol-level path to assert its own canonical data, even when domain control proves it could. The spec resolves this by letting a child brand publish its own canonical document while the house remains the authority for who is in the family. Inline brands[] stays a first-class option (parent owns the data); brand_refs[] adds pointer children whose canonical document lives elsewhere (child owns the data). A house mixes freely. The hierarchy is one level deep — only a house declares ownership; a brand cannot itself have children.

File location

Brands host the brand.json file at:
https://example.com/.well-known/brand.json
Following RFC 8615 well-known URI conventions.

Variants

The brand.json file supports five variants:
#VariantUse when
1Authoritative Location RedirectThe canonical document is hosted at another URL
2House RedirectThe brand domain rolls up to a larger house
3Brand AgentAn MCP agent provides authoritative brand identity
4House PortfolioA house publishes its brands (inline, by pointer, or both)
5Brand Canonical DocumentA brand self-publishes its own identity (with optional house_domain pointer up)
Variants 1–3 are mutually exclusive with each other and with variants 4–5. Variants 4 and 5 compose: a House Portfolio (4) can reference Brand Canonical Documents (5) via brand_refs[], and a Brand Canonical Document can point back at its house via house_domain. See Mutual-assertion trust model for how the two halves resolve.

1. Authoritative Location Redirect

Points to a hosted brand.json at another URL:
{
  "$schema": "https://adcontextprotocol.org/schemas/v3/brand.json",
  "authoritative_location": "https://adcontextprotocol.org/brand/abc123/brand.json"
}
Use this when:
  • Brand.json is hosted centrally (e.g., by a service provider)
  • CDN distribution is needed
  • Managed brand services
Optional fields (shared with House Redirect — see Redirect ergonomics):
  • redirect_reason: structured signal for cache handling (acquisition, rebrand, regional, legacy, consolidation, other)
  • redirect_effective_at: ISO timestamp when the redirect became effective
  • note: free-text rationale

2. House Redirect

Points to the house domain that contains the full brand portfolio:
{
  "$schema": "https://adcontextprotocol.org/schemas/v3/brand.json",
  "house": "nikeinc.com",
  "note": "Regional site - see house for brand portfolio"
}
Optional fields:
  • region: ISO 3166-1 alpha-2 country code (e.g., “CN”)
  • redirect_reason: structured signal for cache handling (see Redirect ergonomics)
  • redirect_effective_at: ISO timestamp when the redirect became effective
  • note: free-text rationale
Use this when:
  • Brand domain is owned by a larger house
  • Regional/localized domains point to main house
  • Legacy domains redirect to canonical

Redirect ergonomics

Both redirect variants accept optional redirect_reason and redirect_effective_at to help consumers handle redirect transitions without sitting on stale cached state. redirect_reason is an enum:
ValueMeaningCaching guidance
acquisitionThe owning entity was acquired (e.g., one holdco buys another)Shorten cache TTL until stable; many fields may move
divestitureThe owning entity spun out or sold offShorten cache TTL until stable; new ownership chain
rebrandThe brand or house renamed/repositionedShorten cache TTL until stable
consolidationSub-brands consolidated into the targetShorten cache TTL until stable
regionalRegional/localized domain points to main houseStable; standard caching
legacyOld domain that redirects to canonicalStable; standard caching
otherReason not captured by the aboveFree-text rationale belongs in note
redirect_effective_at (ISO 8601 timestamp) is the hard cache invariant: caches MUST treat any entry cached before this timestamp as stale and re-fetch through the redirect. The TTL-shortening guidance above is a SHOULD; this timestamp is a MUST and is the load-bearing fix for cache poisoning during M&A and other transitions. This is the brand.json analogue to the migration patterns in IAB Tech Lab’s ads.txt (OWNERDOMAIN) and sellers.json (seller_type), which historically relied on out-of-band coordination — there was no machine-readable transition signal. redirect_reason + redirect_effective_at close that gap for brand.json. Example — acquisition redirect:
{
  "$schema": "https://adcontextprotocol.org/schemas/v3/brand.json",
  "house": "wpp.com",
  "redirect_reason": "acquisition",
  "redirect_effective_at": "2026-04-15T00:00:00Z",
  "note": "Acquired by WPP April 2026"
}

3. Brand Agent

Designates an MCP agent that provides brand information:
{
  "$schema": "https://adcontextprotocol.org/schemas/v3/brand.json",
  "version": "1.0",
  "brand_agent": {
    "url": "https://agent.acme.com/mcp",
    "id": "acme_brand_agent"
  }
}
Optional fields:
  • contact: Contact information
When a brand has an agent, the agent is the authoritative source for brand identity data.

4. House Portfolio

The house publishes its brands. A house may carry inline child definitions, pointer references to brands that self-publish, or both:
  • brands[] — inline child definitions. Parent owns the data. Best for sub-brands without their own domain (Nike SB, an internal product line) or sub-brands the holdco wants to manage centrally.
  • brand_refs[] — pointer entries. Child owns the data at its own canonical document (variant 5). Best for sub-brands with their own domain that want self-publish authority (Converse, Jordan).
A given child appears in exactly one of the two arrays. At least one of brands[] or brand_refs[] must be present. Simple house (inline only):
{
  "$schema": "https://adcontextprotocol.org/schemas/v3/brand.json",
  "version": "1.0",
  "house": {
    "domain": "nikeinc.com",
    "name": "Nike, Inc.",
    "architecture": "hybrid"
  },
  "brands": [
    {
      "id": "nike",
      "names": [{"en": "Nike"}],
      "keller_type": "master",
      "properties": [
        {"type": "website", "identifier": "nike.com", "primary": true}
      ]
    }
  ]
}
Mixed hybrid (inline + pointer):
{
  "$schema": "https://adcontextprotocol.org/schemas/v3/brand.json",
  "version": "1.0",
  "house": {
    "domain": "nikeinc.com",
    "name": "Nike, Inc.",
    "architecture": "hybrid"
  },
  "brands": [
    {
      "id": "nike_sb",
      "names": [{"en_US": "Nike SB"}],
      "keller_type": "sub_brand"
    }
  ],
  "brand_refs": [
    { "domain": "converse.com", "brand_id": "converse" },
    { "domain": "jordan.com",   "brand_id": "jordan" }
  ]
}
The brand_refs[] entry shape:
FieldRequiredMeaning
domainyesWhere the child’s canonical brand.json lives. Must be unique within brand_refs[].
brand_idyesStable identifier for this brand within the house’s portfolio. Must be unique within brand_refs[] and MUST NOT also appear in brands[].
managed_bynoDomain of the entity that operationally manages this brand (e.g., an agency network within a holdco). House-declared. Consumers MUST NOT use it for trust or authorization decisions. Aggregation across houses (“show me everything BBH manages”) is the intended use — it’s a directory field, not a trust field.
effective_atnoISO 8601 timestamp when the house established this ownership claim. Consumers age mutual-assertion edges from this date; omit and consumers age from their own first observation.
Trust semantics for the relationship between this entry and the child’s house_domain claim are defined in Mutual-assertion trust model below. House with delegation (WPP): Holdcos delegate brand management to agency networks. WPP plc owns brands but Ogilvy or BBH actually runs them day-to-day. managed_by on a brand_refs[] entry captures this as a unilateral declaration by the owning house. The leaf brand doesn’t reference the manager. UIs render BBH Sport under BBH for agency views; trust validation walks BBH Sport → WPP only.
{
  "$schema": "https://adcontextprotocol.org/schemas/v3/brand.json",
  "version": "1.0",
  "house": {
    "domain": "wpp.com",
    "name": "WPP plc"
  },
  "brand_refs": [
    { "domain": "bbh-sport.com",     "brand_id": "bbh_sport",     "managed_by": "bbh.com" },
    { "domain": "ogilvy-toyota.com", "brand_id": "ogilvy_toyota", "managed_by": "ogilvy.com" },
    { "domain": "wpp-direct.com",    "brand_id": "wpp_direct" }
  ]
}
managed_by is a directory field, not a trust field. It exists so consumers can group brands by who actually runs them day-to-day — the canonical view a buyer-side DSP wants when shopping inventory across an agency network. Consumers MUST NOT use it for trust or authorization decisions; that line still flows through mutual assertion between leaf and house. See Conformance.

5. Brand Canonical Document

Self-published per-brand document where the brand owns its own identity attributes. Hosted at the brand’s own /.well-known/brand.json (or via authoritative location redirect). A brand may declare its house via house_domain or stand alone (no parent house — Patagonia, Liquid Death — omit the field). Trust semantics for the house_domain relationship are defined in Mutual-assertion trust model below. With a house — Converse under Nike:
{
  "$schema": "https://adcontextprotocol.org/schemas/v3/brand.json",
  "version": "1.0",
  "id": "converse",
  "names": [{"en_US": "Converse"}],
  "keller_type": "sub_brand",
  "house_domain": "nikeinc.com",
  "logos": [
    {"url": "https://converse.com/logo.svg", "variant": "primary"}
  ],
  "tagline": "Sneaker for the streets"
}
Standalone — Patagonia:
{
  "$schema": "https://adcontextprotocol.org/schemas/v3/brand.json",
  "version": "1.0",
  "id": "patagonia",
  "names": [{"en_US": "Patagonia"}],
  "keller_type": "independent",
  "logos": [
    {"url": "https://patagonia.com/logo.svg", "variant": "primary"}
  ],
  "tagline": "We're in business to save our home planet."
}
Use this when a brand has its own domain and wants self-publish authority for its identity (logos, colors, tone, taglines). The brand carries the same identity fields as an inline entry in brands[]. Top-level fields specific to this variant:
FieldTypeRequiredDescription
idstringYesBrand identifier (lowercase alphanumeric with underscores)
namesarrayYesLocalized names
house_domainstring (domain)NoPointer to the corporate house this brand belongs to. The brand is treated as standalone if omitted. Single-hop — a brand cannot itself declare brand_refs[].
$schema, version, last_updatedstringNoDocument metadata
All other brand-identity fields apply (logos, colors, fonts, tone, tagline, visual_guidelines, keller_type, parent_brand, properties[], industries[], target_audience, description, agents[], contact, trademarks[], data_subject_contestation, etc. — see Brand definition for the full field list). The document MUST NOT carry house-only fields (house, brands, brand_refs, authorized_operators) or redirect fields (authoritative_location, house as string, region, note, redirect_reason, redirect_effective_at).

Mutual-assertion trust model

Trust resolves at two layers — brand identity (logos, colors, tone, tagline, etc.) and brand relationships (who owns this brand, who can speak for it). The two layers separate cleanly. Identity is verifiable from a single TLS-served document; relationships require both sides to reciprocate.
EdgeIdentity trustRelationship trustNotes
Inline child in brands[]Trusted (parent’s TLS covers the data)Trusted (the house authored the entry)The classic shape. Parent owns the data.
Mutual assertion: leaf says house_domain: A, A’s brand_refs[] includes leafTrusted (leaf’s TLS)Trusted (both sides reciprocate)Full trust. Governance propagation, member-feature inheritance, billable inclusion all flow.
Leaf-only: leaf says house_domain: A, A’s brand_refs[] does not include leafTrusted (leaf’s TLS)UnverifiedIdentity is real — the brand controls its own domain. The parent claim is unverified; governance and billable inclusion are blocked pending reciprocation. See Self-healing through notification.
House-only: A’s brand_refs[] includes leaf, leaf has no house_domainTrusted (leaf’s TLS — as a standalone document)Unverified in the other directionThe leaf hasn’t claimed A. Treat the leaf as standalone; A’s claim is supportive metadata.
Standalone (no house_domain)Trusted (leaf’s TLS)n/a — no claimed relationshipPatagonia, Liquid Death. The brand is its own thing.
Key asymmetry. A leaf with verified TLS at its own domain is authoritative for its own identity attributes whether or not its parent claim is reciprocated. The relationship layer is what mutual assertion gates. A naïve “claimed, unverified ⇒ ignore the leaf entirely” reading is wrong — the leaf’s logos/colors/tone are still real. Standalone trumps third-party claim. A Brand Canonical Document with no house_domain is standalone. If some other house’s brand_refs[] lists it anyway, the leaf’s silence is dispositive: treat as standalone; the third-party claim is unverified metadata only. See Conformance for the normative statement. Validation is a runtime check (the crawler fetches both documents and compares); the JSON Schema accepts the fields independently.

Self-healing through notification

The leaf-only edge case is common in practice — a sub-brand team stands up its own canonical document before the parent’s portfolio team has time to add the reciprocal entry. Today this leaves the brand stuck: identity is good, but media buys and governance decisions are blocked. The spec defines a self-healing loop. For houses without a brand-agent:
  1. The house publishes a reachable contact.email at the top level of its brand.json.
  2. When a consumer encounters a leaf-only edge — leaf claims house_domain: A, A’s brand_refs[] doesn’t include leaf — the consumer SHOULD notify A’s contact.email that a leaf is claiming reciprocation and is blocked pending verification.
  3. The house team adds the entry to brand_refs[]. On the next crawl/re-validation, the edge upgrades to mutual.
For houses with a brand-agent advertising verify_brand_claim, the consumer asks the agent directly instead — see Agent-augmented verification below. The agent path surfaces richer states (pending_review, transferring, disputed, licensed_in) than the email loop can express, and when both house and leaf publish agents, mutual assertion completes via two signed agent calls without a static-file crawl.

Agent-augmented verification

When the brand publishes a brand-agent (variant 3 or a type: "brand" entry in agents[] on variant 4/5), the agent can be asked verification questions via verify_brand_claim — a single tool that takes a claim_type (subsidiary / parent / property / trademark) and returns the brand’s authoritative answer. The brand-agent is brand.json hidden behind a server: same data the static file carries, plus the richer states the static file can’t capture (pending_review, transferring, disputed, licensed_in, licensed_out). The trust model is asymmetric by direction. Without this asymmetry, a malicious or mistaken house could claim subsidiaries it doesn’t own and have consumers extend trust on the strength of the signature alone.
DirectionTrust rule
Rejection — agent signs disputed or not_oursAuthoritative unilaterally. A brand has standing to refuse association regardless of what any other party publishes. Overrides any reciprocating claim.
Assertion — agent signs owned / pending_review / transferring / licensed_*Informative but NOT trust-extending alone. The reciprocating side must still confirm (via its own brand-agent’s parent claim type, or via static crawl) before relationship trust extends.
When both house and leaf publish brand-agents, mutual assertion can complete at the agent layer: partner calls verify_brand_claim with claim_type: "subsidiary" on the house AND with claim_type: "parent" on the leaf. Both owned → mutual assertion, real-time, signed by both parties, no crawl required. This is the cleanest path for trust extension. Mutual assertion proves consistency between two parties, not standing. Two reciprocally-asserting agents at attacker-controlled domains can sign matching owned responses; mutual assertion confirms only that they agree, not that either has legitimate authority over the underlying brand. The final trust gate is still domain control + TLS — verified on the consumer side, against the legal/operational entity the consumer expects to own the domain. Mutual assertion at the agent layer is the floor; consumer-side standing checks (domain registration, real-world identity) are still the caller’s responsibility for high-trust decisions. Agent responses are signed under the brand’s adcp_use: "response-signing" JWK. See the task reference for the full request/response shapes and per-claim-type details.

Field resolution

There is no inheritance/override block. Each consumer-side question has a single answer:
QuestionResolution
Brand identity (logos, colors, tone, tagline, voice)Read from brand’s own canonical document. For inline children, read from the parent’s brands[] entry.
Brand contact, properties, industriesRead from brand’s own canonical document.
Trademarks, authorized_operators, corporate contactRead from the house’s brand.json.
data_subject_contestation, compliance policies, regulated-category flagsStrictest-of house-level and brand-level. See below.
Mutual-assertion verificationFetch both brand and house, compare house_domainbrand_refs[].
Identity fields (name, names, logos, colors, fonts, tone, voice, tagline, visual_guidelines, avatar): brand-level value is authoritative; the house value is not consulted. Brand teams own brand identity. Compliance and governance fields: the resolved value is the strictest of the house-level and brand-level values. A brand cannot weaken a house’s governance assertions; it can only add stricter constraints. Applies to:
  • data_subject_contestation — both contacts SHOULD be presented to data subjects (consumers may use either; brand-level does NOT replace house-level)
  • compliance_policies, audience exclusions, regulated-category flags — resolved as union (more restrictions wins)
This is the load-bearing reason holdcos publish corporate-level governance: brand teams should not be able to soften compliance by self-publishing. Identity is brand-wins because that’s what brand teams own; governance is strictest-of because that’s how legal/compliance regimes actually work. The schema does not encode this rule; it’s a resolution-layer semantic. See Resolution algorithm below for the full crawler procedure.

Acquisitions and reorganizations

Existing redirect variants handle M&A natively:
  1. Pre-deal: dentsu.com/.well-known/brand.json is a House Portfolio. Dentsu brands’ canonical docs say house_domain: "dentsu.com".
  2. Deal closes: Dentsu’s brand.json is replaced with a House Redirect{ "house": "wpp.com" }. WPP adds the acquired brands to brand_refs[] with managed_by: "dentsu.com" for ops continuity and effective_at set to the deal-close date.
  3. Post-deal: leaves still pointing at house_domain: "dentsu.com" resolve through the redirect to WPP. Mutual-assertion verification follows the redirect chain (see Conformance) and holds. No urgent leaf migration needed.

Adopting brand_refs[] for an existing portfolio

An existing House Portfolio publisher (today on inline brands[]) doesn’t need to migrate. brand_refs[] is additive and pull-based — a brand moves out of brands[] only when its team decides to self-publish. The migration path for a single brand:
  1. The child brand stands up /.well-known/brand.json at its own domain as a Brand Canonical Document, declaring house_domain: "<house>".
  2. The house team removes the child’s entry from brands[] and adds { domain, brand_id, effective_at } to brand_refs[]. brand_id MUST match the value the child uses; otherwise the cross-array uniqueness invariant doesn’t help future readers.
  3. The crawler picks up the mutual assertion on next refresh.
Between steps 1 and 2, the leaf-only edge is unverified at the relationship layer but the leaf’s identity is still trusted on TLS (see Self-healing through notification). Consumers SHOULD email the house’s contact.email to prompt step 2. The AAO registry consumes both shapes today and will not re-classify a brand that moves from brands[] to brand_refs[] — the brand_id is the stable identifier across the migration.

Out of scope

The single-house, single-hop trust model deliberately doesn’t cover four shapes:
  • Joint ventures with two parents (Hulu pre-Disney, JVs in pharma, automotive partnerships). A leaf has at most one house_domain. JV structures must pick one canonical parent or use a holding entity; the protocol won’t model two-parent ownership.
  • PE rollups and white-label arrangements that want opacity. Mutual assertion publishes ownership at well-known URLs. A holdco that wants to operate brands without public disclosure can use the existing monolithic brands[] shape (which doesn’t expose the parent to leaf-domain crawlers) but cannot use mutual-assertion. Mutual assertion trades opacity for verifiability — that’s the design.
  • Jurisdictional governance divergence (e.g., a Marriott franchisee in Germany whose data-subject contestation rules differ from the US parent’s). Strictest-of resolution means brand-level publishers can only add constraints. A brand in a less-regulated jurisdiction cannot drop a house-level rule that doesn’t apply to it. Workaround: the house publishes the strictest applicable per-region rule.
  • Standing licensed relationships as a static brand.json surface. verify_brand_claim with claim_type: "trademark" can return licensed_in / licensed_out because the underlying relationships are real — Marriott franchisees use the MARRIOTT mark under license, music catalogs are licensed-out per territory, jurisdictional licensing splits (“licensed in CN, self-managed elsewhere”) are common. The brand-agent can speak to these from internal records. But brand.json itself doesn’t yet have a publishing surface for standing licensed relationships parallel to brand_refs[] for ownership. The existing rights protocol (rights_agent, acquire_rights) handles transactional licensing — negotiate a deal — not standing declarations. This gap is real and tracked as a follow-up; the verify surface exposes the states because partners need to consume them, but the static-file substrate that backs them is a separate design alongside the rights-protocol team.
These cases belong in governance / corporate-structure specs, not brand.json. brand.json is the brand-identity surface; corporate legal structure and licensing-relationship publishing are their own concerns.

House definition

The house object represents the corporate entity:
FieldTypeRequiredDescription
domainstringYesHouse’s primary domain
namestringYesDisplay name
namesarrayNoLocalized names
architectureenumNobranded_house, house_of_brands, or hybrid

Brand definition

Each brand in the brands array:
FieldTypeRequiredDescription
idstringYesBrand identifier (lowercase alphanumeric with underscores)
namesarrayYesLocalized names (see below)
keller_typeenumNomaster, sub_brand, endorsed, independent
parent_brandstringNoParent brand’s id
propertiesarrayNoDigital properties associated with this brand
brand_agentobjectNoAgent providing brand identity data { url, id }
rights_agentobjectNoRights licensing agent { url, id, available_uses, right_types, countries }
logosarrayNoBrand logo assets
colorsobjectNoBrand color palette
fontsobjectNoBrand typography
toneobjectNoBrand voice and messaging guidelines (voice, attributes, dos, donts)
taglinestringNoBrand tagline or slogan
visual_guidelinesobjectNoStructured visual rules for generative creative systems
trademarksarrayNoRegistered trademarks owned or licensed by this brand (registry, number, mark, optional status, license_type, countries). See Trademarks.

Names Array

Names are localized with language codes:
{
  "names": [
    {"en": "Nike"},
    {"en": "The Swoosh"},
    {"zh": "耐克"},
    {"ja": "ナイキ"}
  ]
}
Multiple entries per language are allowed (for aliases).

Keller Types

Brand architecture classifications from marketing theory:
TypeDescriptionExample
masterPrimary brand of houseNike for Nike, Inc.
sub_brandCarries parent brand nameNike SB
endorsedIndependent identity, endorsed by parentAir Jordan “by Nike”
independentOperates separately from houseConverse

Extended color roles

The colors object has five standard roles (primary, secondary, accent, background, text), but brands can and should provide additional roles for finer granularity. The schema accepts any additional color role via additionalProperties.
{
  "colors": {
    "primary": "#FF6600",
    "secondary": "#0066CC",
    "background": "#FFFFFF",
    "text": "#1A1A1A",
    "heading": "#FF6600",
    "body": "#333333",
    "label": "#666666",
    "border": "#E5E5E5",
    "divider": "#F0F0F0",
    "surface_1": "#F9F9F9",
    "surface_2": "#F0F0F0"
  }
}
RolePurpose
headingHeading text color (when different from body text)
bodyBody text color
labelLabel/caption text color
borderBorder/outline color
dividerDivider/separator color
surface_1Primary surface/card background
surface_2Secondary surface background
These extended roles help creative agents distinguish between text hierarchies and surface levels without guessing.

Visual guidelines

The visual_guidelines object provides structured rules that generative creative systems can use to produce on-brand assets consistently. These are brand constants — they don’t change campaign to campaign.
Visual guidelines complement the basic identity fields (colors, fonts, logos). Colors define what the brand palette is; visual guidelines define how to use it. Fonts define font families; visual guidelines define the type scale.

Photography

Controls how brand photography should look when selected or generated:
{
  "photography": {
    "realism": "natural",
    "lighting": "soft daylight",
    "color_temperature": "warm",
    "contrast": "medium",
    "depth_of_field": "medium",
    "subject": {
      "people": {
        "age_range": "25-45",
        "diversity": "mixed",
        "mood": ["confident", "relaxed"]
      },
      "product_focus": "in-use",
      "setting": "outdoor"
    },
    "framing": {
      "subject_position": "center-left",
      "crop_style": "waist-up",
      "perspective": "eye-level"
    }
  }
}
FieldTypeDescription
realismenumnatural, stylized, hyperreal, abstract
lightingstringLighting style description
color_temperatureenumwarm, neutral, cool
contrastenumlow, medium, high
depth_of_fieldenumshallow, medium, deep
subjectobjectSubject matter guidelines (people, product focus, setting)
framingobjectCamera framing rules (position, crop, perspective)
preferred_aspect_ratiosarrayPreferred aspect ratios (e.g., ["16:9", "4:5", "1:1"])
tagsarrayAdditional style descriptors

Graphic style

Defines the visual language for brand graphics and illustrations:
{
  "graphic_style": {
    "style_type": "flat_illustration",
    "stroke_style": "rounded",
    "stroke_weight": "2px",
    "corner_radius": "12px"
  }
}
Style types: flat_illustration, geometric, gradient_mesh, editorial_collage, hand_drawn, minimal_line_art, 3d_render, isometric, photographic_composite.
FieldTypeDescription
style_typeenumflat_illustration, geometric, gradient_mesh, editorial_collage, hand_drawn, minimal_line_art, 3d_render, isometric, photographic_composite
stroke_styleenumrounded, square, mixed, none
stroke_weightstringStroke weight (e.g., 2px)
corner_radiusstringCorner radius for graphic/illustration elements (e.g., 12px). For UI components, see border_radius.
tagsarrayAdditional style descriptors

Shapes

Brand shapes used as part of visual identity:
{
  "shapes": {
    "primary_shape": "circle",
    "secondary_shapes": ["rounded_rectangle", "diagonal_wave"],
    "usage": {
      "max_per_layout": 2,
      "overlap_allowed": true
    }
  }
}
FieldTypeDescription
primary_shapestringPrimary brand shape (e.g., circle, rounded_rectangle, hexagon)
secondary_shapesarraySecondary shapes in the brand vocabulary
usage.max_per_layoutintegerMaximum distinct shapes per layout
usage.overlap_allowedbooleanWhether shapes may overlap

Iconography

Icon style system and usage rules:
{
  "iconography": {
    "style": "outline",
    "stroke_weight": "2px",
    "corner_style": "rounded",
    "usage": {
      "max_per_frame": 3,
      "size_ratio": "1:8"
    }
  }
}
FieldTypeDescription
styleenumoutline, filled, duotone, flat, glyph, hand_drawn
stroke_weightstringIcon stroke weight (e.g., 2px)
corner_styleenumrounded, square, mixed
usage.max_per_frameintegerMaximum icons per creative frame
usage.size_ratiostringIcon-to-layout size ratio (e.g., 1:8)

Composition

Layout rules for overlays, textures, and backgrounds:
{
  "composition": {
    "overlays": {
      "gradient_style": "linear",
      "gradient_direction": "45deg",
      "opacity": "70%"
    },
    "texture": {
      "style": "subtle_grain",
      "intensity": "low"
    },
    "backgrounds": {
      "types_allowed": ["solid_color", "gradient", "image"]
    }
  }
}
Texture styles: none, subtle_grain, noise, paper, fabric, concrete. Intensity: low, medium, high. Background types: solid_color, gradient, blurred_photo, image, video, pattern, transparent.

Border radius

Named border radius presets for UI components and layout elements. Border radius is one of the most visible brand differentiators — generous radii feel warm and approachable, while small or zero radii feel precise and editorial.
{
  "border_radius": {
    "none": "0",
    "default": "12px",
    "small": "4px",
    "large": "20px",
    "pill": "999px"
  }
}
FieldTypeDescription
nonestringExplicitly sharp corners (0)
defaultstringDefault border radius for UI components (e.g., 8px, 12px)
smallstringSmall radius for compact elements (e.g., 4px)
largestringLarge radius for cards and containers (e.g., 16px, 24px)
pillstringFully rounded / pill shape (e.g., 999px)
Additional named presets can be added beyond the five standard levels.
graphic_style.corner_radius defines a default radius for graphic/illustration elements. border_radius defines a named scale for UI components and layout — buttons, cards, inputs, modals.

Elevation

Named shadow levels that define how elements appear to lift off the surface. Brands use elevation as identity — some prefer dramatic multi-layer shadows, others use a single diffuse shadow.
{
  "elevation": {
    "none": "none",
    "subtle": "0 1px 3px rgba(0,0,0,0.08)",
    "card": "0 4px 8px -1px rgba(0,0,0,0.1), 0 2px 4px -2px rgba(0,0,0,0.06)",
    "modal": "0 20px 25px -5px rgba(0,0,0,0.1), 0 8px 10px -6px rgba(0,0,0,0.06)"
  }
}
Values use CSS box-shadow syntax. Generative systems can apply these directly.
FieldTypeDescription
nonestringNo shadow (none)
subtlestringSlight lift for interactive elements
cardstringCard-level elevation
modalstringModal/overlay elevation
Additional named levels (e.g., dropdown, tooltip) can be added.

Spacing

Spacing system for consistent layout rhythm. A base unit plus a named scale enables creative agents to produce correctly-spaced layouts without guessing.
{
  "spacing": {
    "unit": "8px",
    "scale": {
      "xs": "4px",
      "sm": "8px",
      "md": "16px",
      "lg": "24px",
      "xl": "32px",
      "2xl": "48px"
    }
  }
}
FieldTypeDescription
unitstringBase grid unit this scale was designed from (e.g., 8px). Informational — agents should use the named scale values directly.
scaleobjectNamed spacing scale (xs through 2xl)
The scale object supports standard sizes (xs, sm, md, lg, xl, 2xl) and can include additional named values (e.g., 3xl, section).

Graphic elements

Reusable decorative or structural visual elements that are part of the brand identity — torn paper edges, watermarks, dividers, background patterns:
{
  "graphic_elements": [
    {
      "name": "Paper Tear",
      "type": "frame",
      "description": "Torn paper edge used as section dividers and photo frames. Use primarily vertical orientation.",
      "orientation": "vertical",
      "colors": ["#a75230", "#f6f1f1", "#fba007"],
      "max_per_layout": 2
    },
    {
      "name": "Location Sketch Watermark",
      "type": "watermark",
      "description": "Light hand-drawn building sketch behind content, visible through the logo area",
      "colors": ["#a75230"]
    }
  ]
}
FieldTypeRequiredDescription
namestringYesElement name
typeenumNoborder, divider, frame, watermark, pattern, texture_overlay, decorative
descriptionstringNoHow the element is used in layouts
orientationenumNohorizontal, vertical, any
colorsarrayNoColors this element may appear in
max_per_layoutintegerNoMaximum instances per layout

Motion

Motion and animation rules for video, animated display, and interactive formats:
{
  "motion": {
    "transition_style": "dissolve",
    "animation_speed": "moderate",
    "easing": "ease-in-out",
    "text_entrance": "fade",
    "pacing": "lingering",
    "kinetic_typography": false
  }
}
FieldTypeDescription
transition_styleenumcut, dissolve, slide, wipe, zoom, fade
animation_speedenumslow, moderate, fast
easingstringDefault easing function (e.g., ease-in-out, spring, linear)
text_entranceenumfade, typewriter, slide_up, slide_left, scale, none
pacingenumlingering, moderate, fast_cuts
kinetic_typographybooleanWhether animated/kinetic typography is allowed
tagsarrayAdditional motion style descriptors

Logo placement

Logo placement and clear space rules for automated creative production:
{
  "logo_placement": {
    "preferred_position": "bottom-left",
    "min_clear_space": "0.5x",
    "min_height": "40px",
    "background_contrast": "any"
  }
}
FieldTypeDescription
preferred_positionenumtop-left, top-center, top-right, bottom-left, bottom-center, bottom-right, center
min_clear_spacestringMinimum clear space as a multiple of logo height (e.g., 0.5x, 1x) or fixed value (e.g., 16px)
min_heightstringMinimum logo height for legibility (e.g., 40px)
background_contrastenumlight_only, dark_only, any

Colorways

Named color pairings that define how colors work together. Allows a creative brief to reference “use my primary colorway” without specifying every color:
{
  "colorways": [
    {
      "name": "primary",
      "foreground": "#FFFFFF",
      "background": "#FF6600",
      "accent": "#0066CC",
      "cta_foreground": "#FFFFFF",
      "cta_background": "#0066CC"
    },
    {
      "name": "inverted",
      "foreground": "#FF6600",
      "background": "#FFFFFF",
      "accent": "#0066CC",
      "border": "#FF6600"
    }
  ]
}
FieldTypeRequiredDescription
namestringYesColorway name (e.g., "primary", "inverted", "dark")
foregroundhex colorYesText/foreground color
backgroundhex colorYesBackground color
accenthex colorNoAccent color
cta_foregroundhex colorNoCall-to-action text color
cta_backgroundhex colorNoCall-to-action button color
borderhex colorNoBorder color
channelsarrayNoChannels where this colorway applies (e.g., ["online"], ["print", "pos"]). Omit for universal colorways.

Type scale

Typography scale defining sizes and weights for different text roles:
{
  "type_scale": {
    "base_width": "1080px",
    "heading": {
      "font": "primary",
      "size": "48px",
      "weight": "700",
      "line_height": "1.1"
    },
    "subheading": {
      "font": "primary",
      "size": "24px",
      "weight": "600",
      "line_height": "1.3"
    },
    "body": {
      "font": "secondary",
      "size": "16px",
      "weight": "400",
      "line_height": "1.5"
    },
    "caption": {
      "font": "secondary",
      "size": "12px",
      "weight": "400",
      "line_height": "1.4"
    },
    "cta": {
      "font": "primary",
      "size": "18px",
      "weight": "700",
      "text_transform": "uppercase",
      "letter_spacing": "0.05em"
    }
  }
}
The font field references font roles defined in the brand’s fonts object ("primary", "secondary"), or can specify a font family name directly. When sizes are in pixels, use base_width to indicate the reference canvas these sizes were designed for. Generative systems should scale proportionally for other canvas sizes — a 48px heading designed for 1080px width would scale to 14px on a 320px mobile leaderboard.

Asset libraries

References to managed asset libraries (icon sets, illustration systems, image collections). URLs are for human access — a brand portal, press kit, or DAM landing page that a person can open in a browser.
{
  "asset_libraries": [
    {
      "name": "Brand Illustrations v2",
      "type": "illustration_system",
      "url": "https://brand.example.com/illustrations",
      "description": "Flat illustration system with defined color guide",
      "color_guide": {
        "roles": ["base", "shadow_1", "shadow_2", "highlight_1", "highlight_2", "stroke"],
        "palettes": [
          {
            "name": "orange",
            "colors": {
              "base": "#FF6600",
              "shadow_1": "#CC5200",
              "shadow_2": "#993D00",
              "highlight_1": "#FF8533",
              "highlight_2": "#FFB380",
              "stroke": "#662900"
            }
          }
        ]
      }
    }
  ]
}
FieldTypeRequiredDescription
namestringYesDisplay name of the asset library
typeenumRecommendedicon_set, illustration_system, image_library, video_library, template_library
urlstring (URI)YesURL to the asset library (for human access)
descriptionstringNoDescription of library contents and usage
color_guideobjectNoColor roles and palettes used in the library
The color_guide provides generative systems with the color palettes used in the library — useful for producing on-brand illustrations or icons without accessing the library itself.

Restrictions

Visual prohibitions and guardrails — the visual equivalent of tone.donts. These tell generative systems what to avoid:
{
  "restrictions": [
    "Never place text over the product",
    "Do not use black backgrounds",
    "No stock photography of people on phones",
    "No split-screen layouts"
  ]
}

Trademarks

Registered trademarks may appear at the house level (corporate marks — e.g., NIKE owned by Nike, Inc.) or at the brand level (brand-specific marks — e.g., CONVERSE owned by Converse). Both arrays are valid claims; resolution between them is union.
Licensed-in / licensed-out relationships (Marriott franchisees using the MARRIOTT mark, music catalogs licensed per territory, etc.) are queryable via the brand-agent today through verify_brand_claim with claim_type: "trademark". A static brand.json publishing surface for standing licensed relationships (parallel to brand_refs[] for ownership) is a future RFC alongside the rights-protocol team. The static trademarks[] array below covers ownership only; licensing posture comes from the agent.
{
  "trademarks": [
    {
      "registry": "USPTO",
      "number": "12345678",
      "mark": "CONVERSE",
      "status": "active",
      "license_type": "owned",
      "countries": ["US"]
    }
  ]
}
FieldTypeRequiredDescription
registrystringYesTrademark registry (e.g., USPTO, EUIPO, JPO, CNIPA)
numberstringYesRegistration number as issued by the registry
markstringYesThe registered mark as published
statusenumNoactive, pending, abandoned, cancelled, expired. Omit for active marks if status tracking is not maintained.
license_typeenumNoowned (default), licensed_in, licensed_out
countriesarrayNoISO 3166-1 alpha-2 country codes where this registration applies. Omit for global or where the registry’s jurisdiction is implicit.
Holdcos with cross-jurisdiction conflicts (USPTO CONVERSE vs EUIPO CONVERSE under different owners) should publish each registration as a separate entry and use countries to scope where the mark applies.

Property definition

Properties are digital touchpoints associated with brands:
FieldTypeRequiredDescription
typeenumYesProperty type (see below)
identifierstringYesDomain or app ID
storeenumNoApp store (apple, google, etc.)
regionstringNoISO country code or global
primarybooleanNoIs this the primary property?
relationshipenumNoHow this brand relates to the property: owned (default), direct, delegated, ad_network. Matches delegation_type in adagents.json for bilateral verification. See ad networks.

Property types

Matches AdCP property-type enum:
  • website
  • mobile_app
  • ctv_app
  • desktop_app
  • dooh
  • podcast
  • radio
  • streaming_audio

Property relationships

Properties default to owned — the brand operates the property directly. For networks and SSPs that sell inventory they don’t own, the relationship field declares the commercial arrangement:
ValueMeaningExample
ownedBrand owns and operates this property (default)Your own website
directBrand is the direct sales path, even if a third party runs the techPublisher’s in-house ad team using a vendor’s platform
delegatedBrand manages monetization — in charge of ad salesMediavine managing a food blog
ad_networkBrand sells as part of a network/exchange — a path, not the pathPubMatic as an SSP
This is the AdCP equivalent of sellers.json — the operator’s public declaration of which publishers they work with. The publisher confirms by setting the matching delegation_type on the agent’s authorization in their adagents.json. See ad networks for the bilateral verification pattern.

Resolution algorithm

To resolve a domain to a canonical brand:
  1. Fetch https://{domain}/.well-known/brand.json.
  2. Check variant:
    • authoritative_location: fetch from that URL, continue from step 2.
    • house (string): fetch from house domain, continue from step 2.
    • brand_agent: return agent URL — the agent is authoritative.
    • House Portfolio (house object + brands[] and/or brand_refs[]): for an inline child, find the brand whose properties[] or id matches the query; for a pointer child, follow brand_refs[].domain and resolve once — the followed document MUST be a Brand Canonical Document, never another House Portfolio.
    • Brand Canonical Document (id + names at top level): the document is the brand. If house_domain is present, fetch the house’s brand.json to verify reciprocation in its brand_refs[] (mutual assertion). When the house side is itself a House Redirect, follow the redirect chain on the house side before comparing. Read corporate-level fields (e.g., data_subject_contestation) from the house if not present on the brand; for compliance fields, resolve strictest-of house and brand (see Mutual-assertion trust model).
  3. Return canonical brand information.
Maximum redirect depth: 3 hops. The brand → house lookup is single-hop (no recursive parent walks). See Mutual-assertion trust model for trust semantics.

Complete examples

Small Business

{
  "$schema": "https://adcontextprotocol.org/schemas/v3/brand.json",
  "version": "1.0",
  "house": {
    "domain": "bobsburgers.com",
    "name": "Bob's Burgers LLC"
  },
  "brands": [
    {
      "id": "bobs_burgers",
      "names": [{"en": "Bob's Burgers"}],
      "keller_type": "master",
      "properties": [
        {"type": "website", "identifier": "bobsburgers.com", "primary": true}
      ],
      "logos": [
        { "url": "https://bobsburgers.com/logo.svg", "tags": ["icon"] }
      ],
      "colors": { "primary": "#FF6B35" }
    }
  ]
}

Enterprise with Agent

{
  "$schema": "https://adcontextprotocol.org/schemas/v3/brand.json",
  "version": "1.0",
  "brand_agent": {
    "url": "https://brand-agent.enterprise.com/mcp",
    "id": "enterprise_brand_agent"
  },
  "contact": {
    "name": "Enterprise Brand Team",
    "email": "brand@enterprise.com"
  }
}

Multi-Brand Portfolio

{
  "$schema": "https://adcontextprotocol.org/schemas/v3/brand.json",
  "version": "1.0",
  "house": {
    "domain": "nikeinc.com",
    "name": "Nike, Inc.",
    "architecture": "hybrid"
  },
  "brands": [
    {
      "id": "nike",
      "names": [{"en": "Nike"}, {"zh": "耐克"}, {"ja": "ナイキ"}],
      "keller_type": "master",
      "properties": [
        {"type": "website", "identifier": "nike.com", "primary": true},
        {"type": "website", "identifier": "nike.cn", "region": "CN"},
        {"type": "mobile_app", "store": "apple", "identifier": "com.nike.omega"}
      ]
    },
    {
      "id": "air_jordan",
      "names": [{"en": "Air Jordan"}, {"en": "Jordan"}, {"en": "Jumpman"}],
      "keller_type": "endorsed",
      "parent_brand": "nike",
      "properties": [
        {"type": "website", "identifier": "jordan.com", "primary": true},
        {"type": "website", "identifier": "jumpman23.com"},
        {"type": "mobile_app", "store": "apple", "identifier": "com.nike.snkrs"}
      ]
    },
    {
      "id": "converse",
      "names": [{"en": "Converse"}],
      "keller_type": "independent",
      "properties": [
        {"type": "website", "identifier": "converse.com", "primary": true}
      ]
    }
  ],
  "contact": {
    "name": "Nike Brand Team",
    "email": "brand@nike.com"
  }
}

Talent Agency with Rights

A talent agency managing athlete brands with licensable rights:
{
  "$schema": "https://adcontextprotocol.org/schemas/v3/brand.json",
  "version": "1.0",
  "house": {
    "domain": "lotientertainment.com",
    "name": "Loti Entertainment",
    "architecture": "house_of_brands"
  },
  "brands": [
    {
      "id": "daan_janssen",
      "names": [{"en": "Daan Janssen"}],
      "description": "Dutch Olympic speed skater, 2x gold medalist",
      "industries": ["sports"],
      "logos": [
        {
          "url": "https://cdn.lotientertainment.com/janssen/headshot.jpg",
          "variant": "primary"
        }
      ],
      "brand_agent": {
        "url": "https://rights.lotientertainment.com/mcp",
        "id": "loti_entertainment"
      },
      "rights_agent": {
        "url": "https://rights.lotientertainment.com/mcp",
        "id": "loti_entertainment",
        "available_uses": ["likeness", "voice", "endorsement"],
        "right_types": ["talent"],
        "countries": ["NL", "BE", "DE"]
      }
    }
  ]
}
The rights_agent field tells crawlers what’s licensable without any MCP calls — available uses, rights type, and countries. Buyer agents can search the registry for “Dutch athletes available for voice licensing” and find matches from the indexed brand.json data.

Regional Domain Redirect

On nike.cn/.well-known/brand.json:
{
  "$schema": "https://adcontextprotocol.org/schemas/v3/brand.json",
  "house": "nikeinc.com",
  "region": "CN"
}

Caching

Recommended cache TTLs:
  • Canonical files: 24 hours
  • Redirect files: 24 hours
  • Failed lookups: 1 hour

Conformance

These invariants MUST be enforced by validators and crawlers; JSON Schema cannot express them directly. Portfolio invariants
  • brand_id cross-array uniqueness. A given brand_id MUST NOT appear in both brands[] and brand_refs[] of the same house. Publisher must choose one.
  • brand_id within-array uniqueness. A given brand_id MUST be unique within brands[] and unique within brand_refs[] of the same house.
  • domain within-array uniqueness. Each brand_refs[].domain MUST be unique within the array. Two entries pointing at the same domain with different brand_id values is undefined — there can be only one canonical pointer per domain per house.
  • house_domain placement. house_domain MUST NOT appear on entries inside brands[]. It is a Brand Canonical Document top-level field; an inline child cannot carry a parent pointer of its own.
Trust invariants
  • Mutual-assertion is the relationship-trust edge. Consumers MUST NOT extend relationship trust (auto-provisioning, member-feature inheritance, billable seat inclusion) through one-sided claims. Mutual assertion (child’s house_domain matches a brand_refs[] entry on the named house) is the canonical trust edge.
  • Identity is TLS-only. A leaf brand’s own identity attributes (logos, colors, tone, tagline, visual_guidelines) are authoritative based on the leaf’s TLS-served document alone, regardless of mutual-assertion state. A leaf-only relationship claim does not invalidate the leaf’s identity.
  • House Redirects on the house side MUST be followed. When verifying mutual assertion, if the named house’s brand.json is a House Redirect, the consumer MUST follow the redirect chain (up to the 3-hop limit) before comparing brand_refs[] membership. Otherwise post-acquisition leaves silently lose trust.
  • Standalone trumps third-party claim. A Brand Canonical Document with no house_domain is standalone, regardless of any third-party house’s brand_refs[] claim about it. The leaf’s silence is dispositive. (Stated once here; descriptive prose elsewhere defers to this clause.)
  • managed_by is a directory field, not a trust field. Consumers MUST NOT use managed_by for trust or authorization decisions. Aggregation by managed_by (“show me everything BBH manages”) is the intended use — it’s an operational directory across houses, not a trust assertion.
Resolution invariants
  • Compliance fields strictest-of. For governance fields — including data_subject_contestation, compliance_policies, policy_categories, audience exclusions, regulated-category flags, and brand-level disclaimers[] that the house also publishes — the resolved value is the union/strictest of house-level and brand-level. Brand-level publishers MUST NOT rely on weakening house-level assertions. This is distinct from relationship trust — strictest-of is a resolution rule, not a trust gate.
  • Edge aging. Mutual-assertion edges SHOULD be aged: consumers SHOULD treat an edge as one-sided when the gap between the publisher-declared brand_refs[].effective_at (or, if absent, the consumer’s first observation) and the last successful re-validation exceeds the consumer’s chosen TTL. AAO’s reference crawler ages at 180 days; consumers MAY choose differently.
Self-healing
  • Leaf-only edges SHOULD trigger notification. When a consumer encounters a leaf claiming house_domain: X with no reciprocal entry on X, the consumer SHOULD notify X’s contact.email so the house team can complete the reciprocation. Notifying parties MUST rate-limit per {leaf, house} pair to avoid flooding.
  • Agent-augmented verification. When the named house publishes a brand-agent advertising verify_brand_claim in its supported_tasks with a relevant claim_type (subsidiary / parent / property / trademark), consumers SHOULD call the agent in addition to performing crawl-based mutual-assertion inference. The trust model is asymmetric by direction: signed disputed / not_ours overrides any reciprocating claim (rejection is unilateral); signed owned / pending_review / transferring / licensed_* does NOT replace mutual-assertion verification — the reciprocating side must still confirm before relationship trust extends. When both sides have brand-agents, mutual assertion completes via two signed agent calls (subsidiary on the house + parent on the leaf). The crawl path is the fallback when the agent is unreachable or returns unknown. The email notification SHOULD continues to apply for houses without a brand-agent. See Agent-augmented verification for the full trust table.

Prior art

The mutual-assertion trust primitive mirrors the IAB Tech Lab’s ads.txt and sellers.json reciprocal-publication model — and the app-ads.txt extension that proved the pattern moves cleanly from web bundles to mobile apps. A buyer is trusted as a seller’s reseller iff both sides publish the relationship at well-known URLs. Same trust shape, same non-cryptographic “who claims what about whom” verification, same fallback to one-sided / unverified for partial publication. A deployed, durable industry pattern. The well-known URL plus structured JSON resource discovery shape predates ads.txt — see WebFinger (RFC 7033) and host-meta (RFC 6415) for the IETF analogue. brand.json borrows this convention via RFC 8615. Within AdCP, the provenance verifier contract (seller-publishes / buyer-represents / seller-confirms) uses the same family of construction for a different field family.

Best practices

  1. Start simple: Begin with minimal brand.json and add complexity as needed
  2. Use redirects for subsidiaries: Point brand domains to house domain
  3. List all properties: Include regional domains, apps, and legacy domains
  4. Keep names current: Include localized names and common aliases
  5. Visual guidelines are optional: Add them when you need generative systems to produce on-brand assets consistently. Start with colorways and restrictions — they have the highest immediate impact.
  6. Keep portfolios lean: For house portfolios with many brands, include visual guidelines only on brands that need them. Full visual guidelines on every brand in a large portfolio increases file size significantly.