BrewPage API — REST Reference
Publish HTML, Markdown, files, KV entries, JSON documents, and multi-file sites over HTTPS.
No signup required to publish. Keep the X-Owner-Token or the management link from the response to edit or delete later.
API docs & tools
/v3/api-docs.yaml.
JSON
OpenAPI 3.1 spec (JSON)
For programmatic clients, MCP servers, codegen. Alias /v3/api-docs.
LLM
llms.txt
Compact machine-readable reference for LLM agents.
LLM
llms-full.txt
Full AI-agent reference with every endpoint, field, error code.
MCP
brewpage-mcp
MCP server on npm for Claude, Codex, Cursor, Gemini.
SK
brewdoc:publish
Claude Code skill — publish documents from the IDE.
GH
brewpage-openapi
GitHub repo with the OpenAPI spec and Scalar site source.
Human-oriented walk-through of every resource: /help.
Basics — URL, auth, limits
- Base URL
https://brewpage.app/api/*- Publish auth
- None. Every POST returns
ownerTokenandmanageUrl; send the token asX-Owner-Tokento edit or delete later. - Namespace
- Send
ns=publicfor anything meant to be found or shared (docs, guides, demos, portfolios, reports, landing pages): listed in the public gallery and sitemap, so Google, Bing and AI search index it and people discover it. Public pages are served right on the brewpage.app domain, which gives them the strongest reach in search; a page whose code needs its own origin (cookies, storage) gets its own subdomain automatically. Anyone can find and read a public page: never put secrets, tokens or personal data there. Nons(default): private. Unlisted and not indexed; anyone who has the link can still open it. Public pages, sites and files are listed; JSON and KV are never listed or indexed. BrewPage MCP generates an unlisted namespace when omitted; passpublicexplicitly to list it. Other namespaces are excluded from the gallery, sitemap and search. Anyone with an unpassworded link can read it; an unlisted address is not a secret. - Password
- Optional
X-Passwordheader for access-gated content. Programmatic readers use this header on apex API endpoints. New browser links stay clean and use trusted unlock; legacy?p=behavior is unchanged. - Admin
/api/admin/*requiresX-Admin-Password. Not for end-user traffic.- Rate limits
- Uploads & reads are rate-limited per IP.
429responses includeRetry-After. Details: /help#rate-limits. - User-Agent
- Required on every request. Format
AgentName/version. - TTL
- 15 days default, 30 days max (90 with a profile token). Override with
ttlquery param or body field. Expired content is permanently deleted by the nightly cleanup job.
Quick start — curl
Publish HTML (public)
curl -X POST "https://brewpage.app/api/html?ns=public" \
-H "Content-Type: application/json" \
-d '{"content":"<h1>Hello</h1>"}'
Response: {"id":"aB3xK9mP2q","namespace":"public","link":"https://brewpage.app/public/aB3xK9mP2q","ownerToken":"...","manageUrl":"..."}. Save ownerToken.
Upload a file
curl -X POST "https://brewpage.app/api/files?ns=public" \
-F "file=@report.pdf"
Write a KV entry
curl -X POST "https://brewpage.app/api/kv?ns=public" \
-H "Content-Type: application/json" \
-d '{"key":"config","value":"v1"}'
Store a JSON document
curl -X POST "https://brewpage.app/api/json?ns=public" \
-H "Content-Type: application/json" \
-d '{"title":"Note","body":"..."}'
Update in place (PUT)
Already published? Replace the content without changing the short URL —
PUT /api/html/{ns}/{id}, PUT /api/json/{ns}/{id}, PUT /api/kv/{ns}/{id}/{key}.
Send the original X-Owner-Token.
curl -X PUT https://brewpage.app/api/html/public/aB3xK9mP2q \
-H "Content-Type: application/json" \
-H "X-Owner-Token: $OWNER_TOKEN" \
-d '{"content":"<h1>v2</h1>"}'
Multi-file sites republish the same way — PUT /api/sites/{ns}/{id} with your
X-Owner-Token does a full replace of the file set, keeping the same short URL and ID.
curl -X PUT https://brewpage.app/api/sites/public/aB3xK9mP2q \
-H "X-Owner-Token: $OWNER_TOKEN" \
-F "archive=@site-v2.zip"
Immutable on update: filename, showTopBar.
To change those, delete and recreate. HTML and site updates: ?tags= (sites: form field) replaces the stored tags; omit it to keep them. Token workflow: /help#owner-token.
Old publications (made before 5 October 2026) are read-only: 409 OLD_PUBLICATION_READ_ONLY; POST the content to its
createUrl (same namespace) and report only the new reader URL. Keep the owner token private; never paste it into chat. HTML also adds republishUrl (browser). The old link keeps working; delete still works.
Owner actions
With X-Owner-Token: hide from gallery & search, change link, reset management link, set a password,
extend 90 days (profile token), per-page stats. Profile tokens: scope publish or admin
(also manages tokens), optional expiry at creation. Endpoints: OpenAPI.
Guide: /help#manage.
Publication hosting
New publications with persisted routingCohort: "new-v1" support
Domain (path, a branded brewpage.app link) and
Subdomain (subdomain, the publication's own BrewPage subdomain).
Sites and HTML pages in a non-public namespace always get a subdomain; an explicit path is still published there, with deliveryModeMatched: false and a deliveryNotice.
Other publications default to the BrewPage path address, including password-protected ones, and may choose a subdomain.
Public pages without a password can be indexed by search engines in both modes.
Send optional X-Delivery-Mode: path|subdomain on HTML, Markdown, file, JSON, KV or site creation.
Any kind may use a subdomain: HTML pages and sites are served there as authored documents, every other kind
opens in the same BrewPage viewer (top bar, Download) on either address.
This header is transport metadata, never a field added to an authored JSON document or upload.
PUT keeps the address mode and ignores the header (with a notice); a PUT that makes a
non-public BrewPage-link page HTML moves it to a subdomain, and the old link redirects there.
POST /api/html without X-Delivery-Mode: a public HTML or Markdown page whose own
inline code clearly needs browser features a BrewPage link (path) does not provide may be
published on its own subdomain. The response then carries deliveryModeReason: "auto:<codes>",
a plain-text deliveryNotice and a subdomain link;
requestedDeliveryMode stays null. Codes are comma-separated:
storage, cookies, history, downloads,
top-navigation, media-capture (camera, microphone, screen or location),
pointer-lock, embeds, fullscreen.
An explicit header always wins; with path, and on PUT or an idempotent duplicate
(neither changes the address), the response may carry deliveryModeReason: "advisory:<codes>"
and a notice instead. Both fields are absent when nothing applies, and not every such page is recognized.
To move a page back, change its hosting with "deliveryMode":"path".
Follow the returned link; do not construct a hostname from the mixed-case resource ID.
Hosts use a separate permanent lowercase identifier. New responses include managementLink,
routingCohort, deliveryMode, requestedDeliveryMode,
effectiveDeliveryMode, deliveryModeMatched, access,
modeLocked and hostingVersion.
Mode and version mismatches are reported, not rejected: the request does the closest valid thing,
returns the real link, and adds a plain-text deliveryNotice with a
deliveryModeReason code (both absent when nothing applies).
Unrequested modes have null request/match fields. access is public,
unlisted or protected. Management and owner API links remain on the apex.
A create request can return an existing publication. Its identity, cohort, mode and link remain those of the existing publication;
a requested mode does not change it. Matching between new publications is supported; matching against legacy
publications is not guaranteed. Legacy publications retain their URLs and behavior, have locked hosting,
and report routingCohort: "old" with null mode/version/management metadata.
Owner-only GET /api/{type}/{ns}/{id}/hosting supports
html|files|json|kv|sites. Owner-only PATCH at the same path supports
html|files|json|kv for new publications without a required subdomain; sites, forced pages
and legacy publications answer 200 unchanged with a notice. Both use X-Owner-Token
and return hosting metadata with Cache-Control: private, no-store.
Change a new publication to Subdomain
curl -X PATCH https://brewpage.app/api/html/public/aB3xK9mP2q/hosting \
-H "Content-Type: application/json" \
-H "X-Owner-Token: $OWNER_TOKEN" \
-d '{"deliveryMode":"subdomain","expectedVersion":1}'
Read the current version first and send it as expectedVersion. A real change increments it;
a same-mode request with the current version leaves it unchanged. Switching either way retains the same
host reservation and owner/content/TTL. A stale or missing version is not rejected: the change applies
to the stored version (a stale one adds a deliveryNotice). Incorrect owner proof returns
403 OWNER_AUTHORIZATION_FAILED; an unknown mode or a malformed version (not a positive integer)
returns 400; unavailable publications return 404.
While new hosting is paused, real changes return 503 HOSTING_CREATION_PAUSED
with Retry-After: 1; current-version no-ops still succeed.
Subdomain hosts serve publication content only, with no platform API.
HTML pages and site HTML documents run natively (scripts, modules, forms, navigation; no sandbox, no rewriting)
and carry the small BrewPage attribution badge; nothing else is injected. Files, JSON and KV are never modified.
For Markdown, code/text, files, JSON and KV a browser document navigation to the subdomain returns the BrewPage viewer;
any other request receives the stored bytes as before.
One dedicated host serves the entire new site bundle, including every page and asset; it is not shared across a user's sites.
Sites retain native assets, directory indexes and multipage links; missing paths return 404, without SPA fallback.
New subdomain short URLs redirect to the returned host; active API documents use safe attachment disposition.
New p query parameters do not authenticate and are removed before trusted unlock.
BrewPage-mode HTML uses stricter script, cookie, embed and navigation restrictions.
See hosting and password limits before choosing a mode.
Revoke existing browser reader access with owner-only
POST /api/{type}/{ns}/{id}/access/revoke, using X-Owner-Token.
Supported types: html|files|json|kv|sites. Protected new publications return
200 {"revoked":true}; readers must unlock again. Content, password, host and hosting version stay unchanged,
and other publications' grants remain usable. Legacy or unprotected publications return
400 ACCESS_REVOKE_UNAVAILABLE; incorrect owner proof returns 403.
This cannot erase previously downloaded or offline content.
Resources & limits
| Resource | Endpoint | Size | Per-NS limit |
|---|---|---|---|
| HTML | POST /api/html |
5 MB | — |
| Markdown | POST /api/html?format=markdown |
5 MB | — |
| File | POST /api/files |
5 MB (video 20 MB, audio 5 MB) | 1 000 files |
| Site (multi-file) | POST /api/sites |
20 MB total (uncompressed) · 5 MB/file · 200 files | — |
| Site republish | PUT /api/sites/{ns}/{id} |
20 MB total (uncompressed) · 5 MB/file · 200 files | — |
| KV entry | POST /api/kv |
1 MB per value | 1 000 keys |
| JSON document | POST /api/json |
1 MB per doc | 10 000 docs / collection |
Each upload request: up to 25 MB. Site uploads skip system files such as .DS_Store and __MACOSX/; they don't count toward the limits. Current values: GET /api/limits.
TTL: default 15 days, max 30 days for every resource (90 with a profile token). After TTL the nightly cleanup job permanently deletes content — no recovery.
Integrate your AI agent
Three ways, easiest first:
Install the BrewPage publish skill in Claude Code: /plugin marketplace add kochetkov-ma/claude-brewcode /plugin install brewdoc@claude-brewcode Then run /publish to share the current document.
Install the BrewPage MCP server for my agent: npx -y brewpage-mcp@1.16.8 Then register it under "brewpage" in my MCP config and restart. No install: add https://brewpage.app/mcp as a remote MCP server (no auth).
curl -sS -X POST https://brewpage.app/api/html \
-H "Content-Type: application/json" \
-d '{"content":"<h1>hi</h1>"}' | jq -r .link
Drop this into your agent’s system prompt
LLM integration
Two text files describe the API for LLMs:
| File | Size | When to use |
|---|---|---|
| /llms.txt | ~4 KB | Short reference — paste into a system prompt so the LLM knows how to call the API. |
| /llms-full.txt | ~30 KB | Full reference with every endpoint, field, error code. Use for RAG or long-context agents. |
| OpenAPI YAML | ~25% smaller than JSON | Preferred for LLM context. Fewer tokens, same information. |
| OpenAPI JSON | — | Programmatic clients, MCP servers, OpenAPI codegen. |
Ready-made prompts for Claude / ChatGPT / Cursor
Paste into the system prompt
Use https://brewpage.app/llms.txt as your quick reference for the BrewPage REST API.
When asked to publish a page, file, or JSON document, call the endpoints listed there.
Full-context variant
For the complete endpoint / field / error reference, fetch
https://brewpage.app/llms-full.txt and treat it as the authoritative BrewPage
API spec for this session.
Stats & views
Public aggregates live at GET /api/stats and GET /api/stats/timeseries. No auth.
What counts as a view?
The canonical definition of a view (which HTTP paths increment counters, today vs total, excluded paths) is the Views section of docs/architecture.md. When in doubt, that section is the source of truth.
Live chart with the same numbers: home page stats section.
See also
- /help — human-friendly guide to every resource type.
- /advanced — browser UI for Owner Token, KV, JSON, file manager.
- How do I delete a page? — FAQ entry on the home page.
- Frequently Asked Questions — home page FAQ.
- brewpage-openapi — GitHub repo with the OpenAPI spec and Scalar site.