Docs menu

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.

MethodPathNotes
GET/devicesFilters: state=online|offline, metadata[...]
GET/devices/{id}
PATCH/devices/{id}name, metadata
POST/devices/{id}/revokeInvalidates 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_tokensReturns 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
}
  • state is online, offline, or revoked.
  • agent_version is the build the machine is running right now, not the one it enrolled with. It updates when the agent updates. os is recorded at enrollment time only.
  • virtual is 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 409 device_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 with printer_disabled.

Printers

Printers are discovered automatically by the agent. They are not created through the API.

MethodPathNotes
GET/printersFilters: 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": {}
}
  • name is your alias and is what PATCH changes. system_name is the queue name as the operating system reports it, and is what identifies the printer across removals and revivals.
  • state is online or offline, and is offline whenever the device is.
  • capabilities.papers maps each paper name the driver offers to its size in tenths of a millimetre, or to null where the driver reports a name without a size (common on CUPS). The names are the values options.paper accepts on a job.
  • default_options merge underneath per-job options, so you can configure a printer once (always 203 dpi, tray 2) instead of repeating it on every job.
  • capabilities.queue is raw when the print queue has no driver and driver when it has one; capabilities.render lists the page languages the printer's agent can convert PDFs to. Both are absent where the agent cannot tell or predates conversion.
  • rendering is 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 } }
languageForSettings
driverThe default. PDFs go to the print driver unchanged.none
zplZebra and ZPL-compatible label printersdpi: 152, 203, 300, or 600
escposESC/POS receipt printersdpi: 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 null or { "language": "driver" } to go back to the default. A PATCH that leaves rendering out does not change it. Changing it needs the manage scope.
  • 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 a page_scaled warning, or cropped from its top-left corner with page_cropped if the job sets fit_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.suggestion is 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 rendering field.
  • 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 with agent_update_required rather 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.

MethodPathNotes
GET/scalesFilter: 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"
}
  • state is online or offline, and is offline whenever the device is.
  • reading is null until 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

  1. From your server, POST /enrollment_tokens → { "token": "enr_...", "expires_at": ... }.
  2. Run the agent installer on the target machine with that token (CLI flag or paste into the GUI).
  3. The agent exchanges the token for device-scoped credentials. The device appears as dev_... and device.enrolled fires.
  4. Printers are discovered automatically; a printer.discovered event 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.