Errors and limits
Error shape, status codes, rate limits and timeouts.
Error shape
Every error response has the same body:
{
"error": {
"code": "scope_not_writable",
"message": "you are not cleared for scope \"engineering\""
}
}
Branch on code, which is stable. message is written for people and may change.
Codes
| Status | code | Meaning | What to do |
|---|---|---|---|
| 400 | invalid_json | The body is not a JSON object | Fix the request |
| 400 | missing_query | query is empty | Fix the request |
| 400 | query_too_long | query is over 2000 characters | Shorten it |
| 400 | missing_content | content is empty | Fix the request |
| 400 | content_too_long | content is over 20000 characters | Split it |
| 400 | missing_scope | A scope is required and was not given | Send scope |
| 400 | invalid_tags | tags is not a list of strings | Fix the request |
| 400 | invalid_purpose | purpose is not post, image or video | Fix the request |
| 400 | invalid_candidate | A proposal is missing content or has an unknown category or confidence | Fix the request |
| 429 | too_many_pending | The key or session already has too many proposals waiting | Wait for a person to review them |
| 401 | unauthenticated | No agent key or token was sent | Send Authorization: Bearer … |
| 401 | invalid_key | The key is wrong, revoked or expired | Reconnect or issue a new key |
| 401 | token_required | A strict key was sent to a data endpoint | Exchange it at /token and send the access token |
| 401 | invalid_token | The access token is malformed or has expired | Exchange the key for a new token, then retry once |
| 401 | key_required | A token was sent to the token exchange | Send the key there |
| 401 | signature_required | The key requires signed requests and the headers are missing | Sign the request |
| 401 | invalid_signature | The signature does not match the request | Sign the exact method, path and body you send |
| 401 | stale_request | The timestamp is missing, malformed or over five minutes off | Check the server clock; send milliseconds |
| 401 | replayed_request | This exact signed request was already received | Retry with a fresh timestamp |
| 403 | scope_not_writable | The key cannot write to that scope | Use a scope from /me → scopes.write |
| 403 | publishable_not_readable | /context was called with a key that cannot read the Publishable scope | Issue a key that includes Publishable |
| 404 | fact_not_found | No such fact is available to this key | Treat as absent |
| 429 | rate_limited | Too many requests | Wait for Retry-After, then retry |
| 500 | internal | Something failed on Buddhi's side | Retry once, then carry on without context |
Rate limit
Each key may make 120 requests a minute. Beyond that the API returns 429 with a Retry-After header giving the number of seconds to wait.
Timeouts and failure
Set your own timeout on every call. Ten seconds is a reasonable ceiling for /context and /recall.
Company context improves generated content; it should never be the reason generation fails. If a call errors or times out, generate without the context and, where it helps, tell the user that company context was unavailable.
async function companyContext(brief: string): Promise<string> {
try {
const res = await fetch(`${process.env.BUDDHI_API_URL}/context`, {
method: "POST",
headers: {
authorization: `Bearer ${process.env.BUDDHI_API_KEY}`,
"content-type": "application/json",
},
body: JSON.stringify({ query: brief }),
signal: AbortSignal.timeout(10_000),
});
if (!res.ok) return "";
const { found, context } = await res.json();
return found ? context : "";
} catch {
return ""; // unreachable or slow: generate without company context
}
}
Retrying
- Retry
429after theRetry-Afterdelay, and500once. - On
invalid_token, exchange for a new token and retry once. Oninvalid_key, stop: the connection has been revoked or has expired. - Every retry of a signed request needs a new timestamp and signature.
- Do not retry
400,401,403or404; the request will fail the same way. POST /memoriesis safe to retry when you send asourceUrl: the same content is stored once. Without one, a retried write creates a second memory.