Security
An Integration API key grants read access to whatever data its scopes and store restriction allow. Treat it exactly like a database password or a payment API secret key - not like a client-side config value.
- Store it in an environment variable or a secret manager on your server.
- Load it at process startup, not per-request.
- Use it only from server-to-server code - your backend calling EPOS, not a browser calling EPOS directly.
- Use a separate key per environment (Development / Production) and, where it makes sense, per deployment (staging vs. production instance of your own integration).
- Rotate it periodically and immediately if you suspect exposure.
- Include the request ID from an error response when reporting a problem - never the key itself.
- Never commit a key into source control - not in code, not in a
.envfile that gets committed, not in a commit message, not in a config file checked into a public or shared repository. - Never expose it in frontend/browser JavaScript. Anything shipped to a browser is visible to anyone who opens developer tools. If your integration has a browser-facing component, that component should call your backend, and your backend should hold the EPOS key.
- Never log the full key. If you need to identify which key made a request in your own logs, log the key’s public prefix (the non-secret part of the format described in API Keys) - never the full string.
- Never share one key across unrelated integrations or teams. Create a separate
IntegrationClientper integration so access can be scoped and revoked independently.
If a key may have been exposed
Section titled “If a key may have been exposed”Treat it as compromised: rotate it immediately. Rotation issues a new secret and invalidates the old one in the same step, so there’s no window where both an old, possibly-leaked key and a new key are simultaneously assumed safe.
Store restrictions and scopes are part of your security posture too
Section titled “Store restrictions and scopes are part of your security posture too”Request only the scopes your integration actually needs, and ask for a
store restriction if your integration only ever needs one store’s data. A key that can only read
inventory.stock.read for one store is safer to hold than one with every scope for every store -
even though both would technically work for a single-store stock dashboard.