Error Codes
This page documents all error codes returned by the FinBrain API and how to handle them in your application.
Error Response Format
Section titled “Error Response Format”All errors are returned as JSON with the following envelope structure:
{ "success": false, "error": { "code": "ERROR_CODE", "message": "Human-readable error message", "details": { } }}The details object may contain additional context depending on the error type. For example, a validation error may include the specific fields that failed validation.
HTTP Status Codes
Section titled “HTTP Status Codes”400 Bad Request
Section titled “400 Bad Request”The request is malformed or contains invalid parameters.
{ "success": false, "error": { "code": "BAD_REQUEST", "message": "Invalid ticker symbol: XYZ123", "details": { } }}The VALIDATION_ERROR code is also returned with a 400 status when specific input fields fail validation:
{ "success": false, "error": { "code": "VALIDATION_ERROR", "message": "Invalid value for parameter 'type'. Expected 'daily' or 'monthly'.", "details": { "field": "type", "expected": ["daily", "monthly"] } }}Python SDK Exception: BadRequest
Common causes:
- Invalid ticker symbol
- Invalid market identifier
- Invalid prediction type (not
dailyormonthly) - Malformed date parameters
How to fix:
- Verify the ticker symbol exists using
/available/tickers - Check the market name using
/available/markets - Ensure dates are in YYYY-MM-DD format
401 Unauthorized
Section titled “401 Unauthorized”API key missing or invalid.
{ "success": false, "error": { "code": "UNAUTHORIZED", "message": "Invalid or missing API key", "details": { } }}Python SDK Exception: AuthenticationError
Common causes:
- Missing
tokenquery parameter - Invalid API key
- Expired API key
- Typo in API key
How to fix:
- Ensure the
tokenparameter is included in every request - Verify your API key is correct
- Check your account dashboard for key status
403 Forbidden
Section titled “403 Forbidden”Authenticated, but not authorised to perform this action.
{ "success": false, "error": { "code": "FORBIDDEN", "message": "Access denied for this resource", "details": { } }}Python SDK Exception: PermissionDenied
Common causes:
- Endpoint not included in your subscription tier
- Account suspended
- Accessing a premium endpoint with a free tier key
How to fix:
- Check your subscription tier and available endpoints
- Upgrade your subscription if needed
- Contact support if you believe this is an error
404 Not Found
Section titled “404 Not Found”Requested data or endpoint not found.
{ "success": false, "error": { "code": "NOT_FOUND", "message": "Ticker INVALID not found in market S&P 500", "details": { } }}Python SDK Exception: NotFound
Common causes:
- Ticker doesn’t exist in the specified market
- Endpoint path is incorrect
- Data not available for the specified date range
How to fix:
- Verify the ticker exists using
/available/tickers - Check the endpoint path in the API reference
- Try a different date range
405 Method Not Allowed
Section titled “405 Method Not Allowed”Endpoint exists, but the HTTP method is not supported.
{ "success": false, "error": { "code": "METHOD_NOT_ALLOWED", "message": "POST method not supported for this endpoint", "details": { } }}Python SDK Exception: MethodNotAllowed
Common causes:
- Using POST instead of GET
- Using PUT, DELETE, or PATCH on read-only endpoints
How to fix:
- All FinBrain API endpoints use GET requests
- Change your HTTP method to GET
429 Too Many Requests
Section titled “429 Too Many Requests”You have exceeded the rate limit for your subscription tier.
{ "success": false, "error": { "code": "RATE_LIMIT_EXCEEDED", "message": "Rate limit exceeded. Please retry after 30 seconds.", "details": { "retryAfter": 30 } }}Python SDK Exception: RateLimitExceeded
Common causes:
- Sending too many requests in a short time window
- Exceeding your plan’s requests-per-minute quota
- Running parallel requests without throttling
How to fix:
- Check the
X-RateLimit-Remainingheader before sending requests - Implement exponential backoff when you receive a 429
- Wait until the time indicated by the
X-RateLimit-Resetheader - Upgrade your subscription for higher rate limits
500 Internal Server Error
Section titled “500 Internal Server Error”Internal error on FinBrain’s side. Retrying later may help.
{ "success": false, "error": { "code": "INTERNAL_ERROR", "message": "An unexpected error occurred", "details": { } }}Python SDK Exception: ServerError
Common causes:
- Server-side issues
- Database connectivity problems
- Temporary service disruption
How to fix:
- Retry the request after a short delay
- Check FinBrain status page for outages
- Contact support if the issue persists
Rate Limiting
Section titled “Rate Limiting”The FinBrain v2 API includes rate limiting headers on every response, regardless of status code. Use these headers to monitor your usage and avoid hitting limits.
| Header | Description |
|---|---|
X-RateLimit-Limit | Maximum number of requests allowed in the current time window |
X-RateLimit-Remaining | Number of requests remaining in the current time window |
X-RateLimit-Reset | Unix timestamp (seconds) when the current rate limit window resets |
Example response headers:
HTTP/1.1 200 OKX-RateLimit-Limit: 100X-RateLimit-Remaining: 87X-RateLimit-Reset: 1706400000When X-RateLimit-Remaining reaches 0, subsequent requests will return a 429 status with the RATE_LIMIT_EXCEEDED error code until the window resets.
Error Handling Examples
Section titled “Error Handling Examples”from finbrain import FinBrainClientfrom finbrain.exceptions import ( AuthenticationError, NotFound, RateLimitExceeded, ServerError, FinBrainError)import time
fb = FinBrainClient(api_key="YOUR_API_KEY")
def get_predictions_with_retry(ticker, max_retries=3): """Get predictions with automatic retry on failure""" for attempt in range(max_retries): try: return fb.predictions.ticker(ticker, prediction_type="daily") except AuthenticationError: # Auth error - don't retry raise Exception("Invalid API key") except NotFound: # Not found - don't retry raise Exception(f"Ticker {ticker} not found") except RateLimitExceeded as e: # Rate limited - wait and retry wait_time = e.retry_after or (2 ** attempt) print(f"Rate limited. Retrying in {wait_time}s...") time.sleep(wait_time) except ServerError: # Server error - retry with backoff if attempt == max_retries - 1: raise wait_time = 2 ** attempt print(f"Server error. Retrying in {wait_time}s...") time.sleep(wait_time) except FinBrainError: # Other API error - retry if attempt == max_retries - 1: raise time.sleep(1)
raise Exception("Max retries exceeded")
# Usagetry: data = get_predictions_with_retry("AAPL") print(data)except Exception as e: print(f"Error: {e}")const API_KEY = "YOUR_API_KEY";
async function getPredictionsWithRetry(ticker, maxRetries = 3) { for (let attempt = 0; attempt < maxRetries; attempt++) { try { const response = await fetch( `https://api.finbrain.tech/v2/ticker/${ticker}/predictions/daily?token=${API_KEY}` );
if (response.ok) { return await response.json(); }
if (response.status === 401) { throw new Error("Invalid API key"); }
if (response.status === 404) { throw new Error(`Ticker ${ticker} not found`); }
if (response.status === 429) { // Rate limited - use reset header or backoff const resetTime = response.headers.get("X-RateLimit-Reset"); const waitTime = resetTime ? Math.max(0, resetTime * 1000 - Date.now()) : Math.pow(2, attempt) * 1000; console.log(`Rate limited. Retrying in ${Math.ceil(waitTime / 1000)}s...`); await new Promise(resolve => setTimeout(resolve, waitTime)); continue; }
if (response.status === 500) { // Server error - retry with backoff if (attempt === maxRetries - 1) { throw new Error("Server error"); } const waitTime = Math.pow(2, attempt) * 1000; console.log(`Server error. Retrying in ${waitTime}ms...`); await new Promise(resolve => setTimeout(resolve, waitTime)); continue; }
// Other error - don't retry throw new Error(`HTTP ${response.status}`);
} catch (error) { if (attempt === maxRetries - 1) { throw error; } } } throw new Error("Max retries exceeded");}
// Usagetry { const data = await getPredictionsWithRetry("AAPL"); console.log(data);} catch (error) { console.error("Error:", error.message);}Python SDK Exception Classes
Section titled “Python SDK Exception Classes”The Python SDK provides typed exceptions for each error code:
| Exception | HTTP Status | Error Code | Description |
|---|---|---|---|
BadRequest | 400 | BAD_REQUEST, VALIDATION_ERROR | The request is malformed or contains invalid parameters |
AuthenticationError | 401 | UNAUTHORIZED | API key missing or invalid |
PermissionDenied | 403 | FORBIDDEN | Authenticated, but not authorised to perform this action |
NotFound | 404 | NOT_FOUND | Requested data or endpoint not found |
MethodNotAllowed | 405 | METHOD_NOT_ALLOWED | Endpoint exists, but the HTTP method is not supported |
RateLimitExceeded | 429 | RATE_LIMIT_EXCEEDED | Too many requests; slow down or wait for the rate limit window to reset |
ServerError | 500 | INTERNAL_ERROR | Internal error on FinBrain’s side |
InvalidResponse | N/A | N/A | Response couldn’t be parsed as JSON |
FinBrainError | N/A | N/A | Base class for all SDK exceptions |
Best Practices
Section titled “Best Practices”- Always check status codes - Don’t assume success; inspect the
successfield in every response - Implement retry logic - Use exponential backoff for 429 and 500 errors
- Respect rate limits - Monitor
X-RateLimit-Remainingand pause before hitting zero - Cache responses - Reduce API calls by caching data locally
- Validate inputs - Check ticker symbols before making requests
- Handle errors gracefully - Provide meaningful error messages to users
- Parse the error envelope - Use the
error.codefield for programmatic error handling anderror.messagefor user-facing output