Specifications Draft for comment

Emissar Resolve v0.1

A public registry that maps a phone number, domain or brand name to the A2A Agent Card that answers for it, with proof of who controls the identifier.

JSON Schema · OpenAPI · Example (Node) · Sample data · Validator (Python)

Document Emissar Resolve, version 0.1 (draft for comment)
Status Draft for comment. Not a commitment
Date 2026-09-26; published for comment 2026-10-05
Author Emissar team
Extension URI https://emissar.ai/ext/resolve/v1 (redirects to this document)
Companion files JSON Schema resolve-v0.1.schema.json; OpenAPI resolve-v0.1.yaml; runnable example resolve-example.mjs with its directory-sample.json and validator validate.py

Abstract

Resolve is a public registry that maps an E.164 telephone number, a domain name, or a brand name within one country to the URL of an A2A Agent Card, with how strongly and when Emissar checked the mapping. An agent queries Resolve before it contacts a business: if a record exists, it fetches the card and sends an A2A task; if not, it uses the business’s normal channels. This document defines identifier normalization, the record format, verification levels and proof-of-control methods per identifier type, a public rate-limited HTTPS lookup API, seeding of the first read-only version from published Agent Cards, and the dispute, abuse and privacy rules.

Status of this document

A working draft in the style of an IETF specification, published for comment on 2026-10-05 so that it can be reviewed line by line. It is not an Internet-Draft and has not been submitted anywhere. Comments and questions: the contact form at https://emissar.ai/contact (topic “General”).

Phase What exists Records
v0 read-only Lookup API (section 8) over records seeded from crawled public Agent Cards (section 9) observed domain records only
Claims Businesses claim identifiers and prove control (section 7) verified-control domain records; verified-organization records for all three types

Emissar’s Resolve page promises that the verification methods are published in this specification before the registry accepts any claims. This draft publishes them for review; claims stay closed until that review is done and claim and dispute review is staffed (open question 12).

1. Introduction

1.1 Problem

A2A discovery starts from a domain: a client fetches https://{domain}/.well-known/agent-card.json (A2A section 8.2; the suffix is registered as permanent, section 14.3). Section 8.2 also lists registries and catalogs, and the A2A discovery guide notes that the specification prescribes no standard registry API [A2A-DISC].

A person’s agent usually starts from something else: the phone number on a bill, a company name, or the domain of a support address. Nothing public maps a phone number or brand name to an agent endpoint, or says whether the business has an agent at all, so agents contact businesses through channels built for people. Resolve adds a lookup that runs first, backed by proof that whoever registered a mapping controls the identifier.

1.2 Scope and non-goals

Out of scope:

  • Anything that happens during a telephone call. Resolve is consulted before the client contacts the business by any channel. It defines no in-call behavior of any kind and no signaling on the telephone network. Call handling is outside the scope of this document.
  • Trust in the agent itself (Emissar Verify and the client’s policy) and authority to act for a person (Emissar Mandate).
  • Search by skill, category or text; Resolve answers exact-identifier lookups only.
  • Email addresses, URLs and DIDs as identifiers (5.4).

1.3 Design principles

  1. Fail to the normal channel. A negative answer leaves the client where it is today; a wrong positive answer sends a person’s request to the wrong party. When in doubt, Resolve withholds the answer.
  2. Proof of control, not endorsement. A record says someone showed control of an identifier by a named method at a named time. It does not say the business is honest or the agent safe.
  3. Resolve points; the card speaks. Records carry a card URL and verification facts, never the business’s self-description. The client fetches and validates the card.
  4. One answer for numbers and domains; candidates for brands. Different organizations can hold one brand name in different lines of business.
  5. Minimum public data. No personal data is published.
  6. Everything expires. Numbers and domains change hands.

2. Conventions and terminology

2.1 Requirements language

The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “NOT RECOMMENDED”, “MAY”, and “OPTIONAL” in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here.

2.2 Terminology

Term Meaning
Identifier A telephone number, domain name, or brand name plus country, in the canonical form of section 5
Record The registry’s statement that an identifier maps to one Agent Card URL, with its verification facts (section 6)
Registry The Resolve service and its store of records. Operated by Emissar
Client Software that queries the lookup API, usually an agent acting for a person or a business
Claimant An organization asking the registry to create or change a record
Holder The claimant whose record is current
Level How strongly a record is checked: observed, verified-control or verified-organization (section 7.1)
Resolve extension The A2A extension https://emissar.ai/ext/resolve/v1 in which an Agent Card lists the identifiers it answers for (section 7.2)
Negative answer A 404 response stating that the registry holds no current record for an identifier

3. Overview

 person's agent                        Resolve                       business
 ──────────────                        ───────                       ────────
 has: "+1 519-555-0142" (from a bill)
 normalize (5.1) -> +15195550142
 GET /v0/tel/+15195550142  ─────────►  record found?
                           ◄─────────  200 {cardUrl, level, method,
                                            lastVerifiedAt, expiresAt}
 GET cardUrl  ─────────────────────────────────────────────────────►  Agent Card
 validate card (TLS, host, signature,
   Resolve extension lists the number)
 A2A SendMessage  ─────────────────────────────────────────────────►  A2A endpoint

 or:                       ◄─────────  404 not-found
 use the business's published channels

Records are either seeded (section 9: the crawler found a public card at a domain’s well-known URI; level observed) or claimed (section 7: an organization proved control of the identifier and lists it in its card; level verified-control or verified-organization).

4. Relationship to existing work

System What it maps How control is proven Relevance to Resolve
A2A well-known URI (A2A 8.2, 14.3) Domain to Agent Card Serving the file on the domain Resolve’s observed level is exactly this fetch. For domains, a client can always do it itself
WebFinger [RFC7033] A URI (for example acct:) to links, at /.well-known/webfinger Serving the answer on the domain Prior art for identifier-to-endpoint lookup over HTTPS: CORS required (RFC 7033 section 5), 404 for unknown resources, and a harvesting warning with IP rate limiting as a mitigation (RFC 7033 section 9.3)
ENUM [RFC6116] E.164 number to URIs via DNS NAPTR under e164.arpa Delegation per country code, approved through the ITU, with RIPE NCC operating e164.arpa [RIPE-ENUM] [ITU-ENUM] Prior art for number-to-endpoint mapping. It depends on national delegation and DNS publication by the number’s operator; Resolve does not
MCP Registry [MCP-REG] Reverse-DNS server names to MCP server metadata GitHub sign-in, or a DNS TXT record or /.well-known/mcp-registry-auth file carrying a public key, then a signed timestamp A registry for a neighboring protocol, in preview since September 2025. It proves namespace control, keeps its metadata “deliberately unopinionated”, and leaves curation to downstream aggregators. Its HTTP well-known path is not in the IANA registry
AGNTCY OASF and Agent Directory [OASF] [AGNTCY-DIR] Agent records (OASF schema) in a peer-to-peer directory Records signed with Cosign-compatible signatures; optional name verification when https://<domain>/.well-known/jwks.json holds the signing key Domain-scoped naming only; no phone numbers or brands
Agentic Resource Discovery (ARD, v0.91 proposal) and AI Catalog Domain-published catalogs of agents, MCP servers and other resources, plus a search API A catalog’s publisher identity must match the domain it is published on Where A2A maintainers pointed registry proposals in 2026 when closing them [A2A-741] [A2A-1295]. Domain-based; nothing for phone numbers [ARD]
NANDA Index [NANDA-IDX] [NANDA-PAPER] Organization identities (domain, email, URN) to agent catalogs or card hosts DNS TXT challenge for domain organizations; email verification alone for personal entries A running index service with a resolve API. No telephone-number identifier

Apart from ENUM, which maps numbers to generic URIs through national DNS delegation, none of the systems checked maps a telephone number or a country-scoped brand name to an agent endpoint with proof of control; that, plus the verification levels, is what Resolve adds. Domains are included so one query shape covers all three starting points.

5. Identifiers and normalization

Each identifier has one canonical form, and the registry stores and matches only that. Clients SHOULD normalize before querying; the registry normalizes again and redirects non-canonical requests (8.2). The runnable example (Appendix A) implements these rules.

5.1 Telephone numbers (tel)

The canonical form is the E.164 international number: +, then the country code and the national significant number, ASCII digits only, at most 15 digits in total, not counting the international prefix [E164 clause 6.1]. Example: +15195550142 (555-0100 to 555-0199 are NANPA’s reserved fictitious numbers [NANPA-555]).

Normalization:

  1. Apply NFKC, which maps full-width digits and plus signs to ASCII.
  2. Strip a leading tel:. A tel URI with any parameter (;ext=, ;isub=, ;phone-context=) MUST be rejected: extensions are not part of the E.164 number, and phone-context marks a local number [RFC3966].
  3. Remove visual separators: space, -, ., (, ) [RFC3966], and Unicode spaces and dashes.
  4. The result MUST start with +; the registry never guesses a country. A client holding a national number (519-555-0142 on a Canadian bill) converts it from what it knows about the source.
  5. Only digits may follow + (clients convert vanity letters themselves); the first MUST NOT be 0; at most 15.
  6. Country code 1 (the North American Numbering Plan, covering the US and Canada): exactly 10 digits MUST follow, as NXX-NXX-XXXX with N from 2 to 9 [CFR52.7]. Toll-free codes (800, 833, 844, 855, 866, 877, 888) are classed nanp-toll-free for method policy (7.4); the class is not part of the identifier.
  7. Other country codes get only step 5 in v0.1; implementations SHOULD also check national numbering-plan data.

5.2 Domain names (domain)

The canonical form is the fully qualified host name in lowercase A-labels, without a trailing dot. Example: opensea.io; the input Bücher.example becomes xn--bcher-kva.example.

Normalization:

  1. Reject input that contains a scheme, path, port or user part. The identifier is a host name, not a URL.
  2. Remove one trailing dot.
  3. Map and convert to A-labels with UTS #46 non-transitional processing [UTS46], which also lowercases (DNS comparisons are case-insensitive [RFC4343]). Reject any failure.
  4. Reject IP literals, single-label names, labels that are not 1-63 LDH characters (letters, digits, hyphen; no leading or trailing hyphen), names over 253 characters [RFC1035] [RFC5891], and an all-numeric top-level label.
  5. Names under special-use top-level labels (localhost, local, internal, invalid, test, example, onion, arpa, home, lan, alt) normalize, but the lookup API answers 400: they are never registered.

Matching is exact. www.example.com and example.com are different identifiers, as they are in DNS. The Unicode (U-label) form MAY be returned as display for people and MUST NOT be used for matching.

5.3 Brand names (brand)

A brand identifier is a pair: an ISO 3166-1 alpha-2 country code [ISO3166] and a brand key. Trademark rights are national, and the same name is often held by unrelated companies in different countries, so a brand is never looked up without a country.

The brand key is computed from the brand as people write it:

  1. Normalize with Unicode NFKC and apply full case folding (NFKC_Casefold) [UAX15] [UNICODE-CF].
  2. Split into tokens at every character that is not a letter, mark or digit.
  3. While more than one token remains and the last token is a legal-form designator from Appendix B (for example inc, ltd, ltée, gmbh), remove it.
  4. Join the remaining tokens with no separator.
  5. The key MUST be 2 to 64 code points.

So EXAMPLE TELECOM, Inc. and Example-Telecom Ltée both give exampletelecom, and AT&T and AT & T both give att. Words are not translated (& is not rewritten as “and”, which would favor one language); a holder known by several spellings claims each (7.5).

At claim time the registry computes the UTS #39 skeleton [UTS39] of the key and holds for manual review any claim whose skeleton matches a different existing key’s (for example a Cyrillic а for a Latin a). Skeletons are never used for lookup matching.

5.4 Identifiers Resolve does not define

  • Email addresses. A client that starts from a support address such as help@example.com MAY look up the domain part as a domain identifier. Resolve defines no email identifier: the local part is often personal data, and querying it would send that data to the registry.
  • URLs. A client with a URL already has a domain.
  • DIDs. DID methods define their own resolution.

6. Records

6.1 Fields

A record is a JSON object. The normative definition is the JSON Schema resolve-v0.1.schema.json (root schema; Draft 2020-12).

Field Type Meaning
id string rsv_ + 20 base32 chars Stable record id, used in disputes and logs
identifier object {type: "tel", value}, {type: "domain", value, display?} or {type: "brand", value, country, display?}, canonical per section 5
cardUrl https URL Where the Agent Card is served
status active or disputed disputed records are returned with that status (section 10). Suspended and expired records are never returned
source crawl or claim Seeded (section 9) or claimed (section 7)
verification.level observed, verified-control, verified-organization Section 7.1
verification.method string The control method (section 7), such as crawl-well-known, dns-txt, sms-otp
verification.lastVerifiedAt RFC 3339 UTC [RFC3339] When the method last succeeded (for observed, when the card was last fetched)
verification.expiresAt RFC 3339 UTC After this instant the record is not returned unless re-verified
verification.evidence[] array Public summaries of each check: kind, optional authority and ref, checkedAt. Never a secret, one-time code, personal name or contact detail
organization object Only at verified-organization: legal name, country, and registry {authority, id}
updatedAt RFC 3339 UTC Last change to the record

The schema also encodes the cross-field rules: seeded records are observed, domain-only, crawl-well-known, without organization; only seeded records are observed; methods are restricted per type; tel and brand records exist only at verified-organization; organization is present exactly at that level. validate.py confirms that eleven records breaking these rules are rejected (Appendix A.2).

6.2 Record rules

  1. For tel and domain, the registry MUST hold at most one current record per identifier. A claimed record supersedes an observed record for the same domain.
  2. For brand, the registry MAY hold several records per identifier, one per organization.
  3. The registry MUST NOT return a record after its expiresAt, whether or not a re-check is pending.
  4. cardUrl MUST be an https URL without user information. The registry fetches it with the SSRF controls already used by Emissar’s public tools.
  5. A record never contains text taken from the Agent Card (name, description, provider). The client reads the card itself.

7. Claims and proof of control

Claims stay closed until a reviewed version of this section is published. It is written now so that the record format and API are designed around it.

7.1 Verification levels

Level Allowed for What it proves What it does not prove
observed domain, seeded only At lastVerifiedAt, an HTTPS server with a valid certificate for the domain (or a subdomain it redirected to) served an Agent Card at the domain’s well-known URI That anyone asked to be listed; that the organization named in the card runs the domain; that the card is still there; anything about numbers or brands; that the agent is trustworthy
verified-control domain At lastVerifiedAt, an Emissar account passed a challenge only the domain’s controller could pass (7.3), and the card lists the domain in its Resolve extension (7.2) The account holder’s legal identity; that control will last; that the agent is trustworthy
verified-organization domain, tel, brand (the only level for tel and brand) The above for the identifier’s type, plus: Emissar found the holder in an authoritative register and linked the claimant to it (7.6); for brands, a trademark registration or Verified Mark Certificate shows the organization’s rights in the name in that country (7.5) That the organization is honest or licensed; that it is the only holder of a brand; that its agent behaves well (Verify’s job); for one-time-code methods, protection against SIM swap or unauthorized porting (11.2)

Levels are ordered observed < verified-control < verified-organization, and clients MAY require a minimum per action. Telephone records start at verified-organization because the organization check is what keeps personal numbers out (12.2). Brand records start there because “control” of a name has no technical meaning; only registered rights do.

7.2 Endpoint binding: the Resolve extension

Every claimed record requires the card at cardUrl to list the identifier in an A2A extension declaration (AgentCapabilities extensions, A2A section 4.4.4):

{
  "uri": "https://emissar.ai/ext/resolve/v1",
  "description": "Identifiers this agent answers for in Emissar Resolve",
  "required": false,
  "params": {
    "identifiers": [
      { "type": "tel", "value": "+15195550142" },
      { "type": "domain", "value": "agent.example.com" },
      { "type": "brand", "value": "Example Telecom", "country": "CA" }
    ]
  }
}
  1. The registry normalizes each entry (section 5) and MUST refuse a claim whose identifier is not listed. required MUST be false, so clients that do not know the extension are unaffected.
  2. The listing is the card operator’s consent to receive traffic for the identifier; the claim proves control of the identifier. Both are required, so neither party alone can create a record. The claimant need not control the card’s host: hosted cards, such as the cards Emissar Front Door hosts for businesses, are expected.
  3. The registry re-fetches the card weekly and suspends the record once the identifier has been missing for 14 days. Removing the entry is how an operator withdraws consent.
  4. During a card-token claim, params also carries "challenge": "<token>". A signed card (A2A section 8.4) must be re-signed after either change.

7.3 Domain methods

Method Claimant does Registry checks
dns-txt Publishes _emissar-resolve-challenge.{domain}. TXT "token=<token>" and leaves it in place The TXT RRset contains the token
card-token Adds challenge: <token> to the Resolve extension of the card at https://{domain}/.well-known/agent-card.json The card, fetched over HTTPS, carries the token
  1. Tokens carry at least 128 random bits, lowercase base32, one per claim, bound to the claiming account, valid 7 days for the first proof. This follows ACME’s token entropy [RFC8555 section 8.3] and the DNS verification draft’s advice on random tokens and underscore-prefixed, provider-specific owner names [DCV-DRAFT sections 6.1.1, 6.2].
  2. The registry MUST check from at least three network perspectives in different regions, accepting only if all but at most one agree, and MUST use a DNSSEC-validating resolver. This mirrors the multi-perspective corroboration the CA/Browser Forum has required for public TLS certificates since 2025-03-15 [CABF-BR section 3.2.2.9] and ACME’s advice [RFC8555 section 10.2].
  3. card-token reuses the A2A well-known URI, already registered (A2A section 14.3), so Resolve needs no well-known URI of its own, which RFC 8615 would require to be registered [RFC8615 section 3]. Fetches use the same SSRF controls as Emissar’s public tools and never follow a redirect to another registrable domain.
  4. Claims on ICANN-section public suffixes [PSL] MUST be refused [DCV-DRAFT section 9.9]; names in the list’s private section MAY be claimed. A proof covers exactly one name; there are no wildcards.
  5. The dns-txt record stays in place and is re-queried every 30 days, similar to the CA/Browser Forum’s persistent-value method [CABF-BR section 3.2.2.4.22].

As ACME notes, anyone who can change the domain’s DNS or web content, including its hosting provider, passes these checks [RFC8555 section 10.2], and a new owner of a lapsed domain can re-create old records [DCV-DRAFT section 9.11]. Re-checks and the transfer hold (7.8) limit the damage.

7.4 Telephone methods

Preconditions: the number is in the North American Numbering Plan (other countries are open question 7); the organization check (7.6) has passed before any code is sent; the number is listed in the organization’s card (7.2).

Method How it works Allowed for Strength and limits
sms-otp Registry texts a code; claimant enters it in the Emissar console Non-toll-free NANP numbers Proves possession of the line at that moment. NIST SP 800-63B-4 classes PSTN out-of-band codes as restricted because of SIM swap, porting and device-change risks [NIST-63B sections 3.1.3.3, 3.2.9]
voice-otp Registry places an automated call that reads a code; claimant enters it in the console All NANP numbers, including toll-free and contact-center lines Same class as sms-otp. The call carries nothing but the code
stir-delegate-cert Claimant signs a registry challenge with the key of a STIR delegate certificate whose TNAuthList covers the number, and sends the chain Numbers for which the organization holds a delegate certificate A certification authority under the STIR/SHAKEN governance framework certified this number to the key holder [RFC9060] [ATIS-1000092]. Not exposed to SIM swap; few enterprises hold one

One-time codes: at least 8 digits (NIST’s minimum is 6 [NIST-63B section 3.1.3.2]), random, single use, valid 10 minutes, at most 5 attempts, at most 3 sends per number per 24 hours, plus per-account and per-prefix caps. Where the telephony provider exposes SIM-change or port events, the registry SHOULD check them first and hold the claim for 7 days after either, as NIST recommends [NIST-63B section 3.1.3.3].

sms-otp MUST NOT be used for toll-free numbers. Somos, the FCC-appointed toll-free administrator, documents that a request to text-enable a toll-free number takes effect immediately, with the RespOrg only notified and approval by default after two business days [SOMOS-TSS]. A third party could receive the code.

For stir-delegate-cert, the chain MUST validate to a certification authority trusted under the US STI governance framework [ATIS-1000080], unexpired and unrevoked, and the number MUST appear in the TNAuthList as a single number or inside a range [RFC8226 section 9]. RespOrg-issued delegate certificates are accepted for toll-free numbers [ATIS-1000093]. Standard SHAKEN certificates are not: each names a provider through one Service Provider Code, not a subscriber’s number [ATIS-1000080 section 6.3.4.1]. Because the standard leaves the provider’s vetting of the delegate’s customer out of scope [ATIS-1000092 section 5.3.3.1], the organization check still applies.

Not accepted as proof of control:

Evidence Why not
SHAKEN “A” attestation on a call from the number The attest claim [RFC8588] reflects the signing provider’s own verified association between its customer and the number, under each provider’s own policy [ATIS-1000074 section 5.2.4]
Carrier invoices, letters of authorization Toll-free ports rely on an LOA stored in Somos’s Resp Org Change system [SOMOS-HIST], but Emissar cannot check one against carrier records; supporting evidence only
Number on the organization’s website; RespOrg lookup; 10DLC registration Publication, not control; the RespOrg lookup names the managing RespOrg, not the subscriber [SOMOS-RESPORG]; The Campaign Registry’s pages describe brand vetting, not number ownership [TCR]

7.5 Brand methods

Preconditions: the organization check (7.6) has passed; the card lists the brand with its country (7.2); v0.1 accepts US and CA only.

Method Evidence Registry checks
trademark-registration A registered (not pending, cancelled or expired) mark in the brand country’s office: USPTO or CIPO The owner of record is the verified organization, its parent, subsidiary or affiliate, or a licensor that authorized the claim in writing; the mark’s word element gives the claimed key (5.3)
mark-certificate A Verified Mark Certificate for a registered mark, issued under the BIMI Group’s Mark Certificate requirements [MC-REQ] Chain and validity (at most 398 days [BIMI-FAQ]); subject is the verified organization; the registration is in the brand’s country; its word element gives the key
  1. Owner matching follows the Mark Certificate requirements, under which the issuing authority confirms that the owner of record is the vetted organization or its parent, subsidiary or affiliate, or else obtains a license and authorization letter [MC-REQ section 3.2.17.1].
  2. Programmatic checks, as of 2026-09-26. USPTO’s TSDR API answers 401 without a key [USPTO-TSDR]; keys now need a USPTO.gov account with multi-factor authentication and ID.me identity verification [USPTO-ODP-REG], and the Open Data Portal lists no trademark metadata API [USPTO-ODP-RL]. CIPO offers web search and bulk data (weekly XML, quarterly CSV) but no API was found [CIPO-SEARCH] [CIPO-DATA], so checks run against a weekly mirror. The WIPO Global Brand Database forbids automated queries [WIPO-GBD-TERMS] and is not used.
  3. Common Mark Certificates are not accepted: a prior-use CMC shows a logo on a verified domain for at least 12 months [MC-REQ section 3.2.16.1], which is evidence of use, not of rights in a name.
  4. Several organizations may hold one key in one country; each gets a record and lookups return all of them. A holder known by several spellings claims each one with evidence for it.

7.6 Organization verification

Required for verified-organization. The registry:

  1. Finds the organization, active, in an authoritative register: Corporations Canada or a provincial register, a US state register, or GLEIF. The GLEIF API is free and its data CC0 [GLEIF-API]; an LEI record gives legal name, jurisdiction and registration authority id, but has no domain or brand field and does not authenticate whoever asks [GLEIF-LEI].
  2. Links the claimant to it: the account MUST hold a verified-control record for a domain the organization demonstrably uses (for example one named in its register filing or trademark record) and MUST submit an officer-signed authorization, reviewed by Emissar staff.
  3. Publishes organization {name, country, registry {authority, id}} with business-registry or lei evidence.

7.7 Re-verification and expiry

Record Re-check expiresAt
observed Weekly re-check and monthly full crawls (https://emissar.ai/bot) Last observation + 35 days
Card listing (all claims) Card re-fetched weekly Suspended after 14 days unlisted
dns-txt, card-token Every 30 days (card-token by the weekly re-fetch); two consecutive failures suspend Last success + 90 days
sms-otp, voice-otp New code every 90 days; US numbers checked against the Reassigned Numbers Database every 30 days (11.3) Last success + 90 days; 45 days for US numbers without that check
stir-delegate-cert Validity and revocation weekly; new challenge every 90 days Earlier of certificate expiry and last success + 90 days
Organization Register status every 90 days; full review yearly Last full review + 365 days
trademark-registration, mark-certificate Office status every 90 days; certificate validity weekly Last success + 365 days, and never past certificate expiry

A record’s expiresAt is the earliest expiry among its checks. Holders are notified 30 and 7 days ahead.

7.8 Changes of holder

  1. A claim on an identifier another account holds does not take effect immediately. The registry notifies the holder, suspends the record (10.2) and waits 7 days; if the holder does not re-prove control, the new record takes effect.
  2. If both parties prove control, the identifier stays suspended until dispute review (section 10) decides.
  3. A holder changing its own cardUrl authenticates in its account, the new card must list the identifier, and all account contacts are notified. A holder can delete a record at any time; edge caches are purged.

8. Lookup API

The lookup API is public, anonymous, read-only, and served over HTTPS only. The OpenAPI 3.1 document resolve-v0.1.yaml is normative for paths, status codes and headers; the JSON Schema is normative for bodies.

8.1 Endpoints

Request Identifier
GET /v0/tel/{number} E.164 number, for example /v0/tel/+15195550142
GET /v0/domain/{domain} Domain, for example /v0/domain/opensea.io
GET /v0/brand/{country}/{name} Brand key in one country, for example /v0/brand/CA/exampletelecom

HEAD is supported. + is a literal character in a URL path; %2B is also accepted. There is no search, list or bulk endpoint (sections 11, 12).

8.2 Normalization and redirects

The registry MUST normalize the path identifier with section 5. Then:

  • If normalization fails: 400 (section 8.6).
  • If the canonical path differs from the request path: 308 Permanent Redirect with Location set to the canonical path and Cache-Control: public, max-age=86400. Example: /v0/domain/OpenSea.IO redirects to /v0/domain/opensea.io.
  • Otherwise: answer (sections 8.3 and 8.5).

Redirecting keeps exactly one cache key per identifier.

8.3 Positive answers

Status 200, Content-Type: application/json, body per $defs/LookupResponse:

{
  "resolve": "0.1",
  "query": { "type": "domain", "value": "opensea.io" },
  "answer": "found",
  "records": [ { "id": "rsv_nup2w2no4sqhpjxxnxn2", "...": "one record per section 6" } ]
}

records holds one record for tel and domain and one or more for brand, strongest level first, then newest lastVerifiedAt. The body has no timestamps of its own, so identical answers give identical ETags.

8.4 Client processing

A client that receives a positive answer:

  1. MUST fetch the card from cardUrl over HTTPS and validate it as A2A requires, including signatures when present (A2A section 8.4.3).
  2. For a claimed record, MUST check that the card’s Resolve extension lists the queried identifier (7.2), and SHOULD treat the answer as negative if not; this catches stale records.
  3. MUST read an observed record as “this domain publishes this card”, nothing more.
  4. MUST NOT act on a disputed record without the person’s confirmation.
  5. MUST NOT choose among several brand records without further evidence, such as a domain or number the person already holds for the business, or the person’s own choice.
  6. SHOULD show the person the level and any organization.name before a consequential action.
  7. If the card fetch fails, SHOULD fall back to the normal channel.

8.5 Negative answers

When the registry holds no current record, it answers 404 with Content-Type: application/problem+json [RFC9457]:

{
  "type": "https://emissar.ai/specs/resolve/v0.1#not-found",
  "title": "No record for this identifier",
  "status": 404,
  "resolve": "0.1",
  "answer": "not-found",
  "query": { "type": "tel", "value": "+15195550199" }
}

A negative answer is a normal result, identical whether the identifier was never registered, expired, suspended or removed, so it reveals no history. It carries Cache-Control: public, max-age=300, so a new record is visible within five minutes.

8.6 Errors

Status type suffix When Caching
400 #invalid-identifier Section 5 rejects the identifier; detail says why public, max-age=3600
405 none (no body) Method other than GET or HEAD; Allow: GET, HEAD not cached
429 #rate-limited Client over quota (section 8.8) no-store
503 #unavailable Temporary failure; Retry-After when known no-store

Clients MUST treat 5xx and network failures like a negative answer for the current attempt and MUST NOT cache them.

8.7 Caching and ETags

  • Every 200 response MUST carry a strong ETag [RFC9110 section 8.8.3]. The reference implementation uses the first 27 characters of the base64url SHA-256 of the RFC 8785 [RFC8785] canonical form of the body.
  • Every 200 response MUST carry Cache-Control: public, max-age=N [RFC9111 section 5.2.2.1], where N is at most 3600 and never extends past the earliest expiresAt among the returned records.
  • A request whose If-None-Match matches the current ETag gets 304 with no content, carrying the same ETag and Cache-Control a 200 would have [RFC9110 sections 13.1.2 and 15.4.5].
  • The registry SHOULD purge edge-cached answers when a record changes, so suspensions take effect before max-age runs out.
  • Clients SHOULD cache answers per these headers and MUST NOT use a cached record after its expiresAt.

8.8 Rate limiting

  • The registry MUST rate-limit lookups per client. The v0.1 default is 60 lookups per 60 seconds per IPv4 address or IPv6 /64, counted at the edge before any cache. The limit applies to all statuses, including 404, because negative answers are what an enumerator collects (section 12).
  • Over the limit, the registry answers 429 [RFC6585 section 4] with a problem body, Retry-After in seconds [RFC9110 section 10.2.3] and Cache-Control: no-store (RFC 6585 forbids caches from storing 429 responses).
  • The registry SHOULD send RateLimit-Policy and RateLimit fields from the RateLimit header fields draft [RATELIMIT], for example "default";q=60;w=60 and "default";r=12;t=41. The draft is not an RFC, so these fields are informative; Retry-After is the normative signal.
  • Clients MUST back off on 429 and honor Retry-After.
  • Keyed tiers with higher limits are not part of v0.1.

8.9 Transport and CORS

  • HTTPS only. The registry MUST NOT answer lookups over plain HTTP; a plain HTTP request gets a redirect with no answer body.
  • Every response MUST carry Access-Control-Allow-Origin: * and Access-Control-Expose-Headers: ETag, Retry-After, RateLimit, RateLimit-Policy. Lookups are public, like DNS, and browser-based agents need them. OPTIONS preflight MUST allow the If-None-Match request header.
  • Responses MUST carry X-Content-Type-Options: nosniff.

9. Seeding from crawled public Agent Cards

The first public version is read-only and seeded from Agent Cards that companies already publish. The source is Emissar’s agent directory (https://emissar.ai/directory), built from the results of EmissarBot, Emissar’s crawler (https://emissar.ai/bot). The crawler requests https://{domain}/.well-known/agent-card.json once per crawl (then /.well-known/agent.json if the first is not a card), after honoring robots.txt and the opt-out list. An observation proves only that, at fetch time, an HTTPS server with a valid certificate for the host served a document with Agent Card structure at that path.

9.1 Seeding rules

For each directory entry, the seeder:

  1. MUST use the entry’s domain as the identifier, skipping it unless already canonical (5.2).
  2. MUST use the entry’s card.url (the final URL after redirects) as cardUrl, skipping the entry when that URL is missing, not HTTPS, or on a host that is neither the domain nor a subdomain of it. A redirect from activecampaign.com to www.activecampaign.com is kept; one to another registrable domain is not.
  3. MUST set source: "crawl", level observed, method crawl-well-known, lastVerifiedAt and updatedAt to the entry’s lastSeen, expiresAt to lastSeen + 35 days, and one evidence item {kind: "crawl", ref: <crawl id>, checkedAt}.
  4. MUST NOT create tel or brand records, even when a card mentions a phone number or its provider.organization names a company: anyone can write any organization name into a card.
  5. MUST NOT copy the card’s name, description, provider or skills into the record, and MUST NOT mark a seeded record verified or upgrade it without a claim.
  6. MUST apply the directory’s exclusions: the crawler’s opt-out list and the directory’s editorial exclusion list, with subdomains and www. forms (the directory already applies both). Whether infrastructure should also apply the editorial exclusions is open question 5.
  7. SHOULD include entries the directory marks noindex; that flag concerns search indexing of thin or duplicate pages, not whether the mapping is true.

Weekly re-check and monthly full crawls refresh lastVerifiedAt; a domain whose card disappears drops out within 35 days of its last successful fetch.

9.2 Purpose and supersession

For a domain, an observed record adds little beyond what the well-known URI gives directly. Its value is that v0 answers real queries with real data, the API, caches and limits are exercised before claims open, and each business has a record it can later claim. When a domain claim succeeds, the claimed record replaces the observed one; if the claim later lapses, the observed record may return on the next crawl. Operators can remove an observed record through the directory removal channel, honored within seven days, as /bot and /trust already promise.

10. Disputes and takedown

10.1 Who can raise what

Case Raised by First action
Misroute: a record for my number, domain or brand points to someone else’s card The party that says it controls the identifier Suspend within 24 hours when the report is credible (section 10.3)
Unwanted listing: my card is listed for an identifier I do not use The card’s operator Suspend; the claimed record already requires the card to list the identifier, so removing it from the card also ends the record
Brand conflict: we also hold rights in this name Another organization No suspension. Review the claimant’s evidence; if it qualifies, add its record to the candidate set
Abuse: the endpoint is used for fraud Anyone Suspend when corroborated; refer to Verify’s abuse process once it exists
Opt-out of an observed record Domain operator Remove within 7 days
Personal data The person concerned Remove within 7 days; within 24 hours if it exposes a personal phone number
Legal order Authority or counsel Per counsel

Reports come in through the site’s contact form (topics “security” and “privacy”); Emissar publishes no email addresses, and Resolve adds none.

10.2 Principles

  1. Suspension is the safe default: it costs the holder some speed but misroutes no one.
  2. Control decides telephone and domain disputes: the party that proves control now, with a method at least as strong as the one behind the record, wins. Emissar does not judge who “should” own a number or domain.
  3. Registries of record decide brand disputes. Emissar does not adjudicate infringement; where two organizations hold qualifying registrations, both records stand, and court or office rulings are followed.
  4. Dispute files are private. The public record shows only status: "disputed" or, when suspended, nothing.

10.3 Process and timelines

Step Target
Acknowledge the report 2 business days
Suspend on a credible misroute or corroborated abuse report 24 hours
Notify the holder through its account, and give it the chance to re-prove control Holder has 7 days
Decide 14 days from the report
One appeal, reviewed by someone other than the first decider 14 days

A record reported as misrouting stays suspended during review; in other disputes it stays active or becomes disputed at the reviewer’s discretion. Every suspension, reinstatement and removal is logged with reasons for the record’s lifetime plus 24 months. Emissar SHOULD publish aggregate dispute and takedown counts once claims open.

11. Security considerations: abuse, spoofing, number recycling, SIM swap

Every mitigation below can end in suspension, and a suspended identifier gives the same negative answer as an unregistered one (8.5). The worst case of a Resolve failure is therefore today’s behavior: the client uses the business’s published channels.

11.1 Threats and mitigations

Threat Example Mitigations
False telephone claim Attacker takes over a business’s line by SIM swap or unauthorized port-out and passes a one-time code Organization check before any code (7.4); transfer hold with notice to the holder (7.8); SIM-change and port signals where available; stir-delegate-cert preferred; 90-day expiry; 24-hour suspension on report (10.3)
Number recycling A number the business gave up is reassigned, and its record still points to the old business Reassigned Numbers Database checks and short expiry (11.3); weekly card-listing checks; holders MUST de-list numbers they give up
Domain takeover A new registrant, whoever controls DNS or hosting, or a routing attack near the registry passes a check 30-day re-checks, transfer hold (7.8), multi-perspective DNSSEC-validated checks (7.3)
Lookalikes examp1e.com, an IDN mixing scripts, a confusable brand UTS #39 skeleton screening at claim time (5.3); display shown beside the A-label; clients show level and organization
Legitimate control, illegitimate purpose A scammer verifies its own number and prints it on fake invoices Resolve proves control, not honesty (principle 2). Clients take identifiers from trustworthy sources and show the organization; abuse reports suspend (10.1); Verify adds reputation
Spoofed caller ID Not applicable Resolve never takes the number of an incoming call as input or proof; the client starts from a number it holds. Caller-ID authentication (STIR/SHAKEN [RFC8224] [RFC8225] [FCC-CALLAUTH]) is a carrier mechanism Resolve neither uses nor replaces
Enumeration A script queries a number range to learn which businesses have agents Rate limits that count 404s (8.8); no bulk tel listing (12.1); scan monitoring. WebFinger’s authors flagged the same harvesting risk and named IP rate limiting [RFC7033 section 9.3]
Paid-message abuse The claim flow is used to send codes to premium or foreign numbers (“SMS pumping”) NANP only; codes only after the organization check; per-account, per-number and per-prefix caps; alerts on volume (7.4)
Toll-free texting hijack A third party text-enables a toll-free number and receives its texts [SOMOS-TSS] No sms-otp for toll-free numbers (7.4)
Withdrawn consent, dead endpoint The card no longer lists the identifier Weekly re-fetch and suspension (7.2); client-side listing check (8.4)
Impersonation, insider error, floods Fake answers; a wrong manual change; lookup floods HTTPS only (8.9; signed answers are open question 9); every change logged with actor and reason, and manual verified-organization changes SHOULD need a second reviewer; edge caching and rate limits

11.2 SIM swap and port-out fraud

A one-time code proves only that the claimant received a message or call on the number at that moment; whoever controls the line then, by legitimate transfer, unauthorized port-out or SIM swap, passes. NIST therefore classes such codes as restricted, requires an alternative to be offered, and recommends checking device-swap, SIM-change and porting signals first [NIST-63B sections 3.1.3.3, 3.2.9].

Carrier protections cannot be assumed:

  • US: FCC 23-95 (November 2023) requires wireless providers to use secure authentication before a SIM change or port-out and adds customer notices and account locks [FCC-23-95]. A July 2024 Wireline Competition Bureau order waived compliance until OMB completes its review and a compliance date is announced [DA-24-649]; the eCFR text current to 2026-09-22 still says compliance is not required until that date is published [ECFR-52-37].
  • Canada: in July 2026 the CRTC approved porting-process wording under which a new provider does not provision a number until the old provider confirms the port, which it describes as helping to safeguard against fraud [CRTC-2026-185]. No binding CRTC rule on SIM swaps was found.

Resolve relies on its own defenses: the organization check before any code, the transfer hold, certificate-based proof where it exists, and expiry.

11.3 Number recycling

Disconnected numbers are reassigned after an aging period: in the US, 45 to 365 days for business numbers and 45 to 90 days for residential [CFR52.15]. In Canada, a dissent in a 2026 CRTC decision cites the assignment guideline’s 3 to 12 months for business numbers and 1 to 3 months for residential and wireless, and the majority noted that numbers disconnected for six weeks may already have been reassigned [CRTC-2026-211].

For US numbers, the FCC’s Reassigned Numbers Database, run by SomosGov for registered, paying callers and caller agents, answers whether a number has been permanently disconnected since a given date (yes, no, or no data) [RND]. The registry SHOULD query it every 30 days with the record’s lastVerifiedAt and suspend on “yes”. Until Emissar can subscribe (open question 10), US telephone records expire after 45 days, the shortest US business aging period.

This draft found no Canadian equivalent. When the CRTC made Do Not Call List registrations permanent in 2014, it encouraged the industry to keep re-examining a mechanism for removing disconnected and reassigned numbers rather than requiring one [CRTC-2014-341]. Canadian records rely on 90-day re-verification, which matches the shortest business aging period, and the weekly card-listing check. A business on a wireless number is the gap, since those can age in a month; a 30-day cadence for Canada is part of open question 10.

12. Privacy considerations

12.1 What is public

Data Public? Why
Identifier, card URL, status, level, method, verification times, expiry Yes, per lookup A client cannot decide without them
Evidence summaries (crawl id, DNS owner name, trademark or entity numbers) Yes They are references to public registers, and they let anyone recheck the registry’s work
Organization legal name and register id Yes, at verified-organization only Business identity is the point of that level
Claimant account, contact person, documents, one-time codes, dispute files Never Not needed by clients
Query logs Never Section 12.3

No bulk listing of tel records is offered, even though each is a published business number. Observed domain records mirror the public directory.

12.2 Personal numbers versus business numbers

A person’s telephone number is personal information. A public record linking it to an agent would disclose that the person uses that agent and let anyone test numbers for membership; hashing does not help, because every possible number can be hashed. So in v0.1:

  • tel claims come only from verified organizations, for numbers they publish as their own; the card’s Resolve extension (7.2) is such a publication.
  • Numbers used by individuals, including sole proprietors’ personal numbers, are out of scope: the registry MUST refuse such claims and remove any record later found to be personal (10.1).
  • Seeding never creates tel records.

Personal agents reachable by personal number would need restricted lookups (open question 3).

12.3 What lookups reveal

A lookup tells the registry which business a person’s agent is about to contact, which is sensitive for a clinic, lender or lawyer. Therefore:

  • The registry MUST NOT store the queried identifier together with the client’s IP address or any client identifier.
  • Rate-limit state keyed by IP address MUST be kept only for the length of the window.
  • Operational metrics are aggregate counts per identifier type, status and hour, with no identifiers.
  • Retention periods for anything else the registry stores (claims, evidence, disputes) MUST be stated in Emissar’s privacy policy and enforced in code before launch, and the telephony provider used for one-time codes MUST be listed as a subprocessor in Emissar’s trust center and privacy policy before it handles any data.

Client caching also reduces what reaches the registry.

Emissar operates from Canada and would serve Canadian and US users first. This section states design intent, not legal conclusions; legal review is pending.

13. Operational considerations

Topic Plan
Resources A dedicated service and database, separate from Emissar’s website. The seed job reads EmissarBot’s crawl results read-only
Host resolve.emissar.ai (open question 2)
Caching Edge cache in front of the registry, keyed by canonical path; purge by URL on record change
Rate limiting An edge rate-limit rule plus a per-client limiter in the registry (section 8.8)
Card checks A scheduled job re-fetches card URLs of claimed records weekly with the same SSRF controls and user agent as Emissar’s public tools, and suspends records whose card no longer lists the identifier for 14 days
Re-verification Scheduled jobs per section 7.7; expiry is checked on every lookup, so expired records drop out automatically
Availability A Resolve outage degrades clients to the phone and web channels they use today. Target: answers served from cache even when the origin is down
Monitoring Counts of 200/404/429 per identifier type, cache hit ratio, re-verification failures, suspensions
Versioning Path prefix /v0/; body field resolve: "0.1". Incompatible changes get a new prefix; additive fields do not
Costs One-time codes cost money per message or call and attract fraud (11.1); claims may need a fee (open question 6)

14. Open questions

# Question Default in this draft
1 Publish this draft for comment? Settled: published on 2026-10-05
2 Host for the API: resolve.emissar.ai or a path on emissar.ai Settled: resolve.emissar.ai
3 Personal numbers: ever in scope? They would need lookups restricted to parties the person authorized Out of scope (12.2)
4 Brands in the first claims release, or later? USPTO keys need ID.me, CIPO has only bulk data, and brand disputes cost the most staff time Recommend domain and tel claims first
5 Should Resolve, as infrastructure, apply the directory’s editorial exclusions (gambling, adult) or only opt-outs? Same exclusions as the directory (9.1)
6 Pricing: fee per claim to cover one-time-code costs; keyed lookup tiers and per-call pricing Free anonymous lookups at 60/min; claims unpriced
7 Telephone numbers outside +1, and brands outside US and Canada NANP and US/CA only
8 Access to the USPTO API (its keys need a person’s ID.me verification) and a mirror of CIPO’s bulk data Not started
9 Signed answers (for example JWS over each record) so caches and mirrors can be verified HTTPS only in v0.1
10 Reassigned Numbers Database: is Emissar eligible to subscribe, and at what cost? Re-verify Canadian numbers every 30 days instead of 90? 45-day expiry for US numbers until subscribed; 90 days in Canada
11 Telephony provider for one-time codes, and whether it exposes SIM-change and port signals. It is a subprocessor: trust center and privacy policy first None chosen
12 Who reviews claims and disputes? Claims closed until staffed
13 Canadian STIR/SHAKEN delegate certificates: accept a Canadian trust list as well as the US one? Not researched for this draft US trust list only
14 What Emissar’s public Resolve page says about the registry’s status Settled: it changes only when a phase ships
15 Extension URI https://emissar.ai/ext/resolve/v1 (parallel to Mandate’s) and problem type URIs under https://emissar.ai/specs/resolve/v0.1 Settled: both resolve to this document

15. References

All sources were accessed on 2026-09-26. Where a page carries a version or date, it is given.

15.1 Normative references

Tag Reference
[A2A] A2A Protocol Specification, main branch (header: latest released version 1.0.0; file last changed 2026-08-28), sections 4.4, 8 and 14.3. https://github.com/a2aproject/A2A/blob/main/docs/specification.md
[E164] ITU-T Recommendation E.164 (02/2026), The international public telecommunication numbering plan, approved 2026-02-13, in force. https://www.itu.int/ITU-T/recommendations/rec.aspx?rec=16273
[ISO3166] ISO 3166-1, Codes for the representation of names of countries, alpha-2 codes. https://www.iso.org/iso-3166-country-codes.html
[RFC1035] Domain Names: Implementation and Specification. https://www.rfc-editor.org/rfc/rfc1035
[RFC2119] Key words for use in RFCs to Indicate Requirement Levels (BCP 14). https://www.rfc-editor.org/rfc/rfc2119
[RFC3339] Date and Time on the Internet: Timestamps. https://www.rfc-editor.org/rfc/rfc3339
[RFC3966] The tel URI for Telephone Numbers. https://www.rfc-editor.org/rfc/rfc3966
[RFC4343] DNS Case Insensitivity Clarification. https://www.rfc-editor.org/rfc/rfc4343
[RFC5890] IDNA: Definitions and Document Framework. https://www.rfc-editor.org/rfc/rfc5890
[RFC5891] IDNA: Protocol. https://www.rfc-editor.org/rfc/rfc5891
[RFC6585] Additional HTTP Status Codes (section 4, 429). https://www.rfc-editor.org/rfc/rfc6585
[RFC8174] Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words (BCP 14). https://www.rfc-editor.org/rfc/rfc8174
[RFC8615] Well-Known Uniform Resource Identifiers. https://www.rfc-editor.org/rfc/rfc8615
[RFC8785] JSON Canonicalization Scheme (JCS). https://www.rfc-editor.org/rfc/rfc8785
[RFC9110] HTTP Semantics (STD 97). https://www.rfc-editor.org/rfc/rfc9110
[RFC9111] HTTP Caching (STD 98). https://www.rfc-editor.org/rfc/rfc9111
[RFC9457] Problem Details for HTTP APIs. https://www.rfc-editor.org/rfc/rfc9457
[UAX15] Unicode Standard Annex #15, Unicode Normalization Forms (revision 58). https://www.unicode.org/reports/tr15/
[UNICODE-CF] The Unicode Standard 18.0.0, chapter 3, section 3.13 (default case folding, toNFKC_Casefold). https://www.unicode.org/versions/latest/core-spec/chapter-3/
[UTS39] Unicode Technical Standard #39, Unicode Security Mechanisms (revision 34). https://www.unicode.org/reports/tr39/
[UTS46] Unicode Technical Standard #46, Unicode IDNA Compatibility Processing (revision 36). https://www.unicode.org/reports/tr46/

15.2 Informative references

Tag Reference
[A2A-DISC] A2A project, Agent Discovery in A2A. https://github.com/a2aproject/A2A/blob/main/docs/topics/agent-discovery.md
[A2A-741] A2A discussion #741, “Agent Registry - Proposal” (closed 2026-08-20). https://github.com/a2aproject/A2A/discussions/741
[A2A-1295] A2A issue #1295, “[Proposal]: New Repo: a2a-registry” (closed 2026-04-07). https://github.com/a2aproject/A2A/issues/1295
[ARD] Agentic Resource Discovery specification v0.91 (proposal, 2026-08-26). https://github.com/ards-project/ard-spec/blob/main/spec/ard.md
[AGNTCY-DIR] AGNTCY Agent Directory (v1.7.1) and its trust model, including name verification. https://github.com/agntcy/dir
[ATIS-1000074] ATIS-1000074.v003, Signature-based Handling of Asserted information using toKENs (SHAKEN), joint standard, approved 2022-08-16, section 5.2.4. https://access.atis.org/apps/group_public/download.php/67436/ATIS-1000074.v003.pdf
[ATIS-1000080] ATIS-1000080.v006, SHAKEN: Governance Model and Certificate Management, approved 2025-09-15, section 6.3.4.1. https://cdn.atis.org/sti-ga.atis.org/2026/03/31143346/ATIS-1000080.v006.pdf
[ATIS-1000092] ATIS-1000092.v002, SHAKEN: Delegate Certificates, approved 2025-06-01, section 5.3.3.1. https://access.atis.org/higherlogic/ws/public/download/81651/ATIS-1000092.v002
[ATIS-1000093] ATIS-1000093, Toll-Free Numbers in the SHAKEN Framework, approved 2020-11-12, section 5.3. https://access.atis.org/apps/group_public/download.php/56853/ATIS-1000093.pdf
[BIMI-FAQ] BIMI Group, FAQs for senders and ESPs (certificate validity). https://bimigroup.org/faqs-for-senders-esps/
[CABF-BR] CA/Browser Forum, TLS Baseline Requirements v2.3.0 (2026-09-07), sections 3.2.2.4.7, 3.2.2.4.22 and 3.2.2.9. https://github.com/cabforum/servercert/blob/main/docs/BR.md
[CFR52.7] 47 CFR 52.7, numbering definitions (NXX-NXX-XXXX). https://www.ecfr.gov/current/title-47/section-52.7
[CFR52.15] 47 CFR 52.15(f)(1)(ii), aging of disconnected numbers. https://www.ecfr.gov/current/title-47/section-52.15
[CIPO-DATA] CIPO, trademark data: applications and registrations (weekly XML). https://ised-isde.canada.ca/site/canadian-intellectual-property-office/en/trademark-data-applications-and-registrations-xml-png
[CIPO-SEARCH] CIPO, Canadian Trademarks Database search. https://ised-isde.canada.ca/cipo/trademark-search/srch
[CRTC-2014-341] Compliance and Enforcement Regulatory Policy CRTC 2014-341, Permanent number registration (National DNCL), 2014-06-25. https://crtc.gc.ca/eng/archive/2014/2014-341.htm
[CRTC-2026-185] Telecom Decision CRTC 2026-185, switch provisioning and NPAC subscription creation (2026-07-24). https://crtc.gc.ca/eng/archive/2026/2026-185.htm
[CRTC-2026-211] Telecom Decision CRTC 2026-211, Ztar Mobile Canada v. Rogers, with dissent (2026-08-18). https://crtc.gc.ca/eng/archive/2026/2026-211.htm
[DA-24-649] FCC Wireline Competition Bureau, Order DA 24-649 (2024-07-05). https://docs.fcc.gov/public/attachments/DA-24-649A1.txt
[DCV-DRAFT] Domain Control Validation using DNS, draft-ietf-dnsop-domain-verification-techniques-13 (2026-06-22, work in progress). https://datatracker.ietf.org/doc/draft-ietf-dnsop-domain-verification-techniques/
[ECFR-52-37] 47 CFR 52.37, port-out authentication (compliance date pending). https://www.ecfr.gov/current/title-47/section-52.37
[FCC-23-95] FCC 23-95, Protecting Consumers from SIM-Swap and Port-Out Fraud, 88 FR 85794 (2023-12-08). https://www.federalregister.gov/documents/full_text/text/2023/12/08/2023-26338.txt
[FCC-CALLAUTH] FCC, Combating Spoofed Robocalls with Caller ID Authentication. https://www.fcc.gov/call-authentication
[GLEIF-API] GLEIF API documentation (60 requests per minute). https://api.gleif.org/docs
[GLEIF-LEI] GLEIF, The Legal Entity Identifier. https://www.gleif.org/en/organizational-identity/lei-vlei/the-legal-entity-identifier-lei
[ITU-ENUM] ITU-T, ENUM delegations approved. https://www.itu.int/en/ITU-T/inr/enum/Pages/delegations.aspx
[MC-REQ] BIMI Group, Minimum Security Requirements for Issuance of Mark Certificates, version 1.8 (2026-06-11), sections 3.2.16.1 and 3.2.17.1. https://bimigroup.org/resources/VMC_Requirements_latest.pdf
[MCP-REG] MCP Registry repository, README and docs (about, authentication). https://github.com/modelcontextprotocol/registry
[NANDA-IDX] NANDA Index v2 repository. https://github.com/projnanda/nanda-index-v2
[NANDA-PAPER] Raskar et al., “Beyond DNS: Unlocking the Internet of AI Agents via the NANDA Index and Verified AgentFacts”, arXiv:2507.14263 (2025-07-18). https://arxiv.org/abs/2507.14263
[NANPA-555] NANPA, 555 Line Numbers (555-0100 to 555-0199 reserved as fictitious). https://www.nanpa.com/numbering/555-line-numbers
[NIST-63B] NIST SP 800-63B-4, Digital Identity Guidelines: Authentication and Authenticator Management (final, July 2025), sections 3.1.3.2, 3.1.3.3 and 3.2.9. https://pages.nist.gov/800-63-4/sp800-63b.html
[OASF] AGNTCY Open Agentic Schema Framework (v1.1.0). https://github.com/agntcy/oasf
[PSL] Public Suffix List. https://publicsuffix.org/
[RATELIMIT] RateLimit header fields for HTTP, draft-ietf-httpapi-ratelimit-headers-11 (2026-05-23, work in progress). https://datatracker.ietf.org/doc/draft-ietf-httpapi-ratelimit-headers/
[RFC6116] The E.164 to URI DDDS Application (ENUM). https://www.rfc-editor.org/rfc/rfc6116
[RFC7033] WebFinger. https://www.rfc-editor.org/rfc/rfc7033
[RFC8224] Authenticated Identity Management in SIP. https://www.rfc-editor.org/rfc/rfc8224
[RFC8225] PASSporT: Personal Assertion Token. https://www.rfc-editor.org/rfc/rfc8225
[RFC8226] Secure Telephone Identity Credentials: Certificates (TNAuthList). https://www.rfc-editor.org/rfc/rfc8226
[RFC8555] Automatic Certificate Management Environment (ACME). https://www.rfc-editor.org/rfc/rfc8555
[RFC8588] PASSporT Extension for SHAKEN (attest, origid). https://www.rfc-editor.org/rfc/rfc8588
[RFC9060] STIR Certificate Delegation. https://www.rfc-editor.org/rfc/rfc9060
[RIPE-ENUM] RIPE NCC, ENUM (operation of e164.arpa). https://www.ripe.net/manage-ips-and-asns/dns/enum/
[RND] Reassigned Numbers Database, About. https://www.reassigned.us/about
[SOMOS-HIST] Somos, TFNRegistry: A History of Toll-Free Numbers (Resp Org Change system and LOAs). https://support.somos.com/hc/en-us/articles/6876889063956-TFNRegistry-A-History-of-Toll-Free-Numbers
[SOMOS-RESPORG] Somos, “I have a Toll-Free Number. Who is my Resp Org?”. https://support.somos.com/hc/en-us/articles/7878050695444-I-have-a-Toll-Free-Number-Who-is-my-Resp-Org
[SOMOS-TSS] Somos, TSS Registry: the Resp Org’s role (text-enablement). https://www.somos.com/TSSRespOrgRole
[TCR] The Campaign Registry. https://www.campaignregistry.com/
[USPTO-ODP-REG] USPTO Open Data Portal, universal registration (MFA and ID.me for API keys). https://data.uspto.gov/support/universal-registration
[USPTO-ODP-RL] USPTO Open Data Portal, API rate limits. https://data.uspto.gov/apis/api-rate-limits
[USPTO-TSDR] USPTO TSDR API (answers 401 without an API key). https://tsdrapi.uspto.gov/
[WIPO-GBD-TERMS] WIPO Global Brand Database, terms of use (November 2022), section 2.1. https://www.wipo.int/en/web/global-brand-database/terms_and_conditions

Appendix A. Example run output

Real output, captured on 2026-10-05 with Node v24.13.0 and Python 3.14.3, jsonschema 4.26.0, PyYAML 6.0.3, openapi-spec-validator 0.9.0, rfc3339-validator 0.1.4, by running the published files from their folder. The three observed records come from directory-sample.json: three entries of the directory export of crawl full-20260926-39db43. The three claimed records are Illustrative: they use reserved example identifiers and are not real claims. The demo rate limit is 6 lookups per 60 seconds so that the walkthrough reaches it; the specified default is 60.

A.1 Walkthrough

$ node resolve-example.mjs
Emissar Resolve v0.1 example. Clock fixed at 2026-09-26T23:00:00.000Z.

== 1. Normalization (section 5) ==
  tel    "+1 (519) 555-0142"                -> +15195550142 [nanp-geographic]
  tel    "tel:+1-519-555-0142"              -> +15195550142 [nanp-geographic]
  tel    "+1 800 555 0199"                  -> +18005550199 [nanp-toll-free]
  tel    "519-555-0142"                     -> REJECT: no leading '+' and country code; convert national numbers before lookup
  tel    "+1 800 FLOWERS"                   -> REJECT: letters are not allowed (vanity numbers must be converted to digits)
  tel    "+1 (019) 555-0142"                -> REJECT: NANP area code must start with 2-9
  tel    "tel:+1-519-555-0142;ext=22"       -> REJECT: tel URI parameters (extension, phone-context) are not E.164
  tel    "+44 20 0000 0000 0000"            -> REJECT: more than 15 digits (E.164 maximum)
  domain "OpenSea.IO."                      -> opensea.io
  domain "Bücher.example"                   -> xn--bcher-kva.example display=bücher.example [special-use]
  domain "https://opensea.io/"              -> REJECT: a domain only: no scheme, path, port or user part
  domain "localhost"                        -> REJECT: single-label names are not allowed
  domain "-bad-.example.com"                -> REJECT: labels must be 1-63 letters, digits or hyphens, not starting or ending with a hyphen
  brand  "EXAMPLE TELECOM, Inc. / ca"       -> exampletelecom (CA)
  brand  "Example-Telecom Ltée / CA"        -> exampletelecom (CA)
  brand  "Straße Co. / DE"                  -> strasse (DE)
  brand  "Inc. / US"                        -> inc (US)

== 2. Seeding observed records from the directory export (section 9) ==
  source: directory-sample.json (crawl full-20260926-39db43, status complete, exported 2026-09-27T15:08:40.361Z, 3 entries)
  opensea.io               card says name="OpenSea", organization="OpenSea" -> observed record rsv_nup2w2no4sqhpjxxnxn2, card https://opensea.io/.well-known/agent-card.json, expires 2026-10-31T21:18:41.132Z
  activecampaign.com       card says name="ActiveCampaign", organization="ActiveCampaign, LLC" -> observed record rsv_xyb77jznf3d2ev7ipuif, card https://www.activecampaign.com/.well-known/agent-card.json, expires 2026-10-31T22:08:30.866Z
  modelcontextprotocol.io  card says name="Model Context Protocol", organization="Model Context Protocol" -> observed record rsv_3ovtoti4gpiox25taidd, card https://modelcontextprotocol.io/.well-known/agent-card.json, expires 2026-10-31T22:18:49.521Z
  (No tel or brand record is created from a card, and the card's self-described name and organization are not copied.)

== 3. Illustrative claimed records (reserved example identifiers; not real claims) ==
  domain:agent.example.com   verified-control via dns-txt -> https://agent.example.com/.well-known/agent-card.json
  tel:+15195550142           verified-organization via voice-otp -> https://agent.example.com/.well-known/agent-card.json
  brand:CA:exampletelecom    verified-organization via trademark-registration -> https://agent.example.com/.well-known/agent-card.json

== 4. Lookups (section 8) ==

> GET /v0/domain/OpenSea.IO  [non-canonical domain redirects]
< 308
< RateLimit-Policy: "default";q=6;w=60
< RateLimit: "default";r=5;t=60
< Location: /v0/domain/opensea.io
< Cache-Control: public, max-age=86400

> GET /v0/domain/opensea.io  [observed domain record]
< 200
< RateLimit-Policy: "default";q=6;w=60
< RateLimit: "default";r=4;t=59
< ETag: "Yls0Y4tKKVJj-Xc7Ap8sR__okBx"
< Cache-Control: public, max-age=3600
< Content-Type: application/json
  {
    "resolve": "0.1",
    "query": {
      "type": "domain",
      "value": "opensea.io"
    },
    "answer": "found",
    "records": [
      {
        "id": "rsv_nup2w2no4sqhpjxxnxn2",
        "identifier": {
          "type": "domain",
          "value": "opensea.io"
        },
        "cardUrl": "https://opensea.io/.well-known/agent-card.json",
        "status": "active",
        "source": "crawl",
        "verification": {
          "level": "observed",
          "method": "crawl-well-known",
          "lastVerifiedAt": "2026-09-26T21:18:41.132Z",
          "expiresAt": "2026-10-31T21:18:41.132Z",
          "evidence": [
            {
              "kind": "crawl",
              "ref": "full-20260926-39db43",
              "checkedAt": "2026-09-26T21:18:41.132Z"
            }
          ]
        },
        "updatedAt": "2026-09-26T21:18:41.132Z"
      }
    ]
  }

> GET /v0/domain/opensea.io {"If-None-Match":"\"Yls0Y4tKKVJj-Xc7Ap8sR__okBx\""}  [conditional request, unchanged]
< 304
< RateLimit-Policy: "default";q=6;w=60
< RateLimit: "default";r=3;t=58
< ETag: "Yls0Y4tKKVJj-Xc7Ap8sR__okBx"
< Cache-Control: public, max-age=3600

> GET /v0/tel/+15195550142  [tel lookup (illustrative claim)]
< 200
< RateLimit-Policy: "default";q=6;w=60
< RateLimit: "default";r=2;t=57
< ETag: "GUQqsQU6_upDe4iqhyHdjjaXWE4"
< Cache-Control: public, max-age=3600
< Content-Type: application/json
  {
    "resolve": "0.1",
    "query": {
      "type": "tel",
      "value": "+15195550142"
    },
    "answer": "found",
    "records": [
      {
        "id": "rsv_wvvnmfpqnpdhnm7it4d6",
        "identifier": {
          "type": "tel",
          "value": "+15195550142"
        },
        "cardUrl": "https://agent.example.com/.well-known/agent-card.json",
        "status": "active",
        "source": "claim",
        "verification": {
          "level": "verified-organization",
          "method": "voice-otp",
          "lastVerifiedAt": "2026-09-23T23:00:00.000Z",
          "expiresAt": "2026-12-22T23:00:00.000Z",
          "evidence": [
            {
              "kind": "voice-otp",
              "checkedAt": "2026-09-23T23:00:00.000Z"
            },
            {
              "kind": "card-listing",
              "ref": "https://agent.example.com/.well-known/agent-card.json",
              "checkedAt": "2026-09-23T23:00:00.000Z"
            },
            {
              "kind": "business-registry",
              "authority": "Corporations Canada",
              "ref": "0000000-0",
              "checkedAt": "2026-09-23T23:00:00.000Z"
            }
          ]
        },
        "organization": {
          "name": "Example Telecom Inc.",
          "country": "CA",
          "registry": {
            "authority": "Corporations Canada",
            "id": "0000000-0"
          }
        },
        "updatedAt": "2026-09-23T23:00:00.000Z"
      }
    ]
  }

> GET /v0/brand/CA/exampletelecom  [brand lookup (illustrative claim)]
< 200
< RateLimit-Policy: "default";q=6;w=60
< RateLimit: "default";r=1;t=56
< ETag: "TXpRQw5plSOhd9-6Khj08M0f1GB"
< Cache-Control: public, max-age=3600
< Content-Type: application/json
  {
    "resolve": "0.1",
    "query": {
      "type": "brand",
      "value": "exampletelecom",
      "country": "CA"
    },
    "answer": "found",
    "records": [
      {
        "id": "rsv_glj2do72g2ywtajuilus",
        "identifier": {
          "type": "brand",
          "value": "exampletelecom",
          "country": "CA",
          "display": "Example Telecom"
        },
        "cardUrl": "https://agent.example.com/.well-known/agent-card.json",
        "status": "active",
        "source": "claim",
        "verification": {
          "level": "verified-organization",
          "method": "trademark-registration",
          "lastVerifiedAt": "2026-09-23T23:00:00.000Z",
          "expiresAt": "2027-09-23T23:00:00.000Z",
          "evidence": [
            {
              "kind": "trademark-registration",
              "authority": "CIPO",
              "ref": "TMA000000",
              "checkedAt": "2026-09-23T23:00:00.000Z"
            },
            {
              "kind": "card-listing",
              "ref": "https://agent.example.com/.well-known/agent-card.json",
              "checkedAt": "2026-09-23T23:00:00.000Z"
            },
            {
              "kind": "business-registry",
              "authority": "Corporations Canada",
              "ref": "0000000-0",
              "checkedAt": "2026-09-23T23:00:00.000Z"
            }
          ]
        },
        "organization": {
          "name": "Example Telecom Inc.",
          "country": "CA",
          "registry": {
            "authority": "Corporations Canada",
            "id": "0000000-0"
          }
        },
        "updatedAt": "2026-09-23T23:00:00.000Z"
      }
    ]
  }

> GET /v0/tel/+15195550199  [negative answer]
< 404
< RateLimit-Policy: "default";q=6;w=60
< RateLimit: "default";r=0;t=55
< Cache-Control: public, max-age=300
< Content-Type: application/problem+json
  {
    "type": "https://emissar.ai/specs/resolve/v0.1#not-found",
    "title": "No record for this identifier",
    "status": 404,
    "resolve": "0.1",
    "answer": "not-found",
    "query": {
      "type": "tel",
      "value": "+15195550199"
    }
  }

> GET /v0/domain/example.com  [rate limit reached]
< 429
< RateLimit-Policy: "default";q=6;w=60
< RateLimit: "default";r=0;t=54
< Retry-After: 54
< Cache-Control: no-store
< Content-Type: application/problem+json
  {
    "type": "https://emissar.ai/specs/resolve/v0.1#rate-limited",
    "title": "Too many lookups",
    "status": 429,
    "resolve": "0.1",
    "detail": "Retry after 54 seconds."
  }

> GET /v0/domain/example.com  [another client is not limited: negative answer]
< 404
< RateLimit-Policy: "default";q=6;w=60
< RateLimit: "default";r=5;t=53
< Cache-Control: public, max-age=300
< Content-Type: application/problem+json
  {
    "type": "https://emissar.ai/specs/resolve/v0.1#not-found",
    "title": "No record for this identifier",
    "status": 404,
    "resolve": "0.1",
    "answer": "not-found",
    "query": {
      "type": "domain",
      "value": "example.com"
    }
  }

> GET /v0/tel/519-555-0142  [invalid identifier (national format)]
< 400
< RateLimit-Policy: "default";q=6;w=60
< RateLimit: "default";r=4;t=52
< Cache-Control: public, max-age=3600
< Content-Type: application/problem+json
  {
    "type": "https://emissar.ai/specs/resolve/v0.1#invalid-identifier",
    "title": "Invalid identifier",
    "status": 400,
    "resolve": "0.1",
    "detail": "no leading '+' and country code; convert national numbers before lookup"
  }

> GET /v0/domain/modelcontextprotocol.io  [after the window resets]
< 200
< RateLimit-Policy: "default";q=6;w=60
< RateLimit: "default";r=5;t=59
< ETag: "k2AYY82PQpLLoeIWvwN4dMfHzda"
< Cache-Control: public, max-age=3600
< Content-Type: application/json
  {
    "resolve": "0.1",
    "query": {
      "type": "domain",
      "value": "modelcontextprotocol.io"
    },
    "answer": "found",
    "records": [
      {
        "id": "rsv_3ovtoti4gpiox25taidd",
        "identifier": {
          "type": "domain",
          "value": "modelcontextprotocol.io"
        },
        "cardUrl": "https://modelcontextprotocol.io/.well-known/agent-card.json",
        "status": "active",
        "source": "crawl",
        "verification": {
          "level": "observed",
          "method": "crawl-well-known",
          "lastVerifiedAt": "2026-09-26T22:18:49.521Z",
          "expiresAt": "2026-10-31T22:18:49.521Z",
          "evidence": [
            {
              "kind": "crawl",
              "ref": "full-20260926-39db43",
              "checkedAt": "2026-09-26T22:18:49.521Z"
            }
          ]
        },
        "updatedAt": "2026-09-26T22:18:49.521Z"
      }
    ]
  }

Summary: 17 normalization cases (9 accepted), 3 observed + 3 illustrative records, 10 lookups: 4x200, 1x304, 1x308, 1x400, 2x404, 1x429

A.2 Schema and OpenAPI checks

$ python validate.py
JSON Schema (resolve-v0.1.schema.json, Draft 2020-12, format checks on)
  PASS  record rsv_nup2w2no4sqhpjxxnxn2 domain:opensea.io (observed)
  PASS  record rsv_xyb77jznf3d2ev7ipuif domain:activecampaign.com (observed)
  PASS  record rsv_3ovtoti4gpiox25taidd domain:modelcontextprotocol.io (observed)
  PASS  record rsv_z4g344c4suhbf7yckcd4 domain:agent.example.com (verified-control)
  PASS  record rsv_wvvnmfpqnpdhnm7it4d6 tel:+15195550142 (verified-organization)
  PASS  record rsv_glj2do72g2ywtajuilus brand:exampletelecom (verified-organization)
  PASS  308 /v0/domain/OpenSea.IO has no body
  PASS  200 /v0/domain/opensea.io body is a valid LookupResponse
  PASS  304 /v0/domain/opensea.io has no body
  PASS  200 /v0/tel/+15195550142 body is a valid LookupResponse
  PASS  200 /v0/brand/CA/exampletelecom body is a valid LookupResponse
  PASS  404 /v0/tel/+15195550199 body is a valid Problem
  PASS  429 /v0/domain/example.com body is a valid Problem
  PASS  404 /v0/domain/example.com body is a valid Problem
  PASS  400 /v0/tel/519-555-0142 body is a valid Problem
  PASS  200 /v0/domain/modelcontextprotocol.io body is a valid LookupResponse
Schema negative tests (each MUST be rejected)
  PASS  observed tel record
  PASS  crawl record marked verified-control
  PASS  brand record from a crawl
  PASS  claimed record at level observed
  PASS  brand record without organization
  PASS  brand record below verified-organization
  PASS  tel record verified by dns-txt
  PASS  tel record below verified-organization
  PASS  non-canonical tel value
  PASS  non-canonical domain value
  PASS  http card URL
OpenAPI (resolve-v0.1.yaml)
  PASS  YAML parses; openapi 3.1.0
  PASS  openapi-spec-validator: valid OpenAPI 3.1 (external $refs resolved)
  PASS  all 17 distinct $refs resolve
  PASS  308 for /v0/domain/OpenSea.IO is declared in the OpenAPI document (/v0/domain/{domain})
  PASS  200 for /v0/domain/opensea.io is declared in the OpenAPI document (/v0/domain/{domain})
  PASS  304 for /v0/domain/opensea.io is declared in the OpenAPI document (/v0/domain/{domain})
  PASS  200 for /v0/tel/+15195550142 is declared in the OpenAPI document (/v0/tel/{number})
  PASS  200 for /v0/brand/CA/exampletelecom is declared in the OpenAPI document (/v0/brand/{country}/{name})
  PASS  404 for /v0/tel/+15195550199 is declared in the OpenAPI document (/v0/tel/{number})
  PASS  429 for /v0/domain/example.com is declared in the OpenAPI document (/v0/domain/{domain})
  PASS  404 for /v0/domain/example.com is declared in the OpenAPI document (/v0/domain/{domain})
  PASS  400 for /v0/tel/519-555-0142 is declared in the OpenAPI document (/v0/tel/{number})
  PASS  200 for /v0/domain/modelcontextprotocol.io is declared in the OpenAPI document (/v0/domain/{domain})

ALL CHECKS PASSED

Removed from the end of a brand (after case folding) by section 5.3 step 3: inc, incorporated, corp, corporation, co, company, llc, llp, lp, ltd, limited, plc, ltee, ltée, limitee, limitée, ulc, gmbh, ag, sa, sas, srl, bv, nv, pty.

The list is closed in v0.1 and covers common Canadian, US and European forms. Adding a form changes brand keys, so it requires a new version of this document.