API
Automate Learny Brain from your own code. Create a workspace-scoped bearer token and call the API to list brains and trigger a fresh crawl of indexed URLs.
Get an API key
- As a workspace admin, open Settings in the left sidebar.
- Scroll to the API Keys panel at the bottom and click Manage API keys (or go to
/settings/api-keys). - Optionally give the key a name (e.g.
Production script) and click Generate API key. - Copy the secret shown on the next screen — it starts with
lba_and is shown only once. Store it securely; it is hashed in the database and cannot be recovered.
All keys for the workspace are listed with their prefix, name, creation date, and last-used timestamp. Revoke any key at any time — it stops working immediately.
Treat keys like passwords. Use a secrets manager or environment variable, never commit them to git, and revoke and rotate if a key may have leaked.
Authentication
Pass the key as a Bearer token in the Authorization header on every request. Keys are scoped to the workspace that created them — they cannot access other workspaces.
Authorization: Bearer lba_<your-secret>
Base URL: your workspace host, e.g. https://acme.learny.co (or https://brain.learny.co — the token determines the workspace). All API paths below are relative to that host.
curl -H "Authorization: Bearer lba_xxxxxxxxxxxxxxxx" https://acme.learny.co/api/brains
A missing or invalid token returns 401 { "error": "missing bearer token" } or 401 { "error": "invalid bearer token" }.
List brains
GET /api/brains — returns every brain in your workspace with its identifier.
GET /api/brains Authorization: Bearer lba_...
Example response:
{
"ok": true,
"org": { "id": 12, "subdomain": "acme", "name": "Acme Inc" },
"brains": [
{
"id": 7,
"public_id": "3ec4c2a8-5f1e-4b5a-9b1a-0f2a5a6b7c8d",
"name": "Company Brain",
"slug": "company-brain",
"is_company_brain": true,
"access": "org"
}
]
}
Use public_id (the UUID you also see in /brains/<public_id>/chat) as the brain identifier for other endpoints. id and slug are also returned for convenience.
Recrawl URLs for a brain
POST /api/brains/:brainPublicId/recrawl — re-scrapes and re-indexes every enabled context source (URLs and sitemaps) attached to that brain. This is the same job that runs on “Re-crawl all now” in the UI and on a nightly schedule, but triggered on demand. Crawls can take a while, so the endpoint is asynchronous: it responds immediately with 202 and a statusUrl you poll for completion. When the crawl finishes, every active workspace admin is emailed a summary (sources, pages indexed, per-URL status).
POST /api/brains/3ec4c2a8-5f1e-4b5a-9b1a-0f2a5a6b7c8d/recrawl Authorization: Bearer lba_...
Example response (202):
{
"ok": true,
"message": "Crawling has started. Poll statusUrl for completion.",
"brain": { "id": 7, "public_id": "3ec4c2a8-...", "name": "Company Brain" },
"job": {
"id": "9f3a...",
"status": "running",
"statusUrl": "/api/brains/3ec4c2a8-.../recrawl/jobs/9f3a...",
"startedAt": "2026-09-18T10:00:00.000Z"
}
}
404 { "error": "brain not found" }if the UUID does not belong to your workspace.503 { "error": "crawling is not enabled for this workspace" }if URL scraping isn't configured.500 { "error": "failed to trigger recrawl" }if the job can't start.
Check a recrawl's status
GET /api/brains/:brainPublicId/recrawl/jobs/:jobId — poll the statusUrl from the 202 response. status is running, done (with result totals and a per-URL sources breakdown), or error.
GET /api/brains/3ec4c2a8-5f1e-4b5a-9b1a-0f2a5a6b7c8d/recrawl/jobs/9f3a... Authorization: Bearer [REDACTED]
Example response (finished):
{
"ok": true,
"job": {
"id": "9f3a...",
"status": "done",
"startedAt": "2026-09-18T10:00:00.000Z",
"finishedAt": "2026-09-18T10:04:12.000Z",
"result": { "sources": 3, "docs": 12, "skipped": 0 },
"sources": [
{ "url": "https://example.com/docs", "status": "ok", "docCount": 3, "lastScrapedAt": "2026-09-18T10:01:00.000Z", "lastError": null }
],
"error": null
}
}
An unknown job ID — or one from another workspace — returns 404 { "error": "job not found" }.
Examples
curl -X POST \ -H "Authorization: Bearer lba_xxxxxxxxxxxxxxxx" \ https://acme.learny.co/api/brains/3ec4c2a8-5f1e-4b5a-9b1a-0f2a5a6b7c8d/recrawl
// Node.js (Node 18+)
const res = await fetch('https://acme.learny.co/api/brains/3ec4c2a8-.../recrawl', {
method: 'POST',
headers: { 'Authorization': 'Bearer ' + process.env.LEARNY_API_KEY }
});
const started = await res.json();
console.log(started.job.statusUrl); // poll this until job.status === 'done'
let job;
do {
await new Promise((r) => setTimeout(r, 5000));
const poll = await fetch('https://acme.learny.co' + started.job.statusUrl, {
headers: { 'Authorization': 'Bearer ' + process.env.LEARNY_API_KEY }
});
job = (await poll.json()).job;
} while (job.status === 'running');
console.log(job.result); // { sources: 3, docs: 12 }
Rate limits & errors
The API shares the global rate limiter (400 requests per 15 minutes per IP) and the per-brain crawl limits. Exceeding it returns 429. All endpoints return JSON; non-2xx responses include an error key.
What’s next: listing brains and recrawling URLs are the first endpoints. We’ll expand the API over time; this page will stay up to date as new capabilities land.