Error Handling
Understand error responses and how to handle them gracefully.
Error Response Format
All error responses follow a consistent JSON structure. The HTTP status code indicates the error category, and the response body provides details.
{
"error": {
"code": "invalid_parameter",
"message": "The 'start_date' parameter must be in ISO 8601 format (YYYY-MM-DD).",
"param": "start_date",
"request_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}
}
Always include the
request_id when contacting support about an error.
It helps us trace exactly what happened.
Error Codes
| HTTP Status | Error Code | Description |
|---|---|---|
| 400 | invalid_parameter | A parameter value is missing, invalid, or out of range |
| 401 | invalid_api_key | Missing, invalid, or revoked API key |
| 403 | historical_limit | Free tier key requesting data older than 12 months |
| 404 | not_found | The requested resource does not exist |
| 429 | rate_limit_exceeded | You have exceeded your daily or per-minute rate limit |
| 500 | internal_error | An unexpected error occurred on our end |
| 503 | service_unavailable | The API is temporarily unavailable for maintenance |
Handling Errors in Code
Here's how to properly handle errors in your application:
import requests
response = requests.get(
"https://commodityfundamentals.com/api/v1/commodities/INVALID",
headers={"Authorization": "Bearer YOUR_API_KEY"}
)
if response.status_code == 200:
data = response.json()
elif response.status_code == 429:
reset = int(response.headers.get("X-RateLimit-Reset", 0))
print(f"Rate limited. Resets at {reset} (unix timestamp).")
elif response.status_code == 401:
print("Check your API key.")
else:
error = response.json().get("error", {})
print(f"Error {error.get('code')}: {error.get('message')}")
require "net/http"
require "json"
uri = URI("https://commodityfundamentals.com/api/v1/commodities/INVALID")
req = Net::HTTP::Get.new(uri)
req["Authorization"] = "Bearer YOUR_API_KEY"
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http|
http.request(req)
}
case res
when Net::HTTPSuccess
data = JSON.parse(res.body)
when Net::HTTPTooManyRequests
reset = res["X-RateLimit-Reset"]
puts "Rate limited. Resets at #{reset} (unix timestamp)."
when Net::HTTPUnauthorized
puts "Check your API key."
else
error = JSON.parse(res.body)["error"]
puts "Error #{error["code"]}: #{error["message"]}"
end
# Check HTTP status code with -w flag
curl -s -w "\n%{http_code}" \
-H "Authorization: Bearer YOUR_API_KEY" \
"https://commodityfundamentals.com/api/v1/commodities/INVALID"
# Output:
# {"error":{"code":"not_found","message":"Commodity 'INVALID' not found.","request_id":"a1b2c3d4-e5f6-7890-abcd-ef1234567890"}}
# 404
Retry Strategy
For transient errors (429, 500, 503), we recommend implementing exponential backoff:
- For 429 errors, wait until the
X-RateLimit-Resettimestamp - For 500/503 errors, wait 1s, then 2s, then 4s, up to 3 retries
- Do not retry 400, 401, 403, or 404 errors -- these require a code fix