Skip to main content
GET /api/v2/storefront/discover-agents Queries the agenticadvertising.org registry for operator records and resolves the publisher’s adagents.json path, including fallback discovery, for a domain. Use it to see what the AAO registry and publisher identity documents say before you connect or list. Results are server-side cached for 2 minutes; pass refresh=true to bypass the cache.

Request

curl
curl "https://api.interchange.io/api/v2/storefront/discover-agents?domain=acme-media.example.com" \
  -H "Authorization: Bearer $SCOPE3_API_KEY"

Parameters

ParamInTypeRequiredNotes
domainquerystringYesOperator domain to discover agents for. Must be a valid domain (e.g. example.com)
refreshquery"true" | "false"NoSet to "true" to bypass the 2-minute server-side cache and refetch
x-aao-api-keyheaderstringNoAAO session token for the calling user. When provided, the registry response is scoped to their account and includes private/draft agents. Falls back to the platform key when omitted

Response

{
  "domain": "acme-media.example.com",
  "operator": {
    "domain": "acme-media.example.com",
    "member": {
      "slug": "acme-media",
      "display_name": "Acme Media"
    },
    "lookup_status": "member",
    "agents": [
      {
        "url": "https://agent.acme-media.example.com/mcp",
        "name": "Acme Media Sales Agent",
        "type": "sales",
        "compliance": {},
        "storyboards": [],
        "authorized_by": []
      }
    ]
  },
  "publisher": {
    "domain": "acme-media.example.com",
    "member": {
      "slug": "acme-media",
      "display_name": "Acme Media"
    },
    "lookup_status": "member",
    "adagents_valid": true,
    "discovery_method": "direct",
    "manager_domain": null,
    "resolved_url": "https://acme-media.example.com/.well-known/adagents.json",
    "hosting": {
      "mode": "self",
      "last_validated": "2026-06-25T14:48:42.000Z"
    },
    "properties": [],
    "authorized_agents": []
  }
}
FieldTypeDescription
domainstringThe domain that was queried
operatorobjectAgents registered to this operator domain
operator.domainstringOperator domain
operator.memberobject | nullRegistry member: { slug, display_name, is_founding_member?, membership_tier?, membership_tier_label? }, or null. When null, read operator.lookup_status to tell why
operator.lookup_statusenumWhy member is what it is: member (a record is present), not_member (looked up with full visibility, no record), scope_limited (looked up without your AAO key, so members-only records may be hidden), or lookup_failed (the registry call timed out or errored — retry with refresh)
operator.agents[]arrayEach agent: { url, name, type } plus optional compliance, storyboards[], authorized_by[]
publisherobjectPublisher record from the AAO registry or the adagents.json fallback
publisher.domainstringPublisher domain
publisher.memberobject | nullRegistry member { slug, display_name }, or null. When null, read publisher.lookup_status to tell why
publisher.lookup_statusenumWhy member is what it is: member, not_member (publisher lookups have no visibility tiers, so a null member is always definitive), or lookup_failed (registry call timed out or errored — retry with refresh)
publisher.adagents_validboolean | nullWhether the adagents.json fallback validated, or null when not checked
publisher.discovery_methodstringHow the file was resolved — direct (the domain’s own /.well-known/adagents.json), authoritative_location (a centrally-hosted file covering many publishers), or ads_txt_managerdomain (the domain hosts no file of its own and delegates via its ads.txt managerdomain). Absent when no file resolved
publisher.manager_domainstring | nullThe manager domain the file was resolved from when discovery_method is ads_txt_managerdomain (e.g. cafemedia.com); null otherwise
publisher.resolved_urlstring | nullThe URL the authoritative adagents.json was actually fetched from
publisher.hosting.modestringThe registry’s hosting state for the publisher record: self, self_invalid, aao_hosted, self_redirected, or none. This is registry metadata, not the same thing as discovery_method
publisher.hosting.last_validatedstring | nullWhen the registry last successfully validated the publisher-origin file. null means it has not successfully validated that origin yet
publisher.properties[]arrayPublisher property records
publisher.authorized_agents[]arrayAgents authorized to sell this publisher’s inventory

How adagents.json resolves

adagents.json is the file a publisher publishes to declare which agents are authorized to sell its inventory. Discovery does not stop at a 404 on the publisher’s own domain — a missing file there is normal for publishers managed by a network. Resolution follows this order:
  1. Direct — fetch https://<domain>/.well-known/adagents.json. Redirects are followed only within the same registrable domain (an SSRF guard: a third-party host can’t bounce the request onto an internal address).
  2. Authoritative-location redirect — if the direct file is a pointer (it sets authoritative_location and lists no authorized_agents of its own), follow that one hop to the centrally-hosted file it names. This is how a network or SSP can serve a single adagents.json for many publishers without each one hosting a full file. When this path is used, the response reports discovery_method: "authoritative_location".
  3. Manager domain fallback — if there is no direct file at all, read the domain’s ads.txt and follow its managerdomain declaration one hop, fetching that manager’s adagents.json instead. This is what makes network-managed publishers resolve at all: e.g. every Raptive/CafeMedia-managed domain hosts no file of its own and delegates to cafemedia.com. When this path is used, the response reports discovery_method: "ads_txt_managerdomain" and the manager_domain it resolved from.
  4. Authorization is bound to the publisher domain. An agent is authorized only when the resolved file grants it a property that belongs to the queried domain — not by mere presence in authorized_agents[]. A centrally-hosted file covering many publishers cannot make an agent authorized for a domain it wasn’t granted.

Hosting mode vs. resolved file

publisher.hosting.mode describes the AAO registry’s current publisher-record state. It is useful for diagnosing setup, but it is not a replacement for the resolved adagents.json verdict.
ModeMeaning
selfThe registry successfully validated a publisher-origin file at https://<domain>/.well-known/adagents.json
self_invalidThe publisher origin returned a file, but it failed validation
aao_hostedAAO hosts a publisher document for this domain. The publisher still needs to make its own origin prove that document is authoritative, typically by serving an authoritative_location stub at https://<domain>/.well-known/adagents.json pointing to the AAO-hosted URL
self_redirectedThe publisher origin points to another HTTPS location through authoritative_location or an HTTP-layer redirect
noneThe registry has no publisher-hosted or AAO-hosted file configured yet
When a publisher moves from AAO-hosted to self-hosted, the registry only converges after the queried domain’s well-known URL is crawler-accessible. A file on a sibling host such as www.<domain> is not enough by itself; https://<domain>/.well-known/adagents.json must return the file or a crawler-accessible redirect that the resolver can follow. Browser-only access, bot-gated responses, or HEAD/GET differences can leave the registry in an unvalidated state even when a human can view a JSON file in a browser. For AAO-hosted records, aao_hosted does not mean the publisher has self-hosted a full file. It means AAO has a hosted publisher document. Origin attestation happens when the publisher origin points at that hosted document and the registry can verify the pointer. Until then, buyers may see AAO-hosted intent without adagents_json origin verification. For source families that sell publisher inventory through an agent URL, choose the authorized agent URL from the storefront source model:
  • If the seller connects an external AdCP sales agent, publishers authorize that agent’s own URL.
  • If the seller connects its ad server directly to Interchange and uses Interchange’s hosted storefront agent, publishers authorize the canonical Interchange storefront agent URL: https://interchange.io.
Linked storefront inventory uses the upstream storefront’s own authorization model. Modular sources only need publisher adagents.json authorization when the module or execution path exposes a publisher-facing agent URL. For network-managed publishers, this authorization usually belongs in the manager’s file, with publishers delegating to that file through managerdomain or authoritative_location. If one publisher has a direct adagents.json that points somewhere else, that direct file can shadow the manager-domain fallback. Fix the conflict by making the publisher’s file delegate to the same manager file, or by removing the publisher file so its ads.txt managerdomain delegation is used.
AdCP 3.1 resolution semantics. The spec extends adagents.json for managed networks: a manager publishing a large agent network can use the compact publisher_domains[] form (the authoritative file caps at 20 MB), and revocation is expressed via a time-bound revoked_publisher_domains[] — a published, dated fact rather than a silent removal. Interchange resolves all three discovery paths above (direct, authoritative_location, and managerdomain fallback); the compact publisher_domains[] / time-bound revoked_publisher_domains[] content forms are a tracked follow-up.

Errors

  • 400 VALIDATION_ERRORdomain missing or empty.
  • 401 UNAUTHORIZED — missing or invalid bearer token.
See Errors for the full error contract.

Storefront tasks

All core storefront operations.

Resolve brand

Look up a brand profile by domain.

Storefront overview

Marketplace review and AAO signals.