API reference
Version 1 · Base URL https://app.botclarify.com/v1
The API lets your own systems ask questions about your documents and get the same answers, with the same sources, as the chatbot in the browser. It is read-only by design: a key can ask and can list what it is allowed to ask about, and can do nothing else.
Before you start
The API is included in the Business plan. Create a key in the console under API, in the left-hand menu of your organisation admin pages. The key is shown once, at the moment you create it, and never again — we store only a one-way hash of it, so nobody can recover it for you afterwards. If you lose one, revoke it and make another.
Authentication
Send the key as a bearer token:
Authorization: Bearer bck_xxxxxxxxxxxxxxxxxxxx
An X-API-Key: bck_... header is accepted too, for tools where a custom
header is easier than an Authorization one. A key is never read from the query string,
because URLs end up in server logs, proxy logs and Referer headers.
POST /v1/chat
Ask a question. This is the endpoint most integrations only ever need.
curl https://app.botclarify.com/v1/chat \
-H "Authorization: Bearer $BOTCLARIFY_KEY" \
-H "Content-Type: application/json" \
-d '{
"question": "How much notice do I have to give before taking annual leave?"
}'
{
"answer": "Annual leave has to be requested at least five working days in advance, and anything longer than five consecutive days needs your line manager's approval in writing.",
"sources": [
{ "document_id": "6f1c...", "filename": "Employee handbook 2026.pdf" }
],
"usage": { "calls_this_month": 412, "calls_included": 20000, "calls_remaining": 19588 }
}
| Field | Type | Notes |
|---|---|---|
question | string | Required. Up to 2,000 characters. |
folder_ids | string[] | Optional. Search only these folders. They must be folders the key is already allowed to read — this narrows the search, it cannot widen it. |
The answer is written in the language of the question. If nothing in the documents the
key can reach is relevant, answer says so plainly and sources
is empty — the model is not asked to fill the gap from its own knowledge.
GET /v1/folders
The folders this key may ask about, so you can discover the ids to pass as
folder_ids rather than guessing them. scoped is
true when the key was restricted to particular folders.
curl https://app.botclarify.com/v1/folders \ -H "Authorization: Bearer $BOTCLARIFY_KEY"
GET /v1/documents
Metadata for the documents the key can reach — id, filename, folder, status, size, date.
Never the file itself and never its text; the answer from /v1/chat is the
only way content leaves the system through this API.
Takes folder_id, limit (up to 200, default 50) and
offset.
GET /v1/me
What this key is, which folders it is scoped to, and how much of the month's allowance is left. The first thing to call when a key is not behaving the way you expected.
Folder scope
A key can be restricted to particular folders when you create it. This is what makes a key safe to put behind a public-facing help page: it reads the handbook and cannot reach the contracts, even if somebody later adds a contracts folder, because a scoped key names its folders explicitly rather than inheriting whatever exists.
A scoped key also stops seeing documents that are filed in no folder at all. If you want those included, either file them or leave the key unscoped.
Quota and rate headers
Calls are counted per calendar month across the whole organisation and reset on the 1st. Every response carries the state:
X-RateLimit-Limit: 20000 X-RateLimit-Remaining: 19588 X-RateLimit-Reset: 2026-10-01T00:00:00.000Z
Requests rejected for a bad key or a malformed body are not counted —
debugging your integration does not spend the month's allowance. Once the allowance is
gone, calls answer 429 until the 1st.
Errors
Every error has the same shape, with a stable code to branch on. The
message is for a human reading a log and may be reworded; the code will not
change.
{ "error": { "code": "quota_exceeded", "message": "This organization has used all 20,000 API calls included this month. The allowance resets on the 1st." } }
| Status | Code | What happened |
|---|---|---|
| 400 | missing_question | No question field. |
| 400 | question_too_long | Over 2,000 characters. |
| 401 | missing_key | No key was sent. |
| 401 | invalid_key | The key is unknown or has been revoked. These are deliberately the same answer. |
| 401 | expired_key | The key was created with an end date that has passed. |
| 402 | subscription_inactive | The organisation's plan has lapsed. |
| 403 | api_not_in_plan | The plan does not include API access. |
| 403 | folder_not_allowed | A folder was requested that this key cannot read. The denied field lists which. |
| 403 | no_folders_in_scope | Every folder this key was scoped to has been deleted. |
| 403 | organization_suspended | The organisation is suspended. |
| 404 | unknown_endpoint | No such endpoint under /v1. |
| 413 | payload_too_large | The request body is bigger than we accept. |
| 400 | malformed_request | The body could not be read as JSON. |
| 429 | quota_exceeded | The month's allowance is spent. |
| 500 | internal_error | Something failed on our side. Safe to retry. |
A worked example
A help-desk page that answers from the handbook folder only:
// Your server. The key never reaches the browser.
const res = await fetch('https://app.botclarify.com/v1/chat', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.BOTCLARIFY_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ question: userQuestion }),
});
if (res.status === 429) {
return reply('Our document assistant has reached its limit for this month.');
}
if (!res.ok) {
const { error } = await res.json();
console.error('botclarify', error.code, error.message);
return reply('Sorry — I could not check the documents just now.');
}
const { answer, sources } = await res.json();
return reply(answer, sources.map((s) => s.filename));
Versioning
The version is in the path. Anything that would break an existing integration — a field
removed, a field's meaning changed, an error code retired — arrives as
/v2, not as a change to this one. New optional fields may be added to
responses within /v1, so parse leniently and ignore what you do not
recognise.
Questions
Write to support@botclarify.com or use the contact form. If something in this page is wrong or missing, that is worth telling us too.