Documentation

API reference

Publish and manage HTML files from your own tools.

Docs

Start

Getting started

Build

CLI API MCP Skills ChatGPT App

Operate

Troubleshooting

Quick actions

Copy upload curlPublish HTML with an API key.
Copy update curlReplace an existing page.
Copy list files curlFetch account files.
Create an API keyOpen account settings.
Copy integration promptGive this to a coding agent.

Base URL

Use the production Worker API:

https://pagr.link

Published pages are served from:

https://uc.pagr.link/<slug>

All endpoint paths in this reference are relative to the Worker API base URL unless otherwise noted.

Authentication

Authenticated API requests use a Pagr API key or a Clerk bearer token in the Authorization header.

Authorization: Bearer $PAGR_API_KEY

Create or rotate API keys from the Pagr settings or CLI page. Do not expose API keys in browser code, generated pages, public repositories, or AI prompts.

POST /api/upload is the only endpoint that accepts anonymous requests. All other API endpoints require authentication.

Upload HTML

Send raw HTML as the request body.

POST /api/upload
Content-Type: text/html; charset=utf-8
X-Pagr-Title: Optional title
X-Pagr-TTL: 30d
X-Pagr-Hide-Banner: true
curl -X POST https://pagr.link/api/upload \
  -H "Authorization: Bearer $PAGR_API_KEY" \
  -H "Content-Type: text/html; charset=utf-8" \
  -H "X-Pagr-Title: Research brief" \
  -H "X-Pagr-TTL: 30d" \
  --data-binary @brief.html

If X-Pagr-Title is omitted, Pagr tries to extract the document title from the uploaded HTML.

Authenticated TTL values are never, 24h, 7d, 30d, and 1-visit. Missing TTL values use the account tier default: Free = 7d, Pro/Team = never. Free accounts can explicitly use 24h or 7d; never, 30d, and 1-visit require Pro or Team.

X-Pagr-Hide-Banner: true hides the hosted Pagr banner for Pro and Team accounts.

Anonymous uploads

The same endpoint accepts anonymous uploads when the Authorization header is omitted. Anonymous uploads are intended for quick sharing.

  • Limit: 1 MB per file.
  • Expiry: 24 hours.
  • Rate limit: 10 uploads per hour per source IP.
  • Response includes expiresAt, ttl, anonymous, and claimToken.

Anonymous pages can be claimed into an authenticated account before they expire.

Authenticated upload response

Authenticated uploads return a JSON object like this:

{
  "documentId": "9f631a9d-4b07-4c65-91f0-3a3f3de741cb",
  "slug": "weekly-report",
  "autoSlug": "weekly-report",
  "canonicalSlug": "weekly-report",
  "url": "https://uc.pagr.link/weekly-report",
  "expiresAt": 1790000000,
  "ttl": "30d"
}

Store documentId if your integration needs to update the same page even after a slug changes.

Update by slug

Replace the HTML content for an existing page by slug.

PUT /api/upload/:slug

This overwrites the current HTML while keeping the public URL stable. Pagr does not keep older copies for restore.

curl -X PUT https://pagr.link/api/upload/weekly-report \
  -H "Authorization: Bearer $PAGR_API_KEY" \
  -H "Content-Type: text/html; charset=utf-8" \
  --data-binary @brief.html

Optional update headers:

  • X-Pagr-Title updates the page title.
  • X-Pagr-Hide-Banner can be true or false for Pro and Team accounts.

Update by document ID

Document IDs are stable even when a custom slug changes.

PUT /api/upload/id/:documentId

Use this path for CLI, MCP, and other automation that stores page metadata between runs. It replaces the current HTML content for the page and returns the current canonical slug and URL.

List files

GET /api/files?limit=100&cursor=...

The response includes files and an optional cursor for pagination. The limit parameter is normalized by the API and defaults to the service limit when omitted or invalid.

Get one file

GET /api/files/:slug

Returns metadata for a file owned by the authenticated account.

Patch metadata

PATCH /api/files/:slug
Content-Type: application/json

The JSON body can include:

  • title to rename the page in dashboards and metadata.
  • slug to set a custom slug.
  • slug as null or "" to remove the custom slug and return to the auto slug.
  • password as a non-empty string to enable password protection.
  • password as null or "" to remove password protection.
  • ttl as never, 24h, 7d, 30d, or 1-visit to change or renew expiration.
  • hideBanner as a boolean to show or hide the hosted Pagr banner.

Custom slugs, password protection, and hiding the banner are plan-gated features. Changing expiration uses the same tier policy as upload: Free can choose 24h or 7d; Pro and Team can choose all TTL values.

Delete file

DELETE /api/files/:slug

Deletes the file content, metadata, aliases, and related document ID mapping.

Claim anonymous upload

POST /api/files/:slug/claim
Content-Type: application/json
{
  "claimToken": "claim_token_from_upload_response"
}

This transfers an anonymous upload into the authenticated account before it expires. The user must have enough file quota.

Analytics

GET /api/analytics/:slug

Analytics are available on Pro and Team plans. The response includes recent totals, daily views, top referrers, top countries, and the analytics retention window for the account.

User and API keys

GET /api/user
PATCH /api/user/settings
GET /api/api-keys
POST /api/api-keys
DELETE /api/api-keys/:hash

GET /api/user returns the active plan, resolved feature limits, settings, file count, and subscription state. PATCH /api/user/settings currently supports hideHostedBanner for Pro and Team accounts.

API key create/list/delete endpoints manage hashed API keys for the authenticated user or active organization scope. POST /api/api-keys returns the full key once; store it immediately.

Plan limits

Current production limits from the live tier catalog:

  • Free: 25 active files, 1 MB per file, 7-day default TTL.
  • Pro: 500 active files, 25 MB per file, permanent by default.
  • Team: 1000 active files, 50 MB per file, permanent by default.

Pro and Team unlock custom slugs, password protection, analytics, read-once pages, and hiding the hosted Pagr banner.

Errors

Handle errors directly and show the API message to the user when possible.

  • 400 for invalid JSON or request bodies.
  • 401 for missing or invalid authentication on protected endpoints.
  • 403 for plan-gated features or quota limits.
  • 404 when a file or document is not found.
  • 409 for claim conflicts or slug conflicts.
  • 413 when the HTML file is too large.
  • 415 when upload content is not text/html.
  • 429 when rate limits are exceeded.