Controllers
Controllers
A controller is an E-BON mobile app instance — a phone or tablet running the E-BON app that owns and bridges one or more fiscal devices (AMEFs) on the local network to the cloud over a single WebSocket connection. The Controllers API lets you inspect and update the presence of the controllers connected to the e-bon backend for the authenticated organization, and register the FCM token used to wake a backgrounded controller.
Entries returned by the list endpoint are read straight from the in-memory controller gateway, so they reflect live connectivity, not Firestore state. The presence write endpoints update the persisted controller record (location binding, app version, device model, OS version, last-connected timestamp).
The routes live under /api/v1/controllers and accept either an API key (x-api-key / Authorization: Bearer …) or a Portal JWT.
GET /devices/statuses. For Firestore-persisted device records use GET /devices.GET /api/v1/controllers
Returns the list of E-BON controllers currently connected via WebSocket for the authenticated organization. Each entry includes the metadata captured during the WebSocket handshake (appVersion, deviceModel, osVersion, connectedAt), a controllerName resolved from the controller record — falling back to the raw controllerId if none is set — and connectedDevices, the ids of the owned devices whose local transport is currently up.
- Auth scope:
devices:read
Response (200 OK)
{
"instances": [
{
"controllerId": "ctrl_01HZ...",
"controllerName": "Tejghea POS 1",
"appVersion": "2.4.1",
"deviceModel": "Samsung Galaxy Tab A8",
"osVersion": "Android 14",
"connectedAt": "2026-04-09T08:00:00.000Z",
"connectedDevices": ["dev_pos_01", "dev_pos_02"]
}
]
}
Example
curl https://api.e-bon.ro/api/v1/controllers \
-H "x-api-key: ebon_live_acme_corp_a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6"
Error codes
UNAUTHORIZED/FORBIDDEN— see Authentication › Handle auth errors.
The full HTTP catalogue is on API overview › HTTP error code catalogue.
POST /api/v1/controllers/:controllerId
Registers (or fully replaces) the presence record for the controller with the given :controllerId, at the given location. Idempotent upsert — re-posting the same body is safe, and the controller record is created if it does not yet exist.
- Auth scope:
devices:write
Path parameters
controllerId— the controller (app instance) id.
Request body
{
"locationId": "loc_main_floor",
"appVersion": "2.4.1",
"deviceModel": "Samsung Galaxy Tab A8",
"osVersion": "Android 14",
"connectedAt": "2026-04-09T08:00:00.000Z"
}
locationId(string, required, 1–255 chars) — required because presence without a location binding is meaningless for routing fiscal traffic.appVersion,deviceModel,osVersion,connectedAt— optional.
Response (200 OK)
Returns the updated controller document with timestamps serialized to ISO-8601.
Example
curl -X POST https://api.e-bon.ro/api/v1/controllers/ctrl_01HZ... \
-H "x-api-key: ebon_live_acme_corp_a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6" \
-H "Content-Type: application/json" \
-d '{"locationId":"loc_main_floor","appVersion":"2.4.1"}'
Error codes
VALIDATION_ERROR (400)— body did not match the schema (missinglocationId, out-of-range string lengths).UNAUTHORIZED/FORBIDDEN— see Authentication › Handle auth errors.
PATCH /api/v1/controllers/:controllerId
Partially updates the presence record — e.g. when an operator moves a tablet between counters and only locationId changes.
- Auth scope:
devices:write
Path parameters
controllerId— the controller (app instance) id.
Request body
At least one field must be provided. All fields are optional individually, but the body must be non-empty.
{
"locationId": "loc_terrace"
}
Accepted fields: locationId, appVersion, deviceModel, osVersion, connectedAt — same shape and validation rules as POST.
Response (200 OK)
Returns the updated controller document with timestamps serialized to ISO-8601.
Example
curl -X PATCH https://api.e-bon.ro/api/v1/controllers/ctrl_01HZ... \
-H "x-api-key: ebon_live_acme_corp_a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6" \
-H "Content-Type: application/json" \
-d '{"locationId":"loc_terrace"}'
Error codes
VALIDATION_ERROR (400)— empty body, or fields failed schema checks.UNAUTHORIZED/FORBIDDEN— see Authentication › Handle auth errors.
POST /api/v1/controllers/:controllerId/fcm-token
Registers the Firebase Cloud Messaging registration token for the controller. The token is used solely as a wake-up channel: when the API needs a controller that is not currently connected via WebSocket, it sends a data-only push so the app reconnects and drains any pending fiscal commands. Idempotent — re-posting a refreshed token overwrites the previous one. Writes only the fcmToken and updatedAt fields (merge upsert), leaving presence fields untouched.
- Auth scope:
devices:write
Path parameters
controllerId— the controller (app instance) id.
Request body
{
"fcmToken": "fGc...:APA91b..."
}
fcmToken(string, required, 1–4096 chars).
Response (200 OK)
{ "controllerId": "ctrl_01HZ..." }
Error codes
VALIDATION_ERROR (400)— missing or out-of-rangefcmToken.UNAUTHORIZED/FORBIDDEN— see Authentication › Handle auth errors.
See also
- Devices — manage the fiscal devices these controllers own.
- Authentication — scope catalogue (
devices:read/devices:writeare documented here). - API overview — base URL, error envelope, rate limits, idempotency, pagination.
Billing
REST endpoints for managing the organization's Stripe subscription — checkout sessions, customer portal, subscription status, cancel/resume, invoices, and the Stripe webhook handler.
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.