Skip to main content

Authentication

Haltless supports multiple authentication methods depending on your use case.

Overview

MethodUse caseHeader
JWT Bearer TokenInteractive users, dashboardsAuthorization: Bearer <token>
API KeyEdge agents, server-to-serverX-API-Key: <key>
SSO (OIDC)Enterprise single sign-onRedirect flow

JWT Bearer tokens

Login

curl -X POST https://api.haltless.io/api/v1/auth/login \
-H "Content-Type: application/json" \
-d '{
"email": "user@example.com",
"password": "your_password"
}'
{
"access_token": "eyJhbGciOiJIUzI1NiIs...",
"token_type": "bearer",
"mfa_required": false
}

The response also sets a refresh_token as an httpOnly cookie. Use the access token in subsequent requests:

curl https://api.haltless.io/api/v1/machines \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."

Token payload

Access tokens contain:

ClaimDescription
subUser UUID
tenant_idTenant UUID
tenant_tierSubscription tier (free, pro, enterprise)
roleUser role (admin, operator, viewer)
expExpiration timestamp
jtiUnique token ID (for revocation)

Refreshing tokens

When your access token expires, exchange the refresh cookie for a new pair:

curl -X POST https://api.haltless.io/api/v1/auth/refresh \
--cookie "refresh_token=..."

The old refresh token is immediately invalidated (token rotation).

Logout

curl -X POST https://api.haltless.io/api/v1/auth/logout \
-H "Authorization: Bearer YOUR_TOKEN"

This blocklists both the access and refresh token JTIs.

API keys

API keys are designed for machine-to-machine communication , primarily edge agents and read-only integrations. Every key is scoped to a limited set of permissions, following the principle of least privilege.

Scopes

Each API key carries a list of scopes that determine which endpoints it can access:

ScopeAccess granted
ingestPOST /ingest , push sensor data
agentGET /agent/heartbeat , edge agent health
read:machinesGET /machines , list/read machines
read:sensorsGET /sensor-data/* , query readings

API keys cannot access user management, billing, alert configuration, ERP settings, or any other administrative endpoint. Those actions require a JWT token from an interactive login.

Creating a key

curl -X POST https://api.haltless.io/api/v1/settings/api-keys \
-H "Authorization: Bearer ADMIN_JWT" \
-H "Content-Type: application/json" \
-d '{
"name": "edge-agent-building-a",
"scopes": ["ingest", "agent"]
}'
{
"id": "...",
"name": "edge-agent-building-a",
"key": "hlts_abc12345_FULL_KEY_VALUE",
"scopes": ["ingest", "agent"],
"tenant_id": "...",
"created_at": "2026-04-04T10:00:00Z"
}

If scopes is omitted, the key defaults to ["ingest", "agent"] (edge agent preset).

caution

The key field is only returned once at creation. Store it securely.

Using a key

Pass the key in the X-API-Key header:

curl -X POST https://api.haltless.io/api/v1/ingest \
-H "X-API-Key: hlts_abc12345_FULL_KEY_VALUE" \
-H "Content-Type: application/json" \
-d '{"readings": [...]}'

Using a key on an endpoint outside its scopes returns 403 Forbidden.

Key validation

Keys are validated by computing a SHA-256 hash of the provided key and comparing it against the stored hash. Expired or revoked keys return 401 Unauthorized.

Subscription enforcement

API key requests also check your subscription status:

StatusBehavior
active / trialingAllowed
past_due / unpaidAllowed during grace period, then 402
canceled402 Payment Required immediately

Revoking a key

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

See the Managing API Keys guide for rotation strategies and best practices.

Multi-Factor Authentication (MFA)

Haltless supports TOTP-based MFA (compatible with Google Authenticator, Authy, etc.).

Setup flow

  1. Enable MFA:
curl -X POST https://api.haltless.io/api/v1/auth/mfa/setup \
-H "Authorization: Bearer YOUR_TOKEN"

Returns an otpauth_uri for scanning as a QR code and the raw secret.

  1. Confirm with a code:
curl -X POST https://api.haltless.io/api/v1/auth/mfa/verify-setup \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"code": "123456"}'

Login with MFA

When MFA is enabled, /auth/login returns "mfa_required": true with a short-lived pending token. Complete the login:

curl -X POST https://api.haltless.io/api/v1/auth/mfa/verify \
-H "Content-Type: application/json" \
-d '{
"mfa_token": "PENDING_TOKEN_FROM_LOGIN",
"code": "123456"
}'

This returns the full access token and sets the refresh cookie.

SSO (Enterprise)

Enterprise tenants can configure OIDC single sign-on with their identity provider.

Configuration

Admins configure SSO via:

curl -X POST https://api.haltless.io/api/v1/auth/sso/config \
-H "Authorization: Bearer ADMIN_JWT" \
-H "Content-Type: application/json" \
-d '{
"provider_name": "Okta",
"client_id": "0oabc123...",
"client_secret": "secret_value",
"discovery_url": "https://your-org.okta.com/.well-known/openid-configuration",
"domain": "yourcompany.com"
}'

Login flow

  1. Client calls GET /auth/sso/check?email=user@yourcompany.com
  2. If SSO is configured for the domain, the response includes the IdP redirect URL
  3. User authenticates with the IdP
  4. IdP redirects to /auth/sso/callback with an authorization code
  5. Haltless validates the code, provisions the user if needed, and redirects to the frontend with a short-lived sso_code
  6. Frontend exchanges the code via POST /auth/sso/exchange for JWT tokens

Brute-force protection

Login, MFA, and registration endpoints are protected by a sliding-window throttle:

ParameterValue
Window10 minutes
Max failures10
Lockout duration15 minutes

After the threshold is reached, further attempts return 429 Too Many Requests. The counter resets on successful authentication.

Roles and permissions

PermissionAdminOperatorViewer
Read machines & alertsYesYesYes
Create/edit machinesYesYesNo
Delete machinesYesNoNo
Manage alert rulesYesNoNo
Manage maintenance & work ordersYesYesNo
Manage usersYesNoNo
Manage API keysYesNoNo
Read audit logsYesYesYes
Manage settingsYesNoNo