SmartEPI External API
Integrate SmartEPI with your ERP, BI, or internal tooling. The API lets you:
- Read your organization — sectors, cost centers, job roles, groups, access groups, employees, and products.
- Read transactions — withdrawals, returns, and exchanges. These are read-only: they originate on the devices, never through the API.
- Manage your organization — create, update, and delete those org entities.
References are validated, so you can't point an employee at a cost center that
doesn't exist in your organization (
422). - Receive webhooks — real-time, HMAC-signed events the moment a transaction happens, so you don't have to poll.
Base URL & versioning
All requests go to your base host:
https://{your-api-host}/v1
Find it in the web console under Settings ▸ API Integration, shown next to your API keys. Copy it from there rather than hardcoding the placeholder from this page. Your API key is what scopes every request to your organization's data.
The contract is versioned in the path (/v1). Within a version, changes are
additive only — we never remove or repurpose a field you already depend on.
Data scope
Every API key is bound to your organization. A key reads and writes only your
own data — you never see or affect anyone else's. A write that references an ID
your organization doesn't own is rejected (422).
Conventions to know
- Server-to-server only. The API is designed to be called from your backend,
not directly from a browser. There is no CORS support — a browser pre-flight
(
OPTIONS) is not answered withAccess-Control-*headers, so a front-endfetch()straight to the API will be blocked by the browser. Keep your API key on the server (never ship it to a browser or mobile client) and proxy calls through your backend. POSTis not idempotent. Retrying a create makes a new record. Most resources are de-duplicated server-side — org entities and products reject a duplicate name (409), and an employee rejects a duplicate identification or email (409). But an employee created with neither an identification nor an email has no unique key, so two identicalPOSTs create two employees. If your client retries on a network error or a5xx, give each employee a uniqueidentification(oremail) so a replay collides (409) instead of duplicating.- One relationship filter per list request. On list endpoints, the relationship
filters (
sectorId/costCenterId/jobRoleId/groupIdfor employees;employeeId/productId/costCenterId/sectorIdfor transactions) each route to a different index, so you may send at most one per request — combining two returns400. You may combine that one relationship filter with aname(or, for employees,identification) search — the API applies the extra condition safely across pages. A relationship filter cannot be combined with a transaction time window (createdSince/createdUntil), which also returns400.
Quick start
-
In the web console, go to Settings ▸ API Integration and create an API key. Copy the key immediately — it is shown only once.
-
Call the API with the key as a bearer token:
curl https://{your-api-host}/v1/employees \-H "Authorization: Bearer sk_…" -
Optionally register a webhook endpoint (same console page) to receive real-time events.
Continue to Authentication for key handling.