HTML Docs turns static HTML into a collaborative document. On import the page is split into regions — the block-level elements (paragraphs, headings, list items, table cells) — and each region becomes independently editable. The API is how an agent reads those regions, edits them, comments on them, and tracks every change.
All endpoints live under https://www.html-docs.com/api/v1. Requests and responses are JSON unless noted; document content is HTML or Markdown. The maximum request body is 2 MB.
The reference below is mirrored from the running code. The always-current machine-readable contract is GET /api/v1.
Getting started
Authentication#
Two ways to authorize a request — an account key, or a per-document token.
Agent API keys are account-level. A key acts as its owner and can reach every document that account owns or collaborates on. Send it as a bearer token (or the x-api-key header). Mint and revoke keys at /settings/api-keys. Keys are shown once and start with hdk_.
curl https://www.html-docs.com/api/v1/docs/<id> \ -H 'Authorization: Bearer hdk_live_xxx'
Document tokens are per-document share tokens — the kind returned by POST /docs. A token authorizes one document. It always grants read access; it grants write access on anonymous documents, and on human-owned documents only when the owner has enabled link editing.
curl https://www.html-docs.com/api/v1/docs/<id> \ -H 'x-doc-token: <token>' # or as a query param curl 'https://www.html-docs.com/api/v1/docs/<id>?token=<token>'
x-agent-name header (e.g. Claude Code) to label the comments and versions your agent creates. They are attributed to that name and rendered distinctly from human contributions in the editor.Status codes
200 / 201 / 204OK · Created · No Content (a successful delete).
400Malformed JSON, a missing required field, or an invalid parent_id.
401No credentials were supplied at all.
403Invalid/revoked key, wrong doc token, a read-only document, or editing a human-authored comment.
404Unknown — or unreachable — document, region, comment, or version. Existence is not leaked.
413The request body exceeded the 2 MB limit.
429Too many requests in the window. Honor the Retry-After header.
500Something failed server-side. Safe to retry with backoff.
{
"error": "Invalid token for this document."
}Each credential — an agent key or a doc token — gets 600 reads and 60 writes per rolling 60-second window. Over the limit, the API responds 429 with a Retry-After header in seconds — wait that long and retry.
HTTP/1.1 429 Too Many Requests
Retry-After: 42
{ "error": "Rate limit exceeded. Slow down and retry." }# 1 — publish a page (no auth — hosted at /site/<slug>)
curl -sS -X POST https://www.html-docs.com/api/v1/docs \
-H 'Content-Type: text/html' --data-binary @page.html
# → { "url": "https://www.html-docs.com/site/page-a7k2b9f1", "slug": "page-a7k2b9f1",
# "editUrl": "https://www.html-docs.com/s/ab12cd34?present=1", "token": "ab12cd34" }
# 1b — or publish with an agent key + custom slug (permanent, owned)
curl -sS -X POST 'https://www.html-docs.com/api/v1/docs?slug=my-dashboard' \
-H 'Authorization: Bearer hdk_live_xxx' \
-H 'Content-Type: text/html' --data-binary @dashboard.html
# → { "url": "https://www.html-docs.com/site/my-dashboard", "slug": "my-dashboard", "owned": true }
# 2 — read it back: title, html_content, and editable regions
curl -sS https://www.html-docs.com/api/v1/docs/d3f… -H 'x-doc-token: ab12cd34'
# 3 — edit one region in place (comment anchors survive)
curl -sS -X PATCH https://www.html-docs.com/api/v1/docs/d3f…/regions/region-7a1c \
-H 'x-doc-token: ab12cd34' -H 'Content-Type: application/json' \
-d '{"content":"<p>The revised opening paragraph.</p>"}'
# 4 — leave a comment anchored to a span of text
curl -sS -X POST https://www.html-docs.com/api/v1/docs/d3f…/comments \
-H 'x-doc-token: ab12cd34' -H 'Content-Type: application/json' \
-d '{"content":"Tighten this claim.","region_key":"region-7a1c","selected_text":"revised opening"}'That is the whole loop. No SDK, no install — every other endpoint is a variation on these four calls.
/api/v1/docsTurn an HTML or Markdown payload into a shareable document with a live URL in one call. Two auth modes:
- No auth — anonymous, unlisted. The response
tokenis the doc's share token; keep it for later updates. - Agent key (
Authorization: Bearer hdk_…) — permanent, private, owned by your account. Shows in your dashboard.
Send the body as raw text/html / text/markdown, or as JSON { html | markdown, title }.
<script> tags through untouched. This is the instant-hosting path — publish once, get a live URL with working JavaScript.Body
html / markdownThe document source. Raw body, or a JSON field. One or the other.
titleOptional title. Also accepted as a ?title= query param. Inferred from the HTML when omitted.
slugOptional custom slug for the hosted URL. Pass as ?slug= query param or X-Slug header. Auto-generated when omitted.
Response fields
idDocument UUID.
urlHosted page URL at /site/<slug> — raw HTML, no editor chrome.
slugThe published slug. Use for updates or custom URLs.
editUrlEditor URL (/s/<code>) for converting to a collaborative doc.
tokenShare token for later reads and edits via the API.
ownedPresent and true when created with an agent key.
visibilityPresent on owned docs. "private" by default.
Anonymous (zero friction)
# Anonymous — zero friction, auto-published at /site/<slug> curl -sS -X POST https://www.html-docs.com/api/v1/docs \ -H 'Content-Type: text/html' \ -H 'x-agent-name: Claude Code' \ --data-binary @page.html
{
"id": "d3f8a1c2-…",
"url": "https://www.html-docs.com/site/page-a7k2b9f1",
"slug": "page-a7k2b9f1",
"editUrl": "https://www.html-docs.com/s/ab12cd34?present=1",
"token": "ab12cd34"
}Authenticated (permanent, owned)
# Authenticated — permanent, owned, slug derived from title curl -sS -X POST https://www.html-docs.com/api/v1/docs \ -H 'Authorization: Bearer hdk_live_xxx' \ -H 'Content-Type: text/html' \ -H 'x-agent-name: Claude Code' \ --data-binary @dashboard.html
{
"id": "e7a4b2d1-…",
"url": "https://www.html-docs.com/site/launch-plan-c8d2",
"slug": "launch-plan-c8d2",
"editUrl": "https://www.html-docs.com/s/cd56ef78?present=1",
"token": "cd56ef78",
"owned": true,
"visibility": "private"
}Custom slug
# Custom slug — choose your own URL curl -sS -X POST 'https://www.html-docs.com/api/v1/docs?slug=my-dashboard' \ -H 'Authorization: Bearer hdk_live_xxx' \ -H 'Content-Type: text/html' \ --data-binary @dashboard.html # or via header: curl -sS -X POST https://www.html-docs.com/api/v1/docs \ -H 'Authorization: Bearer hdk_live_xxx' \ -H 'X-Slug: my-dashboard' \ -H 'Content-Type: text/html' \ --data-binary @dashboard.html
/api/v1/docs/:idRead a document: its title, metadata, full html_content (the shell, with {{region-key}} placeholders), and the regions array — each an independently editable block.
curl -sS https://www.html-docs.com/api/v1/docs/d3f8a1c2-… \ -H 'x-doc-token: ab12cd34'
{
"id": "d3f8a1c2-…",
"title": "Launch plan",
"visibility": "unlisted",
"share_can_edit": false,
"html_content": "<!doctype html>… {{region-7a1c}} …",
"regions": [
{ "region_key": "region-7a1c", "content": "<p>The opening paragraph.</p>" },
{ "region_key": "region-b920", "content": "<h2>Milestones</h2>" }
],
"updated_at": "2026-05-18T19:04:22.118Z"
}/api/v1/docs/:idReplace a document's content wholesale (PATCH is an alias). The prior state is snapshotted to version history first, so a PUT is always restorable.
PUT re-derives every region key, so comments anchored to the old content are orphaned. For a targeted change, prefer PATCH /regions/:key — it preserves anchors.curl -sS -X PUT https://www.html-docs.com/api/v1/docs/d3f8a1c2-… \ -H 'x-doc-token: ab12cd34' \ -H 'Content-Type: text/markdown' \ --data-binary @rewrite.md
/api/v1/docs/:id/regions/:regionKeyRead one region's current HTML content.
curl -sS https://www.html-docs.com/api/v1/docs/d3f8a1c2-…/regions/region-7a1c \ -H 'x-doc-token: ab12cd34'
/api/v1/docs/:id/regions/:regionKeyReplace one region's content. Only the named region changes — every other region, and the comments anchored to it, are left intact. This is the precise edit path an agent should reach for. Editing a human-owned document checkpoints a version first. An unknown region key returns 404 — regions are never created this way.
Body
contentThe replacement HTML. JSON { "content": "…" }, or a raw text/html body.
curl -sS -X PATCH https://www.html-docs.com/api/v1/docs/d3f8a1c2-…/regions/region-7a1c \
-H 'x-doc-token: ab12cd34' \
-H 'Content-Type: application/json' \
-d '{"content":"<p>The revised opening paragraph.</p>"}'{
"region_key": "region-7a1c",
"content": "<p>The revised opening paragraph.</p>"
}/api/v1/docs/:id/commentsList comment threads — root comments with nested replies.
Query parameters
resolvedFilter by resolved state. Defaults to all.
region_keyRestrict to comments anchored to one region.
curl -sS 'https://www.html-docs.com/api/v1/docs/d3f8a1c2-…/comments?resolved=false' \ -H 'x-doc-token: ab12cd34'
{
"comments": [
{
"id": "c1a2…",
"author_type": "human",
"author_name": "Priya",
"region_key": "region-7a1c",
"selected_text": "revised opening",
"content": "Can we lead with the metric instead?",
"resolved": false,
"replies": [
{ "id": "c9f0…", "author_type": "agent", "author_name": "Claude Code",
"content": "Done — moved the 4x figure into the first line." }
]
}
]
}/api/v1/docs/:id/commentsAdd a comment. A comment with a selected_text snippet shows a highlight on the page; one with only a region_key is invisible to the reader — so always pass a short, exact, plain-text snippet. Created comments are attributed author_type: "agent".
Body
contentThe comment text.
region_keyAnchor the comment to a region. Must exist on the document.
selected_textA short, exact, verbatim plain-text snippet to highlight within the region.
parent_idPost as a reply within an existing thread on this document.
anchor_offsetDisambiguate when selected_text repeats in the region. Usually omitted.
curl -sS -X POST https://www.html-docs.com/api/v1/docs/d3f8a1c2-…/comments \
-H 'x-doc-token: ab12cd34' \
-H 'Content-Type: application/json' \
-d '{
"content": "This number needs a source.",
"region_key": "region-b920",
"selected_text": "3.8x faster"
}'{
"comment": {
"id": "c1a2b3c4-…",
"author_type": "agent",
"author_name": "Claude Code",
"region_key": "region-b920",
"selected_text": "3.8x faster",
"content": "This number needs a source.",
"resolved": false,
"replies": []
}
}/api/v1/docs/:id/comments/:commentId/api/v1/docs/:id/comments/:commentIdEdit ({ content }) or delete a comment. An agent may only modify comments authored by an agent — editing or deleting a human's comment returns 403. A delete returns 204.
/api/v1/docs/:id/comments/:commentId/resolveResolve or unresolve a thread with { "resolved": true | false } (omit the body to resolve). Resolving is thread management, not editing — it works on any comment, human- or agent-authored, and is idempotent.
curl -sS -X POST \
https://www.html-docs.com/api/v1/docs/d3f8a1c2-…/comments/c1a2b3c4-…/resolve \
-H 'x-doc-token: ab12cd34' \
-H 'Content-Type: application/json' \
-d '{"resolved":true}'/api/v1/docs/:id/versionsList versions, newest first. The heavy snapshot blob is omitted unless ?include=snapshot is set.
{
"versions": [
{
"id": "v7c2…",
"version_number": 4,
"name": "Draft sent to client",
"author_type": "agent",
"agent_name": "Claude Code",
"created_by_name": null,
"created_at": "2026-05-18T19:10:00.000Z",
"region_count": 22
}
]
}/api/v1/docs/:id/versionsCapture a version of the current state. Pass an optional { "name": "…" }. A capture with no change since the latest version is deduped.
curl -sS -X POST https://www.html-docs.com/api/v1/docs/d3f8a1c2-…/versions \
-H 'x-doc-token: ab12cd34' \
-H 'Content-Type: application/json' \
-d '{"name":"Draft sent to client"}'/api/v1/docs/:id/versions/:versionId/restoreRoll the document back to a version. The current state is captured as a new version first, so the restore is itself undoable.
/api/v1/docs/:id/activityRecent events — comments created/edited/deleted/resolved, versions captured, content edits — newest first, covering human and agent activity alike. Poll it with ?since= for a cheap way to react to changes without a webhook.
Query parameters
sinceOnly events strictly after this time.
typeRestrict to event types, e.g. comment.created,version.created.
limitPage size. Default 50, max 200.
curl -sS 'https://www.html-docs.com/api/v1/docs/d3f8a1c2-…/activity?since=2026-05-18T19:00:00Z&type=comment.created' \ -H 'x-doc-token: ab12cd34'
{
"events": [
{
"type": "comment.created",
"actor_type": "human",
"actor_name": "Priya",
"region_key": "region-7a1c",
"created_at": "2026-05-18T19:06:41.220Z"
}
]
}Register a callback URL and HTML Docs will POST a JSON payload to it on each event. Account webhooks (POST /api/v1/webhooks) need an agent key; omit document_id to watch every document you own. Per-document webhooks (POST /api/v1/docs/:id/webhooks) also accept a doc token, so a token-only caller can subscribe to its one document.
Event types
comment.createdA new comment or reply was added.
comment.updatedA comment’s content was edited.
comment.deletedA comment was deleted.
comment.resolved / .unresolvedA thread was resolved or reopened.
version.createdA version was captured.
document.updatedDocument or region content changed.
/api/v1/webhooksBody
urlA public HTTPS callback URL.
document_idScope to one document. Omit to watch every document you own.
event_typesSubscribe to specific events. Omit for all of them.
descriptionAn optional label for your own bookkeeping.
curl -sS -X POST https://www.html-docs.com/api/v1/webhooks \
-H 'Authorization: Bearer hdk_live_xxx' \
-H 'Content-Type: application/json' \
-d '{
"url": "https://your-host.dev/htmldocs-hook",
"event_types": ["comment.created"],
"description": "Ping me on new comments"
}'{
"id": "wh_8a1c…",
"url": "https://your-host.dev/htmldocs-hook",
"document_id": null,
"event_types": ["comment.created"],
"scope": "account",
"signing_secret": "whsec_… (shown once — store it now)",
"note": "Store signing_secret now — it is not shown again."
}The response carries signing_secret once. Verify every delivery with an HMAC-SHA256 of the raw request body keyed by that secret, and compare it against the X-HtmlDocs-Signature header. GET /api/v1/webhooks lists your hooks; DELETE /api/v1/webhooks/:id revokes one.
import crypto from 'node:crypto'
// Verify an incoming webhook delivery.
function isValid(rawBody: string, signature: string, secret: string) {
const expected = crypto
.createHmac('sha256', secret)
.update(rawBody)
.digest('hex')
return crypto.timingSafeEqual(
Buffer.from(expected),
Buffer.from(signature),
)
}
// signature arrives in the X-HtmlDocs-Signature headerInstall the one-file HTML Docs skill and Claude Code can drive every endpoint above with curl — or use the MCP server for native tool integration. It creates a doc, hands you the link, and then keeps editing it while you comment. The four patterns below are the ones that pay off the fastest.
mkdir -p ~/.claude/skills/html-docs \ && curl -fsSL https://www.html-docs.com/agents/skill.md -o ~/.claude/skills/html-docs/SKILL.md
Instant web hosting for agents
Publish any HTML — a dashboard, a chart, an interactive app — and get a live URL in seconds. Inline scripts survive, so Chart.js, D3, Plotly, and SPAs all work. One curl, one URL, done.
Build an interactive dashboard showing <TOPIC> with Chart.js charts and publish it to HTML Docs. Use the API: curl -X POST https://www.html-docs.com/api/v1/docs -H 'Content-Type: text/html' --data-binary @dashboard.html. Give me the live URL.
A living implementation log
The agent keeps a notes doc current as it codes — design decisions, deviations, open questions — so you can follow along and comment in real time instead of reading a wall of diffs at the end.
Implement <SPEC>. Create one HTML Docs page as a running implementation log and PATCH its regions as you go — capture design decisions, deviations from the spec, tradeoffs, and open questions. Give me the link now so I can comment while you work.
A design-review loop
The agent publishes a page, you mark it up with comments, and it pulls your comments back through GET /comments and revises the affected regions — then resolves each thread it addressed.
Design a landing page for <PRODUCT> and publish it to HTML Docs. Then poll the comments on that doc; when I leave feedback, revise the relevant regions, reply to each comment with what changed, and resolve it.
Review a doc someone sent you
Hand the agent any HTML Docs link. It reads every region and leaves specific, text-anchored comments — the same workflow a human reviewer uses.
Review this HTML Docs page critically: <LINK>. Leave a comment on each issue you find, anchored to the exact text, and use the name "Reviewer Agent".
React to changes as they happen
Register a webhook (or poll the activity feed with ?since=) so the agent wakes only when a human comments — then answers or revises without you re-prompting it.
Register a webhook on this doc for comment.created events pointing at <YOUR_ENDPOINT>. When a human comment comes in, address it and resolve the thread.
PATCHes keep comment anchors stable across a long editing session, every write is snapshotted so nothing is lost, and the comment thread gives the agent a structured channel to receive your feedback. The agent edits; you review in place; it revises from your comments. That is the loop.The @html-docs/cli package includes a built-in Model Context Protocol server. MCP gives your agent native tools for publishing, reading, editing, and commenting — no curl commands, no skill file required.
{
"mcpServers": {
"html-docs": {
"command": "npx",
"args": ["@html-docs/cli", "--mcp"]
}
}
}Available tools
| Tool | Description | Required params |
|---|---|---|
| publish | Publish HTML content to a live URL | html |
| publish_file | Publish a local HTML file | path |
| update | Update an existing document | id, html |
| read | Read document content and regions | id |
| comment | Add a comment anchored to text | id, content, region_key, selected_text |
| list_comments | List all comments on a document | id |
All tools also accept optional api_key, token, slug, and title params where applicable. Auth falls back to the HTMLDOCS_API_KEY env var or ~/.htmldocs/credentials (saved via npx @html-docs/cli auth).
One curl away from a collaborative doc.
Start with the quickstart, or hand the skill to your agent and let it make the first one.
Core resources
Comments#
Threaded, text-anchored comments — the channel between an agent and a human reviewer.