Examples
Last updated: 2026-10-11
These examples select ns=public, which lists HTML, sites and files in the gallery and sitemap for Google, Bing and AI search. Omitted ns publishes privately: unlisted and not indexed; anyone with the link can still open it. The MCP wrapper also defaults to a private namespace. Password-protected publications are never listed. Ordinary TTL is 1–30 days, default 15, up to 90 with an owner token in a profile; owner-specific caps and eligible automatic extensions can affect expiry. Use returned expiresAt.
Use the returned primary link exactly. NEW sites and non-public HTML pages of format html require Dedicated subdomain (subdomain); everything else in any namespace defaults to Promotion (path). Creation can return an existing publication whose OLD/NEW cohort, link, and actual mode stay unchanged. OLD links retain their historical behavior. See delivery and authentication.
HTML Publishing
Simple HTML Page
curl -X POST 'https://brewpage.app/api/html?ns=public&format=html' \
-H 'Content-Type: application/json' \
-d '{"content":"<html><body><h1>Hello!</h1></body></html>"}'
Markdown with Password Protection
curl -X POST 'https://brewpage.app/api/html?ns=public&format=markdown' \
-H 'Content-Type: application/json' \
-H 'X-Password: replace-with-your-password' \
-d '{"content":"# Team Notes\n\nThis page requires a password."}'
Share a NEW protected publication’s clean returned link; browser readers unlock through the trusted gateway. API readers use X-Password. Never append ?p= to NEW links.
Custom TTL and Dedicated Subdomain
curl -X POST 'https://brewpage.app/api/html?ns=public&format=html&ttl=30' \
-H 'Content-Type: application/json' \
-H 'X-Delivery-Mode: subdomain' \
-d '{"content":"<p>This expires in 30 days</p>"}'
Namespace, format, and TTL belong in query parameters; password and delivery mode are headers. They are not fields in the authored content body.
Key-Value Store
Create, Read, and Update a Store
created=$(curl --fail-with-body -sS -X POST 'https://brewpage.app/api/kv?ns=public' \
-H 'Content-Type: application/json' \
-d '{"key":"theme","value":"dark"}')
id=$(printf '%s' "$created" | jq -r '.id')
owner_token=$(printf '%s' "$created" | jq -r '.ownerToken')
printf '%s' "$created" | jq -r '.link'
curl --fail-with-body "https://brewpage.app/api/kv/public/$id/theme"
curl --fail-with-body -X PUT "https://brewpage.app/api/kv/public/$id/theme" \
-H 'Content-Type: application/json' \
-H "X-Owner-Token: $owner_token" \
-d '{"value":"light"}'
Create with POST /api/kv; later PUT writes require the returned owner token. Keys can be read at GET /api/kv/{namespace}/{id}. Owner-scoped store listing uses GET /api/kv?ns=public with X-Owner-Token.
JSON Documents
Send the JSON document itself, without a document wrapper or collection route:
created=$(curl --fail-with-body -sS -X POST 'https://brewpage.app/api/json?ns=public' \
-H 'Content-Type: application/json' \
-d '{"name":"Alice","role":"admin"}')
id=$(printf '%s' "$created" | jq -r '.id')
owner_token=$(printf '%s' "$created" | jq -r '.ownerToken')
printf '%s' "$created" | jq -r '.link'
curl --fail-with-body "https://brewpage.app/api/json/public/$id"
curl --fail-with-body -X PUT "https://brewpage.app/api/json/public/$id" \
-H 'Content-Type: application/json' \
-H "X-Owner-Token: $owner_token" \
-d '{"name":"Alice","role":"editor"}'
Owner-scoped document listing uses GET /api/json?ns=public with X-Owner-Token.
File Hosting
curl -X POST 'https://brewpage.app/api/files?ns=public' -F 'file=@screenshot.png'
curl -X POST 'https://brewpage.app/api/files?ns=public' -F 'file=@report.pdf'
Sites (Multi-File HTML)
Upload a Site
curl -X POST 'https://brewpage.app/api/sites?ns=public' \
-F 'files=@index.html;type=text/html' \
-F 'files=@style.css;type=text/css' \
-F 'paths=index.html' \
-F 'paths=style.css'
Illustrative NEW site response (additional fields omitted):
{
"id": "aBcDeFgHiJ",
"namespace": "public",
"entryFile": "index.html",
"link": "https://k8m2n6p4q1.brewpage.app/",
"ownerLink": "https://brewpage.app/api/sites/public/aBcDeFgHiJ",
"routingCohort": "new-v1",
"deliveryMode": "subdomain",
"modeLocked": true,
"hostingVersion": 1,
"fileCount": 2,
"ownerToken": "your-secret-token"
}
The host label above is illustrative and independent of the resource ID. Use the actual returned link, not that label. The complete bundle shares one publication-specific host; /style.css and relative links resolve natively. Missing files return 404, without an SPA fallback. Existing OLD site links remain in their original form.
Or upload a built ZIP archive:
curl -X POST 'https://brewpage.app/api/sites?ns=public' \
-F 'archive=@site.zip;type=application/zip'
PUT /api/sites/{namespace}/{id} with X-Owner-Token and a new bundle replaces the entire file set at the same link; absent files are removed. Content replacement preserves hosting. MCP exposes publish_site and republish_site; SDK and CLI module specifications do not imply implemented clients.
Change Hosting
Only eligible NEW publications (not sites, not non-public html-format HTML) can switch between Promotion and Dedicated subdomain. Obtain current metadata with the owner-only hosting GET, then supply its hostingVersion (optional, recommended):
curl --fail-with-body 'https://brewpage.app/api/html/public/aBcDeFgHiJ/hosting' \
-H 'X-Owner-Token: replace-with-owner-token'
curl --fail-with-body -X PATCH 'https://brewpage.app/api/html/public/aBcDeFgHiJ/hosting' \
-H 'Content-Type: application/json' \
-H 'X-Owner-Token: replace-with-owner-token' \
-d '{"deliveryMode":"subdomain","expectedVersion":1}'
Replace the illustrative ID/token and version with your own current values. Mismatches are reported, not rejected: a stale version still applies, while OLD links, sites, and non-public html-format HTML pages stay unchanged; the 200 response then carries deliveryModeMatched: false, deliveryModeReason and deliveryNotice. Use the returned primary link. The reserved host survives both directions; ordinary content updates do not switch modes.
JavaScript / Fetch
const response = await fetch('https://brewpage.app/api/html?ns=public&format=html', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ content: '<h1>Published from JS</h1>' })
});
if (!response.ok) throw new Error(`Publish failed: ${response.status}`);
const { link, ownerToken } = await response.json();
console.log('Published at:', link);
// Save ownerToken securely for later owner operations.
Python
import requests
response = requests.post(
'https://brewpage.app/api/html',
params={'ns': 'public', 'format': 'markdown'},
json={'content': '# Report\n\nGenerated by Python script.'},
timeout=30,
)
response.raise_for_status()
data = response.json()
print(f"URL: {data['link']}")
# Save data['ownerToken'] securely for later owner operations.
Platform Statistics
curl -sS https://brewpage.app/api/stats | jq .
Gallery (Public Content)
curl https://brewpage.app/api/gallery
curl 'https://brewpage.app/api/gallery?q=hello&sort=date'
Owner listing uses GET /api/gallery?mine=true with X-Owner-Token; the MCP equivalent is search_gallery(mine=true, ownerToken="...").