hw-connector
A local web service through which web applications work with the computer's point-of-sale hardware: fiscal registers, payment terminals, printers, customer displays, scanners and card readers.
The service runs on the computer the hardware is connected to and accepts requests only from that
computer: http://localhost:7790. It has two sides:
- Setup page — http://localhost:7790/: adding and checking devices, printers, report templates, the operation journal.
- REST API —
http://localhost:7790/api/v1: a web application in the browser or a program on this computer prints receipts, takes card payments, prints documents. The full description with examples is in Swagger UI (in Russian and English), the OpenAPI schema — /v3/api-docs/en and /v3/api-docs/ru.
The service runs in the background, shows an icon in the Windows tray and starts with Windows.
Quick start
- Install the hardware software if needed (see Hardware): the DTO10 x64 driver for ATOL registers, the bank software for the terminal.
- Open the setup page: tray icon → “Open interface” or http://localhost:7790/.
- On the Devices tab click “Add device”, choose the type, fill in the fields and click “Save and check”. The device card shows “online” or what to fix.
- On the Printers tab assign printers for tickets and documents, set the paper and print a test page.
- On the Workplace tab enter the cashier and, if needed, the sender email, place of settlement and tax system.
- Connect the web application to the API (see API).
Menu
The interface language is switched with the RU / EN buttons in the page header, in the help and in the tray icon menu.
Devices
Device cards: fiscal registers, terminals, driverless printers, customer displays, scanners, card readers, cash drawers, ports. The number in the card corner (No. 1, No. 2…) is the device number in the API.
- Switch — enable or disable the device. A disabled device does not accept operations.
- Check — check the connection without money operations: for a register — the shift state, for a terminal — the bank software or the terminal reply, for a scanner — whether the port is open and the last code.
- Operations — manual actions. Register: open shift, X report, close shift (Z report), open the cash drawer, cash in and cash out. Terminal: settlement, the slip is shown on screen. Printer: print text, open the drawer (ESC/POS). Display: show lines, clear, open the second-monitor page. Drawer: open. Port: send bytes and see the reply. Scanners and readers have no operations — codes and cards arrive as events.
- ⚙ Configure — change settings or delete the device.
- Add device — choose the type and fill in the fields. The COM port is picked from a list with device names; the ⟳ button searches for ports again. Changes apply immediately, without restarting the service.
Printers
- Roles — the printer for tickets and the printer for documents. The application prints “by role”
(
role) without knowing the printer name. Without a role — the default Windows printer. A driverless printer from the device list can be assigned too. - Print settings — paper (as in the document, ticket stock 148 × 79 mm, 80 or 58 mm roll, A4 or custom
size), scale (as in the document, fit to paper, shrink if it does not fit), orientation.
Applied to PDFs, images and reports; printer commands (
raw) go as is. - Test page — printer name, date and Cyrillic text: you see right away that printing and fonts work.
Reports
- The list of JasperReports templates (
*.jrxml) with parameters$P{…}and fields$F{…}. - The installation includes the TICKET template — a ticket on 148 × 79 mm stock. Each data row is printed
as a separate ticket on its own page; fields:
top_line,upper_line,pos_line,addr_line,service_line,date_line,place_line,price_line,sold_line,sale_line,control_line,bottom_line,footer_line. - Upload template or drop files onto the page. The template is checked by compiling it: a template with errors is not saved. You can also just put files into the template folder — its path is shown on the page.
- Generate — enter parameters and data rows in JSON, open the PDF or send it to a printer.
Workplace
Default values for register operations. The service uses them only when the request does not contain them; what is passed in the request always wins.
- Cashier: full name (tag 1021) and tax ID (tag 1203). If the cashier is set, the
operatorfield can be omitted in requests. If the cashier is set neither in the request nor here, the operation is rejected (422). - Sender email (tag 1117): the return address of electronic receipts.
- Place of settlement (tag 1187): empty — as registered in the register.
- Tax system: “As in the register” — the register chooses it itself.
Further down the same tab — access to the agent and PDF printing. Changes apply at once, without a restart,
and are saved in data\access.json; “As in the settings file” returns the values from config\application.yml.
- Allowed sites: addresses of the POS program (for example
https://bigbilet.com) that may call the agent from the browser. Requests from other sites are rejected. - API token: if set, the POS program sends
Authorization: Bearer <token>(for events —?access_token=). “Create” makes up a random token — copy it into the POS program settings, otherwise it gets 401. Empty — no token needed. - Where printing is allowed from: the beginning of PDF addresses the agent downloads for printing; download wait, largest file size and number of files in one job.
Journal
All device operations: status, what is happening now, result or error. Updates live (the green dot by the tab means events are connected). Clicking a row shows the whole operation. The last 1000 operations are kept, including after a restart.
Tray icon
The icon shows that the service is running; the tooltip and the top menu lines show the version, the number of enabled devices and the port. Double-click opens the interface. Menu (right click):
- Open interface, Operation journal, Help — pages in the browser.
- Check devices — checks the connection to all enabled devices, the result arrives as a Windows notification.
- Program folder — settings (
config\,data\), report templates and logs. - Start with Windows — a shortcut in Startup; available in the installed program. Autostart turns on by itself at the first start after installation.
- Язык / Language — Russian or English. The language is shared by the icon, the setup page and the help; on the page it is switched with the RU / EN buttons in the header.
- Exit — after confirmation: while the service is stopped, devices and printing are unavailable.
Supported hardware
| Device | Connection | Needed on the computer |
|---|---|---|
| ATOL fiscal registers (platform 5) | COM port, USB, network | DTO10 x64 driver |
| Shtrih-M registers, Mercury in fiscal printer mode, Retail, ELVES, Paykiosk | Network or USB (RNDIS, port 7778), COM port; exchange protocol version 1 or 2 | Nothing: the service talks to the register directly |
| Pirit 2F, Viki Print 57/80, Dreamkas-F registers | COM port (57600 by default), network via the Wi-Fi module | Nothing; FFD 1.2 mode |
| KIT registers (KASBI): KIT Online-F, Terminal-FA | Network (port 50003) or COM port; FFD 1.05 and 1.2 | Nothing; a cash drawer cannot be connected to KIT |
| INPAS terminal (Verifone, PAX) | Via DualConnector | INPAS DualConnector |
| Sberbank terminal | Via UPOS (sb_pilot.exe) | UPOS distribution, the PIN pad port is in its pinpad.ini |
| ARCUS 2 terminal (Ingenico) | Via Arcus-2 (CommandLineTool.exe) | Arcus-2 software |
| SBP QR payment: T-Bank, Sberbank | The bank's internet acquiring over HTTPS | Nothing; keys from an acquiring contract with SBP enabled |
| Terminal with the TTK2 protocol | Network (usually port 888) | Nothing; enable commands from the POS on the terminal |
| UCS terminal | Cable (COM port) or network | Nothing |
| ESC/POS receipt printer (Epson, Xprinter, Posiflex, ATOL, Shtrih…) | Network (port 9100), COM port, Windows printer in RAW mode | Nothing; for USB without COM — the printer installed in Windows (Generic / Text Only works) |
| Label and ticket printer ZPL (Zebra), TSPL (TSC), EZPL (Godex) | Network (9100), COM port, Windows printer in RAW mode | The same |
| Boca Systems ticket printer (FGL) | Network (9100), COM port, Windows printer in RAW mode; 200 or 300 dpi | The same |
| Any Windows printer | Windows driver | Printer driver |
| QR code display Mertech QR-PA, QR-Screen | COM port (USB as a virtual COM) | The display's virtual COM driver |
| VFD/LCD customer display (Epson ESC/POS, CD5220) | COM port (USB as a virtual COM) | The display's virtual COM driver |
| Customer display on a second monitor | Page display.html?device=N full screen | A browser |
| Cash drawer | Via the register, via an ESC/POS printer or its own COM port | Nothing |
| Barcode scanner | COM port (USB as a virtual COM) or USB HID POS | For COM — the scanner's virtual COM driver |
| NFC/RFID card reader (ACR122U, ACR1252, Omnikey…) | USB, PC/SC | The reader's CCID driver (usually installs itself), the Smart Card service |
| UPS | USB, Windows sees it as a battery | Nothing |
| Another device on a COM port or the network | “Device port”: the application sends and receives the bytes | Nothing |
To test without hardware there are register and terminal emulators (the “For development” group).
Compatible fiscal registers
Many registers of other brands use the Shtrih-M or Pirit protocol inside. They need no separate driver: each has its own item in the “Add a device” window, and the settings are the same as for registers with that protocol.
| Register | Protocol | How to connect |
|---|---|---|
| Retail-01F, Retail-02F, Retail-Combo-01F | Shtrih-M | “Retail” item: USB (RNDIS, 192.168.137.111, port 7778) or COM port; cashier and administrator passwords are 30 by default |
| ELVES-FR-F | Shtrih-M | “ELVES” item: same as Shtrih-M |
| Paykiosk PayOnline-01-FA, Pay VKP-80K-FA | Shtrih-M | “Paykiosk” item: usually USB as a virtual COM port — choose “COM port” and press “Find ports” |
| RR-01F, RR-02F, RR-03F, RR-04F (RR-Electro) | Shtrih-M, usually exchange version 2 | “RR-Electro” item: same as Shtrih-M; protocol version 2 is chosen by default |
| Mercury in fiscal printer mode | Shtrih-M | “Shtrih-M, Mercury” item |
| Viki Print 57F, 57+F, 80+F (Dreamkas) | Pirit | “Viki Print” item: COM port (USB as a virtual COM, 57600) or network via the Wi-Fi module; link password PIRI |
| Pirit 1F, 2F, 2SF (Crystal Service) | Pirit | “Pirit” item |
If there is no connection, check the COM port speed and the exchange protocol version on the register itself: they are usually printed in the self-test when it is switched on with the paper feed button held.
SBP QR payment. “SBP QR payment” is added as a payment terminal and called with the same
/terminals/{id}/… methods. On payment the application creates a payment at the bank and shows the QR code:
in the application window, on the customer display whose number is set in the settings (a second monitor, a Mertech or QR-Screen QR code display), and as the qr event for your program.
The customer scans the QR in their bank app; the application asks the bank for the status every 2 seconds.
If it is not paid within the wait time, the payment is cancelled. The bank payment ID is returned in paymentRef.idProcessing
and is used for refunds. No settlement is needed for SBP.
- T-Bank: the TerminalKey and terminal password from the T-Business account (Internet acquiring → Shops → Terminals).
- Sberbank: the API login and password (usually
…-api) issued by the bank. - The “Test” environment uses the banks' test servers: no money is charged, handy for trying it out.
API
Principles
- Operations. Everything that changes a device's state is an operation.
POSTreturns its snapshot:{id, type, status, stage, result, error, warnings, createdAt, startedAt, finishedAt}.status:QUEUED→RUNNING→SUCCEEDEDorFAILED;UNKNOWN— the service restarted during the operation, check the result on the device. - Queue. Operations on one device run one at a time, on different devices — in parallel.
- Idempotency. Every operation
POSTcarries anIdempotency-Keyheader (e.g. a UUID per user action). A repeat with the same key returns the same operation and does not charge the card twice. - Waiting.
Prefer: wait=30— wait up to 30 seconds for the result (180 at most):200if the operation finished, otherwise202andLocationwith the operation URL. - Events.
GET /api/v1/events— Server-Sent Events:operationon every operation change,barcode— a scanner code{deviceId, code, at},card— a card on a reader{deviceId, uid, atr, reader, at},display— second-monitor display lines,qr— the QR for an SBP payment{deviceId, display, payload, amount, paymentId, bank, at}(payload: null— remove the QR),power— power change{source: AC|BATTERY, battery, batteryPercent, minutesLeft},language— interface language change. - Amounts — integer kopecks. Enumerations — strings (
SELL,CARD,VAT20). - Documentation. Swagger UI — all fields and examples; the description language is chosen in the “Select a definition” list.
Methods
| Method | What it does |
|---|---|
GET/api/v1/health | The service is running: version, start time, power (mains or battery) |
GET/api/v1/devices | Devices: number, kind, type, name |
GET/api/v1/language | Interface language: ru or en |
GET/api/v1/registers/{id}/shift | Register shift state |
POST/api/v1/registers/{id}/shift/open | Open shift {operator}* |
POST/api/v1/registers/{id}/shift/close | Close shift (Z report) {operator}* |
POST/api/v1/registers/{id}/reports/x | X report {operator}* |
POST/api/v1/registers/{id}/reports/calculation-state | Current calculation state report {operator}* |
GET/api/v1/registers/{id}/counters | Register counters: receipt count and sums by calculation sign for the shift and the whole fiscal drive (ATOL, Shtrih-M, Pirit) |
GET/api/v1/registers/{id}/fn-documents/{n} | A document from the fiscal drive by number (ATOL, Shtrih-M) |
POST/api/v1/registers/{id}/fn-documents/{n}/print | Print a copy of a document from the fiscal drive (ATOL, Pirit) |
POST/api/v1/registers/{id}/cash/in | Cash in {operator*, amount} |
POST/api/v1/registers/{id}/cash/out | Cash out {operator*, amount} |
POST/api/v1/registers/{id}/cash-drawer/open | Open the cash drawer |
POST/api/v1/registers/{id}/receipts | Print a receipt |
POST/api/v1/registers/{id}/corrections | Correction receipt {receipt, correction: {type: SELF|INSTRUCTION, baseDate, baseNumber}} — ATOL, Shtrih-M, Pirit |
POST/api/v1/registers/{id}/documents | Print non-fiscal text {lines} |
POST/api/v1/terminals/{id}/payments | Card payment {amount} |
POST/api/v1/terminals/{id}/refunds | Refund to card {amount, paymentRef} |
POST/api/v1/terminals/{id}/cancellations | Same-day payment cancellation {amount, paymentRef} |
POST/api/v1/terminals/{id}/settlements | Settlement |
POST/api/v1/terminals/{id}/emergency-reversals | Emergency reversal of the last operation when the POS did not get its result {amount, paymentRef?} |
POST/api/v1/terminals/{id}/reports?full=false | Terminal report on the shift's operations without settlement: short or full (full=true) |
GET/api/v1/terminals/{id}/last-slip | The slip of the last successful operation from the journal — to print it again |
GET/api/v1/qr?text=…&size=400 | QR code PNG image, e.g. for the payload from the qr event |
POST/api/v1/checkouts | A whole sale or refund: card → receipt → slip; if the receipt fails, the payment is cancelled |
GET/api/v1/printers | Windows printers, roles, settings |
POST/api/v1/print-jobs | Printing: urls, document (PDF base64), images, raw, report or text (lines, driverless printer only); printer, device (driverless printer) or role, copies |
POST/api/v1/cash-drawers/{id}/open | Open a cash drawer: id — register, ESC/POS printer or a drawer on a COM port |
POST/api/v1/displays/{id} | Show lines on the customer display {lines}; an empty list clears it |
POST/api/v1/displays/{id}/qr | Show a QR code on a QR code display or second monitor {payload, top, bottom}; an empty payload removes it |
GET/api/v1/displays/{id} | What is shown on the display |
POST/api/v1/channels/{id}/exchange | Send bytes to a device port and get the reply {hex | base64 | text, readTimeoutMs, until} |
GET/api/v1/reports | Report templates with parameters and fields |
POST/api/v1/reports/{name}/render | PDF by template {parameters, rows} — immediate, not an operation |
GET/api/v1/operations/{id} | An operation; with Prefer: wait=N waits for completion |
GET/api/v1/operations?limit=50 | Recent operations |
GET/api/v1/events | Events (SSE) |
* operator can be omitted if the cashier is set on the Workplace tab.
Then the request body is not needed either.
The /api/v1/setup/… methods serve the setup page and are available only from it.
Receipt
{
"type": "SELL", // SELL, SELL_RETURN, BUY, BUY_RETURN
"taxation": "USN_INCOME", // OSN, USN_INCOME, USN_INCOME_OUTCOME, ESHN, PATENT; absent — from Workplace or the register default
"operator": {"name": "Ivanova I.I.", "inn": "770123456789"}, // absent — the cashier from Workplace
"customer": {"contact": "+79991234567"}, // for an electronic receipt
"header": [
{"kind": "TEXT", "text": "Order 123", "align": "CENTER"},
{"kind": "PAIR", "text": "Date:", "right": "01.11.2026 19:00"},
{"kind": "SEPARATOR"}
],
"items": [
{"name": "Service", "price": 150000, "quantity": 1, "amount": 150000,
"vat": "NONE", "paymentMethod": "FULL_PAYMENT", "paymentObject": "SERVICE"}
],
"payments": [{"type": "CARD", "amount": 150000}], // CASH, CARD, PREPAID, CREDIT, OTHER
"footer": [],
"electronic": false, // true — do not print, send to the customer
"senderEmail": "kassa@example.ru", // tag 1117; absent — from Workplace
"settlementPlace": "Cash desk" // tag 1187; absent — from Workplace
}
The sum of payments must equal the sum of items, an item amount — price × quantity. Text lines are wrapped to the register paper width automatically.
Examples
Sale with a card payment — payment, receipt and slip in one operation:
POST /api/v1/checkouts
Content-Type: application/json
Idempotency-Key: 3f6c1d9e-1b2a-4c55-9e0d-6a1f0c2b7d11
Prefer: wait=170
{"registerId": 1, "terminalId": 2, "receipt": { … }, "printSlip": true}
Response: an operation with result.receipt (FD number, fiscal sign, shift, QR code) and result.payment
(paymentRef, card, RRN, authorization code, slip). paymentRef is needed for a refund.
Printing a PDF on the ticket printer:
POST /api/v1/print-jobs
Idempotency-Key: …
{"urls": ["https://example.com/tickets/1.pdf"], "role": "tickets", "copies": 1}
Report by template — a PDF right away or to a printer:
POST /api/v1/reports/ACT/render
{"parameters": {"NUMBER": "15", "DATE": "2026-11-01"},
"rows": [{"NAME": "Item 1", "PRICE": 1500}]}
POST /api/v1/print-jobs
{"report": {"name": "ACT", "parameters": { … }, "rows": [ … ]}, "role": "documents"}
Tickets by the TICKET template — one ticket per row, on the ticket printer:
POST /api/v1/print-jobs
Idempotency-Key: …
{"report": {"name": "TICKET", "rows": [
{"top_line": "Concerts LLC", "pos_line": "Grand hall", "addr_line": "1 Tverskaya St.",
"service_line": "Concert (12+)", "date_line": "Date: 01.11.2026 Start: 19:00",
"place_line": "Stalls row 5 seat 12", "price_line": "Price: 1500.00",
"sold_line": "31.10.2026 10:00 Cashier: Ivanova I.I.", "sale_line": "1911-000123"}
]}, "role": "tickets"}
Printer commands as is (ESC/POS, ZPL) — e.g. a ZPL label:
POST /api/v1/print-jobs
{"raw": "XlhBXkZPNTAsNTBeQTBOLDUwXkZESGVsbG9eRlNeWFo=", "printer": "Zebra ZD220"}
Waiting for an operation and events in the browser:
const events = new EventSource('http://localhost:7790/api/v1/events');
events.addEventListener('operation', e => {
const op = JSON.parse(e.data);
console.log(op.type, op.status, op.stage); // e.g. "tap the card on the terminal"
});
events.addEventListener('barcode', e => console.log(JSON.parse(e.data).code));
Errors
Request errors — RFC 9457 responses (application/problem+json) with a code field:
| HTTP | code | When |
|---|---|---|
| 400 | INVALID_REQUEST or none | Invalid JSON, no Idempotency-Key, field constraints violated (then code: INVALID_REQUEST and the fields in detail) |
| 404 | DEVICE_NOT_FOUND, REPORT_NOT_FOUND | No such device or template |
| 409 | IDEMPOTENCY_KEY_REUSED, DEVICE_BUSY | The key was used for another operation; the device is busy |
| 422 | VALIDATION_ERROR, REPORT_ERROR | Totals do not match, no cashier, invalid parameter value, template with errors |
Device errors arrive in the operation itself: status: FAILED, error: {code, message, details}.
Error texts from devices are in Russian.
| code | What happened |
|---|---|
DEVICE_ERROR | Register, terminal or printer error; the text is in message |
PAYMENT_CANCELLED | The receipt failed after a card payment; the payment was cancelled on the terminal |
PAYMENT_NOT_CANCELLED | The receipt failed and the payment could not be cancelled; payment data is in details |
RECEIPT_FAILED_AFTER_REFUND | Money was refunded to the card, the refund receipt was not printed |
INTERRUPTED | The service restarted during the operation |
Settings and files
Devices, printer roles and settings, the workplace, access, printing limits and the language are changed on the setup page
(values from the page win over the file). Everything else is in
config\application.yml in the program folder:
| Parameter | What it sets |
|---|---|
server.port | Agent port, 7790 by default; needs a restart |
hw.allowed-origins | Web application addresses allowed to call the service from the browser |
hw.api-token | Token: if set, API requests must carry Authorization: Bearer <token> (for events — ?access_token=) |
hw.printer.allowed-url-prefixes | Addresses PDFs may be downloaded from for printing |
hw.reports.dir, hw.reports.font | Report template folder and the Cyrillic font for PDFs |
hw.tray | false — no tray icon |
hw.power-monitor | false — do not monitor power |
| Folder | Contents |
|---|---|
data\devices.json | Devices |
data\printers.json | Printer roles and settings |
data\ui.json | Interface language |
data\workplace.json | Workplace: default cashier and receipt details |
data\access.json | Access and printing set on the setup page |
data\operations.jsonl | Operation journal |
reports\ | Report templates, images, subreports |
logs\ | Logs, 30 days |
Security
- The service listens only on
127.0.0.1: it cannot be reached from other computers. - Browser requests are accepted only from pages in
hw.allowed-originsand from the service's own page; requests from other sites are rejected before execution. - The host name must be
localhostor127.0.0.1— protection against DNS rebinding. - Device setup — only from the service's own page.
- PDFs are downloaded only from allowed addresses, with a timeout and a size limit.
- Report templates contain executable expressions: only someone with access to this computer can upload them.