Docs
Quickstart
From an empty team to a live release on your own domain, using curl. Every step also works in the dashboard and over MCP.
Before you start
You need a PagesPrinter team and an API key. Sign in at app.pagesprinter.com, open API keys and create a key with the Full preset. The secret starts with sk_ and is shown once. Every request sends it as a bearer token.
Shell
export PAGESPRINTER_KEY=sk_…
export API=https://api.pagesprinter.com/v1/pagesprinter
01
Create a site
The slug becomes the preview address. It must be unique, lowercase and at most 63 characters. Leave it out and one is made from the name.
Request
curl "$API/sites" \
-H "Authorization: Bearer $PAGESPRINTER_KEY" \
-H "Content-Type: application/json" \
-d '{"name": "Northwind Docs", "slug": "northwind-docs"}'
Response · 201
{
"id": "5b1d3c0e-8f2a-4c6b-9e7d-2a4f6c8b0d13",
"slug": "northwind-docs",
"name": "Northwind Docs",
"preview_url": "https://northwind-docs.pagesprinter.page",
"production_urls": []
}
Keep the id for the next steps:
export SITE=5b1d3c0e-8f2a-4c6b-9e7d-2a4f6c8b0d13
02
Upload files
Put one file at a path. The body is the raw file, up to 25 MiB. The response includes the preview URL of that page.
One file
curl -X PUT "$API/sites/$SITE/preview/files/index.html" \
-H "Authorization: Bearer $PAGESPRINTER_KEY" \
-H "Content-Type: text/html" \
--data-binary @dist/index.html
Response · 200
{
"path": "index.html",
"etag": "\"9b2c41f07d\"",
"size": 4812,
"preview_url": "https://northwind-docs.pagesprinter.page/"
}
To publish a whole build, pack the folder and send it as one archive of up to 200 MiB. The archive replaces the preview: files that aren't in it are removed. Extraction runs in the background, so the call returns an upload id you can poll.
Build archive
tar -czf site.tar.gz -C dist .
curl -X POST "$API/sites/$SITE/preview/archive" \
-H "Authorization: Bearer $PAGESPRINTER_KEY" \
-H "Content-Type: application/gzip" \
--data-binary @site.tar.gz
# 202 {"upload_id": "c7e9a0b4-…"}
curl "$API/uploads/c7e9a0b4-…" \
-H "Authorization: Bearer $PAGESPRINTER_KEY"
# {"status": "done", …}
03
Check the preview
Open https://northwind-docs.pagesprinter.page in a browser. It serves the preview as it is right now, with a noindex header. Then ask what a promote would ship:
Request
curl "$API/sites/$SITE/changes" \
-H "Authorization: Bearer $PAGESPRINTER_KEY"
# {"added": ["index.html", "assets/site.css", …], "changed": [], "deleted": []}
04
Promote
Promote copies the preview into the next numbered release. With ?wait=30 the call returns once the release is ready, or after 30 seconds with its current status. An idempotency_key makes a retried request safe.
Request
curl -X POST "$API/sites/$SITE/promote?wait=30" \
-H "Authorization: Bearer $PAGESPRINTER_KEY" \
-H "Content-Type: application/json" \
-d '{"message": "First release", "idempotency_key": "build-2026-09-26-1"}'
Response · 200
{
"id": "e41f0a92-6d3b-4b8e-a1c5-7f2d9e0b3a64",
"number": 1,
"status": "ready",
"file_count": 124,
"message": "First release",
"via": "api"
}
Production is served only on your own domain. Until you add one, the release is ready but has no public address. The next step fixes that.
05
Add your domain
Bind a subdomain you control to the site's production environment. Apex domains such as northwind.studio are rejected for now: use www. or another subdomain and redirect the apex at your registrar.
Request
curl "$API/domains" \
-H "Authorization: Bearer $PAGESPRINTER_KEY" \
-H "Content-Type: application/json" \
-d '{"hostname": "docs.northwind.studio", "site_id": "'"$SITE"'", "environment": "production"}'
Response · 201
{
"id": "9c2e7b14-0f6a-4d3e-8b51-3e9a7c2d4f80",
"hostname": "docs.northwind.studio",
"status": "pending_dns",
"records": [
{"type": "CNAME", "name": "docs.northwind.studio", "value": "domains.pagesprinter.com"},
{"type": "TXT", "name": "_pagesprinter.docs.northwind.studio", "value": "pp-verify-7f3a9c21e4"}
]
}
Keep the id as DOMAIN and add both records at your DNS provider:
| Type | Name | Value |
|---|---|---|
| CNAME | docs.northwind.studio | domains.pagesprinter.com |
| TXT | _pagesprinter.docs.northwind.studio | pp-verify-7f3a9c21e4 |
PagesPrinter keeps checking for up to 72 hours. To check right away, call verify. The status moves from pending_dns to provisioning_tls to active, and the certificate is renewed for you.
Request
curl -X POST "$API/domains/$DOMAIN/verify" \
-H "Authorization: Bearer $PAGESPRINTER_KEY"
# {"hostname": "docs.northwind.studio", "status": "active", …}
06
Roll back
List the releases and point production at an earlier one. Nothing is copied, and the preview is left as it was.
Request
curl "$API/sites/$SITE/releases" \
-H "Authorization: Bearer $PAGESPRINTER_KEY"
curl -X POST "$API/sites/$SITE/rollback" \
-H "Authorization: Bearer $PAGESPRINTER_KEY" \
-H "Content-Type: application/json" \
-d '{"release_id": "e41f0a92-6d3b-4b8e-a1c5-7f2d9e0b3a64"}'
API keys
Keys belong to a team. Pick a preset when you create one; revoking a key stops it on the next request.
- Agent
- Read sites, read and write preview files, promote and roll back, read domains. For coding agents and CI.
- Read-only
- Read sites, files, releases and domains. For monitoring and reports.
- Full
- Everything above, plus creating and deleting sites and managing domains.
Connect an agent
The MCP server is at https://api.pagesprinter.com/mcp and takes the same key in the Authorization header. Use an Agent key.
Claude Code
claude mcp add --transport http pagesprinter \
https://api.pagesprinter.com/mcp \
--header "Authorization: Bearer $PAGESPRINTER_KEY"
API reference
All routes live under https://api.pagesprinter.com/v1/pagesprinter. Production is read-only through the API: writes to it return 405 production_read_only.
| Route | Does |
|---|---|
| GET, POST /sites | List or create sites |
| GET, PATCH, DELETE /sites/:site_id | Read, change settings, delete |
| GET /sites/:site_id/:env/files | List files in preview or production |
| GET, PUT, PATCH, DELETE /sites/:site_id/preview/files/*path | Read, write, edit, delete a file |
| POST /sites/:site_id/preview/batch | Up to 100 put, delete and move operations |
| POST /sites/:site_id/preview/archive | Replace the preview from a zip or tar.gz |
| GET /sites/:site_id/changes | Preview compared with the live release |
| POST /sites/:site_id/promote | Create the next release |
| POST /sites/:site_id/rollback | Make an earlier release live |
| GET, POST /domains | List or add domains |
| POST /domains/:domain_id/verify | Check DNS now |
| GET /usage | Your team's usage against its limits |