The Paperwright API is a JSON/HTTP API. This page covers the base URL,
authentication, errors, and — most importantly — how the API is versioned and
which endpoints are safe to build on today.
Source of truth: the OpenAPI document at openapi/v2.json (Paperwright.Api | v1, OpenAPI 3.1.1). Every endpoint below maps to an operation in that spec.
Base URL
http://localhost:5110 # local development
https://api.paperwright.dev # production
In dev, an interactive Scalar UI is served at /scalar/v1.
Authentication
| Lane | Header | Scope |
|---|
| JWT (Bearer) | Authorization: Bearer <token> | All management endpoints (auth, templates, keys, workspaces, collaboration) |
| API key | X-Api-Key: <key> | Rendering only |
The render endpoints (POST /api/render, POST /api/templates/{id}/render)
are the only ones that accept both lanes. See
Authentication & Sessions.
Workspace scoping
Every resource belongs to a workspace. A request only ever sees its own
workspace's data. Cross-tenant access returns 404 Not Found (deliberately
not 403 — we don't reveal that a resource exists in another tenant).
Errors
| Status | Meaning |
|---|
200 | Success |
400 | Validation error (bad/missing body fields) |
401 | Missing or invalid credentials |
402 | Quota exceeded (e.g. AI generation limit on the free tier) |
403 | Authenticated, but not allowed (e.g. deleting another user's comment) |
404 | Not found, or not in your workspace |
409 | Conflict — a concurrent edit changed the resource (optimistic concurrency) |
500 | Server error (generic message; no internal detail is leaked) |
Versioning policy
How versions work
- The entire API is served under a single major version, v1, surfaced as the
OpenAPI document
v1.json and (in dev) the Scalar UI at /scalar/v1.
- The major version (
v1) is a contract. Within v1 we only make
backwards-compatible changes: adding endpoints, adding optional request
fields, or adding response fields. We will not remove a field, rename one,
or change a status code within v1.
- A breaking change ships under a new major (
v2) at a new path
(/scalar/v2, openapi/v2.json). v1 continues to run during a published
deprecation window.
- Individual endpoints additionally carry a stability label (below) so you
know how settled an endpoint is within v1.
Stability labels
| Label | Meaning | Your expectation |
|---|
| 🟢 Stable | Shipped, verified, in production use. | Safe to build on. Backwards-compatible changes only. |
| 🟡 Beta | Functionally complete, recently shipped, may still gain fields. | Safe to use; pin to documented fields and expect additive changes. |
| 🟠 Experimental | Feature-flagged or v0; shape may change. | Prototype only. Do not depend on the response shape. |
Master endpoint index
Every endpoint in v1.json, grouped by domain, with its version and stability.
Authentication · 🟢 Stable · v1 → details
| Method | Path | Auth | Stability |
|---|
| POST | /api/auth/signup | Public | 🟢 Stable |
| POST | /api/auth/login | Public | 🟢 Stable |
| POST | /api/auth/verify-email | Public | 🟢 Stable |
| POST | /api/auth/resend-verification | Public | 🟢 Stable |
| POST | /api/auth/forgot-password | Public | 🟢 Stable |
| POST | /api/auth/reset-password | Public | 🟢 Stable |
| POST | /api/auth/refresh | Cookie/JWT | 🟢 Stable |
| POST | /api/auth/logout | JWT | 🟢 Stable |
| POST | /api/auth/logout-all | JWT | 🟢 Stable |
| POST | /api/auth/change-password | JWT | 🟢 Stable |
| GET | /api/auth/me | JWT | 🟢 Stable |
| POST | /api/auth/switch-workspace/{workspaceId} | JWT | 🟢 Stable |
| GET | /api/auth/oauth/{provider}/start | Public | 🟡 Beta |
| GET | /api/auth/oauth/{provider}/callback | Public | 🟡 Beta |
Templates · 🟢 Stable · v1 → details
| Method | Path | Auth | Stability |
|---|
| GET | /api/templates | JWT | 🟢 Stable |
| POST | /api/templates | JWT | 🟢 Stable |
| GET | /api/templates/{id} | JWT | 🟢 Stable |
| PUT | /api/templates/{id} | JWT | 🟢 Stable |
| DELETE | /api/templates/{id} | JWT | 🟢 Stable |
| POST | /api/templates/{id}/base-pdf | JWT | 🟢 Stable |
| GET | /api/templates/{id}/base-pdf | JWT | 🟢 Stable |
| DELETE | /api/templates/{id}/base-pdf | JWT | 🟢 Stable |
| GET | /api/templates/{id}/base-pdf/pages/{index} | JWT | 🟢 Stable |
Rendering · 🟢 Stable · v1 → details
| Method | Path | Auth | Stability |
|---|
| POST | /api/render | JWT or API key | 🟢 Stable |
| POST | /api/templates/{id}/render | JWT or API key | 🟢 Stable |
API Keys · 🟢 Stable · v1 → details
| Method | Path | Auth | Stability |
|---|
| GET | /api/api-keys | JWT | 🟢 Stable |
| POST | /api/api-keys | JWT | 🟢 Stable |
| DELETE | /api/api-keys/{id} | JWT | 🟢 Stable |
| GET | /api/usage | JWT | 🟢 Stable |
Workspaces & Invites · 🟢 Stable · v1 → details
| Method | Path | Auth | Stability |
|---|
| GET | /api/workspaces | JWT | 🟢 Stable |
| GET | /api/workspaces/current/members | JWT | 🟢 Stable |
| POST | /api/workspaces/current/invites | JWT (Owner) | 🟢 Stable |
| DELETE | /api/workspaces/current/members/{userId} | JWT (Owner) | 🟢 Stable |
| PATCH | /api/workspaces/current/members/{userId} | JWT (Owner) | 🟢 Stable |
| GET | /api/invites/{token} | Public | 🟢 Stable |
| POST | /api/invites/{token}/accept | JWT | 🟢 Stable |
| Method | Path | Auth | Stability |
|---|
| POST | /api/presence | JWT | 🟡 Beta |
| GET | /api/presence/{resourceType}/{resourceId} | JWT | 🟡 Beta |
| DELETE | /api/presence/{resourceType}/{resourceId} | JWT | 🟡 Beta |
| GET | /api/templates/{templateId}/comments | JWT | 🟡 Beta |
| POST | /api/templates/{templateId}/comments | JWT | 🟡 Beta |
| DELETE | /api/templates/{templateId}/comments/{commentId} | JWT | 🟡 Beta |
AI · 🟠 Experimental · v1 (v0 feature) → details
| Method | Path | Auth | Stability |
|---|
| POST | /api/ai/generate-template | JWT | 🟠 Experimental |
Batch Render · 🟡 Beta · v1 → details
| Method | Path | Auth | Stability |
|---|
| POST | /api/templates/{id}/render-batch | JWT | 🟡 Beta |
| POST | /api/templates/{id}/render-batch/upload | JWT | 🟡 Beta |
| GET | /api/templates/{id}/render-batch/jobs/{jobId} | JWT | 🟡 Beta |
| GET | /api/templates/{id}/render-batch/jobs | JWT | 🟡 Beta |
| GET | /api/templates/{id}/render-batch/jobs/{jobId}/result | JWT | 🟡 Beta |
Service
| Method | Path | Auth | Stability |
|---|
| GET | /health | Public | 🟢 Stable |
Conventions used in these docs
- UUIDs — path IDs (
{id}, {workspaceId}, {userId}, etc.) are UUIDs
unless noted ({token} is an opaque string; {index} is an integer).
- Request bodies are
application/json unless noted (base-PDF upload is
multipart/form-data).
- Schema names (e.g.
LoginBody, CreateTemplateBody) match the components in
openapi/v1.json.
:::note About response shapes
openapi/v1.json documents request bodies in full but currently describes
responses only as 200 OK. The response examples in these pages are
illustrative of the intended shape and will be pinned to the spec as
response schemas are added.
:::