WebSocket API
This page describes the WebSocket protocol used by the FisCool driver for real-time integration, and how it maps onto the standard HTTP API.
1. The WebSocket Connection
This is a "reverse" (client-initiated) model. You, the integrator, run the WebSocket server; the FisCool driver acts as a WebSocket client and dials out to your server, opening a persistent connection. Your server then drives the local devices over that connection.
Because the driver connects outward, this works without any port forwarding, static IP, or inbound firewall rule on the machine running the driver - even behind NAT. It is the ideal method for controlling a fleet of drivers from your own central backend.
| Role | Who | Responsibility |
|---|---|---|
| WebSocket server | You (the integrator) | Host it, authenticate connections, send requests, read responses. |
| WebSocket client | The FisCool driver | Connects out to your server, executes requests on the local devices, replies. |
Configuration Requirements
To point a driver at your server, you provide it with a configuration certificate - a small JSON object holding your server URL and an authentication token of your choosing. There is nothing to request from us: the URL and token are yours, defined by your own server.
Instructions: the certificate is loaded into the driver from the menu Settings → Sales system certificate.
Certificate Format (JSON)
The JSON file must contain url and token, both pointing at your infrastructure. The token is an opaque shared secret that your server validates when the driver connects (choose any value you like). The driver_id is configured separately in the application UI (the "Driver ID" field) so you can tell your drivers apart; a value present in the file is ignored at import.
{
"url": "wss://api.yourdomain.com/ws", // WebSocket server URL
"token": "abc-123-xyz" // authentication token
}
The driver builds the connection URL as:
{url}?token={token}&driver_id={driver_id_from_ui}
Note: the driver reconnects automatically if the connection drops (retry every 5 seconds), and it monitors the ping packets received from the server to verify the health of the tunnel.
2. The Communication Protocol
All messages are JSON text frames wrapped in a standardised envelope.
Request (Server → Driver)
{
"id": 101, // unique request ID (used to correlate the response)
"type": 0, // 0 = request
"content": {
"action": 203, // action code (see below)
"idempotency_id": "optional-uuid", // OPTIONAL, only honoured by action 203
"parameters": { // action-specific payload
...
}
}
}
The driver only reacts to messages with type = 0; anything else is ignored.
Response (Driver → Server)
{
"id": 101, // same ID as the request
"type": 1, // 1 = response
"status": 0, // 0 = success, 1 = execution error, 2 = unknown action
"content": { // operation result (or error details)
...
}
}
Chunked Responses
Large responses (currently only image search results, action 205) are streamed in chunks of ~5 KB with type = 3:
{
"type": 3, // chunked response frame
"id": 101,
"status": 0,
"content": {
"d": "…partial JSON string…", // data fragment
"f": false // true on the final fragment
}
}
Concatenate all d fragments in arrival order until f = true, then parse the resulting string as JSON.
3. Available Actions
| Action Code | Name | Description |
|---|---|---|
999 | PING | Keep-alive. The driver answers with a pong (see below). |
201 | GET_CASE | Returns the configured fiscal devices. |
204 | GET_POS | Returns the configured POS terminals only. |
203 | DEVICE_OPERATION | Executes a fiscal or POS operation (receipt, Z report, sale, …). This is the main action - see Device Operations for all payloads. |
200 | GET_SYSTEM_PRINTERS | Returns the system printers that are enabled (active) in FisCool. |
202 | PRINT_HTML | Renders HTML and prints it as a bitmap on a system printer. Parameters: {"html": "...", "printer_name": "..."}. |
205 | SEARCH_IMAGES | Searches product images. Parameters: {"query": "...", "limit": 5}. The response (base64 data-URIs) is delivered as a chunked response. |
Action 201 - GET_CASE response
{
"id": 42, "type": 1, "status": 0,
"content": {
"status": 0,
"msg": "Device list retrieved",
"case": [ ... ] // array of fiscal devices (same objects as GET /devices/fiscal)
}
}
Action 204 - GET_POS response
{
"id": 43, "type": 1, "status": 0,
"content": {
"status": 0,
"msg": "POS terminals retrieved",
"terminals": [ ... ]
}
}
Action 200 - GET_SYSTEM_PRINTERS response
{
"id": 44, "type": 1, "status": 0,
"content": {
"status": 0,
"msg": "System printers retrieved",
"printers": ["POS-80", "Microsoft Print to PDF"] // printer names, only those enabled in FisCool
}
}
Action 202 - PRINT_HTML response
{
"id": 45, "type": 1, "status": 0,
"content": {
"status": 0,
"msg": "Bitmap print job completed successfully"
}
}
On failure, the outer status is 1 and content carries a printer error code (2001–2005, see Error Codes).
Action 205 - SEARCH_IMAGES response
Delivered as a chunked response (type = 3, see above). After reassembling the fragments, the content is:
{
"status": 0,
"msg": "Images retrieved",
"images": ["data:image/jpeg;base64,...", ...] // up to "limit" images
}
4. The Keep-Alive Mechanism (Ping/Pong)
To keep the connection alive and detect interruptions, the driver implements a watchdog:
- Timeout: the driver expects at least one inbound frame (typically a PING) every 20 seconds.
- Behaviour: if nothing is received in that window, the driver considers the connection dead, closes it, and reconnects.
- WebSocket protocol-level Ping frames are also answered automatically with Pong frames.
Ping Format (Server → Driver)
{
"id": 9999,
"type": 0,
"content": {
"action": 999,
"parameters": {}
}
}
Pong Format (Driver → Server)
{
"id": 9999,
"type": 1,
"status": 0,
"content": {
"pong": "pong"
}
}
5. Device Operations (Action 203) vs the HTTP API
WebSocket action 203 is the direct equivalent of the HTTP endpoint POST /devices/operation. Both execute the same internal logic; only the transport differs.
Request Structure
WebSocket (action 203): the payload goes into the parameters field of the envelope.
{
"id": 500,
"type": 0,
"content": {
"action": 203,
"parameters": {
"device_id": "device-uuid",
"operation": {
"type": "print_receipt",
"lines": [ ... ]
}
}
}
}
HTTP (POST /devices/operation): the same payload is the JSON request body.
Response Structure and the Double Status
There are two status fields in a WebSocket response. It is important to understand the difference:
| Level | Field | Possible Values | Meaning |
|---|---|---|---|
| 1. Envelope (outer) | status |
0 = execution success 1 = execution error 2 = unknown action |
Whether the driver processed the request. 1 means an exception occurred (communication error, validation, device error, …). |
| 2. Content (inner) | content.status |
0 = logical success > 0 = specific error code |
The business result of the operation - identical to the HTTP API body. See Error Codes. |
Golden rule:
- If the outer
statusis0, the operation fully succeeded (and the inner status is0too). - If the outer
statusis1, readcontent.statusandcontent.errorto find out why (hardware error, invalid parameters, …).
Success Example (outer 0, inner 0)
{
"id": 500,
"type": 1,
"status": 0, // ← OK
"content": {
"status": 0, // ← receipt printed OK
"msg": "Receipt printed",
"slip_number": 123,
"z_report_number": 45,
"fiscal_receipt_count": 1050
}
}
Error Example (outer 1, inner 500)
{
"id": 500,
"type": 1,
"status": 1, // ← an error occurred
"content": {
"status": 500, // ← specific code
"error": "Lipsă hârtie în imprimantă."
}
}
Getting Started
To integrate over WebSocket:
- Run a WebSocket server on your own infrastructure that implements the envelope protocol above.
- Choose an authentication token and have your server accept connections that present it (via the
tokenquery parameter). Usedriver_idto identify which driver connected. - Create a certificate JSON with your server's
urlandtoken, and load it into each driver via Settings → Sales system certificate. - When a driver connects, send it requests (action
203for device operations,201/204to list devices) and read the responses.
For technical questions, contact office@ceapa.cool.