API Overview
This section is a conceptual guide to each resource. For the exact, generated contract - every parameter, every field, every response status - see the API Reference, which is generated directly from the same OpenAPI document EPOS’s own tooling validates against.
Versioning
Section titled “Versioning”Every route lives under /v1/. There is currently one version. A future breaking change would
introduce /v2/ rather than changing /v1/’s behavior underneath you - the Phase 3 build of this
documentation doesn’t promise a specific deprecation policy beyond that, since no breaking change
has ever shipped yet.
Tenant and store scope
Section titled “Tenant and store scope”You never pass a tenant ID - it comes entirely from your API key. Every route that lists data
accepts an optional storeId filter:
- Omit it, and you get data across every store your key is allowed to see.
- Provide it, and it’s validated against your key’s allowed stores. A store outside what your key
is allowed to see returns
404 not_found- the same response as a store that doesn’t exist at all, so a caller can’t use this to discover which stores exist elsewhere in the tenant.
Pagination
Section titled “Pagination”GET /v1/catalog/products and GET /v1/inventory/stock are paginated:
page- 1-indexed, default1.pageSize- default50, maximum100.- The response includes
totalandtotalPages, computed independently of pagination - they always reflect everything matching your filters, not just the current page.
GET /v1/catalog/categories and GET /v1/catalog/promotions are not paginated - they return a
plain array. Both are typically small per-store lists.
Dates and money
Section titled “Dates and money”- Every timestamp is an ISO 8601 UTC string, e.g.
"2026-08-27T17:51:41.976Z". - Every money or decimal-quantity field (prices, VAT percentage, stock quantities) is a string,
e.g.
"1.25", not a native JSON number - this preserves exact decimal precision. Parse it with a decimal-safe library in whatever language you’re using, not a naive float parse, if you’re doing arithmetic on it.
updatedSince for incremental sync
Section titled “updatedSince for incremental sync”Products and inventory stock both accept updatedSince (ISO 8601). Use it to fetch only what
changed since your last successful sync, rather than re-fetching everything on every run - see
Catalog Sync and Inventory Sync for
a full pattern.
activeOnly
Section titled “activeOnly”Every listing route defaults to activeOnly=true (or the promotions-specific equivalent - see
Promotions) - inactive/archived records are hidden unless you explicitly ask
for activeOnly=false.
What’s deliberately not here
Section titled “What’s deliberately not here”This API returns what’s safe to expose to an external integration - not a mirror of EPOS’s
internal database. Cost prices, margins, supplier information, stock movement/adjustment history,
staff references, and internal promotion builder configuration never appear in any /v1 response,
regardless of scope. Each resource page below states exactly what’s excluded for that resource.