Error Handling
The Haltless API uses standard HTTP status codes and returns structured JSON error responses.
Error response format
{
"detail": "Human-readable error message."
}
For validation errors:
{
"detail": [
{
"loc": ["body", "email"],
"msg": "value is not a valid email address",
"type": "value_error"
}
]
}
HTTP status codes
Success codes
| Code | Meaning | When |
|---|---|---|
200 OK | Success | Standard response for successful requests |
201 Created | Resource created | POST requests that create a new resource |
204 No Content | Success with no body | DELETE operations, logout |
207 Multi-Status | Partial success | Batch operations (e.g., ingestion) |
Client error codes
| Code | Meaning | Common causes |
|---|---|---|
400 Bad Request | Invalid request | Missing fields, invalid JSON, constraint violations |
401 Unauthorized | Authentication failed | Missing/expired token, revoked API key |
402 Payment Required | Subscription issue | Canceled subscription, past grace period |
403 Forbidden | Insufficient permissions | Role doesn't have access to this operation |
404 Not Found | Resource not found | Invalid ID, resource belongs to another tenant |
409 Conflict | Duplicate resource | Email already exists, duplicate identifier |
422 Unprocessable Entity | Validation error | Request body fails schema validation |
429 Too Many Requests | Rate limited | Exceeded tier rate limit |
Server error codes
| Code | Meaning | Action |
|---|---|---|
500 Internal Server Error | Unexpected error | Contact support if persistent |
503 Service Unavailable | Service down | Retry after a short delay |
Common error messages
Authentication
| Message | Cause | Solution |
|---|---|---|
Invalid email or password. | Wrong credentials | Check email/password |
Authentication token has expired. | Expired JWT | Refresh your token |
Invalid authentication token. | Malformed or revoked JWT | Re-authenticate |
User account is inactive. | Account deactivated | Contact your admin |
Resources
| Message | Cause | Solution |
|---|---|---|
Machine not found. | Invalid machine ID | Verify the UUID |
A machine with this identifier already exists for this tenant. | Duplicate identifier | Use a unique machine_identifier |
Tenant not found. | Invalid tenant context | Check your authentication |
Rate limiting
| Message | Cause | Solution |
|---|---|---|
Rate limit exceeded. | Too many requests | Wait for Retry-After seconds |
Password verification failed. Sign-off requires re-authentication. | Wrong password on compliance sign-off | Enter the correct password |
Handling errors in code
Python
import requests
response = requests.get(
"https://api.haltless.io/api/v1/machines",
headers={"Authorization": f"Bearer {token}"}
)
if response.status_code == 200:
machines = response.json()
elif response.status_code == 401:
# Token expired , refresh and retry
new_token = refresh_token()
response = requests.get(url, headers={"Authorization": f"Bearer {new_token}"})
elif response.status_code == 429:
retry_after = int(response.headers["Retry-After"])
time.sleep(retry_after)
# Retry the request
else:
error = response.json()
print(f"Error {response.status_code}: {error['detail']}")
TypeScript
async function apiRequest(url: string, token: string) {
const response = await fetch(url, {
headers: { Authorization: `Bearer ${token}` },
});
if (response.ok) {
return response.json();
}
if (response.status === 401) {
// Refresh token and retry
const newToken = await refreshToken();
return apiRequest(url, newToken);
}
if (response.status === 429) {
const retryAfter = parseInt(response.headers.get("Retry-After") || "5");
await new Promise((r) => setTimeout(r, retryAfter * 1000));
return apiRequest(url, token);
}
const error = await response.json();
throw new Error(`API error ${response.status}: ${error.detail}`);
}