Cloud printing API

Print from any app to any printer with one HTTPS call.

PrintHook is a hosted print relay. Your web app, ERP or script posts a PDF or raw label data to api.printhook.io. The PrintHook Agent on the computer next to the printer picks it up and prints it, then tells you what happened.

Try 90 days with 5,000 prints per UTC calendar month. Starts when you verify your email. No card required. No automatic charges.

Prints count submitted document copies and reset on the first of each month at 00:00 UTC. At the trial deadline, new printing stops unless you have an active paid plan; your account stays accessible. Paid checkout is not available yet. Trial terms and planned pricing.

POST https://api.printhook.io/v1/jobs
# one request, any language
curl https://api.printhook.io/v1/jobs \
  -H "Authorization: Bearer $PRINTHOOK_KEY" \
  -H "Idempotency-Key: order-51233" \
  -H "Content-Type: application/json" \
  -d '{"printer_id": "prn_80000017",
       "title": "Order 51233",
       "content": {
         "type": "pdf",
         "url": "https://erp.example.com/labels/51233.pdf"}}'
# 201 Created
{"id": "job_3000000913",
 "status": "queued", "terminal": false,
 "printer": {"id": "prn_80000017",
             "name": "Label printer 1", "status": "online",
             "computer": {"name": "pack-01",
                          "status": "connected"}},
 "expires_at": "2026-09-29T10:22:41.118Z"}

Documentation

Find help, build an integration, or explore the API.

Start with setup instructions, follow a working request, or look up an error while you build.

Customer help
Set up your account and agent, manage printers and jobs, and troubleshoot printing.
Integration guides
Follow the API quickstart, then learn about reliable jobs and signed webhooks.
API Explorer
Browse public endpoints, inspect request schemas, and try supported API calls.
Error reference
Look up error codes, understand what happened, and find the next step.

How it works

An agent, a request, and a report back. Nothing inbound.

  1. Install the agent next to the printer

    A signed installer for Windows, macOS or Linux (or a Docker image for a Raspberry Pi) registers a system service, so printers keep working when nobody is logged in. It opens only outbound HTTPS to api.printhook.io.

    printhook-agent enroll \
      --client-key ck-…
  2. Your app posts a job

    Name the printer, give it a PDF or raw printer bytes (inline or by URL), and get a 201 back at once. The API never waits for the printer. An Idempotency-Key makes retries safe.

    {"printer_id": "prn_80000017",
     "content": {"type": "raw",
                 "data": "XlhBXkZPNTAs…"}}
  3. The agent prints and reports back

    The agent stores the content on disk before it acknowledges, hands it to the spooler, and reports each step. Poll GET /v1/jobs/{id}, subscribe to a signed webhook, or watch the timeline in the console.

    webhook-id: evt_01J8ZKC6…
    webhook-signature: v1,…
    
    {"type": "job.printed",
     "job_id": "job_3000000913",
     "data": { … }}

Job lifecycle

Six statuses, and every one carries terminal.

You never keep your own list of "done" states. Each job says whether it can still change, and each timeline row says whether it is stable.

  • queuedaccepted and durable; not yet on the machine
  • deliveredthe computer has the job and its content on disk
  • printedthe spooler reported successterminal
  • failedit will not print; failure says whyterminal
  • expiredthe deadline passed before it printedterminal
  • canceledcanceled through the API while still queuedterminal

What ships today

Built for the pack station, the label line and the ERP behind them.

PrintHook is the part of your integration you should not have to write: the service on the Windows box, the reconnect logic, the retry rules, the "why is this printer offline" page. The API is strict and versioned so an integration written once keeps working.

The developer overview covers the shapes; the OpenAPI document covers every public route.

PDF and raw content
PDF gets paper, duplex, copies, pages, rotation and fit options checked against the printer's capabilities. Raw bytes (ZPL, ESC/POS, any printer language) go to the queue untouched.
Content by URL, fetched from your network
Point a job at a document on an internal file server. The agent fetches it from inside your network, with Basic or Digest credentials if needed. The platform never sees the bytes.
Exactly-once printing on the agent
A durable job journal records content on disk before acknowledging, and marks spooling before asking the OS to print. Restarts and offline gaps do not double-print or lose a terminal state.
Signed webhooks with history and replay
One event per request, HMAC-SHA256 signed, webhook-id as the deduplication key. The console shows every attempt and lets an operator replay a failed delivery.
Stations: print to a role at a bench
Name a bench, bind its printers to label and slip, and address {"station_id", "role"} instead of a printer id. Swapping hardware is a rebinding in the console, not a code change in your system. A pairing code or a printed barcode claims the bench's computer, and a scan opens a correlation window that groups every job at the bench into one traceable transaction.
USB scales
Readings with mass, resolution, unit conversions, stability and freshness, over the same API as printers.
Agent self-diagnostics and self-update
DNS, TLS, proxy (407 detection), WebSocket, storage and spooler checks on demand, exported as a bundle. Hourly update checks with signed manifests and a rollback command.
Alert rules
Computer offline, printer error and job error burst rules fire once per incident and can post to a webhook.
Console for the people who run it
Guided setup with a tracked test print, team invitations with four roles, authenticator two-step verification, searchable audit history and child accounts for integrators.

API design

The API is strict so your integration stays boring.

Unknown fields are a 400. Enum values are snake_case. Ids are prefixed and opaque. Every error is the same envelope with a stable code, and every limit a client would otherwise hardcode is published by GET /v1/meta.

Frozen surfaces stay frozen byte for byte. New event types ship opt-in, so what an existing ["*"] subscriber receives never changes.

Developer overview

an error, the same shape everywhere
# 400 Bad Request
{"error": {
   "class": "invalid_request",
   "code": "invalid_argument",
   "message": "The request has 2 problems.",
   "request_id": "8f0b4a0c-1f2e-4e7a-9b3d-6a2c5d1e0f77",
   "doc_url": "https://printhook.io/docs/errors/invalid_argument",
   "details": [
     {"field": "quantity", "code": "out_of_range",
      "message": "quantity must be between 1 and 1000."},
     {"field": "options.duplex", "code": "not_allowed",
      "message": "duplex must be one of long-edge, short-edge, one-sided."}],
   "retry_after_sec": null,
   "meta": {}}}

The agent

One static binary per platform, installed as a service.

PlatformMinimumPackageRuns as
WindowsWindows 10 1809 / Server 2019, x64 or arm64MSI (Authenticode signed)Windows service + tray helper
macOS12 Monterey, Intel or Apple silicon.pkg (Developer ID signed, notarized)LaunchDaemon + menu bar helper
Linuxsystemd, CUPS 2.x.deb, .rpm, arm64 for Raspberry Pi OSsystemd unit
DockerDocker 20.10+, host CUPS socket or a network CUPS servermulti-arch image (amd64, arm64)container

Outbound HTTPS on port 443 is the only network requirement. Installation, enrollment and the egress allowlist.

You can print something in the next ten minutes.

Create an account, install the agent on the computer with the printer, send a test page from the console's guided setup, then call the API with the printer id it shows you.