Error Handling
The emissions.dev API uses conventional HTTP response codes to indicate the success or failure of an API request.
HTTP Status Codes
| Code | Meaning |
|---|---|
200 |
Success |
400 |
Bad Request - Missing required parameters |
401 |
Unauthorized - Invalid or missing API key |
403 |
Forbidden - API key doesn't have access |
404 |
Not Found - Endpoint doesn't exist |
422 |
Validation Error - Parameters failed validation |
429 |
Rate Limited - Too many requests |
500 |
Server Error - Something went wrong on our end |
Error Response Format
All errors return a consistent JSON structure:
{
"error": {
"code": "validation_error",
"message": "Country code 'XX' not recognised.",
"field": "origin_country",
"status": 422
}
}
| Field | Description |
|---|---|
code |
Machine-readable error code |
message |
Human-readable description |
field |
The parameter that caused the error (if applicable) |
status |
HTTP status code |
Common Error Codes
unauthorized
{
"error": {
"code": "unauthorized",
"message": "Invalid API key. Get your key at https://emissions.dev/dashboard",
"status": 401
}
}
Cause: Missing or invalid API key.
validation_error
{
"error": {
"code": "validation_error",
"message": "The weight field is required.",
"field": "weight",
"status": 422
}
}
Cause: Required parameter missing or invalid value.
rate_limited
{
"error": {
"message": "Rate limit exceeded. Try again in 1 seconds.",
"status": 429
}
}
Cause: Too many requests per second, or monthly quota exceeded. See Rate Limits for details on limits by plan and usage warning headers.
Handling Errors in Code
JavaScript
try {
const result = await fetch('/api/v1/freight/emissions?...');
const data = await result.json();
if (!result.ok) {
throw new Error(data.error.message);
}
console.log('Emissions:', data.data.attributes.emissions.co2e);
} catch (error) {
console.error('API Error:', error.message);
}
Python
import requests
try:
response = requests.get('https://api.emissions.dev/v1/freight/emissions', params={...})
response.raise_for_status()
data = response.json()
except requests.exceptions.HTTPError as e:
error = e.response.json()
print(f"Error: {error['error']['message']}")
PHP
try {
$response = Http::withToken($apiKey)
->get('https://api.emissions.dev/v1/freight/emissions', [...]);
if ($response->failed()) {
$error = $response->json('error');
throw new Exception($error['message']);
}
$data = $response->json();
} catch (Exception $e) {
Log::error('API Error: ' . $e->getMessage());
}
Retry Strategy
For transient errors (5xx, rate limits), implement exponential backoff:
async function fetchWithRetry(url, options, maxRetries = 3) {
for (let attempt = 0; attempt < maxRetries; attempt++) {
try {
const response = await fetch(url, options);
if (response.ok) return response;
if (response.status === 429 || response.status >= 500) {
const delay = Math.pow(2, attempt) * 1000; // 1s, 2s, 4s
await new Promise(r => setTimeout(r, delay));
continue;
}
throw new Error(`HTTP ${response.status}`);
} catch (error) {
if (attempt === maxRetries - 1) throw error;
}
}
}