Error Handling¶
The API returns standard HTTP status codes with JSON error bodies.
Error response format¶
Error codes¶
400 Bad Request¶
The request body is malformed or violates a constraint.
| Error message | Cause | Fix |
|---|---|---|
Invalid JSON in request body |
Request body is not valid JSON | Check your JSON syntax |
Missing 'services' in request body |
The services array is missing |
Add a services array to the request body |
Batch size exceeds limit for this token |
Too many services in one request | Reduce the number of services or request a higher max_batch_size limit |
Invalid service identifier |
Unrecognised service name | Check the Service Catalogue for valid identifiers |
Invalid region |
Unrecognised cloud region | Check the provider's region list |
401 Unauthorized¶
The token is missing, invalid, expired, or revoked.
| Error message | Cause | Fix |
|---|---|---|
Invalid or expired token |
Token not found in the access grants table, or it has expired | Check the token value. Create a new key if expired. |
Token revoked |
The key has been revoked | Create a new key in the LightPane application |
Check your Authorization header
The header must be exactly Authorization: Bearer followed by the token (with a
single space after Bearer). Common mistakes: missing Bearer prefix, extra spaces,
or a trailing newline in the token value.
403 Forbidden¶
The token is valid but the request is not permitted by its constraints or scope.
| Error message | Cause | Fix |
|---|---|---|
Origin not permitted for this token |
The request's Origin or Referer header does not match the key's allowed_origins |
Add the origin to the key's allowed origins, or use a key with the correct origin restrictions |
IP address not permitted for this token |
The source IP is not in the key's allowed_ips list |
Update the key's IP restrictions or make the request from an allowed IP |
Referer header required for this token |
The key has require_referer: true but no Referer header was sent |
This key is intended for browser use. Use a different key for curl/script access. |
Service {name} not permitted by this token |
The requested service is outside the key's allowed_services scope |
Use a key that includes this service, or add the service to the key's scope |
429 Too Many Requests¶
Rate limit exceeded for this token.
| Error message | Cause | Fix |
|---|---|---|
Rate limit exceeded |
The key's rate_limit_rpm has been exceeded |
Wait and retry. Reduce request frequency. Consider requesting a higher rate limit. |
The Retry-After header indicates how many seconds to wait before retrying.
500 Internal Server Error¶
An unexpected error occurred in the API.
| Error message | Cause | Fix |
|---|---|---|
Internal server error |
Unexpected failure in the discovery pipeline | Retry the request. If persistent, contact support. |
Discovery timeout |
The cloud provider API did not respond in time | Retry. Reduce the number of services in the batch. |
Handling errors in code¶
import requests
response = requests.post(url, headers=headers, json=payload)
if response.status_code == 200:
data = response.json()
elif response.status_code == 401:
print("Authentication failed:", response.json()["error"])
elif response.status_code == 403:
print("Access denied:", response.json()["error"])
elif response.status_code == 429:
retry_after = int(response.headers.get("Retry-After", 60))
print(f"Rate limited. Retry after {retry_after} seconds.")
else:
print(f"Error {response.status_code}:", response.json().get("error"))
const response = await fetch(url, { method: 'POST', headers, body });
if (response.ok) {
const data = await response.json();
} else {
const error = await response.json();
console.error(`Error ${response.status}: ${error.error}`);
if (response.status === 429) {
const retryAfter = response.headers.get('Retry-After') || 60;
console.log(`Retry after ${retryAfter} seconds`);
}
}