Skip to main content

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 with Access-Control-* headers, so a front-end fetch() 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.
  • POST is 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 identical POSTs create two employees. If your client retries on a network error or a 5xx, give each employee a unique identification (or email) so a replay collides (409) instead of duplicating.
  • One relationship filter per list request. On list endpoints, the relationship filters (sectorId/costCenterId/jobRoleId/groupId for employees; employeeId/productId/costCenterId/sectorId for transactions) each route to a different index, so you may send at most one per request — combining two returns 400. You may combine that one relationship filter with a name (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 returns 400.

Quick start

  1. In the web console, go to Settings ▸ API Integration and create an API key. Copy the key immediately — it is shown only once.

  2. Call the API with the key as a bearer token:

    curl https://{your-api-host}/v1/employees \
    -H "Authorization: Bearer sk_…"
  3. Optionally register a webhook endpoint (same console page) to receive real-time events.

Continue to Authentication for key handling.