Devices, printers and scales
A device is a machine running the PrintSocket agent, and printers and scales are the hardware that machine can see. You do not create any of them through this API. The agent discovers them and reports them, so these endpoints are about reading state and reacting to it: which printers exist, which are online, what each one can do, and what the scale on the counter currently weighs.
The one thing you do create here is an enrollment token, which is how a machine joins your account. It is the last section on this page, and it is worth reading before you ship an installer to a customer: the token exchanges for device-scoped credentials, so your account API keys never have to leave your server.
Devices
A device is a machine running the PrintSocket agent.
| Method | Path | Notes |
|---|---|---|
| GET | /devices | Filters: state=online|offline, metadata[...] |
| GET | /devices/{id} | |
| PATCH | /devices/{id} | name, metadata |
| POST | /devices/{id}/revoke | Invalidates the agent's credentials. The device goes to state: revoked and cannot reconnect until it is enrolled again. Reconnecting the machine will not bring it back. |
| POST | /enrollment_tokens | Returns a short-lived (1 h), single-use token for the agent installer. Body: optional name and metadata, pre-applied to the device when it enrolls. |
Device object:
{
"id": "dev_7hk2m",
"object": "device",
"name": "Front desk PC",
"state": "online",
"hostname": "FRONTDESK-01",
"os": { "family": "windows", "version": "11" },
"agent_version": "1.4.2",
"last_seen_at": "2026-07-29T14:01:55Z",
"created_at": "2026-07-01T09:12:40Z",
"metadata": {},
"virtual": false
}
stateisonline,offline, orrevoked.agent_versionis the build the machine is running right now, not the one it enrolled with. It updates when the agent updates.osis recorded at enrollment time only.virtualis true only for the test-mode fixture device, and it is the only field that tells you which one that is: the fixture looks like a real device in every other respect, and you can rename it. Revoke is the single thing it refuses, with a 409device_virtual, because a revoke cannot be undone and nothing would give you a new fixture. Everything else works on it, including disabling its printer, which is how you make a test-mode job fail withprinter_disabled.
Printers
Printers are discovered automatically by the agent. They are not created through the API.
| Method | Path | Notes |
|---|---|---|
| GET | /printers | Filters: device_id, state=online|offline, enabled=true|false, metadata[...] |
| GET | /printers/{id} | Includes full capabilities |
| PATCH | /printers/{id} | name (display alias), enabled (soft-disable: rejects new jobs), default_options, metadata, rendering (page language, below) |
Printer object:
{
"id": "prn_8f2k1",
"object": "printer",
"device_id": "dev_7hk2m",
"name": "Label printer",
"system_name": "ZDesigner ZD420",
"state": "online",
"enabled": true,
"default_options": { "copies": 1 },
"capabilities": {
"color": false,
"duplex": false,
"copies_max": 99,
"dpis": ["203x203"],
"papers": { "4x6": [1016, 1524] },
"trays": ["Main"],
"media": [],
"collate": true,
"custom_paper_size": false,
"queue": "driver",
"render": ["zpl", "escpos"]
},
"rendering": { "language": "driver", "dpi": null, "width_dots": null, "suggestion": null },
"created_at": "2026-07-01T09:13:02Z",
"metadata": {}
}
nameis your alias and is what PATCH changes.system_nameis the queue name as the operating system reports it, and is what identifies the printer across removals and revivals.stateisonlineoroffline, and isofflinewhenever the device is.capabilities.papersmaps each paper name the driver offers to its size in tenths of a millimetre, or tonullwhere the driver reports a name without a size (common on CUPS). The names are the valuesoptions.paperaccepts on a job.default_optionsmerge underneath per-joboptions, so you can configure a printer once (always 203 dpi, tray 2) instead of repeating it on every job.capabilities.queueisrawwhen the print queue has no driver anddriverwhen it has one;capabilities.renderlists the page languages the printer's agent can convert PDFs to. Both are absent where the agent cannot tell or predates conversion.renderingis the printer's page language, below.
Removal. Agents report the complete queue list, so a printer missing from a report has been deleted from the OS. Queues that are present but unreachable are still reported, as offline. A removed printer leaves every listing, GET /printers/{id} returns 404, and printer.removed fires. If the queue reappears under the same system_name, the printer revives with the same id and printer.discovered fires again.
Page language
Label and receipt printers are often set up without a driver (a "raw" queue), so a PDF sent to them prints as garbage, or not at all. Setting a printer's page language makes the agent convert each PDF job into the printer's own language on the computer, then send it raw. Raw jobs are never converted, so ZPL or ESC/POS you generate yourself keeps working exactly as before.
PATCH /v1/printers/prn_8f2k1
{ "rendering": { "language": "escpos", "dpi": 180, "width_dots": 512 } }
language | For | Settings |
|---|---|---|
driver | The default. PDFs go to the print driver unchanged. | none |
zpl | Zebra and ZPL-compatible label printers | dpi: 152, 203, 300, or 600 |
escpos | ESC/POS receipt printers | dpi: 180 or 203; width_dots: the printable width, 576 for most 80 mm printers at 203 dpi, 512 for an Epson TM-T88 at 180 dpi, 384 for 58 mm paper |
- Set
nullor{ "language": "driver" }to go back to the default. A PATCH that leavesrenderingout does not change it. Changing it needs themanagescope. - Each page becomes one label or one receipt. A ZPL label is the size of the job's
options.paper(or the printer's default paper), or the PDF page's own size if neither is set, which is right for carrier labels that are already 4x6. A page that matches the label prints at exactly 1:1, so barcodes keep their bar widths; one that does not is scaled to fit with apage_scaledwarning, or cropped from its top-left corner withpage_croppedif the job setsfit_to_page: false. A landscape page bound for a portrait label is turned to fit. A receipt page is scaled to the paper width and starts and ends where its content does, so no blank paper feeds before or after it. - Labels print with a sharp black-and-white cutoff, which keeps barcode bars exactly as drawn. Receipts dither instead, so photos, logos, and shaded areas print as patterns of dots rather than solid black or nothing (agent v0.1.18 or later).
rendering.suggestionis a setting guessed from the printer's name, offered only for raw queues. PrintSocket never applies it on its own; the dashboard offers it as one click.- A converted job records how it was converted in its
renderingfield. - The agent must be recent enough to convert (its printers list
capabilities.render). A PDF job for a printer with a page language set, on an older agent, fails withagent_update_requiredrather than printing garbage.
Tested on hardware so far: a Zebra ZP 450 (ZPL, 203 dpi), through the API, the dashboard's test print, and MCP print_text, with the barcodes scanning; and an Epson TM-T88V (ESC/POS, 180 dpi, 512 dots), through the API and from an iPhone through a printer share (see Printer sharing).
Scales
Read-only telemetry from USB scales attached to a device.
| Method | Path | Notes |
|---|---|---|
| GET | /scales | Filter: device_id |
| GET | /scales/{id} | Latest reading embedded |
Scale object:
{
"id": "scl_9d3f2",
"object": "scale",
"device_id": "dev_7hk2m",
"system_name": "Mettler Toledo PS60",
"state": "online",
"reading": {
"weight_grams": 1234,
"stable": true,
"captured_at": "2026-07-29T14:02:08Z"
},
"created_at": "2026-07-01T09:13:02Z"
}
stateisonlineoroffline, and isofflinewhenever the device is.readingisnulluntil the agent has reported one.
Scales are discovered and reported by the agent, like printers. A report without a fresh reading keeps the previous one, so check captured_at to see how stale a weight is, and stable to know whether the scale had settled. Read the weight on demand at the moment you need it, typically when buying a label. Scales carry no metadata and emit no webhook events.
Enrolling a device
- From your server,
POST /enrollment_tokens→{ "token": "enr_...", "expires_at": ... }. - Run the agent installer on the target machine with that token (CLI flag or paste into the GUI).
- The agent exchanges the token for device-scoped credentials. The device appears as
dev_...anddevice.enrolledfires. - Printers are discovered automatically; a
printer.discoveredevent fires for each.
Enrollment tokens are short-lived and single-use, and the credentials the agent ends up holding are scoped to that one device. Your account API keys never need to be embedded in an installer or stored on an end customer's machine. The agent page covers what happens on the machine itself: installing, enrolling from the tray or the command line, and what to do when a printer shows offline.