zpl-rest

Self-hosted print server for Zebra label printers. REST API and web UI for ZPL templates with live preview.

View on GitHub

zpl-rest

Print to Zebra label printers from any system via HTTP. zpl-rest is a self-hosted print server that stores your ZPL templates, fills in placeholders from JSON and sends the result to the printer over the network. A web UI shows label previews, print statistics and past print jobs.

Dashboard with print statistics

Why zpl-rest

Zebra printers accept raw ZPL on TCP port 9100, but sending it from an ERP, a warehouse app or a shell script usually means writing socket code in every system. zpl-rest moves that into one place. Your applications send a short JSON request with the label name and the data, and zpl-rest handles templates, printer addresses and the job history.

Features

Quick start

Docker

git clone https://github.com/mrothenbuecher/zpl-rest.git
cd zpl-rest
docker compose up -d

The web UI is then available at http://localhost:8110. Printers, labels and jobs are stored in ./volumes on the host.

Node.js

git clone https://github.com/mrothenbuecher/zpl-rest.git
cd zpl-rest
npm install
npm start

The web UI is then available at http://localhost:8000.

Usage

1. Add a printer

The address is the printer’s IP and raw port, usually 9100. The density is the print resolution in dots per millimetre as used by Labelary (6dpmm, 8dpmm, 12dpmm or 24dpmm).

curl -X POST http://localhost:8000/rest/printer \
  -H "Content-Type: application/json" \
  -d '{"name": "Warehouse 1", "address": "192.168.0.50:9100", "density": "8dpmm"}'

2. Add a label template

Width and height are given in inches.

^XA
^LH0,0
^MTT
^A0N,36,36
^FO236,71
^FD${sometext}^FS
^XZ

3. Print

curl -X POST http://localhost:8000/rest/print \
  -H "Content-Type: application/json" \
  -d '{
        "printer": "<printer id>",
        "label": "<label id>",
        "job_id": "order-4711",
        "data": { "sometext": "hello world" }
      }'

zpl-rest replaces ${sometext} with hello world and sends the finished ZPL to the printer. The job_id is optional. It is stored with the job and shown in the dashboard failure list and on the reprint page.

Web UI

Reprint page with the history of all print jobs:

Reprint page

Label editor with live preview:

Label page with preview

REST API

Method Path Body / query Description
GET /rest/printer none List all printers
GET /rest/label none List all labels
GET /rest/jobs none List all print jobs
GET /rest/preview ?printer=<id>&label=<id>(&zpl=...) Label preview as base64 image
POST /rest/preview {printer, label (, zpl)} Label preview as base64 image
POST /rest/print {printer, label, data (, job_id)} Print a label
POST /rest/reprint/:jobid ({printer, zpl}) Reprint a job, optionally with another printer or changed ZPL
POST /rest/printer add: {name, address, density}
update: {_id, name, address, density}
Add or update a printer
POST /rest/label add: {name, zpl, width, height}
update: {_id, name, zpl, width, height}
Add or update a label
DELETE /rest/printer/:printerid none Remove a printer
DELETE /rest/label/:labelid none Remove a label

Configuration

Settings go into config.json in the project root. Any option you leave out uses its default.

{
  "port": 8000,
  "websocket_port": 8001,
  "public": true,
  "secret": "change-me"
}
Option Type Description Default
port int Port for the REST API and web UI 8000
websocket_port int WebSocket port used by the web UI 8001
public bool If false, the server only listens on localhost true
secret string Session secret, set your own value in production top_secret

Privacy note

Label previews are rendered by the external Labelary service. The ZPL of the label is sent to api.labelary.com for every preview. Printing itself goes directly from zpl-rest to your printer and does not use Labelary.

Contributing

Bug reports, feature ideas and pull requests are welcome. Please open an issue first for larger changes so we can discuss the approach. If you use zpl-rest in production, a short note in Discussions about your setup helps to decide what to work on next.

You can also take part in this short survey.

Credits

Support the project

Donate

License

MIT