# Sealed Print – complete guide

> Sealed Print is a cloud printing service. Computers print through a personal printer URL (IPP) into a cloud queue,
> and jobs are delivered to printers through the relay client, IPP INFRA printers or IPP push. This document explains
> the concepts, the setup and the REST API. Base URL: https://www.sealedprint.com

## Concepts

- **Organization:** a tenant. Every account starts with a personal organization; users can create further
  organizations and switch between them. Members have the role Owner, Admin or User; users only see their own
  sources and jobs.
- **Source:** a computer or person that prints. Each source has a secret **printer URL**
  (`https://www.sealedprint.com/ipp/print/<token>`) plus one URL per destination (`…/ipp/print/<token>/<destination-short-name>`) that
  always prints there. Tokens can be renewed; old URLs stop working immediately.
- **Queue:** every job lands here first. It shows a preview and its status.
- **Destination:** where a job is printed. Destinations belong to an **integration**:
  - *Relay client* (default): a small program on a Windows, macOS or Linux computer or a NAS shares local printers.
  - *INFRA printers*: printers with IPP INFRA (PWG 5100.18) fetch jobs directly from Sealed Print.
  - *IPP push*: Sealed Print sends jobs to a printer reachable over the internet (ipp:// or ipps://).
- **Ingress channels:** how jobs arrive: printer URL (IPP), web upload, sharing from the installed web app, REST API.
  Each channel can be switched on or off per organization.
- **Routing:** jobs without a fixed destination go to the default destination if automatic routing is on; otherwise
  they wait in the queue until someone assigns a destination.
- **Delivery:** each attempt to hand a job to a destination, with a timeline. Pull destinations (relay, INFRA) fetch
  jobs; push destinations are sent to and polled. Temporary errors are retried, up to 5 attempts.

### Job states

| State | Meaning |
|---|---|
| `received` | Receiving: the document is still arriving |
| `pending_routing` | Needs destination: stored, waiting until a destination is assigned |
| `queued`, `fetched` | In transit to the destination |
| `printing` | Printing |
| `completed` | Delivered |
| `failed` | Failed (`stateReason` explains why) |
| `canceled` | Canceled |

`stateReason` codes: `delivery_retry`, `delivery_failed`, `canceled_by_source`, `canceled_in_app`,
`submission_incomplete`, `document_invalid`. `stateMessage` contains details or the printer's own message.

## Printing from a computer

The printer URL is added as a network printer; no driver is installed.

- **Windows 10/11:** Settings → Bluetooth & devices → Printers & scanners → Add device → "Add manually" → "Select a
  shared printer by name" → paste the printer URL.
- **macOS:** `lpadmin -p Sealed Print -E -v ipps://www.sealedprint.com:443/ipp/print/<token> -m everywhere`, or System Settings →
  Printers & Scanners → Add Printer → IP (protocol IPP, queue `/ipp/print/<token>`).
- **Linux (CUPS 2.2+):** `lpadmin -p Sealed Print -E -v ipps://www.sealedprint.com:443/ipp/print/<token> -m everywhere`.
- **ChromeOS:** Settings → Advanced → Print and scan → Printers → Add manually (protocol IPPS).
- **Phones:** use the web upload or share files to the installed web app (Android; iOS does not support sharing to
  web apps).

Accepted formats: PDF, JPEG, PNG and PWG Raster (IPP). Everything is stored as PDF.

## Connecting printers

- **Relay client:** download from https://www.sealedprint.com/download and start the downloaded file once (double-click on Windows).
  It installs itself for the user, starts automatically and connects to this server (the server is part of the
  downloaded file name): the browser opens, an admin confirms the shown code. Then share printers under "Relay
  clients". Further organizations: `sealedprint-relay pair`. The client updates itself (signed releases) and only
  connects outbound.
- **NAS / Docker:** `docker run -d --restart unless-stopped -v sealedprint-relay:/data -e SEALEDPRINT_CLOUD_URL=https://www.sealedprint.com
  -e SEALEDPRINT_PRINTERS="Office=ipp://192.168.1.20/ipp/print" ghcr.io/nova-digital-group/sealedprint-relay`; while
  it is not connected, `docker logs` shows the code and the link to confirm it.
- **INFRA printer:** enable the integration "INFRA printers", create a destination, then enter the infrastructure
  printer URI, user name and password shown under "Device setup" in the printer's settings.
- **IPP push:** enable the integration "IPP push" and create a destination with the printer's ipp:// or ipps:// URI.
  Documents leave Sealed Print for this delivery.

## REST API

The API is described in OpenAPI 3.1: https://www.sealedprint.com/api/openapi.json (interactive: https://www.sealedprint.com/docs/api).

### Authentication

Create an API token in the web app under Settings → API tokens. Tokens start with `sp_api_`, have a name, a role
(User or Admin, at most your own) and an optional expiry, and can be revoked. Send it as
`Authorization: Bearer sp_api_…`. A token acts on behalf of the person who created it and becomes invalid when that
person leaves the organization. Managing tokens and confirming relay pairings requires a browser session.

### Submit a job

The ingress channel "REST API" must be enabled for the organization (Settings → Ingress channels).

```bash
curl -X POST "https://www.sealedprint.com/api/jobs?name=Invoice" \
  -H "Authorization: Bearer sp_api_…" \
  -H "Content-Type: application/pdf" \
  --data-binary @invoice.pdf
```

Multipart works as well: `-F "file=@invoice.pdf" -F "name=Invoice" -F "sinkId=<destination id>"`. Without
`sinkId` the default routing applies. Maximum 50 MB; PDF, JPEG or PNG. The response is the job (HTTP 201).

### Follow a job

- `GET /api/jobs/{id}` – current state.
- `GET /api/jobs/{id}/deliveries` – deliveries with timeline.
- `GET /api/stream/jobs` – Server-Sent Events (`job.created`, `job.updated`), resumable with `Last-Event-ID`.
- `POST /api/jobs/{id}/route` with `{"sinkId": "…"}` – assign or reroute; `POST /api/jobs/{id}/cancel` – cancel.

### Errors

Errors are JSON with `statusCode` and `statusMessage`; validation errors carry details in `data`.
401 = missing or invalid token, 403 = missing permission or ingress channel switched off, 404 = not found or not
visible, 409 = not possible in the current state, 413 = file too large, 415 = unsupported format.

## All endpoints

### Jobs

Submit, query, route and cancel print jobs. Members only see their own jobs, admins see all jobs of the organization.

- `GET /api/jobs` – List jobs (API token or session)
- `POST /api/jobs` – Submit a job (API token or session)
- `GET /api/jobs/{id}` – Get a job (API token or session)
- `GET /api/jobs/{id}/document` – Download the document (API token or session)
- `POST /api/jobs/{id}/route` – Route a job to a destination (API token or session)
- `POST /api/jobs/{id}/cancel` – Cancel a job (API token or session)
- `GET /api/jobs/{id}/deliveries` – Deliveries of a job (API token or session)
- `POST /share-target` – Web share target (browser session only)

### Live

Server-sent events for the live queue.

- `GET /api/stream/changes` – Live invalidation events (API token or session)
- `GET /api/stream/jobs` – Live events of the queue (API token or session)

### Sources

Sources are computers or people that print via personal printer URLs (IPP).

- `GET /api/sources` – List sources (API token or session)
- `POST /api/sources` – Create a source (API token or session)
- `DELETE /api/sources/{id}` – Revoke a source (API token or session)
- `POST /api/sources/{id}/rotate` – Regenerate printer URLs (API token or session)

### Destinations (sinks)

Destinations to which jobs are delivered.

- `GET /api/sinks` – List destinations (API token or session)
- `POST /api/sinks` – Create a destination (API token or session, admin)
- `PATCH /api/sinks/{id}` – Update a destination (API token or session, admin)
- `DELETE /api/sinks/{id}` – Delete a destination (API token or session, admin)
- `GET /api/sinks/{id}/device` – Device credentials of an INFRA printer (API token or session, admin)
- `POST /api/sinks/{id}/device/rotate` – Renew the device password of an INFRA printer (API token or session, admin)

### Settings

Routing and ingress channels of the organization.

- `GET /api/settings` – Get settings (API token or session)
- `PUT /api/settings` – Update settings (API token or session, admin)
- `GET /api/integrations` – List integrations (API token or session)
- `PUT /api/integrations/{channel}` – Enable or disable an integration (API token or session, admin)
- `GET /api/ingress` – List ingress channels (API token or session)
- `PUT /api/ingress/{channel}` – Enable or disable an ingress channel (API token or session, admin)

### API tokens

Manage tokens for machine access. Only allowed in a browser session, not with an API token.

- `GET /api/api-tokens` – List API tokens (browser session only)
- `POST /api/api-tokens` – Create an API token (browser session only)
- `PATCH /api/api-tokens/{id}` – Rename an API token (browser session only)
- `DELETE /api/api-tokens/{id}` – Revoke an API token (browser session only)

### Account

Signed-in user and active organization.

- `GET /api/me` – User and organization (API token or session)
- `PATCH /api/organizations/{id}` – Rename the active organization (browser session only)
- `DELETE /api/organizations/{id}` – Delete the active organization (browser session only)
- `POST /api/organizations` – Create an organization (browser session only)

### Billing

Plans, usage and limits from Stripe. Plan changes and payment details open Stripe pages (Checkout, Customer Portal); the response contains their URL.

- `GET /api/billing` – Plan, usage and limits (API token or session, admin)
- `GET /api/billing/plans` – Available plans (public)
- `PUT /api/billing/details` – Set billing address and VAT ID (browser session only)
- `POST /api/billing/plan` – Change the plan (browser session only)
- `POST /api/billing/portal` – Open the Stripe Customer Portal (browser session only)
- `POST /api/billing/payment-method` – Add a payment method (browser session only)
- `POST /api/billing/webhook` – Stripe webhook (public)

### Legal

Terms of service acceptance and the cancellation button (§ 312k BGB).

- `POST /api/me/terms` – Accept the terms of service (browser session only)
- `POST /api/legal/cancellation` – Cancel a contract (public)

### Relay management

Pair and disconnect relay clients and share their printers.

- `GET /api/relays` – Paired relay clients (API token or session)
- `DELETE /api/relays/{id}` – Disconnect a relay client (API token or session, admin)
- `PATCH /api/relays/printers/{id}` – Share a relay printer (API token or session)
- `GET /api/relays/pairing/{code}` – Show a pairing request (API token or session, admin)
- `POST /api/relays/pairing/{code}/approve` – Approve pairing (browser session only)
- `POST /api/relays/pairing/{code}/deny` – Deny pairing (browser session only)

### Relay client

Endpoints for the local relay client. Authentication with the binding token (rly_…).

- `POST /api/relay/pair/start` – Start pairing (public)
- `POST /api/relay/pair/poll` – Poll pairing status (public)
- `GET /api/relay/config` – Get configuration (relay token)
- `PUT /api/relay/printers` – Report printer inventory (relay token)
- `GET /api/relay/stream` – Wake-up channel (relay token)
- `GET /api/releases/relay` – Latest relay client release (public)
- `GET /downloads/{path}` – Download a release file (public)

### IPP

Printer endpoints per RFC 8010/8011. The body is a binary IPP message (application/ipp), followed by the document data. These endpoints are set up as printers in the operating system; they are not suited for trying out in this interface.

- `POST /ipp/print/{token}` – Printer URL (default routing) (public)
- `POST /ipp/print/{token}/{sink}` – Printer URL with a fixed destination (public)
- `POST /ipp/infra/{sinkId}` – INFRA endpoint of a destination (relay token or device credentials)

### Documentation

This OpenAPI description.

- `GET /llms.txt` – Index for AI agents (llms.txt) (public)
- `GET /llms-full.txt` – Complete guide for developers and AI agents (public)
- `GET /.well-known/api-catalog` – API catalog (RFC 9727) (public)
- `GET /robots.txt` – Robots rules (public)
- `GET /sitemap.xml` – Sitemap of the public pages (public)
- `GET /api/health` – Health check (public)
- `GET /api/openapi.json` – OpenAPI description (public)

## Security notes

- TLS on every connection; documents are deleted after the retention period (7 days after the job finished).
- Printer URLs and API tokens are secrets; only hashes are stored for lookups.
- Relay client releases are signed (Ed25519) and verified before an update is installed.
- Jobs printed through printer URLs are not end-to-end encrypted; Sealed Print processes them to deliver them.
