Skip to main content

Managing API Keys

Overview​

API keys authenticate machine-to-machine traffic: the Edge Agent pushing readings, a script sending data straight to the ingestion endpoint, a dashboard tool reading your machines, or an integration that works with your data on its own. Unlike a user login, an API key is a long-lived credential meant for non-interactive systems.

Interactive access by a person uses a short-lived Bearer JWT instead. See Authentication.

Two kinds of key​

KindUse it forWhat it can reach
edge_agent (default)The Edge Agent, ingestion scripts, read-only dashboard toolsOnly what its scopes allow (below)
service_accountAn integration that needs to work with your data the way a team member doesWhatever its role allows, through the same endpoints a person in that role uses

The kind is fixed when the key is created.

Edge-agent scopes​

ScopeGrants
ingestPOST /api/v1/ingest: send readings
agentGET and POST /api/v1/agent/heartbeat: the Edge Agent's check-in
read:machinesGET /api/v1/machines and GET /api/v1/machines/{machine_id}
read:sensorsGET /api/v1/machines/{machine_id}/readings, /readings/latest, and /summary

A key created without scopes gets ingest and agent, which is what the Edge Agent needs. You can also pass a preset name instead of a list: edge_agent (ingest, agent) or read_only (read:machines, read:sensors). A key with a read scope reads every machine in your company; per-user machine-group restrictions do not apply to it.

An edge-agent key cannot manage anything: users, alert rules, notification channels, integrations, and other settings always need a signed-in user or a service account.

Service accounts​

A service-account key acts as a member of your company with the role you give it (admin, operator, viewer, or one of your custom roles). It can call whatever a person in that role can, with one exception: it can never manage users, roles, API keys, or sign-in settings, however broad its role. That way a leaked key cannot create new credentials that outlive its own revocation.

Creating a key​

Create keys from the Client Portal (Settings → API Keys) or from the API. In both cases, only an account administrator can create a key.

POST /api/v1/settings/api-keys

FieldTypeRequiredDescription
namestringYesA descriptive name (1–255 chars)
kindstringNoedge_agent (default) or service_account
scopesstring[]NoEdge-agent keys only. A list of scopes, or one preset name. Defaults to ingest and agent
rolestringService accounts onlyThe role the account acts with. Required for a service account, refused for an edge-agent key
expires_atstring (ISO 8601)NoWhen the key stops working. Omit it for a key that does not expire

An edge-agent key for a plant:

curl -X POST "https://api.haltless.io/api/v1/settings/api-keys" \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "name": "edge-agent-plant-1" }'

A service account for a maintenance integration:

curl -X POST "https://api.haltless.io/api/v1/settings/api-keys" \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "name": "cmms-sync", "kind": "service_account", "role": "operator", "expires_at": "2027-06-30T00:00:00Z" }'

Response (201 Created):

{
"id": "b1e7c0a2-3d4e-4f5a-9b6c-7d8e9f0a1b2c",
"name": "edge-agent-plant-1",
"key": "<your-new-api-key>",
"scopes": ["ingest", "agent"],
"tenant_id": "7d8e9f0a-1b2c-4f5a-9b6c-b1e7c0a23d4e",
"created_at": "2026-08-05T10:00:00Z",
"kind": "edge_agent",
"role": null
}
warning

The key value is returned only once, at creation. Store it in a secrets manager immediately. If you lose it, revoke the key and create a new one; there is no way to retrieve it later.

Using a key​

Send the key in the X-API-Key header on every request:

curl -X POST "https://api.haltless.io/api/v1/ingest" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "readings": [] }'
ResponseMeaning
401 UnauthorizedThe key is unknown, revoked, or past its expires_at
403 ForbiddenThe key is valid but lacks the scope (edge agent) or the role permission (service account) for this request
402 Payment RequiredAn edge-agent key while your company's account is suspended. See Errors

To push readings with a key, see Direct Ingestion. To configure the Edge Agent with a key, see the Edge Agent configuration guide.

Listing keys​

List the keys on your account. The secret is never returned. You get only a short, non-sensitive prefix so you can tell keys apart:

curl "https://api.haltless.io/api/v1/settings/api-keys" \
-H "Authorization: Bearer YOUR_JWT_TOKEN"
[
{
"id": "b1e7c0a2-3d4e-4f5a-9b6c-7d8e9f0a1b2c",
"tenant_id": "7d8e9f0a-1b2c-4f5a-9b6c-b1e7c0a23d4e",
"name": "edge-agent-plant-1",
"key_prefix": "Xk3vQ9pL...",
"scopes": ["ingest", "agent"],
"created_at": "2026-08-05T10:00:00Z",
"is_active": true,
"expires_at": null,
"last_used_at": "2026-08-06T08:12:44Z",
"kind": "edge_agent",
"role": null
}
]

last_used_at shows when the key last authenticated a request, which helps you find keys nobody uses any more.

Changing a key​

PATCH /api/v1/settings/api-keys/{key_id} changes a key's name, expires_at, and either its scopes (edge-agent keys) or its role (service accounts). Send only the fields you want to change. Omitting expires_at keeps the current expiry; sending "expires_at": null makes the key never expire. Sending scopes to a service account, or role to an edge-agent key, returns 422.

The secret itself cannot be changed. To replace it, rotate the key (below).

Revoking a key​

Revoke a key the moment it is compromised, retired, or replaced:

curl -X DELETE "https://api.haltless.io/api/v1/settings/api-keys/KEY_ID" \
-H "Authorization: Bearer YOUR_JWT_TOKEN"

Revocation takes effect immediately. Any request using the revoked key receives 401 Unauthorized. Revoking a service-account key also deactivates its account.

Rotating keys with zero downtime​

Because more than one key can be active at once, rotation needs no downtime:

  1. Create a new key with a fresh name (for example, edge-agent-plant-1-2026-q3).
  2. Deploy the new key to the agent or system that uses it.
  3. Confirm data is still flowing on the new key (last_used_at updates).
  4. Revoke the old key once you have confirmed the new one is in use.

Security best practices​

  1. Treat keys as secrets. Never commit them to version control or paste them into tickets. Use environment variables or a secrets manager.
  2. One key per system. Don't share a single key across multiple agents; per-system keys make rotation and revocation surgical.
  3. Grant the least access. Give edge-agent keys only the scopes they need, and service accounts the narrowest role that works.
  4. Use descriptive names. Encode the system and environment in the name so you can identify a key at a glance.
  5. Set an expiry, and rotate. An expires_at on keys for temporary integrations, and quarterly rotation for the rest, are sensible defaults.
  6. Revoke on exposure. If a key ever appears in a log, error message, or repository, revoke it immediately and issue a new one.

Rate limits​

Ingestion is limited to 600 requests per minute per network address, so agents and scripts behind the same plant address share that budget; because each request can carry up to 1,000 readings, this supports high sustained throughput. Requests made with a service-account key count toward your company's read and write limits, like a signed-in user's. See Rate Limiting.

note

POST /api/v1/api-keys and GET /api/v1/api-keys from earlier versions of this API still work: they create an edge-agent key with the default scopes and list your keys. Use /api/v1/settings/api-keys for new integrations, since it supports every option above.