API errors
How the Feedjolt API reports errors: HTTP status codes, what to retry with backoff, the X-Request-ID header for bug reports, rate limits, and validation responses.
The API uses standard HTTP codes for outcomes. Error response bodies follow FastAPI's default shape (a detail field with a string or structured payload). Per-endpoint error specifics are in the OpenAPI reference.
HTTP status codes
| Code | Meaning | Should you retry? |
|---|---|---|
| 200, 201, 204 | Success. | n/a |
| 400 | Validation error. Bad request body or query. | No - fix the request. |
| 401 | Missing/invalid auth. | No - fix the auth. |
| 403 | Auth OK but lacks scope or permission. | No - adjust scopes. |
| 404 | Resource not found, OR not accessible to your key. | No - verify the ID. |
| 409 | Conflict (e.g., slug already taken). | Sometimes - depends on cause. |
| 410 | Gone - resource was deleted. | No. |
| 422 | Semantic validation. | No - fix the request. |
| 429 | Rate limited. | Yes, with backoff. |
| 500 | Our bug. Please report. | Yes, with backoff. |
| 502, 503, 504 | Transient infra issue. | Yes, with backoff. |
Request IDs
Every API response includes:
X-Request-ID: <uuid>When you file a bug, include the request ID - it lets us pull the full server trace in seconds rather than guessing from a description.
Hi, I got a 500 calling POST /posts with this body: {...}
X-Request-ID: 7e6f2b71-...404 vs. 403
We deliberately don't differentiate between "doesn't exist" and "exists but you can't see it" - that would leak information about resources your key can't access. If you're sure the resource exists and you should have access, check your scopes first, then your workspace context.
Retry strategy
For codes you should retry (429, 5xx), use exponential backoff:
async function callWithRetry(url: string, init: RequestInit) {
const delays = [200, 800, 2000, 5000, 10000]; // ms
for (const delay of [0, ...delays]) {
if (delay) await sleep(delay);
const res = await fetch(url, init);
if (res.status >= 500 || res.status === 429) continue;
return res;
}
throw new Error("retries exhausted");
}Don't retry 4xx (other than 429) - the request is broken; retrying won't change that.
Rate limits (429)
Some endpoints are rate-limited per IP - currently the auth-related ones (/auth/magic-link, /auth/google, etc.). When you exceed the limit, you get a 429.
Workspace-scoped API endpoints (posts, comments, votes) don't have published per-key rate limits today. If you're doing a bulk migration that's hitting walls, email [email protected] - we can either raise limits temporarily or recommend a kinder pattern.
Validation
Bodies that fail Pydantic validation return 422 with a detail array of the offending fields. The shape is FastAPI's standard - see FastAPI's error response format or the OpenAPI reference for examples.
