# CCN.txt — Customer Care Numbers Verified Publishing Standard **Version:** 0.1 (Draft) **Status:** Open Standard, Public Domain **Authored by:** CallToPerson (calltoperson.com), 2026 **Repository:** https://github.com/calltoperson/ccn-spec **Validator:** https://calltoperson.com/api/ccn/validate?domain=example.com --- ## 1. Why this standard exists Today, every customer-care directory (Justdial, Sulekha, Truecaller, GetHuman) **scrapes or guesses** brand support numbers, IVR menus, and agent shortcuts. Brands have **no machine-readable way** to officially publish: - Verified primary helpline numbers - IVR menu structure - Agent-reach shortcut keys - Operating hours - Languages supported - Last-verified timestamp signed by the brand This causes: - Outdated/wrong numbers spreading across the web - Phone fraud (scammers exploiting un-verified directories) - Brands losing trust signal control - AI assistants (ChatGPT, Perplexity, Google Assistant) returning hallucinated helpline numbers `CCN.txt` solves this by defining a **single well-known location** at `/.well-known/ccn.json` where any brand can publish authoritative customer-care metadata — the same way `robots.txt` (1994), `sitemap.xml` (2005), and `IndexNow` (2021) standardized other publisher signals. --- ## 2. Where to host A compliant publisher MUST serve a UTF-8 JSON document at: ``` https://{brand-domain}/.well-known/ccn.json ``` Discovery clients SHOULD also accept the legacy fallback: ``` https://{brand-domain}/ccn.json ``` The HTTP response MUST set: - `Content-Type: application/ccn+json` (or `application/json`) - `Cache-Control: public, max-age=3600` - Optional `ETag` and `Last-Modified` for crawl efficiency --- ## 3. Document schema (v0.1) ```json { "ccn_version": "0.1", "publisher": { "name": "string (legal entity name)", "domain": "string (canonical domain)", "verified_by": "self | third-party-name", "verified_at": "ISO-8601 timestamp", "signature": "ed25519:base64 (optional, see §6)" }, "support_lines": [ { "label": "string (e.g. 'General Customer Care', 'Premium Support')", "phone": "+91-... (E.164 format preferred)", "languages": ["en", "hi", "ta", ...], "hours": "string (e.g. '24x7' or 'Mon-Fri 9-21 IST')", "toll_free": true|false, "ivr": [ { "key": "1", "label": "string", "agent_path": false }, { "key": "9", "label": "Talk to agent", "agent_path": true } ], "channels": ["voice", "whatsapp", "email", "sms"], "applicable_products": ["array of product/service names"], "applicable_regions": ["IN", "US", ...] } ], "grievance_officer": { "name": "string", "email": "string", "phone": "string", "designation": "string" }, "nodal_officer": { /* same shape */ }, "escalation_url": "https://...", "last_verified": "ISO-8601", "next_review_due": "ISO-8601" } ``` Required fields: `ccn_version`, `publisher.name`, `publisher.domain`, `publisher.verified_at`, at least one `support_lines` entry with `phone` + `label`. --- ## 4. Discovery & crawl ### For aggregators / search engines 1. Attempt fetch `GET https://{domain}/.well-known/ccn.json` 2. If 404, attempt `GET https://{domain}/ccn.json` 3. If 200, parse JSON, validate against §3 schema 4. Honour `Cache-Control` and `ETag` headers 5. If `next_review_due` < `now()`, treat data as "stale, re-verify needed" 6. Bots SHOULD identify themselves with `User-Agent: ... ccn-discovery/` ### For brand publishers After publishing the file, ping the validator to test compliance: ``` GET https://calltoperson.com/api/ccn/validate?domain={your-domain} ``` The validator returns a public report with errors, warnings, and a "verified" badge code that brands MAY embed back-linking to the validator (similar to W3C HTML validator badges). --- ## 5. Public registry CallToPerson hosts a public, append-only registry of all known publishers: ``` https://calltoperson.com/ccn-registry.json ``` Format: ```json { "registry_version": "0.1", "generated_at": "ISO-8601", "publishers": [ { "domain": "example.com", "first_seen": "...", "last_verified": "...", "ccn_version": "0.1" } ] } ``` The registry is **read-only**; new publishers are added automatically once their `ccn.json` is discovered + validates. --- ## 6. Cryptographic signing (optional, recommended for v1.0) Brands MAY sign their `ccn.json` with an Ed25519 keypair to prove authenticity. The public key is published at `/.well-known/ccn-pubkey.txt`. Aggregators SHOULD prefer signed documents over unsigned when both exist. Signing is OPTIONAL in v0.1 to lower the adoption bar. v1.0 will make it RECOMMENDED for high-trust badges. --- ## 7. Security considerations - Brands MUST NOT publish phone numbers belonging to other entities - The validator publicly logs all attempts (transparency) - Publishers SHOULD include a `next_review_due` ≤ 90 days to avoid stale data - Aggregators MUST display the `last_verified` timestamp to end users - Signed documents (§6) prevent tampering during ingestion --- ## 8. Relationship to existing standards | Standard | Year | Scope | |----------|------|-------| | robots.txt | 1994 | Crawler control | | sitemap.xml | 2005 | URL discovery | | ads.txt | 2017 | Ad-seller authorization | | security.txt | 2017 | Vulnerability disclosure | | IndexNow | 2021 | Push-indexing | | llms.txt | 2024 | AI bot guidance | | **CCN.txt** | **2026** | **Customer-care metadata publishing** | --- ## 9. Reference implementation CallToPerson's own `/.well-known/ccn.json` is the canonical reference: ``` https://calltoperson.com/.well-known/ccn.json ``` Open-source parser: `npm install ccn-parser` (coming soon). --- ## 11. Registry Fallback Discovery (the brand-bypass mechanism) The single biggest barrier to adoption of any new web standard is **publisher inertia** — most brands will not voluntarily host a new file at `/.well-known/` until ecosystem pressure exists. CCN.txt v0.1 solves the cold-start problem by formalising a **registry fallback** path that lets discovery clients (AI agents, search engines, voice assistants) get authoritative answers even when the brand has published nothing. ### 11.1 Three-tier resolution order A compliant discovery client SHOULD attempt resolution in this order: ``` 1. GET https://{domain}/.well-known/ccn.json (brand-published, highest authority) 2. GET https://{domain}/ccn.json (legacy fallback, brand-published) 3. GET https://{registry}/registry/{domain}/ccn.json (aggregator mirror, fallback) ``` If steps 1–2 return 200 with valid JSON, that response is **canonical** and steps 3+ MUST NOT override it. Aggregator mirrors exist to fill the gap, not to compete with brand-published authority. ### 11.2 Registry mirror authority levels A registry mirror response MUST include: - `publisher.role: "mirror"` — explicit declaration - `publisher.authoritative: false` — mirrors never claim full authority - `publisher.claim_url` — URL where the brand can claim/take over the listing - HTTP header `X-CCN-Source-Of-Truth: ccn-registry` - HTTP header `X-CCN-Authority: aggregator-mirror` - A human-readable `note` field explaining the mirror status + how to override This transparency lets AI agents present sourced answers honestly: > "According to the CallToPerson aggregator mirror (no brand-published CCN.txt found), Acme Bank's customer care is +91-1800-XXX-XXXX, last verified 2026-04-10." ### 11.3 Single-call resolver API To simplify discovery, registries SHOULD expose a unified lookup endpoint: ``` GET https://{registry}/api/ccn/lookup?domain={brand-domain} ``` Response includes a `_source` field with one of: `"brand_published"`, `"aggregator_mirror"`, `"not_found"`. The registry MUST attempt brand-published resolution before falling back to its own mirror, so this endpoint is safe for AI agents to call directly. ### 11.4 Why this is whitehat (not scraping) - Mirrors only contain **publicly available information** (phone numbers brands already publish on their contact pages) - Mirrors **explicitly defer** to brand-published files (steps 1–2 always win) - Brands can **claim** their mirror at any time and override aggregator data - Mirrors **disclose their status** in both JSON and HTTP headers - License is **CC0** (no commercial lock-in by the aggregator) This is the same pattern used by: - IMDb listing companies' films before companies opt in - Wikipedia hosting biographies before subjects edit them - Justdial / Yelp / GetHuman listing businesses before owners claim - DNS PTR records hosted by registrars before owners customise ### 11.5 Aggregator obligations An aggregator hosting registry mirrors MUST: 1. Provide a public claim flow at `/brand/{slug}/claim` (or equivalent) 2. Honour takedown requests from verified brand owners within 7 days 3. Not paywall access to mirror data (CC0 minimum) 4. Re-verify mirror data at least every 90 days 5. Defer to brand-published `/.well-known/ccn.json` when present 6. Disclose mirror status in every response (see §11.2) ### 11.6 The reference registry CallToPerson operates the canonical reference registry: ``` https://calltoperson.com/api/ccn/lookup?domain={x} https://calltoperson.com/registry/{domain}/ccn.json https://calltoperson.com/brand/{slug} (HTML, AI-citable) https://calltoperson.com/dataset/customer-care-india.jsonl (bulk JSONL, CC0) ``` Other parties MAY operate their own registries — competition is encouraged. The protocol does not centralise authority on any single registry. --- ## 10. Roadmap - v0.1 (current) — schema, discovery, validator, public registry - v0.2 — npm parser package, browser badge embed - v0.3 — Schema.org PR for `ContactPoint.verifiedSource` extension - v1.0 — cryptographic signing recommended; W3C submission --- ## License This specification is dedicated to the public domain (CC0 1.0). Implementations may be released under any license. --- **Feedback / contributions:** open an issue at https://github.com/calltoperson/ccn-spec or email standards@calltoperson.com.