smart_toy Integration guide for AI agents
Floatee is a centralized store of todos, ideas and notes, agent-first. Your coding agent fetches the next todo, comments, marks it done with a resolution note, and searches the full history — all over a REST API. This is the complete, self-contained reference.
.txt. key Getting a token
Tokens are account-scoped (one per machine), created by the human user in the Floatee UI under Settings → Your agent — you do not create tokens yourself. A token looks like flt_… and the same token works in every repo; which project a call targets is passed per request (?project=<slug>). Drop it into a .floatee at the repo root (gitignored):
token=flt_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx api=https://floatee.me/api/v1 project=my-repo
project pins the slug for this repo; a new slug is auto-created in the user's personal workspace on first use (even by a GET). If omitted, use the repo folder name. Treat the token as a secret — never commit, print or log it.
api Conventions
- Base URL
https://floatee.me/api/v1, authAuthorization: Bearer flt_…on every request. - Every call takes
?project=<slug>— including item-by-id (/items/:id). An id is the per-workspace#N; the project you pass resolves the workspace that scopes it. - GET responses are markdown by default (add
?format=jsonfor JSON). Writes (POST/PATCH/DELETE) take and return JSON; field names accept snake_case or camelCase. body_md, comments andresolution_noteare markdown in full UTF-8: send real accents/apostrophes and markdown (blank line = line break). Build the JSON with an encoder andcurl --data @file— don't hand-escape an inline-d '…'(the shell mangles UTF-8/quotes).tagsis a full-array replace (no add-one endpoint);snooze_untilis an absolute Unix epoch in seconds (nullto wake).- Errors are JSON
{ error, code }with a status:400project_required/ bad payload,401invalid/revoked token,403plan_limit/plan_required,404not found / out of scope,429rate-limit.
schema Item model
| id | The per-workspace #N (integer, ≥ 1). Read-only; assigned on create. The ?project you pass resolves the workspace that scopes it. |
| type | todo | idea | note. Default todo. Only todo is returned by /next. Promote by PATCHing type — keeps id, tags, history. |
| status | todos only: pending | in_progress | blocked | done | wontfix. New items start pending. done/wontfix should carry a resolution_note. |
| body_md | Markdown — the whole item. Its first line is the title (you don't send a separate title). GFM task lines - [ ] / - [x] become an interactive done/total checklist. May embed images  — GET that path with your Bearer token to view the bytes; keep such links verbatim when editing. |
| tags | Array of plain strings, e.g. ["bug","ui"] (no #/+ prefix). A write REPLACES the whole array. |
| snooze_until | Absolute Unix timestamp in seconds, or null. A snoozed item is excluded from /next and the default list until it passes, then auto-wakes. NOT a duration. |
| resolution_note | Short "what was done" string, set when resolving. |
| conventional_type | feat | fix | chore | perf | refactor | docs | … , optionally suffixed ! for breaking (feat!). Feeds the changelog. |
| position | Create only: top | bottom (default bottom). Where the new item lands in the manual sort order. |
| assignee | Who owns the item — at most one: a member (assignee_id, assigneeType "user") or an agent (assignee_token_id, assigneeType "token"); read assigneeName for the label. On a write send assignee_id, assignee_token_id, or — friendlier — assignee_handle (a handle from GET /project, or "me" for yourself); null to unassign. New items default to their creator (your token via the API). |
References in text: writing #N anywhere in body_md or a comment links to ticket #N of the same project (rendered as a link).
data_object Endpoints
| Method | Route | Description |
|---|---|---|
| GET | /next?project= | First pending todo, not snoozed, by sort order. Full item (body + tags + activity). Add &claim=1 to atomically lock it in_progress in the same call (fetch + lock, race-safe). Optional &assignee=<member|agent> (id, display name, or token label) or &assignee=me for your own queue. 204 if nothing. |
| GET | /items?project= | List. Params: status, type, tag, q, include_done (1 = all statuses incl. done/snoozed), limit (def 50, max 200), offset. Default: open work, not snoozed. |
| GET | /items/:id?project= | Full detail (item + activity). :id is the per-workspace #N. ?format=json for JSON. |
| POST | /items?project= | Create. JSON: body_md (required — first line is the title), type, tags, position, snooze_until, conventional_type, assignee_id / assignee_token_id / assignee_handle (or "me"). Returns the item (201). Starts pending, assigned to your token unless you set an assignee. |
| PATCH | /items/:id?project= | Update any of: status, resolution_note, conventional_type, body_md, title, tags, type, snooze_until, assignee_id, assignee_token_id, assignee_handle (or "me"). tags REPLACES the array; body_md re-derives the title. (To reorder, prefer /items/reorder — it computes the sort order for you.) |
| DELETE | /items/:id?project= | Soft delete — recoverable, but excluded from lists and search. |
| POST | /items/reorder?project= | Reorder the backlog in one call. JSON: order (ids top-to-bottom), position ("top" default | "bottom"). The listed ids become a block at the top (or bottom), in that exact order; omitted ids keep their relative order. Returns { moved, skipped }. The server assigns sort orders — you never compute them. |
| POST | /items/:id/comments?project= | Append a markdown comment to the activity feed. JSON: body_md. Put long analyses here. |
| GET | /search?q=&project= | FTS over the project — titles, bodies, resolution notes, tags AND comments. Includes done/wontfix. Most-recently-resolved first. |
| GET | /changelog?project= | Done items with a conventional_type, grouped by date, changelog.json shape. Params: since, unexported. Pro plan. |
| POST | /changelog/mark-exported?project= | Mark items exported so ?unexported=1 won't re-emit them. JSON: {"ids":[…]}. Pro plan. |
| GET | /project?project= | Project metadata: name, slug, color, icon, archived, counts by status (+ idea/note totals), and assignees — who you can assign to (members + agents), each with a handle to pass as assignee_handle. |
Create an item
curl -X POST -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{"body_md":"Fix slider overflow\n\nThe range bleeds past the card.","type":"todo","tags":["bug","ui"],"position":"top"}' \
"https://floatee.me/api/v1/items?project=my-repo"Resolve an item
curl -X PATCH -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{"status":"done","resolution_note":"Added px-4 to the container","conventional_type":"fix"}' \
"https://floatee.me/api/v1/items/142?project=my-repo"description GET output shape (markdown, the default)
GET /items/:id returns, e.g.:
# [#142] Fix the slider overflow on mobile
- status: in_progress · type: todo · tags: bug, ui
- created: 2026-06-02 by françois
- sleeping until: 2026-07-01 (only if snoozed)
- resolution: … (only if resolved)
The label runs off-screen on mobile when the value is long.
- [ ] check iOS Safari
- [x] check RTL
## Activity
- 2026-06-03 · status_change pending → in_progress
- 2026-06-03 · comment (agent "Claude Code — laptop"):
Reproduced. The container has no horizontal padding… List/search GETs return one line per item: - [#142] <title> — status: … · type: … · tags: … · 3/7. Add ?format=json on any GET to parse structured data instead.
One call for both: single-item JSON responses (/next, /items/:id, and the JSON from a create POST / PATCH) also include a markdown field — the exact rendering above. One call gives the relayable markdown and the structured fields; a PATCH response carries the post-change markdown, so a close needs no follow-up GET. (List responses omit it.)
menu_book Recipes
Add / remove a tag (the array is replaced)
# tags is a FULL-ARRAY replace — there is no add-one endpoint.
# 1) read the current tags
curl -H "Authorization: Bearer $TOKEN" \
"https://floatee.me/api/v1/items/142?project=my-repo&format=json" # -> "tags":["bug"]
# 2) PATCH the complete desired set (use [] to clear all)
curl -X PATCH -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{"tags":["bug","ui"]}' \
"https://floatee.me/api/v1/items/142?project=my-repo"Snooze (absolute Unix epoch)
# snooze_until is an absolute Unix epoch (seconds) — compute it yourself.
UNTIL=$(date -d '+14 days' +%s) # GNU date; macOS: date -v+14d +%s
curl -X PATCH -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d "{\"snooze_until\": $UNTIL}" \
"https://floatee.me/api/v1/items/142?project=my-repo"
# wake it now (un-snooze): {"snooze_until": null}- Promote an idea/note → todo —
PATCH {"type":"todo"}(keeps id, tags, history). - Block —
PATCH {"status":"blocked"}+ a comment stating exactly what you need to proceed. - Reference a ticket — write
#Nin a body or comment. - Create at the top —
POST {"body_md":"…","position":"top"}.
workspace_premium Plan limits (why a 403 happens)
- Free caps the number of active items per account (history — done/wontfix/deleted — is never counted). Over the cap →
403 plan_limit. - Snooze is Pro+ : setting
snooze_untilon Free →403 plan_required. Clearing it (null) is always allowed. - Changelog endpoints are Pro+ →
403 plan_required.
checklist Typical flow ("process the next todo")
GET /next?project=…&claim=1&format=json→ fetches the next todo AND locks itin_progressin one call (204 = nothing to do; stop). Relay itsmarkdownfield; use the structured fields for the rest.GET /search?q=…&project=…if it looks like something tried before (wontfix carries why).- Do the fix. Post any long analysis as a comment.
PATCH /items/{id}{"status":"done","resolution_note":"…","conventional_type":"fix","tags":[…]}(orwontfix+ note, orblocked+ a comment). The PATCH response carries the post-changemarkdown→ summarise from it, no extra GET. Auto-tag on close: 1–3 tags for the area/nature, merged with the existing tags (full-array replace → send existing ∪ new, never drop a tag).
One todo per invocation. Always re-fetch the item; don't trust prior context. Found an unrelated problem mid-fix? File it (POST /items, tag found-by-agent) instead of interrupting.
info Any agent, one block
These same rules are summarised in the AGENTS.md block on the project's "Set up your agent" tab. Paste it into your repo's AGENTS.md and any tool that reads it — Claude Code, Codex, Copilot, Cursor, Gemini CLI, Aider, Zed, Windsurf — knows how to process your todos. Claude Code users also get a /todo slash command.