Error Codes¶
All API errors follow the same JSON envelope:
{
"error": "ERROR_CODE",
"message": "Human-readable description.",
"request_id": "550e8400-e29b-41d4-a716-446655440000"
}
Use request_id when contacting support — it correlates to the server log entry.
Error code reference¶
| HTTP | error | Description |
|---|---|---|
| 400 | INVALID_TIMEFRAME | Timeframe is not one of 1m, 5m, 15m, 1h, 4h, 1d (or funding for features) |
| 400 | INVALID_TIMESTAMP | start or end could not be parsed as ISO8601 or Unix ms |
| 400 | INVALID_TIME_RANGE | start is after end |
| 400 | MISSING_FEATURES | features parameter was empty |
| 400 | UNKNOWN_FEATURES | One or more feature names are not in the catalogue |
| 400 | MISSING_SYMBOLS | symbols parameter was empty (multi-asset) |
| 400 | KEY_CREATION_DISABLED | Key creation requested but ADMIN_TOKEN not configured server-side |
| 400 | INVALID_TIER | Unknown tier value passed to key creation |
| 401 | UNAUTHORIZED | API key missing, invalid, or revoked |
| 403 | TIER_LIMIT_EXCEEDED | Request requires a higher tier (timeframe, history, or symbol count) |
| 404 | QUALITY_NOT_FOUND | No quality data available for the requested symbol/timeframe |
| 404 | KEY_NOT_FOUND | Key hash not found when attempting to revoke |
| 429 | RATE_LIMIT_EXCEEDED | Daily request quota exhausted |
| 500 | DATABASE_ERROR | Unexpected internal error — retry with exponential backoff |
| 503 | SERVICE_UNAVAILABLE | A backend dependency is temporarily unavailable |
Rate limit response¶
Two independent limits apply: daily (resets at midnight UTC) and per-minute (resets each calendar minute). A 429 is returned when either is exceeded:
{
"error": "RATE_LIMIT_EXCEEDED",
"message": "Rate limit exceeded for free plan. Resets in 42s.",
"retry_after_secs": 42,
"request_id": "..."
}
HTTP/1.1 429 Too Many Requests
Retry-After: 42
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1704067260
X-RateLimit-Limit-Minute: 10
X-RateLimit-Remaining-Minute: 0
All successful responses also include these headers so you can track consumption proactively.
Tier limit response¶
403 responses for tier limits include an upgrade URL:
{
"error": "TIER_LIMIT_EXCEEDED",
"message": "1m timeframe requires Pro plan. Current plan: free. Upgrade at https://hypquant.com/pricing",
"upgrade_url": "https://hypquant.com/pricing",
"request_id": "..."
}
Recommended retry strategy¶
import time
import requests
def request_with_retry(url, headers, params, max_retries=3):
for attempt in range(max_retries):
resp = requests.get(url, headers=headers, params=params)
if resp.status_code == 429:
retry_after = int(resp.headers.get("Retry-After", 60))
time.sleep(retry_after)
continue
if resp.status_code == 500:
time.sleep(2 ** attempt) # exponential backoff
continue
resp.raise_for_status()
return resp.json()
raise RuntimeError("Max retries exceeded")
Health check¶
GET /health — no authentication required.
Returns 200 when all dependencies are healthy, 503 otherwise. Use this for load balancer health checks and uptime monitoring.