Rate limits & errors
Quota per tier and error format.
Rate limits & errors
Quotas by tier
Quotas are enforced per hour (not per month). The window resets at the top of each hour UTC.
| Tier | Requests per hour | Daily approximate |
|---|---|---|
| Free | 14 | ~336/day |
| Starter | 278 | ~6,672/day |
| Growth | 1,389 | ~33,336/day |
| Enterprise | Custom SLA | Custom SLA |
Rate limit headers
Every /v1/* response includes:
| Header | Description |
|---|---|
X-RateLimit-Limit | Hourly quota for your tier |
X-RateLimit-Remaining | Requests remaining in the current hour window |
X-RateLimit-Reset | UNIX timestamp of the end of the current hour window |
Error format
All errors return structured JSON:
{
"error": "rate_limit_exceeded",
"message": "You have exceeded your hourly quota of 14 requests.",
"retry_after": 1748736000,
"upgrade_url": "https://portfoliq.io/pricing"
}
401 — Unauthorized
{
"error": "unauthorized",
"message": "API key required"
}
403 — Forbidden (scope gate)
{
"error": "forbidden",
"message": "This endpoint requires the 'fundamentals:read' scope.",
"required_scope": "fundamentals:read",
"upgrade_url": "https://portfoliq.io/pricing"
}
HTTP status codes
| Code | Meaning |
|---|---|
200 OK | Success |
401 Unauthorized | Missing or invalid API key |
403 Forbidden | Valid key, insufficient tier scope |
404 Not Found | Asset or resource does not exist |
429 Too Many Requests | Hourly rate limit exceeded |
500 Internal Server Error | API error — contact support |
503 Service Unavailable | Planned maintenance or upstream outage |
Not financial advice. Not a fatwa. Methodology disclosed.