Device Operations
This section is the complete reference for the device operations that can be executed via the HTTP API (POST /devices/operation), the WebSocket API (action 203), or - for a subset - INP files. All transports execute exactly the same internal logic; only the transport differs.
Request Envelope
Every operation request has the same top-level structure:
{
"device_id": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d", // UUID of a configured device
"operation": {
"type": "operation_name", // snake_case operation type
// ... operation-specific fields
}
}
device_idis the configuration UUID of the device (theconfig.idfield returned byGET /devices/fiscal/GET /devices/pos). It is not the hardware serial number.- Fiscal operations require a fiscal device UUID; POS operations require a POS terminal UUID. Sending a POS operation to a fiscal device (or vice versa) returns error
400. Hybrid devices (fiscal devices with a built-in POS) appear in both lists with the same UUID and accept both operation families. - All monetary amounts are integers in cents (bani) unless explicitly stated otherwise.
- An optional
Idempotency-Key(HTTP header) /idempotency_id(WebSocket) makes the operation idempotent: repeated submissions with the same key return the result of the single execution.
Response Envelope
On success every operation returns JSON with "status": 0, a human-readable msg, plus operation-specific fields (documented per operation below). On failure the response is:
{
"status": 500, // application-specific error code (positive integer)
"error": "Lipsă hârtie în imprimantă.", // human-readable message (Romanian)
"receipt": "..." // OPTIONAL: only on some POS errors (e.g. declined sale slip)
}
See Error Codes for the complete list. Note that error codes are positive integers.
Fiscal Device Operations
print_receipt
Description: Prints a fiscal receipt with items, free text, payments and optional buyer information. This is the most complex and most important operation in the system.
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
lines | Array<ReceiptLine> | Yes | Receipt lines in print order (items, free text, subtotal). At least one item line is required unless the receipt is voided. |
payments | Array<PaymentLine> | Yes | Payment lines. The sum must equal the receipt total exactly (see Validation below). May be [] only when close_action is "void". |
buyer | BuyerInfo | No | Buyer identification for receipts with the customer's fiscal code (CUI/CIF). |
receipt_discount | Discount | No | Whole-receipt discount or surcharge, applied to the total. |
flags | ReceiptFlags | No | Behaviour flags. Default: {"is_invoice": false, "skip_background_sync": false}. |
close_action | String | Yes | "close" (fiscalise normally) or "void" (open, then cancel the whole receipt - nothing is fiscalised). |
ReceiptLine Object
A receipt line is a tagged object - type selects the variant:
// Item (sale) line
{
"type": "item",
"description": "Product Name", // "name" is accepted as an alias
"quantity_thousandths": 1000, // 1000 = 1.000 pieces (3 implied decimals)
"unit_price_cents": 1500, // 1500 = 15.00; negative values are accepted for value corrections
"vat": "19%", // see "VAT values" below
"discount": { // OPTIONAL item-level discount/surcharge
"kind": "percent",
"basis_points": 1000, // 1000 = 10.00%
"is_surcharge": false
},
"um": "buc", // OPTIONAL unit of measure; empty/missing becomes "buc"
"department": 3 // OPTIONAL department code (1-99)
}
// Free text line
{
"type": "text",
"text": "Custom text to print"
}
// Subtotal line
{
"type": "subtotal",
"discount": { // OPTIONAL discount/surcharge applied to the running subtotal
"kind": "percent",
"basis_points": 1000,
"is_surcharge": false
}
}
VAT values (vat field)
The vat field is a string accepting the following forms:
| Form | Example | Meaning |
|---|---|---|
| Percentage | "19%", "9.5%" | The driver maps the percentage to the device VAT group with that exact rate. If no active group matches, the operation fails with a descriptive error. "0%" prefers group E. |
| Letter | "A" … "H" | Direct device VAT group. Must be active on the device (checked against the rates read at connect), except "D" which is always accepted. Lowercase letters are rejected. |
"scutit" | "scutit" | VAT-exempt: identical to "0%" - maps to a 0% group, preferring E. |
"neimpozabil" | "neimpozabil" | Non-taxable: maps to a 0% group, preferring a non-E group and falling back to E only if it is the only 0% group. |
PaymentLine Object
{
"method": "cash", // see payment methods table
"amount_cents": 1500
}
Payment methods (method):
| Code | Name |
|---|---|
cash | Cash (numerar) |
card | Card |
credit | Credit |
tichete_masa | Meal vouchers (tichete de masă) |
tichete_valorice | Value vouchers (tichete valorice) |
voucher | Voucher |
plata_moderna | Modern payment |
cashback | Card payment + cash advance. The paid amount must exceed the receipt total; the difference is handed to the customer as cash. |
alte_metode | Other methods |
BuyerInfo Object
{
"vat_number": "RO12345678" // customer fiscal code (CUI/CIF)
}
Discount Object
Used for item-level, subtotal-level and receipt-level discounts/surcharges. kind selects the variant:
// Percentage
{
"kind": "percent",
"basis_points": 1000, // 1000 = 10.00%
"is_surcharge": false // false = discount, true = surcharge
}
// Absolute amount
{
"kind": "absolute",
"amount_cents": 500, // 500 = 5.00 (always positive)
"is_surcharge": false
}
ReceiptFlags Object
| Flag | Type | Default | Description |
|---|---|---|---|
is_invoice | boolean | false | Opens the receipt as an invoice-type receipt (with buyer fiscal code). |
skip_background_sync | boolean | false | Skips the internal post-print sales synchronisation for this receipt. |
Validation & Preprocessing
Before anything is sent to the device, the driver validates and normalises the request. A failed validation returns error 400 with a descriptive message and nothing is printed.
- Diacritics are removed from item descriptions, units of measure and free-text lines.
- Zero-priced items (
unit_price_cents = 0) are converted to free-text notes (e.g.2 buc PUNGA 0 lei) because fiscal devices reject zero-value sale lines. - The receipt must contain at least one item line (unless voided).
- The receipt total must be strictly positive after all discounts (unless voided).
- The sum of payments must equal the receipt total exactly. Exception: when a
cashbackpayment is present, the sum must be greater than or equal to the total. Line totals are computed asquantity_thousandths × unit_price_cents / 1000, rounded half away from zero. - Only one subtotal line with a discount is allowed per receipt, and a subtotal discount cannot be combined with a
receipt_discount. - Each item's VAT is validated against the rates active on the device (see VAT values above).
- When
close_actionis"void", all of the above sale validations are skipped: the receipt is opened and then cancelled, and payments are not tendered.
Response:
{
"status": 0,
"msg": "Receipt printed",
"slip_number": 123, // fiscal receipt number
"z_report_number": 45, // number of the Z report the receipt belongs to
"fiscal_receipt_count": 1050, // device fiscal receipt counter
"bon_id": "1234...32digits" // receipt QR bon-ID (Datecs only, when enabled); null otherwise
}
Auto Card-to-POS: If enabled in the fiscal device configuration (auto_send_card_to_pos + linked_pos_device_id), the summed card and cashback payments are first sent as a sale to the linked POS terminal. If the POS transaction fails, the fiscal receipt is not printed and the POS error is returned.
Connection check: the operation fails immediately with error 1004 if the fiscal device is not in the Connected state.
print_non_fiscal_receipt
Description: Prints a non-fiscal receipt (free text) on the fiscal device. Useful for proforma documents, order slips, or any information that must not be fiscalised.
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
lines | Array<NonFiscalLine> | Yes | Text lines to print. |
NonFiscalLine Object
// Simple text line
{
"type": "text",
"text": "Text to print"
}
// Text line with formatting (honoured on Datecs devices; other devices print plain text)
{
"type": "text",
"text": "Formatted text",
"formatting": {
"bold": true,
"italic": false,
"double_height": true,
"underline": false,
"alignment": "center", // "left" (default), "center", "right"
"condensed": false
}
}
Response: same shape as print_receipt; the numeric fields refer to non-fiscal counters and may be 0 depending on the device:
{
"status": 0,
"msg": "Receipt printed",
"slip_number": 0,
"z_report_number": 0,
"fiscal_receipt_count": 0
"bon_id": null
}
print_x
Description: Prints an X report (daily totals, without closing the fiscal day).
Parameters: none (besides type).
Response:
{
"status": 0,
"msg": "Report printed",
"report_number": 45, // report counter
"grand_total_sell": 123456, // daily grand total, in cents
"payment_totals": [ // per-payment-method totals (may be empty if the device
{ "method": "cash", "amount": 100000 }, // could not report them; amounts in cents)
{ "method": "card", "amount": 23456 }
],
"vat_totals": [ // per-VAT-group totals; only groups with amount > 0
{ "letter": "A", "value": 1900, "amount": 100000 } // value = rate in basis points
],
"full_text": null // full report text; populated only for Z reports on Datecs
}
Notes:
payment_totals[].methoduses the same codes as receipt payments (cash,card, …).- The granularity of
payment_totalsdepends on the device: some devices track fewer physical payment registers and group several methods together. - An empty
payment_totals/vat_totalsarray means the device could not provide the breakdown - it does not mean zero sales.
print_z
Description: Prints a Z report (fiscal daily closure). Resets the daily counters.
Parameters: none.
Response: identical in shape to print_x (see above). full_text contains the complete printed report text on Datecs devices, null elsewhere.
print_department_report
Description: Prints the departments report (daily sales grouped by department), without closing the fiscal day and without resetting any counters.
Parameters: none.
Response: the report prints only on paper - no totals are returned:
{
"status": 0,
"msg": "Operation completed successfully"
}
Notes:
- Supported on Datecs, Daisy, Tremol and Custom devices. Devices whose protocol has no departments report return error
1015(operation not supported). - In the INP file interface, the same report is triggered with
Z,1,______,_,__;3;(legacy/FPrint) orD^(simple/modern).
deposit_cash
Description: Registers a cash deposit (service in) in the fiscal device.
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
amount | integer | Yes | Deposit amount in cents. Must be > 0 (0 returns error 400). |
Response:
{
"status": 0,
"msg": "Cash operation successful",
"total_cash_drawer": 1250.75 // total cash in drawer AFTER the operation,
} // in currency units (lei) as a decimal - NOT cents
withdraw_cash
Description: Registers a cash withdrawal (service out) from the fiscal device.
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
amount | integer | Yes | Withdrawal amount in cents. Must be > 0. Withdrawing more than the drawer holds returns error 536. |
Response: same shape as deposit_cash (total_cash_drawer in lei, decimal).
chime
Description: Triggers the acoustic signal (buzzer) of the fiscal device. On devices without a controllable buzzer, a short non-fiscal note is printed instead so the action is still observable.
Parameters: none.
Response:
{
"status": 0,
"msg": "Operation completed successfully"
}
open_drawer
Description: Opens the cash drawer connected to the fiscal device.
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
pulse_duration_ms |
number | No | Drawer pulse duration in milliseconds. When omitted, the driver default applies (Datecs: 200 ms; Daisy: the device's last configured value). Tremol devices ignore this parameter entirely. Devices without drawer control return error 1015. |
Response:
{
"status": 0,
"msg": "Operation completed successfully"
}
anaf_export
Description: Exports fiscal data files for ANAF (Romanian tax authority) reporting to a local folder.
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
range | AnafExportRange | Yes | Date range or Z-number range (untagged - the field types decide, see below). |
destination_path | string | Yes | Path where the export is written, on the machine running the driver. |
AnafExportRange Object
// Date range (strings, YYYY-MM-DD)
{ "start": "2023-12-01", "end": "2023-12-31" }
// Z-number range (integers)
{ "start": 1, "end": 10 }
Response:
{
"status": 0,
"msg": "Operation completed successfully"
}
anaf_status
Description: Reads the ANAF synchronisation status from the fiscal device.
Parameters: none.
Response: the data field is a JSON-encoded string containing one of:
{
"status": 0,
"msg": "Report data retrieved successfully",
"data": "\"Success\""
}
// data decodes to one of:
"Success" // last sync OK
{ "Failed": { "error_code": -3, "error_message": "..." } } // last sync failed
"Unknown" // unsupported / unknown
load_logo
Description: Uploads a logo image to the fiscal device, to be printed on receipts. The driver converts the image to the device's native format; use get_logo_dimensions to find the optimal size.
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
image_data | string | Yes | Base64-encoded image (PNG, JPG, …). |
Response:
{
"status": 0,
"msg": "Operation completed successfully"
}
get_logo_dimensions
Description: Returns the logo dimensions (in pixels) supported by the device.
Parameters: none.
Response: data is a JSON-encoded string:
{
"status": 0,
"msg": "Report data retrieved successfully",
"data": "{\"width\":576,\"height\":128}"
}
fiscal_memory_report
Description: Prints a fiscal memory report for a date or Z-number range, on the device printer.
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
range | FiscalRange | Yes | Date range or Z-number range (untagged, same convention as anaf_export). |
report_type | string | Yes | "short" or "detailed". |
FiscalRange Object
// Date range (strings, YYYY-MM-DD)
{ "start": "2023-12-01", "end": "2023-12-31" }
// Z-number range (integers)
{ "start": 1, "end": 10 }
Response:
{
"status": 0,
"msg": "Operation completed successfully"
}
je_report
Description: Generates an electronic journal (JE) report, either printed on the device or returned as text.
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
range | JeReportRange | Yes | Tagged range object (see below). |
doc_type | string | Yes | Document type filter (see list). |
output_mode | string | Yes | "print_on_device" or "read_line_by_line". |
JeReportRange Object (tagged with type)
// Date range
{ "type": "date", "start": "2023-12-01", "end": "2023-12-31" }
// Z-number range
{ "type": "z_number", "start": 1, "end": 10 }
// Document number range
{ "type": "doc_number", "start": 100, "end": 200 }
Document Types (doc_type)
"all"- all document types"fiscal_receipts"- fiscal receipts only"z_reports"- Z reports only"invoices"- invoices only"non_fiscal_receipts"- non-fiscal receipts only"numerar"- cash (deposit/withdraw) operations only
Output Modes (output_mode)
"print_on_device"- the report is printed on the fiscal device;datain the response is empty."read_line_by_line"- nothing is printed; the report text is returned indata.
Response:
{
"status": 0,
"msg": "Report data retrieved successfully",
"data": "line1\nline2\n..." // report text when output_mode = "read_line_by_line"
}
get_vat_rates
Description: Reads the VAT groups currently programmed on the device.
Parameters: none.
Response: data is a JSON-encoded string mapping group letters to rates in basis points (1900 = 19.00%):
{
"status": 0,
"msg": "Report data retrieved successfully",
"data": "{\"A\":1900,\"B\":900,\"C\":500,\"E\":0}"
}
set_vat_rates
Description: Programs the device's VAT groups. Warning: on real devices this is a fiscally-relevant operation - most devices require a Z report first and limit the total number of VAT changes over the device lifetime (e.g. Datecs allows up to 51).
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
rates | object | Yes | Map of VAT group letter → rate in basis points, or null to deactivate the group. |
{
"device_id": "...",
"operation": {
"type": "set_vat_rates",
"rates": { "A": 1900, "B": 900, "C": 500, "D": null, "E": 0 }
}
}
Response:
{
"status": 0,
"msg": "VAT rates programming successful",
"remaining_changes": 42 // remaining allowed VAT changes, or null if the device doesn't report it
}
After programming, the driver re-reads the rates from the device and refreshes its cached state automatically.
schedule_vat_rate_change
Description: Schedules a VAT rate change to be executed automatically at a future time (e.g. a legislated VAT change at midnight). Schedules are persisted and survive driver restarts; on failure, execution is retried every minute.
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
rates | object | Yes | Same format as set_vat_rates. |
execution_time | integer | Yes | Unix timestamp in seconds (UTC) when the change should run. |
Response:
{
"status": 0,
"msg": "Operation completed successfully"
}
Pending schedules are visible in the device object (field scheduled_vat_rate_changes, each entry with its id) returned by GET /devices/fiscal.
cancel_scheduled_vat_rate_change
Description: Cancels a pending scheduled VAT rate change.
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
schedule_id | string (UUID) | Yes | The id of the schedule (from scheduled_vat_rate_changes). |
Response: {"status": 0, "msg": "Operation completed successfully"}. Returns error 400 if the schedule does not exist.
get_settings
Description: Reads driver-managed device settings.
Parameters: none.
Response: data is a JSON-encoded string:
{
"status": 0,
"msg": "Report data retrieved successfully",
"data": "{\"block_on_auto_z_report\":false,\"include_qr_on_receipt\":true}"
}
| Setting | Type | Description |
|---|---|---|
block_on_auto_z_report | boolean | null | true: the device blocks when a Z report is due; false: it prints one automatically; null: the device does not expose this option. |
include_qr_on_receipt | boolean (optional) | Datecs only: whether a bon-ID QR code is appended to each fiscal receipt. Absent when the device doesn't support it. |
set_settings
Description: Writes the settings described at get_settings.
Parameters:
{
"device_id": "...",
"operation": {
"type": "set_settings",
"settings": {
"block_on_auto_z_report": false,
"include_qr_on_receipt": true
}
}
}
Response: {"status": 0, "msg": "Operation completed successfully"}
fiscal_memory_test
Description: Runs a fiscal memory self-test on the device.
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
write_test | boolean | Yes | true performs a write test (consumes a fiscal memory test record!); false performs a read-only test. |
Response: data is a JSON-encoded string:
{
"status": 0,
"msg": "Report data retrieved successfully",
"data": "{\"free_records\":14}" // remaining test records (0-16), or null if unknown
}
read_status
Description: Reads the detailed hardware/state flags of the device (paper, cover, receipt open, fiscal memory, …). The exact set of fields is device-specific.
Parameters: none.
Response: data is a JSON-encoded string:
{
"status": 0,
"msg": "Report data retrieved successfully",
"data": "{\"fields\":[{\"name\":\"NoPaper\",\"description\":\"Lipsă hârtie\",\"value\":0}, ...],\"raw_data\":\"...\"}"
}
fields[]- one entry per status flag:name, human-readabledescription, andvalue(0/1).raw_data- the raw status bytes as reported by the device, for debugging.
POS Terminal Operations
These operations target POS payment terminals (or the POS side of hybrid fiscal devices).
sale
Description: Starts a card payment transaction on the POS terminal.
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
amount | integer | Yes | Transaction amount in cents. Must be > 0. |
suppress_print | boolean | No | Default false. When true, the POS receipt is not printed by the terminal - it is only returned in the response (receipt field), so you can print it yourself. |
Response:
{
"status": 0,
"msg": "Sale successful",
"transaction_id": "000012345678", // RRN - keep it, it is required for void
"authorization_code": "123ABC", // keep it, it is required for void
"receipt": "..." // POS receipt text, when available
}
Error case: a declined/failed transaction returns an error response (codes 600–611) which may also include a receipt field with the decline slip.
void
Description: Voids (reverses) a previous sale transaction.
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
amount | integer | Yes | Original transaction amount in cents. Must be > 0. |
transaction_id | string | Yes | RRN returned by the original sale. |
authorization_code | string | Yes | Authorization code returned by the original sale. |
Response:
{
"status": 0,
"msg": "Void successful",
"receipt": "..." // void receipt text, when available
}
settlement
Description: Performs the end-of-day settlement (batch close) on the POS terminal.
Parameters: none.
Response:
{
"status": 0,
"msg": "Settlement successful",
"receipt": "..." // settlement report text, when available
}
Response Kinds - Summary
Every successful response is one of the following shapes:
| Kind | msg | Extra fields | Returned by |
|---|---|---|---|
| Receipt | Receipt printed | slip_number, z_report_number, fiscal_receipt_count, bon_id (nullable) | print_receipt, print_non_fiscal_receipt |
| Report | Report printed | report_number, grand_total_sell, payment_totals, vat_totals, full_text | print_x, print_z |
| Cash | Cash operation successful | total_cash_drawer (lei, decimal) | deposit_cash, withdraw_cash |
| Data | Report data retrieved successfully | data (JSON-encoded string) | anaf_status, je_report, get_settings, get_vat_rates, get_logo_dimensions, fiscal_memory_test, read_status |
| VAT programming | VAT rates programming successful | remaining_changes | set_vat_rates |
| Empty | Operation completed successfully | - | print_department_report, chime, open_drawer, anaf_export, load_logo, fiscal_memory_report, set_settings, schedule_vat_rate_change, cancel_scheduled_vat_rate_change |
| POS Sale | Sale successful | transaction_id, authorization_code, receipt | sale |
| POS Void | Void successful | receipt | void |
| POS Settlement | Settlement successful | receipt | settlement |
Usage Examples
See the HTTP API and WebSocket API pages for complete transport-level examples of invoking these operations.