REST API

Chats

Project channels, threads, reactions, direct messages and Chats apps.

  • Chats (/chat, one channel per project, like Slack): for the people who work on the project (admin, PO/PM, QA and dev; stakeholders don't see it, 403). GET /chat (tracker:read) lists the token's person's channels (the active projects): unread and mentions totals and channels, each with project (id, slug, name), unread (new messages in the main conversation), mentions (mentions and replies in their threads not yet read), last_message_at and url. GET /projects/{prefix, slug or id}/chat (tracker:read) returns project, url, people (who can be mentioned with @Name: id, name and me, the token's person; with aqua on in the company, aqua comes last, with app aqua; also returned with ?thread_id), unread (the token's person's unread ones), last_read_at, has_more and messages, from the main conversation in the order they were written (without a cursor, the last 50; ?before=<id> the earlier ones, ?after=<id> the ones that arrived later, ?limit= up to 200, ?mark_read=1 marks as read up to the last one returned). With ?thread_id=<id> (the first message of a thread) it returns thread (that message) and replies (the replies, up to 500; ?after=<id> only the new ones; ?mark_read=1 marks the thread's mentions and replies as read). Each message: id, thread_id (the thread it replies in, or null), in_channel and thread_root (author, text: the thread reply that also went to the main conversation and the start of the message it replies to), author, app (a message written by an app, with key and name; null for a person's), author_id, author_avatar_url (the photo, null without a photo), text (markdown; empty when deleted or attachment-only), attachments (the attached files, in order: id, name, type, kind (image, video or file), size_bytes and download_url; empty when deleted), at, edited_at, deleted (by, at), mine (written by the token's person), can_edit and can_delete (what they can do with the message), mentions, mentions_me, issues (the tasks cited by code that the person sees: code, title, open, url), reactions (emoji, count, mine, people), thread (in the main conversation: replies, last_reply_at and people, who replied; null without replies) and url. POST /projects/{ref}/chat (tracker:write) sends {"text": "..."} in the main conversation or {"text": "...", "thread_id": "<id>"} in that message's thread (with a reply's id, it goes into the same thread; "also_in_channel": true also puts the reply in the main conversation, like "Also send to the channel" on screen; reply_to_id is the old name; up to 10,000 characters; @Name mentions someone in the channel, and whoever is in the thread gets the reply, in the Inbox, the bell and on their device) and returns message (id, thread_id, url and aqua_replying: the message called @aqua and it will reply in the thread), 201. Attachments (photos, PDF, zip, spreadsheets, logs, videos: the task attachment formats, png, jpg, jpeg, webp, gif, mp4, mov, pdf, json, txt, log, md, csv, zip): in JSON, "attachments": [{"file_name": "screenshot.png", "content_base64": "..."}] or [{"url": "https://..."}], as in comments; or multipart/form-data with text, thread_id, also_in_channel and one files field per file. Up to 5 per message, 15 MB each and 14 MB combined, and 60 files per hour per person; with an attachment, text can be left out. GET /chat/attachments/{id} (tracker:read) downloads the file, with the same token (accepts Range), for whoever reads the message's conversation. Deleting the message deletes its attachments. POST /projects/{ref}/chat/{id}/reactions (tracker:write) with {"emoji": "👍"} adds the token's person's reaction and DELETE with the same body removes it (each person, each emoji once; up to 20 different emojis per message); returns id, emoji and reacted. PATCH /projects/{ref}/chat/{id} (tracker:write, the author only) fixes it with {"text": "..."}; DELETE /projects/{ref}/chat/{id} (tracker:write, the author or an admin) deletes it (it stays in place as deleted; the previous text goes to the company history). POST /projects/{ref}/chat/read (tracker:read) with {"message_id": "<id>"} (or {}, up to now) marks the main conversation as read and returns unread. GET /projects/{ref}/chat/issues?q= (tracker:read) returns issues, the tasks to cite in a message, like the list that opens when typing # in the field on screen (up to 8; only the ones the token's person sees): without q, by context, first the ones cited last in the conversation (reason cited), then the open ones assigned to the token's person (mine) and the project's open ones touched last (project); with the start of a code (MOB- or MOB-12, which finds MOB-0012), it completes by code, the project's first; with words, the text and meaning search of /search (reason null). Each one: id, code, title, open, project (the name), reason and url; a code written in the text becomes a link and a card. Archived project: read-only (422 when writing). In the MCP: list_chat_channels, list_chat_messages, send_chat_message, react_to_chat_message, edit_chat_message, delete_chat_message and suggest_chat_issues.
  • Direct messages (/chat/direct/<person id>): the private conversation between the token's person and another team member in the same company (anyone who works on one of its projects, except stakeholders, plus admins and owners). Only the two of them read it; not even the admin sees it. GET /chat also returns directs (the conversations with messages, most recent first: id, person (id, name), unread, last_message_at, url) and people (who they can start one with: id, name, url); the top-level unread adds up channels and direct conversations. GET /chat/direct/{person} (tracker:read; the person by id or e-mail; opens the conversation the first time) returns person, url, people (empty: there are no @mentions), unread, last_read_at, has_more and messages, with the same parameters and fields as the project conversation, without threads. POST /chat/direct/{person} (tracker:write) sends {"text": "..."}, with attachments as in the channel (the other person gets a device notification; thread_id gives 422); PATCH/DELETE /chat/direct/{person}/{id} fixes and deletes (the author only; outside the company history), POST/DELETE /chat/direct/{person}/{id}/reactions reacts, POST /chat/direct/{person}/read marks as read and GET /chat/direct/{person}/issues?q= suggests tasks to cite (without a channel project: the ones cited in the conversation and the open ones assigned to the token's person). A person outside the team: 404; someone who left the team later leaves the conversation read-only (422 when writing). In the MCP, the same conversation tools with person instead of project.
  • Chats apps: whoever writes in the channel without being a person (the message comes with app and author_id null; nobody edits it, the admin deletes it). The text apps write and their catalog (name, summary, description and the permission descriptions) come in the reader's language: the one chosen in Your account or, on automatic, the one in Accept-Language; what people write (names, subjects, aqua's answer) stays as written. Each app has a manifest: name, what it asks for (permissions: required ones, always granted, and optional ones, which the admin picks when installing), the events it listens to and what each channel chooses. The permissions: chat:write (write in the conversation), issues:read (see the project's tasks), comments:read (see comments, for the new comment notice), meetings:create (create Google Meet meetings) chat:direct (work in direct conversations) and ai:use (reply with aqua, spending the company's AI credits). The official ones: task_updates (Task updates: posts in the channel when a project task is created, changes status, changes assignee or gets a comment (the last one only with comments:read, optional), with its card; each channel picks the events), google_meet and aqua (see below) and automations (Automations: comes with tracker and writes when an automation rule has the "Send a channel message" action). The company installs (admins and owners only) and the project's PO/PM or an admin turns it on in each channel, or the admin turns it on in every channel at once, including channels created later. In a direct conversation, only apps with chat:direct granted, when one of the two people turns it on; either one turns it off, and the app tells the conversation who turned it on or off. GET /apps (tracker:read) returns apps, the company catalog: key, name, summary, description, official, built_in, company_wide (on across the whole company: no install and no per-channel switch; installed is false when an admin turned it off), permissions (key, description, required: mandatory, and granted: the company granted it), events, installed, installed_at, channels (how many channels it's on in) and all_channels (on in every channel, including new ones). POST /apps/{key} (tracker:write) installs, with {"permissions": ["chat:write", "meetings:create", "chat:direct"]} (the required ones always go in; without a body, only those); PATCH /apps/{key} with {"permissions": [...]} changes what's granted (removing chat:direct turns the app off in every direct conversation); {"all_channels": true}, in the POST or the PATCH, turns the app on in every channel, including new ones (then the channel can't turn it off, only pick the updates), and false goes back to the channels that turned it on one by one (not for personal apps); DELETE /apps/{key} uninstalls (turns it off in every channel and direct conversation; the messages stay). They return key, installed and permissions (the granted ones); a permission the app doesn't ask for gives 422. GET /projects/{ref}/chat/apps (tracker:read, conversation members) returns project, can_manage (can turn on and off), can_install and apps (key, name, summary, built_in, company_wide, installed, enabled, all_channels and, for task_updates, events and allowed_events, the ones the permissions allow choosing). PATCH /projects/{ref}/chat/apps/{key} (tracker:write, PO/PM or admin) with {"enabled": true, "events": ["issue.created", "issue.status_changed", "issue.assigned", "comment.created"]} turns it on and picks the notices (without events, it keeps what it had or the default: task created and status changed) and {"enabled": false} turns it off (with all_channels, it gives 422); an app that isn't installed gives 422. In a direct conversation: GET /chat/direct/{person}/apps (tracker:read; the person by id or e-mail) returns person, active, can_install and apps (key, name, summary, installed, allowed: allowed in direct conversations, enabled and enabled_by: who turned it on); PATCH /chat/direct/{person}/apps/{key} (tracker:write, either of the two people) with {"enabled": true} turns it on and {"enabled": false} turns it off. In the MCP: list_chat_apps (with project, the channel's; with person, the direct conversation's), install_chat_app (with permissions and all_channels) and set_chat_app (with project or person).
  • Google Meet (google_meet, official app): creates the meeting in the channel, in the caller's Google account, and posts the card with the join link. Each person connects their own Google account once, through the browser (Google's screen doesn't open through the API). In the channel, the app comes with account (configured, connected and email, the token's person's account). GET /apps/google_meet/account (tracker:read) returns configured, connected, email and connect_url (open it in the browser, signed in to tracker); DELETE /apps/google_meet/account (tracker:write) disconnects and revokes access at Google. POST /projects/{ref}/chat/meet (tracker:write, conversation members) with {"title": "Sprint planning"} (optional) and "thread_id" (optional: creates it inside that message's thread) creates the room and returns project, message (id, thread_id, url) and meeting (url to join, code, title, starts_at and ends_at), 201. To schedule, also send "starts_at" (ISO 8601 with the offset, e.g. 2026-10-22T14:00:00-03:00), "duration_minutes" (15 to 480, default 30), "time_zone" (IANA, default America/Sao_Paulo) and "guests" (up to 50 e-mails or ids of people in the conversation): tracker creates the event in the caller's Google Calendar, with the Meet room, Google sends the invite to the guests and meeting also has guests (how many were invited). Scheduling requires the Google account to have allowed calendar access; whoever connected before that gets 422 with the link to connect again. GET /apps/google_meet/meetings (tracker:read) returns meetings, the meetings with Meet in the next 14 days of the token's person's calendar: title, url, code, starts_at, ends_at and calendar_url. In a direct conversation, POST /chat/direct/{person}/meet with {"title": "..."} (no thread), with the app on in the conversation. App off in the channel or conversation, or without chat:direct: 403; without the account connected: 422, with the link to connect. The message has card: type meeting, provider google_meet, url, code, title, started_by (the caller's name) and, when scheduled, starts_at, ends_at and event_id (the event in the scheduler's Google Calendar), plus meeting_responses (when scheduled: yes, maybe, no, how many replied through tracker, and mine, the token person's reply; null otherwise). On screen, the camera button next to the field (Start now, Schedule meeting… and Upcoming meetings), /meet subject or /meet lista. In the MCP: start_meeting (with project or person; with starts_at, it schedules) and list_meetings.
  • Google Calendar (google_calendar, official app): personal. The company installs it and each person uses it with their own Google account (the same Google Meet connection, with calendar access), with no per-channel setting: in the catalog, channels is null. Permissions: calendar:read (required: read the calendar of whoever uses it) and calendar:respond (optional: reply to invitations through tracker). GET /apps/google_calendar/agenda (tracker:read), with ?date=YYYY-MM-DD or ?days=1 (from today; default today) and ?time_zone= (default America/Sao_Paulo), returns date, time_zone, can_respond, reminder_minutes and events: id, title, starts_at, ends_at, all_day, meeting_url (the Meet room), calendar_url and response (yes, maybe, no; pending with no reply; null when the person organized it or isn't invited). GET /apps/google_calendar/settings (tracker:read) returns installed, can_respond, account (configured, connected, email and calendar), connect_url and reminder_minutes; PATCH (tracker:write) with {"reminder_minutes": 15} changes the reminder before each meeting (5, 10, 15 or 30; 0 turns it off). The reminder arrives in the bell and on the phone (notification type meeting, "Meetings", in the preferences; no email) and opens the Meet room. Replying to the invitation (with calendar:respond): POST /projects/{ref}/chat/{id}/response or POST /chat/direct/{pessoa}/{id}/response with {"response": "yes"} (yes, maybe, no) on the card of a meeting scheduled through tracker returns responses; POST /apps/google_calendar/events/{id}/response replies to an agenda event. The reply goes to the Google Calendar of whoever answers and Google notifies the organizer; the organizer doesn't reply (422). Without the app: 403; without the permission to reply: 403; without the account connected with calendar access: 422, with the link to connect. On screen, /agenda (or /agenda amanhã) and the agenda button next to the field show, only to whoever asked, the day's agenda, with Join, Yes/Maybe/No and the reminder; the scheduled meeting card gets Yes, Maybe and No and the count. In the MCP: get_agenda, respond_to_meeting (with message and project or person, or with event_id) and set_meeting_reminder.
  • aqua (aqua, official app, company_wide): on in every channel of the company, with no install and no per-channel switch (PATCH /projects/{ref}/chat/apps/aqua gives 422). An admin turns it off for the company with DELETE /apps/aqua and back on with POST /apps/aqua; it also needs aqua (the AI) on in the company. When on, a message with @aqua (in the main conversation or a thread, on screen, through the API or the MCP) gets aqua's reply in that message's thread. aqua immediately writes "Consultando o projeto…" (an app message, with app aqua) and replaces the text with the answer when it's done, without marking it as edited: whoever reads through the API sees the change on the next read of the thread (GET /projects/{ref}/chat?thread_id=<id>, with the id of the calling message, or its thread_id). It looks things up as the caller, with that person's role in the project, read-only; since the answer is for the whole channel, only the channel's project (tasks, sprints, releases, tests, hours, people and the conversation) and the company's documents count: other projects, the Inbox and direct messages stay out. Each answer counts as one AI use for the caller, with the company's credits; without credits, the answer says when they renew. The caller gets the reply notification (the Comments preference). The calling message's attachments go along with the question: aqua sees screenshots and PDFs and reads text files; for other messages she only sees the file names. The app asks for chat:write, issues:read and ai:use.