e-bon
e-bon.ro
Architecture

Authenticate API requests

Authenticate to the e-bon API with an API key or a Portal sign-in token, manage scopes and roles, and handle authentication errors.

Every request to the e-bon API must carry one of two credentials: an API key (for server-to-server integrations and POS partners) or a Portal access token (for users signed in to the e-bon Portal or the on-device app). This page shows you how to obtain each one, how to send it, and what to do when authentication fails.

If you only need to push receipts from a POS or back-office system, use an API key. Portal access tokens are intended for human users signed in to the Portal.

Choose your authentication method

You are…Use this credentialSent as
A POS partner or back-office integrationAPI keyx-api-key: <key> header or Authorization: Bearer <key>
A user signed in to the Portal or on-device appPortal access token (JWT)Authorization: Bearer <token>

The two credentials are not interchangeable. API keys are bound to an organization and have scopes. Portal tokens are bound to a user inside an organization and have a role.

Authenticate with an API key

API keys are the recommended way to call the e-bon API from any server, POS terminal or back-office system. A key looks like this:

ebon_live_{orgId}_{32-hex}

The full key is shown to you only once, in the modal where you create it. Store it in a secure secrets store immediately — e-bon never displays the full secret again. The Portal will only show you the prefix (everything before the random tail) so you can identify the key later.

Send your first authenticated request

Create an API key in the Portal

Sign in to the Portal, open Settings → API keys, click Create API key, give it a label, pick the scopes it needs, and copy the key from the confirmation modal.

Copy the key before closing the modal. Once closed, the secret is unrecoverable. If you lose a key, revoke it and create a new one.

Add the key to your request

Send the key in the x-api-key header (preferred) or in Authorization: Bearer …:

POST /api/v1/receipts HTTP/1.1
Host: api.e-bon.ro
Content-Type: application/json
x-api-key: ebon_live_abc123def456_0123456789abcdef0123456789abcdef

{ "deviceId": "dev_…", "items": [ … ] }

Or, equivalently:

Authorization: Bearer ebon_live_abc123def456_0123456789abcdef0123456789abcdef

Handle the response

On success you get the resource back. On authentication failure you get a 401 or 403 JSON envelope — see Handle authentication errors below.

Revoke or rotate a key

API keys never expire on their own. To stop a key from working, open the Portal, find the key by its prefix and click Revoke. The next request that uses it returns 401 UNAUTHORIZED — API key is inactive. immediately.

There is no in-place rotation. To rotate a key, create a new one, update your secrets store, then revoke the old one once your deployment has rolled out.

Sign in to the Portal

Portal users sign in with email and password and receive a pair of tokens:

  • An access token valid for 15 minutes, sent on every API call as Authorization: Bearer <token>.
  • A refresh token valid for 7 days, used only to mint a new access token.

Complete the sign-in flow

Sign in

POST /api/v1/auth/login
Content-Type: application/json

{ "email": "you@example.com", "password": "…" }

The response contains accessToken, refreshToken and the user profile.

Call protected endpoints

Send the access token on every request:

GET /api/v1/devices
Authorization: Bearer <accessToken>

Refresh before expiry

When the access token expires (or earlier — anytime within the 7-day refresh window), exchange the refresh token for a fresh pair:

POST /api/v1/auth/refresh
Content-Type: application/json

{ "refreshToken": "<refreshToken>" }

The previous refresh token is invalidated immediately. Replace both stored tokens with the new pair returned in the response.

Sign out

POST /api/v1/auth/logout
Authorization: Bearer <accessToken>
Content-Type: application/json

{ "refreshToken": "<refreshToken>" }

This revokes only the supplied refresh token. Sessions on other devices remain active.

Each refresh token can be used once. If the same refresh token is presented twice (for example, after a network retry), the second attempt returns 401 — Refresh token has been revoked. The user must sign in again.

For full request and response shapes, see the Auth API reference.

Manage API key scopes

Every API key carries one or more scopes. Each request requires a specific scope; if the key is missing it, the API returns 403 FORBIDDEN — Insufficient scopes.

ScopeUse it for
receiptsCreate and read fiscal receipts.
receipts:readRead-only receipt access (reporting dashboards, exports).
receipts:adminAdmin-grade receipt actions (void / reversal endpoints).
reportsGenerate and read X, Z, daily and monthly fiscal reports.
devicesGeneral devices access (list, fetch, update).
devices:readRead-only device listing and lookup.
devices:writeCreate, update or delete devices; assign operators; configure fiscal settings.
commandsIssue device commands (POST /devices/:id/commands).
allUniversal access — satisfies any scope check.
Grant the narrowest set of scopes a key needs. A receipt-emitting POS only needs receipts; a reporting dashboard only needs receipts:read and reports.

Manage user roles

Portal users have one of three roles, set when they are added to the organization:

RoleWhat they can do
ownerFull Portal access. Created automatically for the user who signs the organization up. Can delete the organization.
adminSame Portal access as Owner, except for organization-deletion actions.
operatorDay-to-day Portal use — view receipts, run reports, manage operators on devices. Reduced administrative surface.

Roles are evaluated on every Portal API call. If a user tries an action their role does not permit, the API returns 403 FORBIDDEN — Insufficient role.

Understand plan limits

Some actions are gated by your subscription plan:

PlanMaximum devicesAPI keys allowed
Free2No
Pro10Yes
EnterpriseUnlimitedYes

When you hit a plan limit, the API returns 403 TIER_LIMIT_EXCEEDED with a message telling you which limit you hit and how to lift it (typically: upgrade your plan).

Handle rate limits

The API enforces three rate-limit buckets. All three return the same response on exhaustion:

{
  "code": "RATE_LIMIT_EXCEEDED",
  "message": "Too many requests, please try again later.",
  "status": 429
}

Every 429 response includes a Retry-After header in seconds — wait at least that long before retrying.

BucketWindowLimitApplies toKeyed by
Global10 min150 requestsEvery request to the APIAPI-key prefix if present, else client IP
Sign-in10 min30 requestsPOST /auth/register, /auth/login, /auth/refresh, /auth/forgot-passwordClient IP
Device commands10 min50 requestsPOST /devices/:deviceId/commands and the wrapper endpointsAPI-key prefix if present, else client IP
If you are running a high-volume integration, key your traffic by API key (not raw IP), and back off when you see 429 responses with respect to the Retry-After header.

Handle authentication errors

Every authentication and authorization failure returns a structured JSON envelope with a stable code field. Match on code (not on the human-readable message) when building error handling.

HTTPcodeMessageWhat it means
401UNAUTHORIZEDMissing or invalid Authorization header. Expected: Bearer <token>You forgot the Authorization header or sent it in the wrong format.
401UNAUTHORIZEDMissing access tokenThe header is present but the token after Bearer is empty.
401UNAUTHORIZEDInvalid or expired access tokenThe Portal access token is bad, expired or signed by someone else. Refresh it.
401UNAUTHORIZEDRefresh token has been revokedThe refresh token has already been used or was revoked. Sign in again.
401UNAUTHORIZEDInvalid or expired refresh tokenThe refresh token is malformed or past its 7-day window. Sign in again.
401UNAUTHORIZEDMissing API key. Provide via x-api-key header or Authorization: Bearer <key>.No credential at all on a protected endpoint.
401UNAUTHORIZEDInvalid API key format.The key does not match ebon_live_{orgId}_{32-hex}. Probably truncated or copied wrong.
401UNAUTHORIZEDInvalid API key.The key is shaped correctly but is not registered for this organization.
401UNAUTHORIZEDAPI key is inactive.The key was revoked from the Portal. Create a new one.
401UNAUTHORIZEDMissing authentication. Provide an API key via x-api-key header or a JWT via Authorization: Bearer <token>.The endpoint accepts either credential and you sent neither.
403FORBIDDENInsufficient role. Required: <role> or <role>The signed-in user does not have a role allowed for this endpoint.
403FORBIDDENInsufficient scopes. Missing: <scope>, <scope>The API key is valid but is missing the scopes this endpoint requires.
403TIER_LIMIT_EXCEEDEDDevice limit reached. Your <plan> plan allows a maximum of <N> devices (current: <K>). Upgrade your plan to add more devices.You are at your plan's device cap.
403TIER_LIMIT_EXCEEDEDAPI keys are not available on the Free plan. Upgrade to Pro to create API keys.Free plans cannot create API keys.
429RATE_LIMIT_EXCEEDEDToo many requests, please try again later.You hit a rate-limit bucket. Wait at least Retry-After seconds.
The 401 responses do not distinguish a bad signature from an expired token from a malformed one — they all return Invalid or expired access token. Treat any 401 UNAUTHORIZED on a protected endpoint as "the credential is dead, get a new one" rather than as a parseable diagnostic.

Where to go next