Noots.ai alpha is live. Expect some bugs while we polish, and tell us when you meet one.Report a bug

The v1 API

Ten endpoints: what each takes, what it returns, and what it refuses.


Everything lives under https://noots.ai/api/v1. JSON in, JSON out.

Shared rules

Authentication
Authorization: Bearer noots_… on every request. Missing or unrecognised gives 401 {"error":"Invalid or missing API token"}.
Rate limit
600 requests per minute per IP, shared across all API routes. Over it you get 429 with a retry-after: 60 header. Preflight requests count.
CORS
Any origin, for GET, POST, PATCH, DELETE and OPTIONS, with Authorization and Content-Type allowed. A preflight answers 204.
Cookies
Never accepted. Credentials are not allowed on cross-origin requests - the token in the header is the only way in, which is exactly why any origin is safe.

The endpoints

Method & pathBody / queryReturns
GET /me—{ user: { id, email, name }, org: { id, name } }. org is null if the token has none.
GET /me/tasks?status= optional{ tasks: [...] } - the tasks assigned to the token's owner, with key, title, status, priority, due date, project, estimate and logged time.
GET /me/tasks/{id}—{ task } - one task you can see: title, project, status and the board's columns, due date, description, assignees and its checklists with their items. Sends an ETag; repeat it in If-None-Match and an unchanged task answers 304.
PATCH /me/tasks/{id}{ status?, dueDate? } - status is one of the board's column keys, dueDate is YYYY-MM-DD or null to clear{ task } as it now reads. Written through the same rules as the board, so the people on the card are told the same way.
PATCH /me/tasks/{id}/checklist{ itemId, done } - the item must be on that task{ task } as it now reads. Ticking an item notifies the task's assignees and watchers, as ticking it in Noots does.
GET /me/todos—{ ok, today, items: [{ id, kind, title, done, dueDate, nootName, taskId, parentId, editable }] } - your personal checklist (My to-do), in the order Noots shows it. kind is manual, task or step.
POST /me/todos{ title, dueDate? }The list as it now reads, plus addedId.
PATCH /me/todos/{id}{ done?, title? } - id is the list's own id, such as item:… or task:…The list as it now reads. Ticking a task row completes the task on its board; ticking a step ticks that checklist item.
GET /me/notes—{ notes: [{ id, title, updatedAt, project, channel, preview, mine, href }] } - notes you wrote, edited or are named on, most recently changed first, limited to the ones you can still open.
POST /me/notes{ nootId, title?, content? }201 { note } - a new note on that project's Notes tab, written as you (Noots has no private notes, so anyone who can see the project can read it). Needs the write scope and the Notes extension switched on. At most 20 new notes in ten minutes per person.
GET /me/notes/{id}—{ note: { id, title, content, updatedAt, updatedByName, project, channel, inactive, canEdit, href } }. Sends an ETag, like a task.
PATCH /me/notes/{id}{ title?, content?, baseUpdatedAt? }{ note } as it now reads. 409 with the current note when it changed in Noots since baseUpdatedAt, and nothing is saved. 403 when you can read it but not change it.
GET /noots—{ noots: [{ id, name, icon, created_at }] }, newest first.
POST /noots{ name } - trimmed, first 60 characters201 { id, name }.
GET /progress?nootId= optional{ noots: [{ id, name, total, done, in_progress, in_review, todo, percent }] }. Counts are board cards: a subtask counts as part of its parent, not as an extra item - the same total the board shows.
GET /notifications—{ items: [{ text, kind, when }], count }. kind is prompt or activity; count is the pending prompts only.
POST /context/search{ query } - first 120 characters{ hits: [{ type, id, title, subtitle }] }, where type is noot, task or meeting.
POST /context/factcheck{ claim }{ verdict, explanation, sources }. verdict is supported, contradicted or unverifiable.
POST /meetings/capture{ url, nootId?, boardUpdates? } - boardUpdates: false is Record only: written up into the Vault, no board is updated201 { ok, meetingId, botId, notice } when a bot was dispatched; 200 with a notice when one was already on that meeting.
POST /meetings/ingest{ transcript, title?, nootId?, durationMin?, boardUpdates? } - boardUpdates: false is Record only, as above201 { ok, meetingId, summary, decisions, actionItems, summarized }.
Reads are scoped to the token owner's own projects

/noots, /progress, /context/search and /context/factcheck return only the projects that person can actually open. If your integration used to see private projects its owner wasn't on, it no longer does - that was a leak, and closing it is a change you may notice. A nootId you send that doesn't belong to the token's organization is ignored rather than honoured.

Errors

StatusWhen
400A required field is missing (name, claim, transcript, url), the URL isn't a meeting link, or the token has no organization on a route that needs one.
401No Authorization header, a malformed one, or a token that has been revoked or whose owner is no longer an active member.
403A read-only token on a route that writes (the body names the missing scope), or Noots refused the change - for example a task you can see but not edit.
404GET /me when the account behind the token no longer exists, and any {id} route when that item is not there or not yours to see - the two answer identically.
429Over 600 requests in the last minute from your IP, or, on the /me/tasks/{id}, /me/todos and /me/notes routes, over 120 reads or 40 writes in a minute on one token.
502POST /meetings/capture only, when the recording provider refused.
A token with no organization gets an empty answer, not an error

/me/tasks, /noots, /progress, /notifications and /context/search all return 200 with an empty list rather than failing. The routes that have to write something - creating a project, capturing or ingesting a meeting, fact-checking - return 400 instead, because there is nowhere to put the result.

Fact-check degrades rather than failing

With no AI configured, or when the model call fails, /context/factcheck answers 200 with unverifiable and whatever sources it found. It never returns a 5xx, so your caller doesn't have to distinguish "couldn't tell" from "broke" - the verdict already says which.

Tip

POST /meetings/ingest is the route to reach for if you already have a transcript. It runs the whole normal pipeline - summary, decisions, action items, and tasks onto the project you name.

Three more routes exist and are deliberately not documented here

/api/v1/email/* and /api/v1/extension/* are what the Noots browser extension itself calls, and they are not a public contract - they can change shape with the extension in the same release. The eighteen above are the ones to build on.

Still stuck? Open a support ticket and we'll help you out - tracked right inside Noots.