INITE Atlas

AI tools catalogue for agents: match a need to tools, compare prices from verified plans, see price and API changes, and pick an MCP server by its daily check (uptime, tool-definition quality, token weight, warning signs). Remote, open without sign-in.

Servidor MCP alojado

npx add-mcp 'https://inite.ai/api/mcp/atlas'

Se instala en Claude Code, Codex, Cursor y más

Documentación

INITE for agents

The portal, the analyzer and the Atlas, as tools an AI agent can call without an account. Each one also has a signed-in rail for what needs you - adding your tool to the Atlas, your audits, paying - which signs you in when you connect it.

INITE / AGENTS

MCP endpoint

https://inite.ai/api/mcp

Streamable HTTP, stateless. Each rail is also its own endpoint, for a shorter tool list.

The rails

  • Portal https://inite.ai/api/mcp/portal INITE itself: what we sell and for how much in your currency, free call times, booking a call for a named person, writing to the team, the guides.
    • inite_servicesopen
    • inite_slotsopen
    • inite_book_callopen
    • inite_contactopen
    • inite_guidesopen
    • inite_connectopen
  • INITE, signed in https://inite.ai/api/mcp/portal-me Your account: plan, licences and audits left (my_account), and Local Start bought for you (inite_buy), paid from your INITE wallet, by card or PIX, or over x402.
    • my_accountaccount
    • inite_buyaccount
  • Analyzer https://inite.ai/api/mcp/analyzer How AI engines read a website. check_identity is free and instant: crawler access, identity files, schema. visibility_fixes gives the fix plan, most important first, with paste-ready files; compare_sites reads a competitor the same way; visibility_history shows how the reading moved. analyze_site runs the audit and get_analysis reads it.
    • check_identityopen
    • analyze_siteopen
    • get_analysisopen
    • visibility_fixesopen
    • compare_sitesopen
    • visibility_historyopen
  • Analyzer, signed in https://inite.ai/api/mcp/analyzer-me The audit at your account's tier (analyze_site, get_analysis), watch_site re-reading a site every week, your audits (my_reports), and a 12-month licence (visibility_buy_licence).
    • watch_siteaccount
    • my_reportsaccount
    • visibility_buy_licenceaccount
  • Atlas https://inite.ai/api/mcp/atlas Ten thousand AI tools re-read every week. Match a job described in words, read one tool's dated record (price and how it moved, API, MCP server, status, what it states about your data), search by facets, see what changed in the market.
    • match_toolsopen
    • match_mcpopen
    • atlas_lookupopen
    • atlas_searchopen
    • atlas_changesopen
    • get_project_timelineopen
    • atlas_couponsopen
    • atlas_compareopen
    • atlas_dataset_getopen
    • atlas_dataset_changesopen
  • Atlas Owners https://inite.ai/api/mcp/atlas-owners atlas_submit adds your tool from its address and starts the claim; the atlas_owner_* tools prove the domain, run the card and its coupons; atlas_owner_premium pays for premium; atlas_dataset_* publish Live Data comparisons.
    • atlas_my_listingsaccount
    • atlas_submitaccount
    • atlas_owner_claimaccount
    • atlas_owner_verifyaccount
    • atlas_owner_cardaccount
    • atlas_owner_set_read_pagesaccount
    • atlas_owner_remeasureaccount
    • atlas_owner_statsaccount
    • atlas_owner_propose_editaccount
    • atlas_owner_couponsaccount
    • atlas_owner_coupon_addaccount
    • atlas_owner_coupon_setaccount
    • atlas_owner_premiumaccount
    • atlas_owner_releaseaccount
    • atlas_dataset_createaccount
    • atlas_dataset_updateaccount
    • atlas_dataset_publishaccount
    • atlas_dataset_archiveaccount
    • atlas_dataset_placementaccount
  • Directory https://inite.ai/api/mcp/directory Businesses that confirmed their own facts at INITE and proved their domain. find_business searches by what a business does and where it is, in English, Russian, Portuguese or Spanish; business opens one by slug or domain. Each has its own facts server (MCP and A2A). The order is the match and how complete the facts are; no place is for sale. AI tools, which we measure ourselves, are in the Atlas, not here.
    • find_businessopen
    • businessopen

Open, and signed in

A call with no token is a guest. Guests get the open tools of the portal, the analyzer and the Atlas under per-address allowances, and the audit runs as the survey: everything but its two paid steps, as on the website for a visitor without an account. The signed-in rails answer nothing without a token. Their 401 with WWW-Authenticate points at auth.inite.ai, which takes dynamic client registration and PKCE, so the client signs you in (passkey, email link or password) when you add it. Claude and ChatGPT decide whether a connector signs in at the moment it is added, which is why each product has a signed-in rail of its own.

Connect

Any client that speaks remote MCP: add the endpoint. No key is needed to start.

{
  "mcpServers": {
    "inite": {
      "type": "http",
      "url": "https://inite.ai/api/mcp"
    }
  }
}

A client that launches local servers: the npm package adds three checks that run on your machine and forwards the rest to the endpoint.

{
  "mcpServers": {
    "inite": {
      "command": "npx",
      "args": [
        "-y",
        "@inite/visibility"
      ]
    }
  }
}

For tool owners

Your agent can put your tool in the Atlas and run its card: add it from its address, prove the domain, tell the Atlas where your pricing, careers and release-notes pages are, publish discounts, ask for a re-read and buy premium.

  1. 01Connect the Atlas Owners rail, https://inite.ai/api/mcp/atlas-owners, and sign in when the client asks.
  2. 02atlas_submit with your site's address reads the homepage, files the request and starts the claim. It returns three ways to prove the domain: a badge link, a meta tag or a DNS record. Put one on the site, then call atlas_owner_verify. A tool already in the Atlas is claimed with atlas_owner_claim.
  3. 03atlas_owner_card shows what your card reads and what it could not: price, hiring, releases, company.
  4. 04atlas_owner_set_read_pages names your pricing, careers and changelog pages. We read them with the same checks as every other page: a price must be printed there, a board must be yours, entries must carry dates.
  5. 05atlas_owner_coupon_add publishes a discount, shown as stated by the verified owner. atlas_owner_remeasure reads the site again; atlas_owner_stats shows views and clicks.
  6. 06atlas_owner_premium opens premium. It is paid from your INITE wallet if you allowed that; otherwise you get one passkey page, a card or PIX page, and x402 for an agent with its own wallet. Call it again after paying and premium turns on.

A prompt to give your agent

Using the INITE Atlas Owners MCP server, add your-tool.com to the Atlas as mine, place the meta-tag proof on our homepage and verify it. Then show me what the card could not read, and set our pricing, careers and changelog pages.

Nothing an owner states changes a measured fact. Pages you name are read, not believed; corrections go to a person for review.

A2A

The audit is also an A2A v1.0 agent: send it a hostname and get a task that completes in about a minute with the score as an artifact. Same rule: open without a token, the account's tier with one.

https://inite.ai/api/a2a

For your site's developers

A company that confirmed its facts in INITE can serve them from its own domain and publish the articles it approved on its own site. Pick the connector for the site's platform. A site on any other stack calls the same endpoints and listens for the webhook events below.

A company turns INITE Agents on in its cabinet, confirms its facts there and gets the site key the connectors below need. Open INITE Agents

Which connector for which platform

  • WordPress · download the plugin · on GitHub The INITE Agents plugin. Install the zip under Plugins, Add New Plugin, Upload Plugin, and paste the site key under Settings, INITE Agents. It serves the files, the head tags and the robots.txt line, and turns approved articles into posts. New versions arrive on the Plugins screen.
  • Next.js · on GitHub npm install @inite/site-agents The @inite/site-agents package: two route files and one head component serve the files and the tags; createContentQueue fetches the approved articles and reports where they were published.
  • Any site with a head-code box: Tilda, Squarespace, Wix, Webflow, Framer, Ghost, Shopify, Bitrix, Joomla · on GitHub The snippet: one script tag in the page head, made in the cabinet, with the public slug and no key. It loads the WebMCP tools, adds the links to the files on <slug>.inite.ai and the JSON-LD of the confirmed facts. That reaches agents in a browser and crawlers that run JavaScript; for the many AI crawlers that read raw HTML only, the cabinet also gives a static block of the same tags for one version, to copy again after each confirm. Once a day we read the homepage to see which is there.
  • Ghost · on GitHub No plugin to install: paste the Admin API URL and key of a custom integration in the cabinet, and INITE publishes approved articles to Ghost itself. The snippet in Settings, Code injection, serves the head.
  • Any other stack · on GitHub The endpoints and the webhook below, with a site key made for the Webhook platform in the cabinet.
  • Shopify, Wix, Webflow, HubSpot Apps of their own are on the way. Until then, the snippet connects any of these sites, and a developer can use the endpoints and the webhook.

Docs for each platform, webhook receivers in Node.js, PHP and Python that check the signature, and issues for every connector are in one public repository. The source of the plugin and of the package is mirrored beside it, read-only, with a release for each version. inite-ai/inite-agents on GitHub

Key and limits

Every call marked "site key" carries the key from the For agents tab of the cabinet, as Authorization: Bearer isk_…. The key is shown once, when it is made. One key belongs to one site and one platform; send it only to https://inite.ai.

The site-key endpoints take 60 requests a minute from one IP address; sites on one shared server share that allowance. The public facts and the snippet take 30 a minute from one address. Over the limit the answer is 429 with Retry-After in seconds; when the service is busy, 503 with Retry-After. The body says which: {"ok": false, "busy": "rate"}. The WebMCP script has no limit and is cached for a day. Uploads to records take 30 a minute.

Endpoints

  • GET /api/site/v1/manifest site key Which files to serve and at which paths, the head tags, the MCP address, the facts version, and whether articles are switched on. Send the ETag you hold as If-None-Match: 304 means nothing changed. Asking every five minutes is enough.
  • GET /api/site/v1/files/{name} site key One file of the confirmed version, byte for byte, with its content type: llms.txt, llms-full.txt, agent-card.json, mcp.json, api-catalog, robots-signal or jsonld. Each file has its own ETag. Any other name is 404. robots-signal is the Content-Signal line for your robots.txt (search=yes, ai-input=yes, ai-train=no): a stated preference for those who honour it; it blocks no robot.
  • POST /api/site/v1/ping site key Optional, about once a day: your platform, your connector's version, up to 20 paths it serves, and how many times known AI agents read them per day over the last seven days (up to 60 rows). Each count is the day's total so far, so a retried ping writes the same number. Visitors' addresses and user agents are not sent. It may also carry an optional site field with what your platform says about the site: its title, tagline, language and address, and woocommerce.products with the number of published products. INITE suggests the title and tagline to the owner; nothing is published from it. A ping with site and no paths leaves the served paths as they were. With the site's own booking or location plugins it may also carry services, locations and hours in the facts' shape, and from naming the plugins; the owner sees them as suggestions. An optional referrals field counts visitors who came from an AI assistant (chatgpt.com, perplexity.ai, gemini.google.com, copilot.microsoft.com, claude.ai and a few more): day, path, source and hits, up to 60 rows, the same day's-total rule. Counts only: no address, no cookie, nothing about the person.
  • POST /api/site/v1/records site key The site's own content, one group at a time, sent only while the owner switched it on in the connector: content (published pages and posts: id, type, title, url, excerpt, modified, language), products (id, name, url, price, regularPrice, salePrice, currency, stock, sku, excerpt, categories, image) or events (id, title, url, excerpt, starts, ends, venue). Up to 100 items an upload, the changed ones; removed lists the ids that went, present every id still there (the rest is deleted), and clear: true deletes the whole group. Addresses must be on the site's own domain. INITE holds up to 2,000 pages and posts, 2,000 products and 200 events, and the answer says how many it holds. llms.txt, llms-full.txt and the MCP's products are built from them within five minutes; products are published only while the owner turned on Publish my catalogue.
  • GET /api/site/v1/summary site key Read only, for the connector's own dashboard: the AI visibility score and the failed checks of the latest analysis, thirty days of agent reads, MCP calls and visitors from AI assistants, and how many suggestions and articles wait for the owner. INITE rewrites it every three hours; asking every few hours is enough. Which agents, pages and assistants is part of INITE Agents Premium; without it the answer carries the totals.
  • GET /api/site/v1/content/queue site key The articles the owner approved that this site has not published yet, oldest first, ten at most per answer. Empty, with enabled: false, while the owner has articles switched off.
  • POST /api/site/v1/content/{id}/published site key Report that an article is live, with its address. Repeating the same address is safe.
  • POST /api/site/v1/content/{id}/failed site key Report that an article could not be published, with the reason. The article leaves the queue until the owner sends it again.
  • GET /api/site/v1/public/{slug}?d={domain} public, no key The confirmed facts as JSON. Open to every origin: this is what the WebMCP script reads in the browser. Cached for five minutes, with an ETag.
  • GET /api/site/v1/webmcp.js?s={slug}&d={domain}&v={version} public, no key The script for the page head; its address, with the right version, is in the manifest under head.script.src. It gives an AI agent in the browser read-only tools over the confirmed facts. In a browser without WebMCP it does nothing, and it sets no cookie.
  • GET /api/site/v1/snippet.js?s={slug}&d={domain} public, no key The script behind the snippet's tag. Served while the facts are published and the snippet is on in the cabinet, otherwise a comment that does nothing. It registers the WebMCP tools and adds the links and the JSON-LD of the current version; a page whose static block is of that version keeps its own JSON-LD. Cached for five minutes, with an ETag. A load marks the snippet seen in the cabinet, the time only; nothing of the visitor is kept.
  • GET /api/site/v1/public/{slug}/prices.yml?d={domain} public, no key The price list as a YML feed, for Yandex Business to read by link. Only services with one price in RUB, KZT or BYN; written when the facts are confirmed, 404 while they are unpublished. Cached for five minutes, with an ETag.
  • POST /api/site/v1/public/{slug}/requests?d={domain} public, no key What the WebMCP script’s request_contact and request_booking send, open to every origin: {"tool", "arguments"} with the same arguments as the MCP tools. Answered with the request’s id and the checks that say it was done right; 422 names the field to fix, 409 means the owner has requests off, 429 a cap or a duplicate. Three from one address at once, then six an hour.
  • GET /api/site/v1/requests?status={status}&page={page} site key The site’s requests from agents, newest first, 25 a page, with the counts per status. Empty, with enabled: false, unless the owner sends requests to this connector.
  • POST /api/site/v1/requests/{id} site key Mark one request new, answered or spam: {"status": "answered"}. Nothing is sent to anyone because of it.

The site-key endpoints refuse with a JSON body {"ok": false, "error", "message"}, and the message can be shown as it is. 401: no_key, unknown_key or revoked. 403: disabled, the key is switched off. 409: unproved (the domain is not proved yet), unconfirmed (nothing is confirmed to publish), unpublished (the owner took the facts down in the cabinet) or company_inactive. On any of them, stop serving the files. On a timeout or a 5xx, keep the last copy you have.

Polling the manifest

curl -i https://inite.ai/api/site/v1/manifest \
  -H "Authorization: Bearer $INITE_SITE_KEY" \
  -H 'If-None-Match: "m4-Qx…"'
{
  "ok": true,
  "site": {
    "slug": "acme",
    "domain": "acme.com",
    "version": 4,
    "confirmedAt": "2026-10-22T10:00:00.000Z"
  },
  "connector": {
    "id": "cm2x8k1qz0001",
    "platform": "next",
    "enabled": true
  },
  "mcp": {
    "url": "https://acme.inite.ai/mcp"
  },
  "files": [
    {
      "name": "llms.txt",
      "path": "/llms.txt",
      "placement": "path",
      "contentType": "text/plain; charset=utf-8",
      "url": "https://inite.ai/api/site/v1/files/llms.txt",
      "available": true,
      "etag": "\"f4-llms.txt\""
    },
    {
      "name": "agent-card.json",
      "path": "/.well-known/agent-card.json",
      "placement": "path",
      "contentType": "application/json; charset=utf-8",
      "url": "https://inite.ai/api/site/v1/files/agent-card.json",
      "available": true,
      "etag": "\"f4-agent-card.json\""
    },
    {
      "name": "mcp.json",
      "path": "/.well-known/mcp.json",
      "placement": "path",
      "contentType": "application/json; charset=utf-8",
      "url": "https://inite.ai/api/site/v1/files/mcp.json",
      "available": true,
      "etag": "\"f4-mcp.json\""
    },
    {
      "name": "api-catalog",
      "path": "/.well-known/api-catalog",
      "placement": "path",
      "contentType": "application/linkset+json; profile=\"https://www.rfc-editor.org/info/rfc9727\"",
      "url": "https://inite.ai/api/site/v1/files/api-catalog",
      "available": true,
      "etag": "\"f4-api-catalog\""
    },
    {
      "name": "robots-signal",
      "path": null,
      "placement": "robots",
      "contentType": "text/plain; charset=utf-8",
      "url": "https://inite.ai/api/site/v1/files/robots-signal",
      "available": true,
      "etag": "\"f4-robots-signal\""
    },
    {
      "name": "jsonld",
      "path": null,
      "placement": "head",
      "contentType": "application/json; charset=utf-8",
      "url": "https://inite.ai/api/site/v1/files/jsonld",
      "available": true,
      "etag": "\"f4-jsonld\""
    }
  ],
  "head": {
    "html": "<script src=\"https://inite.ai/api/site/v1/webmcp.js?s=acme&amp;d=acme.com&amp;v=4&amp;r=cb\" async crossorigin=\"anonymous\"></script>\n<link rel=\"mcp\" href=\"https://acme.inite.ai/mcp\">\n<link rel=\"service-doc\" href=\"https://acme.inite.ai/llms.txt\" type=\"text/plain\">\n<link rel=\"describedby\" href=\"https://acme.inite.ai/.well-known/agent-card.json\" type=\"application/json\">\n<link rel=\"api-catalog\" href=\"https://acme.inite.ai/.well-known/api-catalog\" type=\"application/linkset+json\">\n<script type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@type\":\"Dentist\",\"name\":\"Acme Dental\",\"url\":\"https://acme.com\"}</script>",
    "script": {
      "src": "https://inite.ai/api/site/v1/webmcp.js?s=acme&d=acme.com&v=4&r=cb",
      "async": true
    },
    "links": [
      {
        "rel": "mcp",
        "href": "https://acme.inite.ai/mcp"
      },
      {
        "rel": "service-doc",
        "href": "https://acme.inite.ai/llms.txt",
        "type": "text/plain"
      },
      {
        "rel": "describedby",
        "href": "https://acme.inite.ai/.well-known/agent-card.json",
        "type": "application/json"
      },
      {
        "rel": "api-catalog",
        "href": "https://acme.inite.ai/.well-known/api-catalog",
        "type": "application/linkset+json"
      }
    ],
    "jsonLd": {
      "@context": "https://schema.org",
      "@type": "Dentist",
      "name": "Acme Dental",
      "url": "https://acme.com"
    }
  },
  "features": {
    "files": true,
    "head": true,
    "webmcp": true,
    "menu": false,
    "content": {
      "enabled": true,
      "queueUrl": "https://inite.ai/api/site/v1/content/queue"
    },
    "requests": {
      "enabled": true,
      "booking": true,
      "url": "https://inite.ai/api/site/v1/public/acme/requests?d=acme.com",
      "listUrl": "https://inite.ai/api/site/v1/requests",
      "toPlugin": true
    }
  },
  "poll": {
    "afterSeconds": 300
  }
}

The ping

curl https://inite.ai/api/site/v1/ping \
  -H "Authorization: Bearer $INITE_SITE_KEY" \
  -H 'Content-Type: application/json' \
  -d '{ "platform": "next", "pluginVersion": "0.2.0", "paths": [ "/llms.txt", "/.well-known/agent-card.json", "/robots.txt" ], "visits": [ { "day": "2026-10-22", "path": "/llms.txt", "agent": "ClaudeBot", "hits": 12 } ], "site": { "title": "Sorriso", "tagline": "Dental clinic in Pinheiros", "language": "pt-BR", "url": "https://sorriso.example/", "woocommerce": { "products": 12 } }, "referrals": [ { "day": "2026-10-22", "path": "/prices/", "source": "chatgpt.com", "hits": 3 } ] }'
{
  "ok": true,
  "visits": 1,
  "referrals": 1,
  "paths": 3,
  "platformMatches": true
}

Sending the site's content

curl https://inite.ai/api/site/v1/records \
  -H "Authorization: Bearer $INITE_SITE_KEY" \
  -H 'Content-Type: application/json' \
  -d @products-page.json
{
  "group": "products",
  "items": [
    {
      "id": "412",
      "name": "Whitening kit",
      "url": "https://sorriso.example/loja/whitening-kit/",
      "price": "149.90",
      "regularPrice": "189.90",
      "salePrice": "149.90",
      "currency": "BRL",
      "stock": "instock",
      "sku": "WK-01",
      "excerpt": "Trays and gel for two weeks at home.",
      "categories": [
        "Care at home"
      ],
      "image": "https://sorriso.example/wp-content/uploads/wk.jpg",
      "modified": "2026-10-22T14:05:00+00:00"
    }
  ],
  "removed": [
    "388"
  ]
}
{
  "ok": true,
  "group": "products",
  "accepted": 1,
  "capped": 0,
  "removed": 1,
  "held": 12,
  "cap": 2000,
  "dropped": 0
}

Articles

INITE writes articles for a company's site from what people actually search for, and the owner approves each one in the cabinet. A connector picks up the approved ones and reports back where each was published. What it receives is the text as approved: title, slug, meta description, the body in Markdown and the same body as HTML, and the sources it cites.

The queue

curl https://inite.ai/api/site/v1/content/queue \
  -H "Authorization: Bearer $INITE_SITE_KEY"
{
  "ok": true,
  "enabled": true,
  "items": [
    {
      "id": "cm2y0v7ka0004",
      "lang": "en",
      "title": "How much does a dental cleaning cost in Austin?",
      "slug": "dental-cleaning-cost-austin",
      "metaDescription": "What a cleaning costs at Acme Dental, what it includes, and when insurance covers it.",
      "body": "## What a cleaning includes\n\nA cleaning at Acme Dental takes about 45 minutes…",
      "html": "<h2>What a cleaning includes</h2>\n<p>A cleaning at Acme Dental takes about 45 minutes…</p>\n",
      "sources": [
        {
          "url": "https://www.ada.org/resources/research/health-policy-institute",
          "title": "ADA Health Policy Institute"
        }
      ],
      "approvedAt": "2026-10-22T09:30:00.000Z",
      "report": {
        "published": "https://inite.ai/api/site/v1/content/cm2y0v7ka0004/published",
        "failed": "https://inite.ai/api/site/v1/content/cm2y0v7ka0004/failed"
      }
    }
  ]
}

Ask on your own schedule, for example hourly, or when the content.approved event arrives. The report addresses in each item are on inite.ai and take the same site key.

Reporting the outcome

curl https://inite.ai/api/site/v1/content/cm2y0v7ka0004/published \
  -H "Authorization: Bearer $INITE_SITE_KEY" \
  -H 'Content-Type: application/json' \
  -d '{ "url": "https://acme.com/blog/dental-cleaning-cost-austin/" }'
{
  "ok": true,
  "status": "published",
  "url": "https://acme.com/blog/dental-cleaning-cost-austin/",
  "already": false
}

The address must be http or https on the site's own domain or a subdomain of it. The same address again is answered with already: true, so a retry after a lost answer is safe. A different address for an article already published is refused with 409 published_elsewhere.

curl https://inite.ai/api/site/v1/content/cm2y0v7ka0004/failed \
  -H "Authorization: Bearer $INITE_SITE_KEY" \
  -H 'Content-Type: application/json' \
  -d '{ "reason": "the blog category is missing" }'
{
  "ok": true,
  "status": "failed",
  "already": false
}

The reason is kept up to 300 characters and shown to the owner. A second failed report for the same article is answered with already: true.

Other answers: 404 not_found (not an article of this site), 409 not_approved (it is not waiting to be published), 422 invalid_url, 400 bad_json, 413 too_large (bodies up to 8 KB).

Webhook

Add an https address in the For agents tab, up to three per site. We send it a signed POST for three events: facts.confirmed, each time the facts are confirmed, and content.approved, each time the owner approves an article. The INITE-Event header and the event field say which. The signing secret is shown once, when the address is added. A third, lead.created, goes for each request from an agent when the owner sends requests to the webhook.

facts.confirmed

POST /your/endpoint
Content-Type: application/json
User-Agent: INITE-Webhooks/1.0 (+https://inite.ai/en/mcp#site-api)
INITE-Event: facts.confirmed
INITE-Webhook-Id: evt_3hGkV0bq9rS1xYw2LmN4pQ7z
INITE-Signature: t=1792663200,v1=5f2b…

{
  "id": "evt_3hGkV0bq9rS1xYw2LmN4pQ7z",
  "event": "facts.confirmed",
  "site": "acme.com",
  "slug": "acme",
  "version": 4,
  "confirmedAt": "2026-10-22T10:00:00.000Z",
  "manifestUrl": "https://inite.ai/api/site/v1/manifest",
  "factsUrl": "https://inite.ai/api/site/v1/public/acme?d=acme.com"
}

content.approved

POST /your/endpoint
Content-Type: application/json
User-Agent: INITE-Webhooks/1.0 (+https://inite.ai/en/mcp#site-api)
INITE-Event: content.approved
INITE-Webhook-Id: evt_Vb1mR8sQx2LkT0wYh7nP4cZd
INITE-Signature: t=1792663200,v1=5f2b…

{
  "id": "evt_Vb1mR8sQx2LkT0wYh7nP4cZd",
  "event": "content.approved",
  "site": "acme.com",
  "slug": "acme",
  "article": {
    "id": "cm2y0v7ka0004",
    "lang": "en",
    "title": "How much does a dental cleaning cost in Austin?",
    "slug": "dental-cleaning-cost-austin",
    "metaDescription": "What a cleaning costs at Acme Dental, what it includes, and when insurance covers it.",
    "body": "## What a cleaning includes\n\nA cleaning at Acme Dental takes about 45 minutes…",
    "html": "<h2>What a cleaning includes</h2>\n<p>A cleaning at Acme Dental takes about 45 minutes…</p>\n",
    "sources": [
      {
        "url": "https://www.ada.org/resources/research/health-policy-institute",
        "title": "ADA Health Policy Institute"
      }
    ],
    "approvedAt": "2026-10-22T09:30:00.000Z"
  },
  "report": {
    "published": "https://inite.ai/api/site/v1/content/cm2y0v7ka0004/published",
    "failed": "https://inite.ai/api/site/v1/content/cm2y0v7ka0004/failed"
  }
}

content.approved carries the same article the queue serves, so a receiver can publish it without asking. Report the outcome to the report addresses with a site key, as a connector does; until then the article also stays in the queue.

lead.created

POST /your/endpoint
Content-Type: application/json
User-Agent: INITE-Webhooks/1.0 (+https://inite.ai/en/mcp#site-api)
INITE-Event: lead.created
INITE-Webhook-Id: evt_Qe5nB2vXk8LmR1tYz0cH7dWs
INITE-Signature: t=1792663200,v1=5f2b…

{
  "id": "evt_Qe5nB2vXk8LmR1tYz0cH7dWs",
  "event": "lead.created",
  "site": "acme.com",
  "slug": "acme",
  "lead": {
    "id": "cm2z4r9tb0007",
    "kind": "booking",
    "name": "Ana Costa",
    "email": "[email protected]",
    "phone": null,
    "message": "A cleaning, and my gums bleed a little.",
    "service": "Dental cleaning",
    "preferredTime": null,
    "windows": [
      {
        "date": "2026-10-30",
        "from": "10:00",
        "to": "12:00"
      }
    ],
    "partySize": null,
    "via": "mcp",
    "client": "claude-code",
    "factsVersion": 4,
    "createdAt": "2026-10-23T14:02:00.000Z"
  },
  "cabinetUrl": "https://inite.ai/en/acme/profile?tab=agents"
}

lead.created goes only where the owner chose “To my webhook” under Requests from agents. It carries the person’s name, contact and message so the business can reply: treat them as personal data. Below, the same request as the WebMCP script posts it.

{
  "tool": "request_booking",
  "arguments": {
    "service": "Dental cleaning",
    "preferred_windows": [
      {
        "date": "2026-10-30",
        "from": "10:00",
        "to": "12:00"
      }
    ],
    "name": "Ana Costa",
    "contact": {
      "email": "[email protected]"
    },
    "user_confirmed": true
  }
}

The signature

Check INITE-Signature before you trust the body. t is when it was signed, in Unix seconds; v1 is the HMAC-SHA256 of t, a dot and the raw body, keyed with your secret. Refuse a t more than five minutes from now. INITE-Webhook-Id stays the same on every retry of one event, so a repeat can be dropped.

Checking the signature in Node.js

import { createHmac, timingSafeEqual } from 'node:crypto'

// rawBody: the request body as received, before JSON.parse.
export function verify(rawBody, header, secret) {
  const parts = Object.fromEntries(header.split(',').map((p) => p.split('=')))
  const t = Number(parts.t)
  if (!t || Math.abs(Date.now() / 1000 - t) > 300) return false
  const want = createHmac('sha256', secret).update(\`${t}.${rawBody}\`).digest('hex')
  const got = String(parts.v1 ?? '')
  return got.length === want.length && timingSafeEqual(Buffer.from(got), Buffer.from(want))
}

Answer with any 2xx within ten seconds. Anything else is retried after 1, 5, 30, 120 and 360 minutes; after the sixth attempt the delivery is marked as failed. Redirects are not followed. The cabinet shows the last ten attempts for each address.