# pushpage
pushpage is a service that accepts HTML and returns a shareable public URL. It is purpose-built for AI agents: instead of dumping HTML or long-form content into chat, an agent POSTs to pushpage and hands the user a clean, clickable link.
## Constraints
- **Pages are public.** Anyone with the URL can read the page. Never publish content that contains secrets, credentials, personal data, or anything the user has not explicitly chosen to share.
- **Max payload:** 1 MB per request (app-level limit; the servlet ceiling is 10 MB but the app rejects above 1 MB).
- **Rate limits:** authenticated users — 10 publishes/min; guests (no API key) — 5 publishes/min per IP. Admin users are exempt.
- **Page retention:** guest pages auto-expire after 30 minutes. Authenticated pages persist for 30 days and are managed from the dashboard.
- **Format:** HTML only. Pages are served directly in a browser — write clean, self-contained HTML (inline CSS, no local file references).
## Base URL
Base URL resolution (pick the first that applies):
1. If `APP_SERVER_URL` is configured in the environment → use it.
2. Otherwise, use `https://pushpage.link` (the managed public instance).
Concrete fallback used in all examples below: `https://pushpage.link`
**HTTPS required:** the public instance (`pushpage.link`) requires HTTPS. Never downgrade to `http://pushpage.link` — requests will fail. Self-hosted instances may use HTTP if that is how `APP_SERVER_URL` is configured.
## Authentication
Most endpoints require an API key. Read it from the credentials file:
```bash
PUSHPAGE_API_KEY=$(cat ~/.config/pushpage/credentials 2>/dev/null | tr -d '[:space:]')
```
If the file is missing or empty, stop and tell the user:
> Your pushpage API key is not configured. Run the following to save it:
> ```bash
> mkdir -p ~/.config/pushpage && echo "pp_your_key_here" > ~/.config/pushpage/credentials
> ```
> You can find your key in the pushpage dashboard under Account → Generate API Key, or in the startup logs of a self-hosted instance.
Pass the key in every authenticated request as `X-Api-Key: $PUSHPAGE_API_KEY`.
**Exception — guest publishing:** `POST /api/pages` accepts requests with no API key. The page is created as a guest page that auto-expires after 30 minutes. Use this for quick one-off shares when no credentials are available.
## New user setup
If the user does not have an account yet, create one:
```bash
curl -s -X POST https://pushpage.link/api/auth/signup \
-H "Content-Type: application/json" \
-d '{"email": "user@example.com", "password": "choose-a-strong-password"}'
```
Returns `201 No Content` on success. The user can then log in at `https://pushpage.link/dashboard` to generate an API key.
## Primary operation — publish HTML
```bash
PUSHPAGE_API_KEY=$(cat ~/.config/pushpage/credentials 2>/dev/null | tr -d '[:space:]')
curl -s -X POST https://pushpage.link/api/pages \
-H "Content-Type: application/json" \
-H "X-Api-Key: $PUSHPAGE_API_KEY" \
-d '{
"html": "..."
}'
```
`title` is optional. When omitted or blank, the server extracts it from the HTML `
` tag; falls back to `"Untitled"`. Pass it explicitly to override what is in the HTML.
Response:
```json
{
"url": "https://pushpage.link/pages/abc123.html",
"id": "abc123"
}
```
Return the `url` to the user. That is the shareable link. Do not paste the HTML into chat.
**File upload variant** (multipart/form-data):
```bash
curl -s -X POST https://pushpage.link/api/pages \
-H "X-Api-Key: $PUSHPAGE_API_KEY" \
-F "file=@report.html"
```
## Secondary operations
### List published pages
```bash
curl -s https://pushpage.link/api/pages \
-H "X-Api-Key: $PUSHPAGE_API_KEY"
```
Returns an array of page objects with `id`, `title`, `created_at`, and `url`. Regular users see only their own pages; admins see all.
### Delete a page
```bash
curl -s -X DELETE https://pushpage.link/api/pages/{id} \
-H "X-Api-Key: $PUSHPAGE_API_KEY"
```
To update an existing page, delete it and publish a new one — pushpage does not support in-place edits via the REST API (use the MCP `publish_page` tool, which replaces by title if you want consistent naming).
### Health check (no auth required)
```bash
curl -s https://pushpage.link/api/health
```
## MCP server
A FastMCP server is available at `https://pushpage.link/mcp` (streamable-http transport). It exposes `publish_page`, `list_pages`, `delete_page`, and `health` tools. If your client supports MCP, prefer it over the direct API — authentication is handled via the `X-Api-Key` header in the MCP config.
### Claude Desktop config
Add to `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) or `%APPDATA%\Claude\claude_desktop_config.json` (Windows):
```json
{
"mcpServers": {
"pushpage": {
"type": "streamable-http",
"url": "https://pushpage.link/mcp",
"headers": {
"X-Api-Key": ""
}
}
}
}
```
Replace `` with the key from `~/.config/pushpage/credentials`. Restart Claude Desktop after saving.
### Other MCP clients
Any client that supports streamable-http MCP servers can connect to `https://pushpage.link/mcp` with the `X-Api-Key` header. Consult your client's documentation for the exact config format.
## Writing good HTML for pushpage
Pages are served directly in a browser — write clean, self-contained HTML:
- Use inline CSS — no external stylesheets
- Add `` for mobile responsiveness
- Include a `` tag — it appears in the browser tab and is used as the page title in the dashboard
- No references to local files; everything must be self-contained
- Tailwind via CDN works well: ``
- Charts: Chart.js CDN works well for data visualisations
## Typical agent flow
1. Read the API key from `~/.config/pushpage/credentials` — stop with the setup message if missing.
2. Build the full HTML for what the user asked for — include a `` tag in the ``.
3. POST to `/api/pages` with the key in `X-Api-Key` — title is extracted from the HTML automatically.
4. Extract the `url` from the response and return it to the user — do not paste the HTML into chat.
## Do not
- Do not publish pages that contain secrets, credentials, or private data — pages are publicly accessible to anyone with the link.
- Do not create duplicate pages for the same content — delete the old one first if you need to republish.
- Do not use `http://` with the managed instance — HTTPS only.
- Do not exceed 1 MB of HTML in a single request — split into multiple pages if needed.