Errors
The consumer API uses a small set of HTTP status codes and a uniform error body. Build your client around the status code first; the message is for humans reading logs.
Error body
Errors return a single-field JSON object:
{
"message": "Invalid or missing API key."
} The message is intentionally short and stable. Do not parse it; switch on
the HTTP status instead.
Status codes
| Status | When you’ll see it |
|---|---|
200 OK | Success. |
401 Unauthorized | API key missing, malformed, or revoked. Re-check headers and key status. |
404 Not Found | The requested released blog does not exist in your workspace, or has not been released. |
500 Internal Server Error | Unexpected failure on our side. Retry with backoff. |
Handling 401
A 401 always means one of:
- No
x-api-keyand noAuthorization: Bearerheader was sent. - The key was sent but has been revoked from the dashboard.
- The key never existed (typo, swapped prefix, copied from a different environment).
Re-check the key in Workspace settings → API keys. The dashboard shows the prefix of every active key for visual confirmation.
Handling 404
A 404 from GET /api/consumer/blogs/{blogId} means the blog ID does not
correspond to a released blog in the workspace bound to your key. The
blog may exist in a different workspace, may still be in draft, or may have
been removed. Cross-check with GET /api/consumer/blogs to discover currently released IDs.
Retrying
The list and get endpoints are pure reads, so retries are safe. A simple exponential backoff is plenty:
async function getWithRetry(url: string, headers: Record<string, string>) {
for (let attempt = 0; attempt < 4; attempt += 1) {
const response = await fetch(url, { headers });
if (response.status < 500) return response;
await new Promise((resolve) => setTimeout(resolve, 250 * 2 ** attempt));
}
throw new Error("Essel API unavailable after 4 attempts.");
} Do not retry 401 or 404 — they will not resolve themselves.
Rate limits
There is no fixed rate limit today, but the API is sized for periodic syncs (every few minutes), not per-request fan-out from end users. If you need to serve high-traffic reader pages, cache responses on your side rather than passing every page view through to this API.