When an error occurs, the API returns a JSON response with details:
{
"error": {
"code": "invalid_api_key",
"message": "The API key provided is invalid.",
"status": 401
}
}
| Field | Description |
|---|
code | Machine-readable error code |
message | Human-readable description |
status | HTTP status code |
Error Codes
Authentication Errors (4xx)
| Code | Status | Description | Solution |
|---|
invalid_api_key | 401 | API key is invalid or malformed | Check your API key is correct |
missing_api_key | 401 | No API key provided | Add Authorization: Bearer <key> header |
expired_api_key | 401 | API key has been revoked | Generate a new key in the dashboard |
insufficient_permissions | 403 | Key doesn’t have required permissions | Use a key with appropriate permissions |
Request Errors (4xx)
| Code | Status | Description | Solution |
|---|
invalid_request | 400 | Request body is malformed | Check your JSON syntax |
missing_required_field | 400 | Required field is missing | Include all required fields |
invalid_field_value | 400 | Field value is invalid | Check field types and formats |
limit_not_found | 404 | Limit doesn’t exist | Verify the limit ID |
meter_not_found | 404 | Meter doesn’t exist | Verify the meter ID |
rate_limit_exceeded | 429 | Too many API requests | Slow down and retry with backoff |
Limit Check Responses
These are not errors, but responses from limits.check:
| Response | Meaning | Action |
|---|
allowed: true | Usage is within limits | Proceed with the operation |
allowed: false, reason: "limit_exceeded" | Customer exceeded a limit | Block or notify customer |
Server Errors (5xx)
| Code | Status | Description | Solution |
|---|
internal_error | 500 | Unexpected server error | Retry the request; contact support if persistent |
timeout | 504 | Request timed out | Retry the request |
Handling Errors in SDKs
Python
from limitry import Limitry
from limitry.errors import (
AuthenticationError,
NotFoundError,
RateLimitError,
APIError
)
client = Limitry()
try:
response = client.limits.check(customer_id="cust_123")
except AuthenticationError as e:
print(f"Check your API key: {e.message}")
except NotFoundError as e:
print(f"Resource not found: {e.message}")
except RateLimitError as e:
print(f"Rate limited. Retry after: {e.retry_after}s")
except APIError as e:
print(f"API error: {e.code} - {e.message}")
TypeScript
import Limitry from '@limitry/sdk';
import {
AuthenticationError,
NotFoundError,
RateLimitError,
APIError
} from '@limitry/sdk';
const client = new Limitry();
try {
const response = await client.limits.check({ customerId: 'cust_123' });
} catch (e) {
if (e instanceof AuthenticationError) {
console.error('Check your API key:', e.message);
} else if (e instanceof NotFoundError) {
console.error('Resource not found:', e.message);
} else if (e instanceof RateLimitError) {
console.error(`Rate limited. Retry after: ${e.retryAfter}s`);
} else if (e instanceof APIError) {
console.error(`API error: ${e.code} - ${e.message}`);
}
}
Handling Check Responses
The limits.check response isn’t an error, but you should handle both cases:
response = client.limits.check(customer_id="cust_123")
if response.allowed:
# Proceed with the API call
result = call_api()
# Record the usage
client.events.record(
customer_id="cust_123",
event_type="api_call",
values={"requests": 1}
)
else:
# Handle the denial
exceeded = [l for l in response.limits if l.exceeded]
raise LimitExceededError(f"Limit exceeded: {exceeded[0].name}")
Limitry API Rate Limits
The Limitry API itself has rate limits:
| Limit | Value |
|---|
| Requests per minute | 1,000 |
| Requests per day | 100,000 |
These are limits for calling the Limitry API, separate from the rate limits you configure for your customers.
Retry Strategy
For transient errors (5xx, timeouts), implement retry with exponential backoff:
import time
from limitry import Limitry
from limitry.errors import APIError
client = Limitry()
def check_with_retry(customer_id, max_retries=3):
for attempt in range(max_retries):
try:
return client.limits.check(customer_id=customer_id)
except APIError as e:
if e.status >= 500 and attempt < max_retries - 1:
time.sleep(2 ** attempt) # 1s, 2s, 4s
continue
raise
response = check_with_retry("cust_123")
Getting Help
If you encounter persistent errors:
- Check the Status Page for outages
- Review logs in the dashboard
- Contact support@limitry.com with:
- Error code and message
- Request ID (from response headers)
- Timestamp of the error