Documentation

EntityRoot V1 API - Verified business facts for AI systems

Quick Start

  1. 1

    Create an Account

    Sign up at entity-root.com/register

  2. 2

    Verify Your Domain

    Add a DNS TXT record to prove domain ownership

  3. 3

    Enter Business Facts

    Add your business name, address, phone, hours, and service areas

  4. 4

    Publish

    Your facts are cryptographically signed and made available via API

Public API Endpoints

GET/ai/entity/{id}

Returns cryptographically signed business facts for an entity. Bundles are Ed25519-signed and byte-for-byte mirrored to a durable S3 archive on publish.

{id} accepts either a UUID (e.g. 102a45e4-7d63-...) or a verified domain (e.g. beardemo.com.au). Both forms return the same bundle.

Example Response
{
  "entity_id": "102a45e4-7d63-45b6-92f3-cfc439fe2895",
  "facts": {
    "@context": "https://schema.org",
    "@type": "Organization",
    "name": "Example Business",
    "alternateName": "EX",
    "url": "https://example.com.au",
    "telephone": "+61 2 1234 5678",
    "description": "...",
    "address": {
      "@type": "PostalAddress",
      "streetAddress": "...",
      "addressLocality": "...",
      "addressRegion": "Queensland",
      "postalCode": "4740",
      "addressCountry": "Australia"
    }
  },
  "hash": "ace6f0848bea876e829595f26aa785c3f8d9a8a15964756a32ce469328eeb295",
  "signature": "ed25519-sig-v1:YkWfZskRdwIG0qTigWWLs2Ja3...",
  "key_id": "prod-key-001",
  "issued_at": "2026-05-11T04:31:21.592234Z",
  "version": 6,
  "schema_version": "1.0"
}
GET/ai/trust-score/{id}

Returns the EntityRoot V1 Identity Trust Score (0–100) computed from four equally weighted factors. Each factor is reported as a 0–100 sub-score; the top-level score is their weighted average (25% each).

{id} accepts either a UUID or a verified domain, same as /ai/entity.

Example Response
{
  "entity_id": "102a45e4-7d63-45b6-92f3-cfc439fe2895",
  "label": "EntityRoot V1 Identity Trust Score",
  "score": 43,
  "factors": {
    "identity_completeness": 50,
    "signing_status": 0,
    "schema_compliance": 100,
    "verification_depth": 25
  },
  "calculated_at": "2026-05-11T06:04:55Z"
}
GET/ai/verify/{id}

Returns verification data with masked PII for public display.

GET/.well-known/entityroot.json

Discovery endpoint for AI systems. Advertises the V1 public endpoints and the active signing key.

Example Response
{
  "entityroot_version": "1.0",
  "api_base": "https://www.entity-root.com/api/v1",
  "public_key": "yqV197dIzZI0SKagXmCVZK0Akfyj6E+a/R8wydbbXNQ=",
  "endpoints": {
    "entity": "/ai/entity/{id}",
    "trust_score": "/ai/trust-score/{id}"
  },
  "documentation": "https://www.entity-root.com/docs"
}
GET/llms.txt?domain={domain}

Machine-readable entity summary in markdown for LLM consumption.

Pass the verified domain as a query parameter (e.g. /llms.txt?domain=beardemo.com.au), or hit /ai/llms/{entityId} to fetch by UUID. When the Cloudflare worker is deployed to your origin, it forwards the bot's host header so a bare /llms.txt on the tenant domain works without a query parameter.

GET/health

Health check endpoint for monitoring.

X-Entity-Trace Header

Every response served through the EntityRoot Cloudflare Worker includes an X-Entity-Trace diagnostic header so consumers can verify what happened on the edge.

Format:

[STATUS];[LATENCY_MS]ms;[REASON];v1

Examples:

x-entity-trace: INJECTED;612ms;OK;v1       # Bot received the JSON-LD injection
x-entity-trace: SKIPPED;0ms;HUMAN;v1       # Human visitor — no injection
x-entity-trace: FAIL_OPEN;3349ms;TIMEOUT;v1  # Edge could not reach origin in time; original site served
FieldPossible values
STATUSINJECTED · SKIPPED · FAIL_OPEN
LATENCY_MSInteger milliseconds from request receipt to response start
REASONOK · HUMAN · TIMEOUT · ERROR

Rate Limiting

API endpoints are bucketed into three tiers. Limits are enforced per client (IP address, or shared secret for edge callbacks) using a token bucket — sustained rate plus an instant burst.

TierScopeSustainedBurst
publicAnonymous /ai/*, /facts/*, /.well-known/*, /llms.txt100 req/min20
authenticatedJWT-bearing /api/v1/*300 req/min50
edgeCloudflare worker callbacks (/webhooks/*) keyed by shared secret1000 req/min200

Headers on every response:

x-ratelimit-limit:     100         # bucket size for this tier
x-ratelimit-remaining: 19          # tokens left right now
x-ratelimit-reset:     1778480098  # epoch seconds when bucket refills
x-ratelimit-tier:      public

429 Too Many Requests: retry after the seconds value in the Retry-After header (always ≥ 1).

Human Verification Page

Each published entity has a public verification page at:

https://www.entity-root.com/verify/{entityId}

This page displays:

  • Business name and trading name
  • Masked contact info (privacy-safe)
  • City/State/Country location
  • Verification status and trust score
  • Cryptographic signature validation

Signature Verification

Every bundle is signed with Ed25519. The signature covers the canonical (sorted-key, no-whitespace) JSON of the facts object.

Step 1. Fetch the active signing keys (JWKS-style):

GET https://www.entity-root.com/api/v1/keys/public

{
  "keys": [
    {
      "kid": "prod-key-001",
      "alg": "Ed25519",
      "use": "sig",
      "public_key": "caa575f7b748cd923448a6a05e609564ad0091fca3e84f9afd1f30c9d6db5cd4",
      "created_at": "2026-05-11T06:15:22Z"
    }
  ]
}

Step 2. From the bundle, match the key_id field to a kid in the JWKS, parse the public key (hex), and strip the ed25519-sig-v1: prefix from the signature.

The signature payload after the prefix is standard base64.

Step 3. Re-canonicalize the bundle's facts object (RFC 8785 / JCS — sort keys lexicographically, no whitespace, UTF-8) and verify with Ed25519 against the parsed signature.

Signature format: ed25519-sig-v1:{base64-signature}  ·  Hash format: hex(SHA-256(canonical_facts))  ·  same canonical bytes used for both, so verifying hash and verifying signature are equivalent checks.

Cloudflare Edge Integration

EntityRoot deploys a Cloudflare Worker to your origin that:

  • Detects 30+ AI bots (GPTBot, ClaudeBot, PerplexityBot, Googlebot, etc.) via User-Agent
  • Injects schema.org JSON-LD into the page <head> for bot requests
  • Emits the X-Entity-Trace diagnostic header on every response
  • Fails open within 3 s — never breaks your site if EntityRoot is degraded

Pre-signed bundle storage: on every publish, the backend mirrors the signed bundle to a per-domain Cloudflare KV namespace (entityroot-{domain}) under key bundle:{domain}, plus an S3 archive for durability. Operators can verify edge state via the Cloudflare KV API at any time.