e-bon
e-bon.ro
API reference

Commands

REST endpoints for queueing fiscal commands against an AMEF — submit a command, list and filter the queue, poll a single command for completion, and cancel a pending one.

Commands

The Commands API is the public surface of e-bon's command-queue model. A POS or back-office integration submits a fiscal command (print_receipt, x_report, cash_in, set_datetime, …) to e-bon over REST; the server persists the command, dispatches it to the matching device over WebSocket in the background, and returns a pending record immediately so the HTTP caller is never blocked by the device round-trip. The integration then polls GET /api/v1/commands/{commandId} until the command reaches a terminal status (completed, failed, timeout) or subscribes to the command.completed / command.failed / command.timeout events on the Webhooks channel.

All endpoints in this group live under /api/v1/commands and are governed by a single API-key scope: commands. They also accept a Portal JWT through the combined-auth middleware. See Authentication › Choose scopes for the full scope catalogue.

POST /api/v1/commands returns 201 with status: "pending"before the command has actually run on the AMEF. The HTTP 201 only confirms that the command has been persisted and queued — the device may still reject it (failed) or never reply (timeout). Always check the final status, either by polling GET /api/v1/commands/{commandId} or by listening for command.* webhook events.

The error envelope, idempotency rules and rate limits used below are documented once on API overview; only the per-endpoint error codes are listed in full on this page.

POST /api/v1/commands

Queues a fiscal command targeting a device in your organization. The command is dispatched to the device over WebSocket asynchronously; the response is returned immediately with status: "pending".

  • Auth scope: commands
  • Idempotency: supports the Idempotency-Key header (replays return the original 201 response without re-dispatching).
  • Rate limit: the route goes through the dedicated commandRateLimit middleware (50 / 10 min by default) on top of the global limit. See Rate limits.

Request body

FieldTypeRequiredNotes
deviceIdstringyesA device that exists in your organization (≥ 1 char).
typestringyesOne of the CommandType values: print_receipt, void_receipt, x_report, z_report, cash_in, cash_out, get_status, get_cash_amount, set_datetime, print_duplicate, non_fiscal_receipt, set_logo, delete_logo, raw_command, open_drawer, get_vat_rates, set_vat_rates, get_vat_capabilities, get_header_footer_capabilities, get_header_footer, set_header_footer, get_operator_capabilities, set_operator, get_info, get_last_receipt_info, void_open_receipt, print_reversal_receipt.
payloadobjectyesCommand-specific payload. Validated server-side against the per-type payload schema before dispatch.

Response (201 Created)

{
  "id": "cmd_abc123",
  "deviceId": "dev_pos_01",
  "type": "print_receipt",
  "payload": { "items": [], "payments": [] },
  "orgId": "acme_corp",
  "status": "pending",
  "apiKeyId": "apikey_abc",
  "deviceOnline": true,
  "createdAt": "2026-04-09T08:10:00.000Z",
  "updatedAt": "2026-04-09T08:10:00.000Z"
}

deviceOnline is a snapshot of the WebSocket connectivity at the moment the command was queued — false does not block the command (it stays pending and is dispatched as soon as the device reconnects), but it's a useful early-warning signal in your logs.

Example

curl -X POST https://api.e-bon.ro/api/v1/commands \
  -H "Authorization: Bearer ebon_live_acme_corp_a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: order-12345-attempt-1" \
  -d '{
    "deviceId": "dev_pos_01",
    "type": "x_report",
    "payload": {}
  }'

Error codes

  • VALIDATION_ERROR (400) — body failed Zod validation, or the payload failed the per-type payload-schema check (details lists { path, message } per field).
  • NOT_FOUND (404) — deviceId does not exist in your organization.
  • RATE_LIMIT_EXCEEDED (429) — command rate limit hit.
  • UNAUTHORIZED / FORBIDDEN — see Authentication › Handle auth errors.

The full HTTP catalogue is on API overview › HTTP error code catalogue.

GET /api/v1/commands

Lists commands for the organization, newest-first by createdAt. Optional filters narrow the result set; the response is a flat JSON array (no envelope).

  • Auth scope: commands

Query parameters

ParameterTypeDefaultNotes
deviceIdstringFilter by target device.
statusstringOne of the CommandStatus values: pending, sent, processing, completed, failed, timeout.
typestringFilter by CommandType value (see the enum on POST /api/v1/commands).
limitinteger501100.

Response (200 OK)

[
  {
    "id": "cmd_abc123",
    "deviceId": "dev_pos_01",
    "type": "print_receipt",
    "status": "completed",
    "payload": { "items": [], "payments": [] },
    "result": { "success": true, "fiscalId": "AMEF-000123" },
    "orgId": "acme_corp",
    "apiKeyId": "apikey_abc",
    "createdAt": "2026-04-09T08:10:00.000Z",
    "updatedAt": "2026-04-09T08:10:02.500Z"
  }
]

Example

curl "https://api.e-bon.ro/api/v1/commands?deviceId=dev_pos_01&status=failed&limit=20" \
  -H "Authorization: Bearer ebon_live_acme_corp_a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6"

Error codes

GET /api/v1/commands/{commandId}

Returns a single command by ID. Use this to poll for completion after POST /api/v1/commands.

  • Auth scope: commands

Path parameters

ParameterTypeNotes
commandIdstringCommand document ID.

Response (200 OK)

{
  "id": "cmd_abc123",
  "deviceId": "dev_pos_01",
  "type": "print_receipt",
  "status": "completed",
  "payload": { "items": [], "payments": [] },
  "result": {
    "success": true,
    "fiscalId": "AMEF-000123",
    "data": { "receiptNumber": "0000123" }
  },
  "orgId": "acme_corp",
  "apiKeyId": "apikey_abc",
  "createdAt": "2026-04-09T08:10:00.000Z",
  "updatedAt": "2026-04-09T08:10:02.500Z"
}

When the command is in a terminal failed state, result.success is false and error / errorCode / errorMessage are populated. The errorCode value is one of the Fiscal / device error codes.

Example

curl https://api.e-bon.ro/api/v1/commands/cmd_abc123 \
  -H "Authorization: Bearer ebon_live_acme_corp_a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6"

Error codes

POST /api/v1/commands/{commandId}/cancel

Cancels a command that is still in pending or sent status. The command's status is moved to failed with error: "Cancelled by API" and errorCode: "Unknown". Commands already in processing, completed, failed or timeout cannot be cancelled — once the device picks the command up, only the device decides the outcome.

  • Auth scope: commands
  • Side effect: updates the command record. Does not push a cancellation message to the device — if the device has already received the command over WebSocket, it may still finish it; the cancelled status is purely a server-side bookkeeping flag for the API caller.

Path parameters

ParameterTypeNotes
commandIdstringCommand document ID.

Response (200 OK)

{
  "id": "cmd_abc123",
  "deviceId": "dev_pos_01",
  "type": "print_receipt",
  "status": "failed",
  "payload": { "items": [], "payments": [] },
  "error": "Cancelled by API",
  "errorCode": "Unknown",
  "errorMessage": "Cancelled by API",
  "orgId": "acme_corp",
  "apiKeyId": "apikey_abc",
  "createdAt": "2026-04-09T08:10:00.000Z",
  "updatedAt": "2026-04-09T08:10:01.000Z"
}

Example

curl -X POST https://api.e-bon.ro/api/v1/commands/cmd_abc123/cancel \
  -H "Authorization: Bearer ebon_live_acme_corp_a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6"

Error codes

  • NOT_FOUND (404) — no command with that ID in your organization.
  • CONFLICT (409) — the command is no longer cancellable (current status is one of processing, completed, failed, timeout). The error message includes the current status.
  • UNAUTHORIZED / FORBIDDEN — see Authentication › Handle auth errors.

See also

  • Devices — device-scoped command shortcuts (POST /api/v1/devices/{deviceId}/commands and the typed wrappers for cash balance, header/footer, VAT rates, reversals, etc.).
  • Webhooks — subscribe to command.completed, command.failed and command.timeout events instead of polling.
  • Authentication — API-key format, scopes and JWT login flow.
  • API overview — base URL, error envelope, rate limits, idempotency, pagination.
  • Troubleshooting › Command timeouts and the 180s sweep — what command.timeout actually means and how to retry idempotently.