Authentication
Haltless supports multiple authentication methods depending on your use case.
Overview
| Method | Use case | Header |
|---|---|---|
| JWT Bearer Token | Interactive users, dashboards | Authorization: Bearer <token> |
| API Key | Edge agents, server-to-server | X-API-Key: <key> |
| SSO (OIDC) | Enterprise single sign-on | Redirect 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:
| Claim | Description |
|---|---|
sub | User UUID |
tenant_id | Tenant UUID |
tenant_tier | Subscription tier (free, pro, enterprise) |
role | User role (admin, operator, viewer) |
exp | Expiration timestamp |
jti | Unique 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:
| Scope | Access granted |
|---|---|
ingest | POST /ingest , push sensor data |
agent | GET /agent/heartbeat , edge agent health |
read:machines | GET /machines , list/read machines |
read:sensors | GET /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).
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:
| Status | Behavior |
|---|---|
active / trialing | Allowed |
past_due / unpaid | Allowed during grace period, then 402 |
canceled | 402 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
- 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.
- 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
- Client calls
GET /auth/sso/check?email=user@yourcompany.com - If SSO is configured for the domain, the response includes the IdP redirect URL
- User authenticates with the IdP
- IdP redirects to
/auth/sso/callbackwith an authorization code - Haltless validates the code, provisions the user if needed, and redirects to the frontend with a short-lived
sso_code - Frontend exchanges the code via
POST /auth/sso/exchangefor JWT tokens
Brute-force protection
Login, MFA, and registration endpoints are protected by a sliding-window throttle:
| Parameter | Value |
|---|---|
| Window | 10 minutes |
| Max failures | 10 |
| Lockout duration | 15 minutes |
After the threshold is reached, further attempts return 429 Too Many Requests. The counter resets on successful authentication.
Roles and permissions
| Permission | Admin | Operator | Viewer |
|---|---|---|---|
| Read machines & alerts | Yes | Yes | Yes |
| Create/edit machines | Yes | Yes | No |
| Delete machines | Yes | No | No |
| Manage alert rules | Yes | No | No |
| Manage maintenance & work orders | Yes | Yes | No |
| Manage users | Yes | No | No |
| Manage API keys | Yes | No | No |
| Read audit logs | Yes | Yes | Yes |
| Manage settings | Yes | No | No |