API Keys
An API key authenticates a machine, not a person. Keys are project-scoped and are what external systems present when calling REST endpoints published by pipelines.
Creating a key
Keys are managed where they are used: open a REST API ingress node in a pipeline, set its authentication to API Key (X-API-Key), and use Project API Keys → Create Key. Listing, creating and revoking keys requires Access Settings. A key belongs to the project, so every endpoint in that project's pipelines can accept it.
Create API Key asks for a Name, an Expiry — Never, 30 days, 90 days, 1 year or Custom date… — and the scopes, as a preset (Read-only, Ingest / Writer, Full access) or picked one by one. The key list shows each key's prefix, its scopes and when it expires.
- The key value is shown once, at creation. Only a hash is stored — there is no "show key" later, by design.
- Revocation is immediate.
- Give each consumer its own key. One key shared by four systems cannot be revoked without breaking three of them.
Using a key
Send the key in the X-API-Key header to a published REST endpoint,
at http://<gateway>:8090/gateway/<project-slug><pattern>:
curl -X POST http://<gateway>:8090/gateway/plant-a/api/v1/orders \
-H "X-API-Key: <key>" \
-H "Content-Type: application/json" \
-d '{"orderId":"SO-1042"}'
Scopes
A key carries capability scopes; a route can require some. A key without a required scope is rejected even though it is otherwise valid.
| Scope | Grants |
|---|---|
tag:read | Read tags |
tag:write | Write tags |
db:read | Run named queries and read queries |
db:write | Arbitrary SQL, stored procedures, transactions |
hist:read / hist:write | Read / write time-series history |
vars:read / vars:write | Read / write variables |
egress:http | Make outbound HTTP calls to third parties |
file:read / file:write | List and download / upload files in the shared uploads folder |
script:execute | Execute scripts and transform nodes |
* | Everything — the Full access preset, and what a key created before scopes existed holds |
The presets are Read-only (tag:read, db:read, hist:read, vars:read) and
Ingest / Writer (those plus tag:write, db:write, hist:write).
The distinction between db:read and db:write is worth noting: named queries need only
db:read, while arbitrary SQL needs db:write — because arbitrary SQL may write. Building
integrations on named queries lets their keys run at a lower privilege.
The same scope model gates the scripting sandbox.
Scoping example
Key "mes-readonly"
scopes: tag:read, db:read, hist:read
GET /api/v1/line-status requires tag:read ✅
POST /api/v1/setpoint requires tag:write ❌ rejected
The MES can read everything it needs and cannot change anything, without a second gateway or a separate deployment.
Layered protection on a route
An API key is one control. Combine it with the others on the route:
| Control | Stops |
|---|---|
| API key | Unauthenticated callers |
| Required scopes | An authenticated caller exceeding its purpose |
| IP allow-list | Calls from outside the expected network |
| Rate limit + burst | Runaway clients, brute force |
| Max payload size | Memory-exhaustion attempts |
| CORS off | Browser-based cross-origin abuse |
Rotation
A key expires only if you gave it an Expiry when you created it; a Never key lives until it is revoked. Either way, rotate deliberately:
- Create a new key for the consumer.
- Deploy it on their side.
- Confirm traffic on the new key.
- Revoke the old one.
Rotate on a schedule you can actually keep — annually is better than a 90-day policy nobody follows — and immediately whenever someone who had access leaves.
Storing keys
- Treat a key like a password: secrets manager or environment variable, never a repository.
- Never put a key in browser-side code. A key in a web app is a public key.
- If a key is exposed, revoke first and investigate second.
Monitoring
Key usage is recorded in the audit journal. Look for:
- Calls from unexpected source addresses
- Rate-limit rejections, which usually mean a misconfigured client or an attempt
- Keys that have stopped being used — decommissioned integrations whose keys are still live
API keys versus user accounts
| API key | User account | |
|---|---|---|
| Identifies | A system | A person |
| Interactive login | No | Yes |
| Scope | Project + capability scopes | Gateway-wide role permissions |
| Revocation | Immediate | Deactivate the account |
| Use for | Integrations, machine access | People |
Never create a user account for a machine. A machine with a person's credentials makes the audit journal unusable exactly when you need it.