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, andclaimToken.
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-Titleupdates the page title.X-Pagr-Hide-Bannercan betrueorfalsefor 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:
titleto rename the page in dashboards and metadata.slugto set a custom slug.slugasnullor""to remove the custom slug and return to the auto slug.passwordas a non-empty string to enable password protection.passwordasnullor""to remove password protection.ttlasnever,24h,7d,30d, or1-visitto change or renew expiration.hideBanneras 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.
400for invalid JSON or request bodies.401for missing or invalid authentication on protected endpoints.403for plan-gated features or quota limits.404when a file or document is not found.409for claim conflicts or slug conflicts.413when the HTML file is too large.415when upload content is nottext/html.429when rate limits are exceeded.