PrinterTracker

How PrinterTracker works and how to talk to it

This page is written for three people: the client’s IT specialist who has to let the agent onto the network; the service company’s staff who want to understand where the numbers in the panel come from; and the developer wiring PrinterTracker into a billing system.

How PrinterTracker works

PrinterTracker collects counters and status from the copiers at a service company’s clients and shows them in one panel. It has three parts: the agent inside each client location’s network, the cloud that receives and interprets the data, and the service company’s panel. The readings do not end their journey in the panel — the billing system pulls them through the public API.

  1. 1. The agent scans the client’s network

    A small program (Windows or Linux) inside the client’s network asks the printers over SNMP for counters, supplies and status. Every 15 minutes by default; you set the network ranges in the panel.

  2. 2. Data travels to the cloud one way only

    The agent connects out to api.printertracker.com over HTTPS (port 443). Nothing listens inside the client’s network, and there are no ports to open and no VPN to set up.

  3. 3. The cloud interprets the raw data

    The server identifies the model from the serial number and the SNMP identifier, works out mono / colour / scan counters from manufacturer profiles, and spots faults and low toner levels. A new model means a server update, not an agent update.

  4. 4. The service company sees everything in the panel

    Clients → locations → devices. Alerts, counter history, a forecast of when toner runs out, email notifications.

  5. 5. Readings reach billing

    PrinterTracker does not raise invoices. The billing system (PrinterController in MERP, or any other) pulls the readings through the public API described below.

Data model

  • Client (groups/ in the API) — a customer of the service company: a business, a hospital, a public office. It carries a tax ID and a MERP client id you can match on in your own system.
  • Location (subgroups/ in the API) — a site of that client: one network, one agent. A client with three buildings has three locations.
  • Device — a printer or copier identified by its serial number. A newly discovered device waits for approval in the panel (state = new), then it is monitored (active) or ignored.
  • Counter reading — a snapshot of a device’s counters. The cloud keeps at most one reading per device per hour. Within an hour a newer reading replaces the older one, until it has been handed over to billing — after that it is immutable.
  • Alert — either a problem derived from current state (an agent not responding, no readings, a fault, an unrecognised supply), or an occurrence of an alert the service company configured (toner below 10%, say). An alert disappears once the problem is gone.

The SNMP agent on site

The agent is a single static binary with no dependencies: a Windows service or a systemd unit on Linux. The client’s IT team installs it with one command from an install link sent from the panel; the link is valid for 14 days and expires after the first installation.

What it needs

  • Outbound HTTPS to api.printertracker.com (port 443). Nothing else: no inbound ports, no VPN, no port forwarding.
  • SNMP access to the printers (UDP 161) on the network where the machine running the agent sits. The agent tries SNMPv2c and switches automatically when a printer only answers SNMPv1 (some Canon models, for example). Community public; the service company sets the network ranges to scan in the panel.
  • Windows (amd64, arm64) or Linux with systemd (amd64, arm64). One binary, no extra dependencies.

What it does not do

  • It does not read print content, address books or job history — it collects counters, supplies, status and technical configuration.
  • It does not listen on any port and accepts no incoming connections, not even from PrinterTracker. It picks up its configuration every time it contacts the cloud itself.
  • It does not update itself. A new version is installed with the same command; the old installation is cut off the first time the new one makes contact.

Every agent has its own install key tied to a single location. The key can be revoked from the panel at any time — from then on the agent gets a 401 and sends nothing more.

Public REST API

The public API at https://api.printertracker.com/public_api/v1/ gives integrations the same data the service company sees in the panel: clients, locations, devices, counters, supplies, faults and alerts. It is read-only, returns JSON and is versioned in the URL (v1).

Your first request in three steps

  1. The owner of the service company account opens the panel and goes to Moje konto → Integracje (API) (My account → Integrations), then generates a token, saying what it is for (for example “MERP — counter sync”).
  2. The token starts with pt_ and is shown once only. The cloud stores nothing but its hash, so a lost token has to be revoked and replaced.
  3. The token goes into the Authorization header of every request:
curl -H "Authorization: Bearer pt_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
  "https://api.printertracker.com/public_api/v1/devices/?state=active&limit=100"

The complete, always current description of the contract is the OpenAPI schema generated from the server code: https://api.printertracker.com/public_api/v1/schema/?format=json. You can generate a client from it in any language.

Authentication and limits

  • One token, one service company. Everything the API returns belongs to the service company that issued the token. There is no parameter for choosing a client or a service company — an object the token cannot reach returns 404, exactly like an object that does not exist.
  • Scopes. An integration token has the read scope. SNMP agents use separate tokens with the agent scope, which cannot read data — and the other way round; trying gives 403.
  • A limit of 60 requests per minute per token. Every response carries the X-RateLimit-Limit and X-RateLimit-Remaining headers; once you go over, 429 with Retry-After. Syncing every few minutes with pages of 500 objects fits inside this with room to spare; we agree a higher limit individually.
  • Revocation. A token revoked in the panel stops working immediately (401). Up to 20 active tokens per service company — one per integration, so that one can be cut off without touching the rest.
  • A panel session does not work against the API, and an API token does not sign you into the panel. They are two separate doors to the same data.

Pagination and filters

Lists are paginated with a cursor. A response has the shape { "results": [...], "next": "<cursor>" | null }. You fetch the next page with the same request plus cursor=<cursor>, until next is null. The limit parameter sets the page size (100 by default, 500 at most). The cursor is opaque and valid for the same set of filters.

Dates are ISO 8601 in UTC (2026-09-17T09:55:41Z). The time filters (since, until, updated_since) also accept a timezone offset. An unknown filter value gives 400, an id in a filter that does not exist gives 404.

Incremental counter sync

Remember the highest received_at you have seen and ask counters/?since=… for newer readings. The same reading (id) can come back if a newer one replaced it within the current hour — then received_at changes, while a reading already handed over to billing never changes. For billing it is safer to take counter_total when split_confirmed is false: the mono / colour split then comes from a candidate profile that has not yet been confirmed on an invoice.

Endpoint reference

All paths are relative to https://api.printertracker.com/public_api/v1/. The id values are stable; for matching on your own side there are also a device’s serial_number and a client’s merp_client_id.

EndpointReturnsFilters
GETgroups/Clients of the service company, with location and device counts—
GETgroups/{id}/A single client—
GETsubgroups/Locations (one network, one agent) with the state of their agentgroup
GETsubgroups/{id}/A single location—
GETdevices/Devices with current counters, toner levels, state and statusgroup, subgroup, state, status, updated_since
GETdevices/{id}/A single device—
GETdevices/{id}/counters/Counter history for one device, newest reading firstsince, until
GETcounters/Counter readings across the whole service company, newest firstdevice, group, subgroup, since, until
GETdevices/{id}/supplies/Supplies with levels and a forecast—
GETdevices/{id}/faults/Open faults with the manufacturer’s code—
GETalerts/Active system alerts and alerts configured in the panelseverity

Fields worth knowing

state
Device: new (discovered, awaiting approval), active (monitored), ignored.
status
State from the last reading: ok, warning, error, or offline when a monitored device has delivered no reading for over 2 hours.
counters
Current mono, color, scan and total counters; null when the printer does not report a value.
toner
Percentages for k, c, m, y; a missing key means unknown. The full list of supplies, with a forecast of days remaining, is in devices/{id}/supplies/.
source
Reading: backend — counters worked out in the cloud from raw SNMP data (agent 0.2.0+), agent — counters from an agent on 0.1.x.
agent.status
Location: online, offline (out of contact), pending (agent created, not yet installed); null when the location has no agent.
severity
Alert or fault: critical, warning, info. Alerts are sorted most serious first.
rule_id
An alert configured in the panel carries the id of its rule; system alerts have null.

Sample responses

Devices

{
  "results": [
    {
      "id": 214,
      "serial_number": "ZLD1234567",
      "manufacturer": "Canon",
      "model": "iR-ADV C5840",
      "ip_address": "192.168.100.21",
      "location": "Sekretariat, 2 piętro",
      "is_color": true,
      "state": "active",
      "status": "warning",
      "status_message": "Niski poziom tonera",
      "group_id": 12,
      "subgroup_id": 31,
      "counters": { "mono": 184320, "color": 52110, "scan": 90412, "total": 236430 },
      "split_confirmed": true,
      "toner": { "k": 62, "c": 8, "m": 41, "y": 39 },
      "firmware": "68.05",
      "discovered_at": "2026-09-10T08:20:11Z",
      "last_reading_at": "2026-09-17T09:55:41Z"
    }
  ],
  "next": null
}

Counters since midnight, two per page

GET https://api.printertracker.com/public_api/v1/counters/?since=2026-09-17T00:00:00Z&limit=2

{
  "results": [
    {
      "id": 88213,
      "device_id": 214,
      "read_at": "2026-09-17T09:55:41Z",
      "counter_mono": 184320,
      "counter_color": 52110,
      "counter_scan": 90412,
      "counter_total": 236430,
      "split_confirmed": true,
      "source": "backend",
      "received_at": "2026-09-17T09:55:44Z"
    },
    {
      "id": 88102,
      "device_id": 214,
      "read_at": "2026-09-17T08:55:12Z",
      "counter_mono": 184290,
      "counter_color": 52098,
      "counter_scan": 90401,
      "counter_total": 236388,
      "split_confirmed": true,
      "source": "backend",
      "received_at": "2026-09-17T08:55:15Z"
    }
  ],
  "next": "cD04ODEwMg%3D%3D"
}

Active alerts

[
  {
    "id": "fault-5120",
    "severity": "critical",
    "title": "Zacięcie papieru",
    "detail": "Canon iR-ADV C5840 · Sekretariat, 2 piętro",
    "at": "2026-09-17T09:31:07Z",
    "group_id": 12,
    "subgroup_id": 31,
    "device_id": 214,
    "agent_id": null,
    "rule_id": null
  },
  {
    "id": "agent-offline-9",
    "severity": "critical",
    "title": "Agent nie odpowiada",
    "detail": "szpital-oddzial-a — odczyty z 9 urządzeń wstrzymane",
    "at": "2026-09-17T07:12:00Z",
    "group_id": 12,
    "subgroup_id": 31,
    "device_id": null,
    "agent_id": 9,
    "rule_id": null
  }
]

Errors

Every error comes in one envelope. The code field is stable and meant for your code to branch on; message is for a human.

{
  "error": {
    "code": "validation_error",
    "message": "Nieprawidłowe dane.",
    "details": { "status": ["\"broken\" is not a valid choice."] }
  }
}
HTTPcodeWhen
400validation_errorBad parameter; per-field detail in details
401authentication_failedNo token, or the token is unknown or revoked
403permission_deniedToken without the required scope (an agent token, for example)
404not_foundThe object does not exist, or belongs to another service company
429throttledRate limit exceeded; wait Retry-After seconds

Versions and changes

Within v1 changes are additive only: new fields and new endpoints, never the removal of an existing field or a change in what it means. An integration that ignores unknown fields keeps working. A breaking change means v2 at a new address; the old version gets Deprecation and Sunset headers and keeps running for at least another 6 months.

  • 17 September 2026 — resources for integrations: clients, locations, devices, counters, supplies, faults, alerts; tokens from the panel; a limit of 60/min.
  • 16 September 2026 — agent 0.2.0: raw SNMP observations, discovery from the panel.
  • 14 September 2026 — the first version of the API for the SNMP agent.

Missing a field, a filter or a resource? An additive change is cheap — write to us through the contact form and tell us what you are integrating and what data you need.