HTMLRadar · API
The HTMLRadar API
Updated September 2026
The HTMLRadar API is the same set of calls the dashboard and the MCP server use to create tracked links, list them, read who opened one, revoke a link, and replace a document behind links you already sent. Authenticate with a key from Settings; every response below is exactly what the route returns.
Every route here is the same write or read the browser already makes — the MCP server calls the same ones for your agent. Use it directly when a script, a cron job, or your own tool needs the same thing.
Authentication
Create a key at htmlradar.com/settings under API keys. A key is hr_live_ followed by 40 hexadecimal characters, shown once — only a hash is stored, so it can’t be recovered if lost. Send it on every call:
Authorization: Bearer hr_live_…
Choose a scope when you create the key. Full can create, replace and revoke; read-only can only list and read activity — a write from a read-only key comes back as a 403 naming the missing permission. Neither scope can delete anything; that stays on the website, where a person types the confirmation.
GET /api/v1/me
Is this key good, and what plan is it on. No parameters.
curl https://htmlradar.com/api/v1/me \ -H "Authorization: Bearer hr_live_…"
{
"user_id": "c1a2b3c4-…",
"tier": "free",
"free_links_used": 1,
"free_links_cap": 2
}On Pro, free_links_cap is null — there is no lifetime cap to report.
GET /api/v1/documents
The account’s documents, newest first, with how many links point at each one. Same paging as above. The phishing screen’s score is deliberately left out — it’s an operator signal, not a customer number.
curl https://htmlradar.com/api/v1/documents \ -H "Authorization: Bearer hr_live_…"
{
"documents": [
{
"document_id": "22222222-2222-4222-8222-222222222222",
"title": "Q3 proposal",
"created_at": "2026-08-30T10:00:00.000Z",
"share_count": 2
}
],
"next_before": null
}GET /api/v1/shares/{id}/activity
Whether the link was opened, by whom, how long they read, how far they scrolled, and which sections held them, in deck order. Add ?include_detail=true for a nested detail object per viewer — country, city, device and referrer — off by default, since that’s a named person’s location and device.
curl "https://htmlradar.com/api/v1/shares/11111111-1111-4111-8111-111111111111/activity" \ -H "Authorization: Bearer hr_live_…"
{
"share_id": "11111111-1111-4111-8111-111111111111",
"url": "https://htmlradar.page/r/acme-proposal",
"opened": true,
"viewers": [
{
"label": "Acme",
"email": "[email protected]",
"first_open": "2026-08-29T14:02:00.000Z",
"last_seen": "2026-08-29T14:09:00.000Z",
"active_seconds": 252,
"max_scroll": 87,
"sections": [
{ "title": "The Ask", "time_seconds": 161 },
{ "title": "Problem", "time_seconds": 48 }
],
"detail": { "country": "US", "city": "Austin", "device": "desktop", "referrer": null }
}
]
}label is the link’s own recipient_label, the same on every row — not the viewer’s name; detail only appears with include_detail. A link nobody has opened returns { "opened": false, "viewers": [] }.
POST /api/v1/shares/{id}/revoke
Switches a link off. Reversible — send { "revoked": false } to put it back on; an empty body revokes.
curl -X POST "https://htmlradar.com/api/v1/shares/11111111-1111-4111-8111-111111111111/revoke" \ -H "Authorization: Bearer hr_live_…"
{
"share_id": "11111111-1111-4111-8111-111111111111",
"url": "https://htmlradar.page/r/acme-proposal",
"revoked": true,
"revoked_at": "2026-09-04T12:00:00.000Z"
}POST /api/v1/documents/{id}/replace
Puts new content behind every link already sent — same addresses, same settings, same reading history, no second link. The new HTML runs through the same phishing screen as any upload; the previous version stays in the document’s history.
curl -X POST "https://htmlradar.com/api/v1/documents/22222222-2222-4222-8222-222222222222/replace" \
-H "Authorization: Bearer hr_live_…" \
-H "Content-Type: application/json" \
-d '{ "html": "<html>…</html>" }'{
"document_id": "22222222-2222-4222-8222-222222222222",
"version": 2,
"links_unchanged": true
}A conflict — someone else replaced or deleted the document mid-upload — returns a 409 rather than overwriting anything; read the current version and try again.
Errors and rate limits
Every error is JSON with an error field:
| Status | error | When |
|---|---|---|
| 401 | invalid_api_key | The Authorization header is missing or the key is wrong. |
| 402 | free_limit_reached | The free plan’s two-link cap is reached; body has upgrade_url. |
| 403 | read_only_key | A read-only key called a route that creates, revokes or replaces. |
| 404 | not_found | Wrong id, or someone else’s — both read the same, on purpose. |
| 408 | request_timeout | The request body stopped arriving before it finished. |
| 409 | conflict | /replace only: another replace or a delete landed on the document first. |
| 413 | too_large | Over the 5 MB document cap. The body carries max_bytes. |
| 422 | validation | The body is missing a required field or one is the wrong shape. |
| 429 | rate_limited | Over an hourly budget. retry_after_seconds is in the body and the Retry-After header. |
| 500 | internal / storage_failed | Something broke on our side. Nothing was written. |
Every limit is per hour, on a rolling window rather than the clock hour:
| Route | Budget |
|---|---|
| GET /api/v1/me | 60/hour, per key |
| POST /api/v1/shares, POST /api/v1/documents/{id}/replace | 75/hour Pro, 30/hour free, per account — plus 120/hour per address |
| GET /api/v1/shares, GET /api/v1/documents, POST /api/v1/shares/{id}/revoke | 120/hour, per account |
| GET /api/v1/shares/{id}/activity | 300/hour, per key |
| A missing or wrong key | 60/hour, per address |
The same calls from an agent
Everything above is also what the HTMLRadar MCP server calls, wrapped as seven tools an agent asks for in words — share_html is POST /api/v1/shares, get_share_activity is the activity route above. Call the API directly from a script; use the MCP server when an agent should call it for you.
The API stores nothing the dashboard doesn’t already store: the document, the link’s settings, and who opened it. Full detail is in the privacy policy.
Related: MCP server, create an API key, and self-hosted document tracking.