This document provides comprehensive information about error handling in the Fig API, including HTTP status codes, error response formats, and common error scenarios for both REST and WebSocket endpoints.
- HTTP Error Responses
- WebSocket Error Responses
- Authentication Errors
- Rate Limiting Errors
- Validation Errors
- Business Logic Errors
- Common Error Scenarios
- Error Handling Best Practices
All HTTP error responses follow a consistent JSON structure:
{
"code": 400,
"message": "Bad Request",
"reason": [
"Invalid input parameter",
"Missing required field"
]
}| Status Code | Description | Usage |
|---|---|---|
| 200 | OK | Successful request |
| 400 | Bad Request | Invalid request parameters, validation errors |
| 401 | Unauthorized | Missing or invalid authentication token |
| 403 | Forbidden | Insufficient permissions, access denied |
| 404 | Not Found | Resource not found |
| 429 | Too Many Requests | Rate limit exceeded |
| 500 | Internal Server Error | Server-side error |
{
"code": 400,
"message": "Invalid Request",
"reason": [
"Invalid expiry date format: 2024-13-45",
"Direction must be \"bid\" or \"ask\""
]
}{
"code": 401,
"message": "Missing bearer token"
}{
"code": 403,
"message": "Access denied"
}{
"code": 404,
"message": "Not Found"
}{
"code": 429,
"message": "Rate limit exceeded"
}Rate Limit Headers:
X-RateLimit-Limit: Maximum requests allowedX-RateLimit-Remaining: Remaining requests in current windowX-RateLimit-Reset: Unix timestamp when the rate limit resets
{
"code": 500,
"message": "Internal Server Error",
"reason": [
"Failed to process request"
]
}WebSocket endpoints use JSON-RPC 2.0 protocol and return errors in the following format:
{
"jsonrpc": "2.0",
"id": 123,
"error": {
"code": -32601,
"message": "Method not found",
"data": {
"additional": "error details"
}
}
}| Code | Description | Usage |
|---|---|---|
| -32700 | Parse error | Invalid JSON format |
| -32600 | Invalid Request | Invalid JSON-RPC request structure |
| -32601 | Method not found | Unknown method name |
| -32602 | Invalid params | Invalid method parameters |
| -32603 | Internal error | Server-side error |
| -32000 to -32099 | Server error | Reserved for implementation-defined server errors |
{
"jsonrpc": "2.0",
"id": 123,
"error": {
"code": -32700,
"message": "Parse error"
}
}{
"jsonrpc": "2.0",
"id": 123,
"error": {
"code": -32601,
"message": "Method not found"
}
}{
"jsonrpc": "2.0",
"id": 123,
"error": {
"code": -32603,
"message": "Rate limit exceeded",
"data": {
"limit": 100,
"window": "1m0s",
"reset": 1640995200
}
}
}| Error Message | Description | HTTP Status |
|---|---|---|
missing bearer token | No Authorization header provided | 401 |
invalid authorization header | Malformed Authorization header | 401 |
authorisation token expired or not valid | Token is expired or invalid | 401 |
invalid token claims | Token contains invalid claims | 401 |
invalid client ID | Client ID in token is not recognized | 401 |
insufficient permissions | User lacks required permissions | 403 |
account is inactive | User account has been deactivated | 401 |
authentication is not enabled | Authentication is disabled for this endpoint | 401 |
login is disabled | Login functionality is temporarily disabled | 401 |
{
"code": 401,
"message": "missing bearer token"
}{
"code": 401,
"message": "authorisation token expired or not valid"
}{
"code": 403,
"message": "insufficient permissions"
}The Fig API implements distributed rate limiting using Redis:
- Default HTTP Limit: 100 requests per minute
- Default WebSocket Limit: 100 messages per minute
- Key Strategy: User ID for authenticated requests, IP address for unauthenticated requests
{
"code": 429,
"message": "rate limit exceeded"
}{
"jsonrpc": "2.0",
"id": 123,
"error": {
"code": -32603,
"message": "Rate limit exceeded",
"data": {
"limit": 100,
"window": "1m0s",
"reset": 1640995200
}
}
}When rate limit is exceeded, the following headers are included in the response:
X-RateLimit-Limit: Maximum requests allowed (e.g., "100")X-RateLimit-Remaining: Remaining requests in current window (e.g., "0")X-RateLimit-Reset: Unix timestamp when rate limit resets (e.g., "1640995200")
| Error Message | Description |
|---|---|
invalid option format | Invalid option instrument format |
invalid expiry date format | Date format does not match expected pattern |
invalid future spread dates format | Invalid date range for futures spread |
invalid instrument format | Instrument specification is malformed |
invalid future spread format | Futures spread configuration is invalid |
invalid base64 encoding | Base64 encoded data is malformed |
empty value | Required field is empty or null |
invalid request | General request validation failure |
{
"code": 400,
"message": "Invalid Request",
"reason": [
"invalid expiry date format: 2024-13-45"
]
}{
"code": 400,
"message": "Invalid Request",
"reason": [
"Direction must be \"bid\" or \"ask\"",
"Invalid price format",
"Amount must be greater than 0"
]
}| Error Message | Description | HTTP Status |
|---|---|---|
rfq not found | RFQ with specified ID does not exist | 404 |
can only save a draft RFQ | Attempted to save non-draft RFQ | 400 |
can only delete a draft or cancelled RFQ | Attempted to delete active RFQ | 400 |
can only publish a draft RFQ | Attempted to publish non-draft RFQ | 400 |
can only cancel an in progress RFQ | Attempted to cancel non-active RFQ | 400 |
RFQ has expired | RFQ has passed its expiration time | 400 |
can't quote on own RFQ | User attempted to quote on their own RFQ | 400 |
a quote with the same clientQuoteId already exists | Duplicate quote ID provided | 400 |
invalid price | Quote price is invalid | 400 |
price is too low | Quote price below minimum threshold | 400 |
price is too high | Quote price above maximum threshold | 400 |
multiple quotes found for the same RFQ | Ambiguous quote selection | 400 |
| Error Message | Description | HTTP Status |
|---|---|---|
exchange not found | Exchange with specified ID does not exist | 404 |
exchange not implemented | Exchange functionality not available | 400 |
maker not found | Exchange maker not found | 404 |
unable to parse instrument | Instrument specification cannot be parsed | 400 |
instrument not found for leg | Instrument not available for RFQ leg | 400 |
instrument not found for hedge | Instrument not available for hedge | 400 |
failed to fetch instrument for leg | Error retrieving instrument data | 500 |
failed to fetch instrument for hedge | Error retrieving hedge instrument data | 500 |
failed to convert ratio to int | Invalid ratio format | 400 |
| Error Message | Description | HTTP Status |
|---|---|---|
individual with same email already exists | Email address already registered | 400 |
individual with same telegram already exists | Telegram handle already registered | 400 |
exchange credentials with the same alias already exists | Alias already in use | 400 |
credentials not found | Exchange credentials not found | 404 |
encryption key not found | Encryption key not available | 500 |
encrypted value too short | Encrypted data is corrupted | 400 |
invalid padding | Encryption padding error | 400 |
failed to unmarshal exchange credentials | Credential data corruption | 500 |
| Error Message | Description | HTTP Status |
|---|---|---|
desk not found | Desk with specified ID does not exist | 404 |
record not found | Generic record not found error | 404 |
Scenario: Making a request without proper authentication.
Request:
GET /v1/rfq/123Response:
{
"code": 401,
"message": "missing bearer token"
}Solution: Include a valid Bearer token in the Authorization header.
Scenario: Making too many requests in a short time period.
Response:
{
"code": 429,
"message": "rate limit exceeded"
}Headers:
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1640995200Solution: Wait until the rate limit window resets or implement exponential backoff.
Scenario: Requesting a resource that doesn't exist.
Request:
GET /v1/rfq/999999Response:
{
"code": 404,
"message": "Not Found"
}Solution: Verify the resource ID exists and is accessible to your account.
Scenario: Submitting invalid data in a request.
Request:
{
"direction": "invalid",
"price": -100
}Response:
{
"code": 400,
"message": "Invalid Request",
"reason": [
"Direction must be \"bid\" or \"ask\"",
"Price must be greater than 0"
]
}Solution: Review the validation errors and correct the request data.
Scenario: Invalid JSON-RPC message format.
Request:
{
"method": "v1/subscribe",
"params": "invalid"
}Response:
{
"jsonrpc": "2.0",
"id": 123,
"error": {
"code": -32700,
"message": "Parse error"
}
}Solution: Ensure the message follows JSON-RPC 2.0 format.
Always check the HTTP status code before processing the response body. A 2xx status code indicates success, while 4xx and 5xx indicate errors.
When receiving a 429 status code:
- Implement exponential backoff
- Respect the
X-RateLimit-Resetheader - Consider implementing request queuing
Before making requests:
- Validate all required fields are present
- Ensure data types match expected formats
- Check for reasonable value ranges
For transient errors (5xx status codes):
- Implement retry logic with exponential backoff
- Set maximum retry attempts
- Log retry attempts for debugging
For WebSocket connections:
- Always check the
errorfield in JSON-RPC responses - Implement reconnection logic for connection failures
- Handle rate limiting errors appropriately
When errors occur:
- Log the full error response for debugging
- Include request context (endpoint, parameters, user ID)
- Monitor error patterns for system issues
For end-user applications:
- Translate technical error messages to user-friendly language
- Provide actionable guidance when possible
- Hide sensitive information in error messages
{
"type": "object",
"properties": {
"code": {
"type": "integer",
"description": "HTTP status code"
},
"message": {
"type": "string",
"description": "Human-readable error message"
},
"reason": {
"type": "array",
"items": {
"type": "string"
},
"description": "Detailed error reasons"
}
},
"required": ["code", "message"]
}{
"type": "object",
"properties": {
"jsonrpc": {
"type": "string",
"const": "2.0"
},
"id": {
"type": "integer",
"description": "Request ID"
},
"error": {
"type": "object",
"properties": {
"code": {
"type": "integer",
"description": "JSON-RPC error code"
},
"message": {
"type": "string",
"description": "Error message"
},
"data": {
"type": "object",
"description": "Additional error data"
}
},
"required": ["code", "message"]
}
},
"required": ["jsonrpc", "error"]
}If you encounter errors not documented here or need assistance with error handling:
- Check the API Documentation: Ensure you're using the correct endpoint and parameters
- Review Request Format: Verify your request follows the expected format
- Check Authentication: Ensure your authentication token is valid and not expired
- Monitor Rate Limits: Check if you're approaching or exceeding rate limits
- Contact Support: If the issue persists, contact the Fig API support team with:
- Full error response
- Request details (endpoint, parameters, timestamp)
- Your application context
- v1.0: Initial error documentation
- Includes HTTP and WebSocket error handling
- Covers authentication, validation, and business logic errors
- Provides best practices and troubleshooting guidance