REST API
aqua and Inbox
tracker's AI, credits, reviews and the Inbox.
GET /aqua(tracker:read): whether aqua (the AI assistant) is on for the company,{"available": true, "reason": null, "can_review": true}(reason:disabledorno_key;can_review: the person edits issues in some project and sees the aqua screen,GET /aqua/recommendations).POST /aqua(tracker:read): the app's help conversation,{"messages": [{"role": "user", "content": "How do I create an issue?"}], "path": "/issues", "app": "ios"}(up to 20 messages, starting and ending withuserand alternating;app:iosormac, optional). aqua answers usage questions and also questions about the data: it looks up, read-only and as the token's person, what that person sees in the company (their tasks and the ones they watch, projects, sprints, releases, tests, people, hours, inbox, Chats, documents, ideas and status), with the same read queries as the MCP; it doesn't change anything. It also opens task and comment attachments when the question calls for it: it sees screenshots (png, jpg and webp up to 3.7 MB) and PDFs (up to 10 MB) and reads text files (md, csv, txt, log and json), up to 4 images or PDFs per question; no video. aqua also proposes changes when the person asks (create a task, edit or assign, comment, change status, block, watch, plan, log hours, link tasks), but nothing is saved by the question: each proposal comes back inactionsfor the person to confirm. The links in the answer are app addresses (/issues/MOB-0012?org=...). When the question is about a task or a project, send the open screen inpath(/issues/MOB-0012,/projects/mobilidade): aqua understands "this task". A question that looks up data takes a little longer and counts as one AI use. aqua answers in the token's person's language (thelocaleinGET /me; on Automatic, the request'sAccept-Language), and the actions'title,detailsandresultand thestatustexts come in the same language. Every conversation is saved: sendconversation_id(returned in the first answer) to continue the same one; without it, a new conversation (or the recent one with exactly the same messages). Returns{"answer": "...", "conversation_id": "...", "actions": [...]}, each action withid,tool(the MCP tool it runs),input,title(the card's sentence, written by tracker),details,state(pending,running,done,cancelledorfailed),result(textandurl, once done) anderror. With"stream": true, the answer arrives bit by bit as NDJSON (application/x-ndjson, one JSON per line):{"type": "status", "text": "Checking the tasks…"}while it looks things up (text received before astatusno longer counts),{"type": "text", "text": "..."}with each piece of the answer,{"type": "ping"}to keep the connection alive and, at the end,{"type": "done", ...}with the same JSON as without streaming (the answer that counts) or{"type": "error", "message": "..."}; the HTTP status is 200 even on error.POST /aqua/conversations/{id}/actions/{action}(tracker:write) with{"decision": "confirm"}makes the change with the token's person's role (or"cancel"discards it) and returns{"action": ...}; the same action doesn't run twice (422 when it was already decided).GET /aqua/conversations(tracker:read,?limit=up to 50) lists the person's conversations (id,title,messages,created_at,updated_at; the 50 most recent are kept),GET /aqua/conversations/{id}returns the messages (role,content,at,actions) andDELETE /aqua/conversations/{id}(tracker:write) deletes it. In the MCP:list_aqua_conversationsandget_aqua_conversation. 422 when the AI refuses or is off, without a key or at the limit.GET /aqua/credits(tracker:read): the company's AI credits. Without its own key, aqua uses tracker's key and spends credits from a package per 30-day cycle (the one in the company's plan), which renews on its own; with the company's own key, it doesn't spend any. Returnsavailable,reason,key_source(server: credits;organization: own key;nullwithout AI),credits(nullwith the own key):state(ok,lowwith 20% or less,emptywhen it ran out and aqua pauses until it renews,expired),remaining,used,total(per_cycleplusgranted, the credits added by the platform team in the cycle),cycle_days,cycle_start,cycle_end,auto_renewandrenews_at; andusage(admins and owners only,nullfor others):since(the start of the cycle; with the own key, 30 days ago) andby_action, from the most used actions to the least (action,label,calls,failures,credits). Always in credits, never in money. When an AI call returns 422 for lack of credits, the message says when it renews. In the MCP:get_ai_credits. The company's own key (Claude only) is set, changed and removed only on screen, in Company → Integrations → AI assistant (admins and owners): neither the API nor the MCP reads or writes the key.- Inbox (the one on the /inbox screen):
GET /inbox(tracker:read,?view=unreadonly the unread ones or?view=hiddenthe hidden ones; without it, the ones not hidden;?before=<id>pages,?limit=up to 100) returnsunreadanditems, the comments that reached the token's person, most recent first:kind(mention: someone wrote @their name;reply: a reply in a conversation they wrote in),own_thread(the conversation started with a comment of theirs),id(of the comment),text,author,excerpt,issue(id,code,title,project),url,at,readandhidden. Writing on the task after the comment, opening the task or reading its notification also count as read. Mentions and replies in Chats threads come separately, inchat_items(withchat_unread):id(of the notification),kind(mentionorreply, a reply in a thread they're in),own_thread(the thread started with a message of theirs),thread(it came from a thread),text,author,excerpt(the snippet of the message),project,url(straight to the message),at,readandhidden; opening the thread or reading the channel counts as read.POST /inbox(tracker:read) changes the state (of ids fromitemsandchat_items):{"action": "read", "ids": [...]}or{"action": "read", "all": true},{"action": "hide", "ids": [...]}or{"action": "hide", "older_than_days": 30}(hiding counts as read) and{"action": "unhide", "ids": [...]}; returnsupdated,unreadandchat_unread. aqua's summary of the day and the month (the one at the top of the inbox):GET /aqua/summary(tracker:read,?period=day, the default, ormonth, in the Brasília time zone) returnsavailable,reason,periodandsummary(nullbefore asking):headline,highlights(what happened in the person's tasks and the ones they watch),attention(what needs their attention),issues(the ones cited, withcode,idandurl),generated_atandoutdated(news arrived after it).POST /aqua/summary(tracker:read) with{"period": "month"}asks for a new one, written in the token's person's language (it spends AI credits; a period with nothing doesn't); 422 with the AI off, without a key or without credits. In the MCP:list_inbox,update_inboxandget_aqua_summary. - aqua on issues (the same as on screen):
GET /issues/{ref}/aqua(tracker:read) returnsavailable,can_review(whether the person can ask for the review),summary(likeaqua_summaryinGET /issues/{ref}),review(summary,reviewed_at,outdated), the openrecommendations(id,kind:comment,status,field,custom_field,label,duplicateormove;title,before,after,reasonandcomment, the text of the request for information) andsnooze_options.POST /issues/{ref}/aqua/summary(tracker:read) summarizes the conversation (fromsummary_min_commentscomments on) and returns{"summary": ...}.POST /issues/{ref}/aqua/review(tracker:write, whoever edits the issue) reviews it and returns the same as theGET. The review (this one, the batch one and the daily one) also reads the attachments of the issue and its comments: up to 3 screenshots, 1 PDF (up to 5 MB) and the text of up to 2 text or log files, newest first; no video. The cost of reading goes into the credits like the rest of the review.POST /aqua/recommendations/{id}/apply(tracker:write) applies the suggestion (an optional{"comment": "..."}changes the text of the request for information);POST /aqua/recommendations/{id}/dismiss(tracker:write) with{"for": "7"}(1,7,30days orforever) ignores it. The whole aqua screen:GET /aqua/recommendations(tracker:read, optional?project=MOB) returnsavailable,reason,can_review,daily_review(enabled,hour,limit,last_on,last_count,last_error),sentry_waiting(Sentry errors awaiting a decision, inGET /sentry/errors?waiting=true),totalandissues, the issues with open suggestions (from the ones stalled longest to the recent ones), each withid,code,title,project,status(name,color,category),summary,reviewed_at,outdatedandrecommendations(as above), andsnooze_options. "Review open issues" runs on the server:POST /aqua/review-runs(tracker:write, optional{"project": "MOB"}) starts the review of every open issue aqua hasn't seen yet or that changed since the review (up to 500, one at a time; one review at a time per company, and asking again returns the one already running) and returns{"run": ...}(nullwith nothing pending);GET /aqua/review-runs(tracker:read) returns the one running or the last one,GET /aqua/review-runs/{id}the progress (status:running,done,stoppedorfailed;total,reviewed,failed,suggestions,error,created_at,finished_atandissues, each withid,code,title,state—waiting,running,doneorfailed—,suggestionsanderror) andPOST /aqua/review-runs/{id}/stop(tracker:write) stops it.GET /aqua/review-queue(tracker:read,?project=and?limit=up to 25) still returns the queue (id,code,title) to review one by one withPOST /issues/{ref}/aqua/reviewand{"batch": true}(the batch review model). In the MCP:list_aqua_recommendations,start_aqua_review,get_aqua_review,stop_aqua_review,list_issues_to_review,review_issue_with_aqua,apply_aqua_recommendationanddismiss_aqua_recommendation.POST /aqua/draft(tracker:read) with{"text": "free-form report", "project": "MOB"}(projectoptional) returns the fields ofPOST /issuesfilled in andmissing(what the report doesn't say), in the report's language, without creating anything.POST /aqua/improve(tracker:read) with{"project": "MOB", "type": "bug", "title": "...", "description": "..."}(and the form's other texts) returns a rewritten title and texts andnotes, without saving. 422 when the AI is off, without a key or at the limit.