Errors
The API uses conventional HTTP status codes and returns structured error responses.
Error Response Format
json
{
"success": false,
"error": {
"code": "error_code",
"message": "Human-readable description"
}
}HTTP Status Codes
| Code | Meaning |
|---|---|
200 | Success |
401 | Unauthorized — invalid or missing API key |
403 | Forbidden — insufficient scope or site access denied |
404 | Not Found — resource doesn't exist or you don't have access |
405 | Method Not Allowed — wrong HTTP method for this endpoint |
422 | Validation Error — invalid input data |
429 | Rate Limited — too many requests |
500 | Internal Error — server-side error |
Error Codes
| Code | HTTP | Description |
|---|---|---|
invalid_api_key | 401 | API key is missing, invalid, expired, or revoked |
scope_denied | 403 | API key doesn't have the required scope |
site_access_denied | 403 | API key is restricted and doesn't have access to this site |
resource_not_found | 404 | The requested resource was not found |
method_not_allowed | 405 | HTTP method is not supported for this endpoint |
validation_error | 422 | Input validation failed (check the message for details) |
rate_limit_exceeded | 429 | Rate limit exceeded for this API key |
internal_error | 500 | Unexpected server error |
Handling Errors
javascript
const response = await fetch('https://api.looma.chat/v1/leads', {
headers: { 'Authorization': 'Bearer lm_your_key' }
});
const data = await response.json();
if (!data.success) {
console.error(`Error: ${data.error.code} — ${data.error.message}`);
switch (response.status) {
case 401: // Re-authenticate or check key
case 403: // Check scopes or site access
case 404: // Resource doesn't exist
case 429: // Wait and retry
const retryAfter = response.headers.get('Retry-After');
await new Promise(r => setTimeout(r, retryAfter * 1000));
break;
}
}
