Browse the docs

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

StatuscodeMeaningWhat to do
400invalid_jsonThe body is not a JSON objectFix the request
400missing_queryquery is emptyFix the request
400query_too_longquery is over 2000 charactersShorten it
400missing_contentcontent is emptyFix the request
400content_too_longcontent is over 20000 charactersSplit it
400missing_scopeA scope is required and was not givenSend scope
400invalid_tagstags is not a list of stringsFix the request
400invalid_purposepurpose is not post, image or videoFix the request
400invalid_candidateA proposal is missing content or has an unknown category or confidenceFix the request
429too_many_pendingThe key or session already has too many proposals waitingWait for a person to review them
401unauthenticatedNo agent key or token was sentSend Authorization: Bearer …
401invalid_keyThe key is wrong, revoked or expiredReconnect or issue a new key
401token_requiredA strict key was sent to a data endpointExchange it at /token and send the access token
401invalid_tokenThe access token is malformed or has expiredExchange the key for a new token, then retry once
401key_requiredA token was sent to the token exchangeSend the key there
401signature_requiredThe key requires signed requests and the headers are missingSign the request
401invalid_signatureThe signature does not match the requestSign the exact method, path and body you send
401stale_requestThe timestamp is missing, malformed or over five minutes offCheck the server clock; send milliseconds
401replayed_requestThis exact signed request was already receivedRetry with a fresh timestamp
403scope_not_writableThe key cannot write to that scopeUse a scope from /me → scopes.write
403publishable_not_readable/context was called with a key that cannot read the Publishable scopeIssue a key that includes Publishable
404fact_not_foundNo such fact is available to this keyTreat as absent
429rate_limitedToo many requestsWait for Retry-After, then retry
500internalSomething failed on Buddhi's sideRetry 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 429 after the Retry-After delay, and 500 once.
  • On invalid_token, exchange for a new token and retry once. On invalid_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, 403 or 404; the request will fail the same way.
  • POST /memories is safe to retry when you send a sourceUrl: the same content is stored once. Without one, a retried write creates a second memory.