Errors & Status Codes
Every error response returns a JSON object with an error field describing what went wrong.
{
"error": "Description of the problem"
}HTTP status codes
| Code | Meaning | When |
|---|---|---|
400 | Bad Request | Missing or invalid parameters |
401 | Unauthorized | Missing, invalid, inactive, or expired API key |
402 | Payment Required | Insufficient credit balance |
403 | Forbidden | Tier limit reached (e.g., tracked-account quota) |
404 | Not Found | Account not tracked, resource doesn't exist |
409 | Conflict | Resource already exists (e.g., already tracking account) |
429 | Too Many Requests | Rate limit or daily spend cap exceeded |
500 | Internal Error | Server-side issue — retry with backoff |
503 | Service Unavailable | Upstream (X/Twitter) temporarily unreachable — retry |
Error responses by type
401 — Authentication
{ "error": "Missing X-API-Key header" }{ "error": "Invalid or inactive API key" }{ "error": "API key expired" }Verify your API key is correct, active, and unexpired. Keys can be managed in the Developer Portal (opens in a new tab).
402 — Insufficient balance
{
"error": "Insufficient balance",
"required_cents": 10,
"balance_cents": 3,
"top_up": "https://frontrun.vc/api/billing"
}The response tells you exactly how much is needed vs. available. Top up your balance to continue.
429 — Rate limited
Two types of 429 responses:
Per-minute rate limit:
{
"error": "API rate limit exceeded. Please slow down.",
"retry_after_seconds": 60
}Daily spend cap reached:
{
"error": "Daily spend cap reached",
"daily_spent_cents": 5000,
"daily_cap_cents": 5000,
"resets_at": "2026-03-12T00:00:00.000Z"
}The daily spend cap (default $50) prevents runaway agent costs. It resets at midnight UTC.
400 — Invalid parameters
{ "error": "username is required" }{ "error": "Invalid \"since\" parameter. Use \"24h\", \"7d\", or \"YYYY-MM-DD\"." }{
"error": "At least one filter required: sector, keyword, or entity_type",
"example": "/v1/search?sector=AI/ML&entity_type=startup"
}403 — Tier limit
Returned when an action would exceed your subscription tier's quota. Currently used by POST /v1/track when you've reached the tracked-account limit for your tier.
{
"error": "You have reached your limit of 25 tracked accounts. Please upgrade your plan to track more.",
"code": "TRACKED_ACCOUNT_LIMIT",
"tier": "free"
}Upgrade your subscription or untrack existing accounts (DELETE /v1/track/:username) before adding new ones.
404 — Not found
{ "error": "Not tracking @example. Add with POST /v1/track" }The account must be tracked before you can query follows, convergence, or activity.
409 — Already exists
{
"error": "Already tracking this account",
"ready": true
}503 — Upstream unavailable
Returned by the handle-lookup endpoints (/v1/preview/:h, /v1/company/:h, /v1/company/:h/signals, /v1/company/:h/resources, /v1/company/:h/funding, /v1/company/:h/founders, /v1/track) when the upstream X/Twitter data provider is slow or temporarily unreachable.
{
"error": "Twitter upstream temporarily unavailable. Please retry.",
"retry_after_seconds": 30
}The response includes a Retry-After: 30 HTTP header. Back off for the indicated interval and retry — these are transient and usually clear within a minute.
Retry guidance
| Error | Retry? | Strategy |
|---|---|---|
400 | No | Fix the request parameters |
401 | No | Check your API key |
402 | No | Top up your balance |
403 | No | Upgrade plan or delete unused resources |
404 | No | Track the account first via POST /v1/track |
409 | No | Resource already exists — this is a no-op |
429 (rate limit) | Yes | Wait retry_after_seconds, then retry |
429 (spend cap) | Yes | Wait until resets_at timestamp |
500 | Yes | Exponential backoff: 1s, 2s, 4s, max 3 retries |
503 | Yes | Wait retry_after_seconds (from body or Retry-After header), then retry |