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
CNAMEdocs.northwind.studiodomains.pagesprinter.com
TXT_pagesprinter.docs.northwind.studiopp-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 /sitesList or create sites
GET, PATCH, DELETE /sites/:site_idRead, change settings, delete
GET /sites/:site_id/:env/filesList files in preview or production
GET, PUT, PATCH, DELETE /sites/:site_id/preview/files/*pathRead, write, edit, delete a file
POST /sites/:site_id/preview/batchUp to 100 put, delete and move operations
POST /sites/:site_id/preview/archiveReplace the preview from a zip or tar.gz
GET /sites/:site_id/changesPreview compared with the live release
POST /sites/:site_id/promoteCreate the next release
POST /sites/:site_id/rollbackMake an earlier release live
GET, POST /domainsList or add domains
POST /domains/:domain_id/verifyCheck DNS now
GET /usageYour team's usage against its limits