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 .
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="...").