VOLAT

Reference

Every MCP tool takes an action argument; REST routes run the same operations with the same key, scopes and rules. Replies are small by default: add verbose: true (REST ?verbose=1) for the full object. Call help with a topic such as issue.finish from inside a tool for the same facts.

REST routes

All under /api/v1, JSON in and out, Authorization: Bearer mk_YOUR_KEY on every call. Writes answer {"ok": "...", "changeset_id": "..."}.

MethodPathOperationParameters
GET/briefingbriefing.todayquery: since
GET/apps/{ref}/resumecontext.appquery: verbose
GET/issuesissue.listquery: app, state_group, status, release, type, limit, cursor, since, fields
POST/issuesissue.createJSON body
GET/issues/fieldsissue.fieldsquery: app, type
GET/issues/{ref}issue.get
PATCH/issues/{ref}issue.updateJSON body
POST/issues/{ref}/startissue.startJSON body
POST/issues/{ref}/finishissue.finishJSON body
POST/issues/{ref}/moveissue.moveJSON body
POST/issues/{ref}/restoreissue.restoreJSON body
GET/issues/{ref}/commentsissue.commentsquery: limit, cursor, since
POST/issues/{ref}/commentsissue.commentJSON body
POST/issues/{ref}/ciissue.ci_resultJSON body
GET/issues/{ref}/relationsissue.relations
POST/issues/{ref}/relationsissue.relateJSON body
DELETE/issues/{ref}/relations/{id}issue.unrelateJSON body
GET/issues/{ref}/attachmentsissue.attachments
POST/issues/{ref}/attachmentsissue.attachJSON body
POST/issues/{ref}/seenissue.seenJSON body
GET/tasksissue.listquery: app, release, type, limit, cursor, since (state_group is fixed to Todo; blocked and locked tickets are left out)
POST/tasks/{ref}/claimissue.startJSON body
POST/tasks/{ref}/progressissue.commentJSON body
POST/tasks/{ref}/finishissue.finishJSON body
GET/releasesrelease.listquery: app, include_shipped
GET/releases/{ref}release.getquery: app
POST/releasesrelease.createJSON body
PATCH/releases/{ref}release.updatequery: app
POST/releases/{ref}/internalrelease.set_internalquery: app
POST/releases/{ref}/placerelease.placequery: app
POST/releases/moderelease.set_modeJSON body
POST/releases/rulesrelease.set_rulesJSON body
GET/releases/{ref}/readinessrelease.readinessquery: app
POST/release-checks/{id}release.tickJSON body
GET/approvalsapproval.list
POST/approvalsapproval.requestJSON body
GET/approvals/{id}approval.get
POST/approvals/{id}/resubmitapproval.resubmitJSON body
POST/checkout/pingcheckout.pingJSON body
GET/docsdocs.listquery: kind, app, issue, q, limit
POST/docsdocs.putJSON body
GET/docs/{id}docs.get
PATCH/docs/{id}docs.putJSON body
DELETE/docs/{id}docs.archiveJSON body
GET/guidelinesguidelines.listquery: app
GET/guidelines/exportguidelines.exportquery: app, format
GET/connecthelp.connect
GET/helphelp.getquery: topic
GET/mirrorissue.mirror_exportquery: app, format (tasks or backlog)
POST/mirrorissue.mirror_syncJSON body
GET/searchsearch.queryquery: q, kinds, app, apps, states, priorities, assignees, authors, labels, releases, created_from, created_to, updated_from, updated_to, archived, sort, limit, cursor (lists are comma separated). Reply: data, next_cursor, complete
GET/search/listsearch.listquery: q (optional), the same filters as /search, sort (created by default, updated, completed), limit, cursor. Pages every match newest first; pass next_cursor back until it is null. sort=created is the full walk; under sort=updated a record edited mid-walk can be missed and the reply says so (changed_since_first_page, complete false). Reply: data, next_cursor, complete
GET/search/changessearch.changesquery: since, limit
GET/activitysearch.activityquery: actor, app, kind, from, to, q, before, limit
GET/undoundo.listquery: limit
POST/undoundo.applyJSON body
POST/metricsusage.metricsJSON body
GET/feedbackfeedback.listquery: app, status, source, reply, limit, with_reviewer
POST/feedbackfeedback.pushJSON body
POST/feedback/{id}/replyfeedback.replyJSON body
POST/feedback/{id}/postedfeedback.postedJSON body

briefing

briefing.today

today: the first call of every session: what changed since your last briefing (ranked by severity), releases by version with scope left and ready-to-ship-early, who holds which ticket, what waits on Yan, can_take (tickets at your level). Pass since (the cursor of an earlier reply) to see only newer changes

Needs issues:read · REST GET /api/v1/briefing

ArgumentTypeNotes
sincestring | integerOnly what changed after this: the cursor value from an earlier reply

issue

issue.list

list: issues as compact rows (key, title, status, assignee, release), filtered by app, state_group or status, release or type, paged by cursor (limit up to 100, pass next_cursor back until it is gone); fields adds named fields; since returns only issues changed after an earlier reply's cursor (and removed: archived since)

Needs issues:read · REST GET /api/v1/issues, GET /api/v1/tasks

ArgumentTypeNotes
appstringApp key like KID, or its uuid
state_group"triage" | "backlog" | "unstarted" | "started" | "review" | "completed" | "cancelled"Status column
statusstringA status as the rows show it (In Progress) or its group (started)
releasestringRelease version like 11.4 (in the issue's app), or its uuid
type"bug" | "feature" | "chore" | "idea"
limitintegerPage size, 1 to 100 (default 50)
cursorstringnext_cursor from the previous page
sincestring | integerOnly what changed after this: the cursor value from an earlier reply
include"archived"Also list archived tickets
fields"id" | "app" | "state_group" | "priority" | "type" | "severity" | "change_risk" | "difficulty" | "must_have" | "blocked" | "size" | "description" | "done_means" | "custom" | "delegate" | "holder" | "labels" | "source" | "created_at" | "updated_at"[]Extra fields per row: id, app, state_group, priority, type, severity, change_risk, difficulty, must_have, blocked, size, description, done_means, custom, delegate, holder, labels, source, created_at, updated_at
waitingtrueOnly tickets that need Yan, with what is needed

issue.get

get: one issue with its state, release, done means and lock

Needs issues:read · REST GET /api/v1/issues/{ref}

ArgumentTypeNotes
issue requiredstringIssue identifier like KID-4, or its uuid

issue.create

create: a new issue in an app (lands in Triage unless state_group says otherwise); call issue.fields first: the type's template fills description and done_means, and required custom fields must be sent in custom

Needs issues:write · REST POST /api/v1/issues

ArgumentTypeNotes
app requiredstringApp key like KID, or its uuid
title requiredstring
descriptionstring
priorityinteger0 none, 1 urgent, 2 high, 3 medium, 4 low
risk_tier"low" | "medium" | "high"Change risk (old name risk_tier): how risky the change is for an agent; high always routes through approvals
change_risk"low" | "medium" | "high"How risky the change is for an agent; high always routes through approvals. Same field as risk_tier
state_group"triage" | "backlog" | "unstarted" | "started" | "review" | "completed" | "cancelled"Status column
releasestringRelease version like 11.4 (in the issue's app), or its uuid
done_meansstring[]Acceptance checks: what "done" means for this ticket
type"bug" | "feature" | "chore" | "idea"bug, feature or chore (ideas: idea.create)
severity"crash" | "broken" | "degraded" | "cosmetic" | nullBugs only: crash, broken, degraded or cosmetic
source"person" | "agent" | "crash_report" | "app_store_review" | "support_email" | "monitor" | "import"Where it came from
reporterstring | nullWho reported it (a name or handle, not an email)
external_urlstring | nullLink to the crash, review or email thread
affected_versionstring | null
platformstring | nullOS or platform, e.g. iOS 18.1
devicestring | null
repro_stepsstring | nullSteps to reproduce (bugs)
review_stepsstring | nullSteps a reviewer should try, one per line
blockedboolean
blocked_reasonstring | null
snooze_untilstring | null
must_havebooleanMust ship in its release; release readiness counts only must-haves
size"S" | "M" | "L" | nullS, M or L
first_seen_atstring | null
last_seen_atstring | null
occurrence_countinteger
difficultystringMSH-208: easy, medium or hard: the agent level it needs. Agents may raise it, never lower it; new tickets get a suggestion
customobjectMSH-145 custom field values by key, e.g. {"customer_impact": "Many users"}. issue.fields lists the fields for an app and type, their kinds, choices and which are required. Select: one of the options; multi select: a list; checkbox: true/false; member: a member id; version: a release version of the issue's app. On update, null clears a value
no_codebooleantrue marks the ticket no-code: no PR or branch link needed for review or Done. Needs reason
reasonstringWith no_code: true, at least 20 characters: why this ticket has no code change
templatestringTemplate id or name from issue.fields; without one the default template for the type fills description and done_means; "none" for no template

issue.update

update: title, description, priority, change_risk (or risk_tier), done_means, custom (field values by key), type, severity, source, reporter, external_url, affected_version, platform, device, repro_steps, review_steps, blocked, blocked_reason, snooze_until, must_have, size, first/last_seen_at, occurrence_count, waiting_on_yan and release_note (null clears), no_code with reason. Needs the ticket's lock, except a patch of only description and/or done_means, which needs no lock and never changes the state

Needs issues:write · REST PATCH /api/v1/issues/{ref}

ArgumentTypeNotes
issue requiredstringIssue identifier like KID-4, or its uuid
titlestring
descriptionstring | null
priorityinteger0 none, 1 urgent, 2 high, 3 medium, 4 low
risk_tier"low" | "medium" | "high"Change risk (old name risk_tier): how risky the change is for an agent; high always routes through approvals
change_risk"low" | "medium" | "high"How risky the change is for an agent; high always routes through approvals. Same field as risk_tier
done_meansstring[]Acceptance checks: what "done" means for this ticket
type"bug" | "feature" | "chore" | "idea"bug, feature or chore (ideas: idea.create)
severity"crash" | "broken" | "degraded" | "cosmetic" | nullBugs only: crash, broken, degraded or cosmetic
source"person" | "agent" | "crash_report" | "app_store_review" | "support_email" | "monitor" | "import"Where it came from
reporterstring | nullWho reported it (a name or handle, not an email)
external_urlstring | nullLink to the crash, review or email thread
affected_versionstring | null
platformstring | nullOS or platform, e.g. iOS 18.1
devicestring | null
repro_stepsstring | nullSteps to reproduce (bugs)
review_stepsstring | nullSteps a reviewer should try, one per line
blockedboolean
blocked_reasonstring | null
snooze_untilstring | null
must_havebooleanMust ship in its release; release readiness counts only must-haves
size"S" | "M" | "L" | nullS, M or L
first_seen_atstring | null
last_seen_atstring | null
occurrence_countinteger
difficultystringMSH-208: easy, medium or hard: the agent level it needs. Agents may raise it, never lower it; new tickets get a suggestion
waiting_on_yanstring | nullWhat Yan must do; null clears
release_notestring | nullRelease notes line; null clears
customobjectMSH-145 custom field values by key, e.g. {"customer_impact": "Many users"}. issue.fields lists the fields for an app and type, their kinds, choices and which are required. Select: one of the options; multi select: a list; checkbox: true/false; member: a member id; version: a release version of the issue's app. On update, null clears a value
no_codebooleantrue marks the ticket no-code: no PR or branch link needed for review or Done. Needs reason
reasonstringWith no_code: true, at least 20 characters: why this ticket has no code change

issue.fields

fields: the custom fields (kind, choices, required, help) and templates for an app and issue type, so create and update fill them correctly

Needs issues:read · REST GET /api/v1/issues/fields

ArgumentTypeNotes
app requiredstringApp key like KID, or its uuid
type"bug" | "feature" | "chore" | "idea"bug, feature or chore (ideas: idea.create)

issue.move

move: to a status column (state_group) and/or a release; started plus reason on a ticket in review sends it back (needs comments:write); review and Done need a run receipt and a PR or branch link (or no_code with a reason), frozen releases and high-risk work need Yan's approval; the reply gives `state` and `held`, and a held move names the approval it waits on

Needs issues:write · REST POST /api/v1/issues/{ref}/move

ArgumentTypeNotes
issue requiredstringIssue identifier like KID-4, or its uuid
state_group"triage" | "backlog" | "unstarted" | "started" | "review" | "completed" | "cancelled"Status column
releasestring | nullRelease version or uuid; null takes the issue out of every release
cancel_reason"merged" | "duplicate" | "not_needed" | "cut_from_scope"Needed to cancel
ofstringTicket merged into or duplicated
no_codebooleantrue marks the ticket no-code: no PR or branch link needed for review or Done. Needs reason
reasonstringWith no_code: why. With state_group started on a ticket in review: sends it back, kept as a comment

issue.comments

comments: list an issue's comments, oldest first; since returns only comments after an earlier reply's cursor

Needs comments:read · REST GET /api/v1/issues/{ref}/comments

ArgumentTypeNotes
issue requiredstringIssue identifier like KID-4, or its uuid
limitintegerPage size, 1 to 100 (default 50)
cursorstringnext_cursor from the previous page
sincestring | integerOnly what changed after this: the cursor value from an earlier reply

issue.comment

comment: add a comment to an issue

Needs comments:write · REST POST /api/v1/issues/{ref}/comments, POST /api/v1/tasks/{ref}/progress

ArgumentTypeNotes
issue requiredstringIssue identifier like KID-4, or its uuid
body requiredstring

issue.ci_result

ci_result: record a CI run (commit, result pass|fail, flakes, log path); Done needs a pass on the merged commit

Needs comments:write · REST only, not in MCP · REST POST /api/v1/issues/{ref}/ci

ArgumentTypeNotes
issue requiredstringIssue identifier like KID-4, or its uuid
commit requiredstring
result required"pass" | "fail"
flakes requiredinteger
log requiredstring

issue.receipt

receipt: submit the run receipt (files_changed, risks, verified [{what, how}], decisions, next_step, done_means [{item, met, evidence}], head_sha of the commit it covers); needed before review and for the Mishka approval merge check

Needs issues:write · MCP only

ArgumentTypeNotes
issue requiredstringIssue identifier like KID-4, or its uuid
session_idstring
files_changed requiredstring[]Paths of files changed
risksstring[]Open risks, or an empty list
verified requiredobject[]What was verified and how (tests, screenshots, manual steps)
decisionsstring[]
next_step requiredstring
head_shastringThe commit this receipt covers (git rev-parse HEAD). The merge check needs a receipt for the PR's head commit
done_meansobject[]One answer per done-means item: item text or number, met, evidence

issue.review

review: record your pass or fail on one commit of someone else's ticket (head_sha is the full commit; you cannot review a ticket you filed a receipt on); a pass on the commit being merged lets Yan's high-risk rule decide without a click

Needs issues:write · MCP only

ArgumentTypeNotes
issue requiredstringIssue identifier like KID-4, or its uuid
head_sha requiredstringThe full commit you reviewed (git rev-parse HEAD)
verdict required"pass" | "fail"
summary requiredstringWhat you checked and what you found

issue.receipts

receipts: the run receipts on an issue, newest first

Needs issues:read · MCP only

ArgumentTypeNotes
issue requiredstringIssue identifier like KID-4, or its uuid

issue.scan

scan: record a scanner's findings for a commit: tool, head_sha (the commit), findings [{severity high|medium|low, path, line, rule, link}], [] if none. VOLAT runs no scanner. An open high finding blocks approving that commit

Needs issues:write · MCP only

ArgumentTypeNotes
issue requiredstringIssue identifier like KID-4, or its uuid
tool requiredstring
head_sha requiredstring
findings requiredany

issue.restore

restore: take a ticket out of the archive (canceled goes to Backlog)

Needs issues:write · REST POST /api/v1/issues/{ref}/restore

ArgumentTypeNotes
issue requiredstringIssue identifier like KID-4, or its uuid

issue.archive_closed

archive_closed: owner only; archive all due closed tickets (state_group limits it)

Needs issues:write · MCP only

ArgumentTypeNotes
state_group"completed" | "cancelled"

issue.archive

archive: soft-delete a ticket you hold; more than one ticket becomes an approval for Yan

Needs issues:write · destructive · MCP only

ArgumentTypeNotes
issues requiredstring[]Identifiers to archive

issue.code_status

code_status: report branch/PR state on a ticket you hold (repo, branch, pr_number, pr_url, preview_url, pr_state, check_state, mergeable); omit to read

Needs issues:read · MCP only

ArgumentTypeNotes
issue requiredstringIssue identifier like KID-4, or its uuid
repostringowner/name
branchstring
pr_numberinteger
pr_urlstring
preview_urlany
pr_state"open" | "merged" | "closed"
check_state"none" | "pending" | "success" | "failure" | "neutral" | "cancelled"
mergeable"clean" | "conflicting" | "unknown"
head_shastring

issue.relations

relations: what this issue blocks, is blocked by, duplicates or relates to

Needs issues:read · REST GET /api/v1/issues/{ref}/relations

ArgumentTypeNotes
issue requiredstringIssue identifier like KID-4, or its uuid

issue.relate

relate: link to another issue (kind blocks, blocked_by, duplicate_of, related_to); duplicate_of also moves this one to Canceled

Needs issues:write · REST POST /api/v1/issues/{ref}/relations

ArgumentTypeNotes
issue requiredstringIssue identifier like KID-4, or its uuid
kind required"blocks" | "blocked_by" | "duplicate_of" | "related_to"
other requiredstringThe other issue, e.g. KID-7

issue.unrelate

unrelate: remove a relation by its id (from issue.relations)

Needs issues:write · REST DELETE /api/v1/issues/{ref}/relations/{id}

ArgumentTypeNotes
issue requiredstringIssue identifier like KID-4, or its uuid
relation_id requiredstring

issue.seen

seen: intake saw this issue again (a matching crash or review): bumps occurrence_count and last_seen_at instead of filing a duplicate

Needs issues:write · REST POST /api/v1/issues/{ref}/seen

ArgumentTypeNotes
issue requiredstringIssue identifier like KID-4, or its uuid
atstring
countinteger

issue.attachments

attachments: list an issue's screenshots and logs (metadata)

Needs issues:read · REST GET /api/v1/issues/{ref}/attachments

ArgumentTypeNotes
issue requiredstringIssue identifier like KID-4, or its uuid

issue.attach

attach: add a screenshot or log to a ticket you hold (file_name, content_type image/png|image/jpeg|image/gif|image/webp|text/plain|text/csv|application/json|application/pdf|application/zip|application/x-ndjson, content_base64; 10 MB at most)

Needs issues:write · REST POST /api/v1/issues/{ref}/attachments

ArgumentTypeNotes
issue requiredstringIssue identifier like KID-4, or its uuid
file_name requiredstring
content_type required"image/png" | "image/jpeg" | "image/gif" | "image/webp" | "text/plain" | "text/csv" | "application/json" | "application/pdf" | "application/zip" | "application/x-ndjson"
content_base64 requiredstringThe file, base64-encoded

issue.start

start: one call to begin a ticket: takes the lock (checkout.take), starts a session (pass machine and branch) and returns the context pack (context.ticket) with any handoff note

Needs issues:write · REST POST /api/v1/issues/{ref}/start, POST /api/v1/tasks/{ref}/claim

ArgumentTypeNotes
issue requiredstringIssue identifier like KID-4, or its uuid
machinestringThe machine this agent runs on, e.g. mac-mini
branchstringYour git branch
toolstringclaude-code, codex, cursor...

issue.finish

finish: one call to hand a ticket over: files the run receipt (the receipt fields), adds comment, reports the link (repo, branch, pr_url) or no_code: true with a reason, moves it (state_group review by default; completed closes it in this one call when every done_means item is answered met with evidence) and ends your session. The reply gives `state` and `held`; a held finish names the approval it waits on. One refusal lists everything missing; extra done_means items on a ticket with none are kept as notes

Needs issues:write · REST POST /api/v1/issues/{ref}/finish, POST /api/v1/tasks/{ref}/finish

ArgumentTypeNotes
issue requiredstringIssue identifier like KID-4, or its uuid
state_group"triage" | "backlog" | "unstarted" | "started" | "review" | "completed" | "cancelled"Status column
cancel_reason"merged" | "duplicate" | "not_needed" | "cut_from_scope"
ofstringIssue identifier like KID-4, or its uuid
no_codebooleantrue marks the ticket no-code: no PR or branch link needed for review or Done. Needs reason
reasonstringWith no_code: true, at least 20 characters: why this ticket has no code change
repostringowner/name; with branch, reports the code link
branchstring
pr_urlstring
commentstringA comment to add, e.g. what changed and the PR link
summarystringSession summary (defaults to comment)
session_idstring
files_changedstring[]Paths of files changed
risksstring[]Open risks, or an empty list
verifiedobject[]What was verified and how (tests, screenshots, manual steps)
decisionsstring[]
next_stepstring
head_shastringThe commit this receipt covers (git rev-parse HEAD). The merge check needs a receipt for the PR's head commit
done_meansobject[]One answer per done-means item: item text or number, met, evidence

issue.mirror_export

mirror_export: an app's tickets as Markdown files (tasks/KID.md or backlog/tasks/*.md) with stable ids; you write them into the repo

Needs issues:read · REST only, not in MCP · REST GET /api/v1/mirror

ArgumentTypeNotes
appstringApp key like KID, or its uuid
format"tasks" | "backlog"tasks: one tasks/KID.md checklist (default); backlog: one Backlog.md-style file per ticket

issue.mirror_sync

mirror_sync: send the edited mirror files back; preview by default, apply: true writes status ticks, title edits and new tasks in one changeset (Undo), and refuses on conflicts

Needs issues:write · REST only, not in MCP · REST POST /api/v1/mirror

ArgumentTypeNotes
appstringApp key like KID, or its uuid
format"tasks" | "backlog"tasks: one tasks/KID.md checklist (default); backlog: one Backlog.md-style file per ticket
files requiredobject[]The mirror files as they are now in the repo: [{ path, content }]
applybooleantrue writes the changes; without it the reply is a preview

checkout

checkout.take

take: lock a ticket before working on it (one ticket, one agent); returns the previous holder's handoff note

Needs issues:write · MCP only

ArgumentTypeNotes
issue requiredstringIssue identifier like KID-4, or its uuid

checkout.ping

ping: keep your locks alive during long builds or test runs (for coding-tool hooks); any other call also renews them

Needs issues:read · REST POST /api/v1/checkout/ping

ArgumentTypeNotes
issuestringIssue identifier like KID-4, or its uuid

checkout.release

release: let go of a ticket with a handoff note (what was done, next step, open questions)

Needs issues:write · destructive · MCP only

ArgumentTypeNotes
issue requiredstringIssue identifier like KID-4, or its uuid
notestringHandoff note for whoever picks this up next
donestringWhat was done
next_stepstringThe next step
open_questionsstringOpen questions for Yan or the next agent

checkout.pause

pause: stop with a note and release the lock; reason limit_hit (tool reported its plan used up) also offers the ticket to another tool

Needs issues:write · destructive · MCP only

ArgumentTypeNotes
issue requiredstringIssue identifier like KID-4, or its uuid
reason"paused" | "limit_hit"
notestringHandoff note for whoever picks this up next
donestringWhat was done
next_stepstringThe next step
open_questionsstringOpen questions for Yan or the next agent

checkout.resume

resume: take a paused or handed-off ticket and get the note it was left with

Needs issues:write · MCP only

ArgumentTypeNotes
issue requiredstringIssue identifier like KID-4, or its uuid

checkout.mine

mine: the tickets you hold and when each lock expires

Needs issues:read · MCP only

No arguments.

checkout.available

available: tickets offered to another tool (limit hit) and locks that went stale

Needs issues:read · MCP only

No arguments.

context

context.ticket

ticket: everything for one ticket: description, done means, release, linked docs, guidelines, related tickets, comments, receipts, sessions, approvals

Needs issues:read · MCP only

ArgumentTypeNotes
issue requiredstringIssue identifier like KID-4, or its uuid

context.app

app: one app's resume card: why it exists, state, last change, next step, open risks; revive/park/archive if stale

Needs issues:read · REST GET /api/v1/apps/{ref}/resume

ArgumentTypeNotes
app requiredstringApp key like KID, or its uuid

guidelines

guidelines.list

list: the rules every agent follows: first the switches (id "switches", from Settings > Agent rules), then the written rules (workspace-wide, plus the app's own when app is given); read before starting work. Reading them acknowledges the current rules_version

Needs docs:read · REST GET /api/v1/guidelines

ArgumentTypeNotes
appstringApp key like KID, or its uuid

guidelines.get

get: one guideline by id

Needs docs:read · MCP only

ArgumentTypeNotes
id requiredstring

guidelines.export

export: rules as AGENTS.md text for any agent (default), or format claude (CLAUDE.md), both, or skill (a Claude Code SKILL.md); you write the files in your PR

Needs docs:read · REST GET /api/v1/guidelines/export

ArgumentTypeNotes
appstringApp key like KID, or its uuid
formatstring
urlstring

guidelines.put

put: add or update a guideline (needs docs:admin)

Needs docs:admin · MCP only

ArgumentTypeNotes
idstring
title requiredstring
content requiredstring
appstring | null

session

session.start

start: begin a session on a ticket you hold; returns the last pause note on that ticket if there is one

Needs sessions:write · MCP only

ArgumentTypeNotes
issue requiredstringIssue identifier like KID-4, or its uuid
toolstringclaude-code, codex, cursor...
titlestring
machinestringThe machine this agent runs on, e.g. mac-mini (names the instance: tool · machine · branch)
branchstringGit branch, e.g. msh-12-rate-limits
pr_urlstringPull request URL (https)
pr_numberinteger

session.log

log: record a step (kind plan, action, question, result, error); a question waits for Yan's answer

Needs sessions:write · MCP only

ArgumentTypeNotes
session_id requiredstringThe session id from session.start
kind required"plan" | "action" | "question" | "result" | "error"
body requiredstring

session.pause

pause: stop with a handoff note and release the ticket; reason limit_hit offers it to another tool

Needs sessions:write · destructive · MCP only

ArgumentTypeNotes
session_id requiredstringThe session id from session.start
reason"paused" | "limit_hit"
notestring
donestring
next_stepstring
open_questionsstring

session.resume

resume: pick up a paused session (yours or another tool's) from its note; takes the ticket and starts a new session

Needs sessions:write · MCP only

ArgumentTypeNotes
session_idstringThe session id from session.start
issuestringIssue identifier like KID-4, or its uuid

session.finish

finish: end the session as done or error, with a summary and the branch/PR

Needs sessions:write · MCP only

ArgumentTypeNotes
session_id requiredstringThe session id from session.start
status"done" | "error"
summarystring
branchstringGit branch, e.g. msh-12-rate-limits
pr_urlstringPull request URL (https)
pr_numberinteger

session.get

get: one session with all its steps

Needs sessions:read · MCP only

ArgumentTypeNotes
session_id requiredstringThe session id from session.start

session.list

list: sessions, by issue, status or only yours

Needs sessions:read · MCP only

ArgumentTypeNotes
issuestringIssue identifier like KID-4, or its uuid
status"active" | "waiting_for_input" | "paused" | "error" | "done"
mineboolean

session.waiting

waiting: sessions waiting for Yan's answer (Needs-you)

Needs sessions:read · MCP only

No arguments.

release

release.list

list: open releases per app, oldest version first, with open/done counts, checklist counts and ready_to_ship

Needs releases:read · REST GET /api/v1/releases

ArgumentTypeNotes
appstringApp key like KID, or its uuid
include_shippedboolean

release.get

get: one release by uuid, or by version with app

Needs releases:read · REST GET /api/v1/releases/{ref}

ArgumentTypeNotes
release requiredstringRelease version like 11.4 (in the issue's app), or its uuid
appstringApp key like KID, or its uuid

release.readiness

readiness: a release's pre-release checklist (full item ids; who: agent or person for each, so you know before ticking), open must-haves, and what still blocks shipping

Needs releases:read · REST GET /api/v1/releases/{ref}/readiness

ArgumentTypeNotes
release requiredstringRelease version like 11.4 (in the issue's app), or its uuid
appstringApp key like KID, or its uuid

release.tick

tick: tick (done true, the default) or untick a checklist item by its id from readiness, with an optional note as evidence ("build 412 from 3f9c2e1"). On a person-only item (who: person) the note is saved for Yan, who ticks from it; shipping is Yan's alone

Needs releases:write · REST POST /api/v1/release-checks/{id}

ArgumentTypeNotes
item requiredstringChecklist item id from release.readiness
donebooleantrue ticks (default), false unticks
notestring | nullEvidence or a reason; null clears it

release.create

create: a release for an app, with its default checklist (version; kind planned, hotfix or website; name; target_date)

Needs releases:write · REST POST /api/v1/releases

ArgumentTypeNotes
app requiredstringApp key like KID, or its uuid
version requiredstring
kind"planned" | "hotfix" | "website"
namestring | null
target_datestring | nullDate like 2026-11-07

release.update

update: change a release's version, frozen (true freezes; only people unfreeze), stage (not shipped; that is Yan's), target_date or note

Needs releases:write · REST PATCH /api/v1/releases/{ref}

ArgumentTypeNotes
release requiredstringRelease version like 11.4 (in the issue's app), or its uuid
appstringApp key like KID, or its uuid
versionstring
frozenboolean
stage"planned" | "building" | "testing" | "submitted" | "cancelled"
target_datestring | null
notestring | null
internal_onlyboolean

release.set_internal

set_internal: internal_only true marks an internal build (tracked, never shipped or announced as public), false clears it (people only)

Needs releases:write · REST POST /api/v1/releases/{ref}/internal

ArgumentTypeNotes
release requiredstringRelease version like 11.4 (in the issue's app), or its uuid
appstringApp key like KID, or its uuid
internal_only requiredboolean

release.place

place: move a release in the ships-next order, to index (0 ships first) or one step up or down (not for a key limited to one app)

Needs releases:write · REST POST /api/v1/releases/{ref}/place

ArgumentTypeNotes
release requiredstringRelease version like 11.4 (in the issue's app), or its uuid
appstringApp key like KID, or its uuid
indexinteger
direction"up" | "down"

release.set_mode

set_mode: planning mode (versions, dates or combined) for one app (null follows the workspace); the whole workspace needs releases:admin

Needs releases:write · REST POST /api/v1/releases/mode

ArgumentTypeNotes
mode required"versions" | "dates" | "combined" | null
appstringApp key like KID, or its uuid

release.set_rules

set_rules: the workspace release calendar rules; send all seven (needs releases:admin)

Needs releases:admin · REST POST /api/v1/releases/rules

ArgumentTypeNotes
maxCutoffsPerWeek requiredinteger
freezeDays requiredinteger
holidayFreeze requiredboolean
holidayStart requiredstringMonth and day like 12-19
holidayEnd requiredstring
exemptWebsites requiredboolean
exemptHotfixes requiredboolean

release.close_tickets

close_tickets: close several tickets to Done in one call (issues: keys, reason: the comment on each), each under issue.finish's gate; the reply says per key what closed and what was refused and why

Needs issues:write · MCP only

ArgumentTypeNotes
issues requiredstring[]Keys of the tickets to close, e.g. ["FAM-140", "FAM-142"]
reason requiredstringWhy they close; added as a comment on each

approval

approval.request

request: ask Yan before merge_pr, deploy_production, send_external_message, publish_release_notes, rotate_or_create_key, change_agent_permissions; returns a pending approval (moves into frozen releases, high-risk moves and bulk archives become approvals on their own)

Needs approvals:write · REST POST /api/v1/approvals

ArgumentTypeNotes
type required"merge_pr" | "deploy_production" | "send_external_message" | "publish_release_notes" | "rotate_or_create_key" | "change_agent_permissions"
title requiredstringWhat you want approved, in one line
reasonstring
issuestringIssue identifier like KID-4, or its uuid
detailsobjectExternal actions: PR URL, environment, recipient, text...
scopesstring[]Keys: the scopes you need, e.g. issues:write
appstring | nullKeys: limit to one app (key or uuid), or null for all
key_idstringKeys: your key to rotate or change

approval.get

get: one approval, its status and agent_hint (what to do now; a send-back note is in it). An expired approval is refused with approval_expired

Needs approvals:read · REST GET /api/v1/approvals/{id}

ArgumentTypeNotes
approval_id requiredstringThe approval id

approval.list

list: approvals, by status, issue or only yours

Needs approvals:read · REST GET /api/v1/approvals

ArgumentTypeNotes
status"pending" | "revision_requested" | "approved" | "rejected" | "expired"
mineboolean
issuestringIssue identifier like KID-4, or its uuid

approval.resubmit

resubmit: after Yan asks for a revision, send it back with a note saying what changed

Needs approvals:write · REST POST /api/v1/approvals/{id}/resubmit

ArgumentTypeNotes
approval_id requiredstringThe approval id
note requiredstring
detailsobject

idea

idea.get

get: one idea with its research, comments and links

Needs ideas:read · MCP only

ArgumentTypeNotes
id requiredstring

idea.create

create: capture an idea (title is enough); items[] captures several

Needs ideas:write · MCP only

ArgumentTypeNotes
itemsobject[]
titlestring
descriptionstring
appstringApp key like KID, or its uuid
type"improvement" | "new_app" | "new_website" | "other"
keystringFresh random id per idea; send the same one when retrying

idea.update

update: edit title, description, app or type; send the revision you read

Needs ideas:write · MCP only

ArgumentTypeNotes
id requiredstring
revision requiredintegerFrom idea.get; a stale one is refused
titlestring
descriptionstring | null
appstring | null
type"improvement" | "new_app" | "new_website" | "other"
original_textstringRefused: the author's words never change

idea.research_add

research_add: add a research entry (a finding, never an edit to the idea)

Needs ideas:write · MCP only

ArgumentTypeNotes
id requiredstringThe idea
title requiredstring
bodystring
sourcesstring[]

idea.research_edit

research_edit: change a research entry you wrote

Needs ideas:write · MCP only

ArgumentTypeNotes
id requiredstringThe research entry
titlestring
bodystring
sourcesstring[]

idea.comment

comment: add a comment under a research entry

Needs ideas:write · MCP only

ArgumentTypeNotes
id requiredstringThe research entry
body requiredstring

idea.similar

similar: find ideas that may say the same thing

Needs ideas:read · MCP only

ArgumentTypeNotes
q requiredstring
idstring

undo

undo.list

list: your own recent changes that can still be undone (VOLAT data only)

Needs issues:read · REST GET /api/v1/undo

ArgumentTypeNotes
limitinteger

undo.apply

apply: undo one of your own changes by changeset_id; refused if later work touched the same fields or it would re-enter a frozen release

Needs issues:write · destructive · REST POST /api/v1/undo

ArgumentTypeNotes
changeset_id requiredstringFrom undo.list, or the changeset_id a write returned

usage

usage.report

report: spend for this run: input_tokens/output_tokens and/or plan_usage_pct with plan_window (5h, weekly, monthly); idempotency_key makes retries safe

Needs usage:write · MCP only

ArgumentTypeNotes
idempotency_key requiredstringA fresh UUID per report; resend the same one when retrying
toolstring
modelstring
input_tokensinteger
output_tokensinteger
plan_usage_pctnumber
plan_window"5h" | "weekly" | "monthly"
resets_atstringWhen that plan window resets (ISO time); alerts at 90% and at reset
issuestringIssue identifier like KID-4, or its uuid
session_idstring
notestring

usage.limits

limits: this key's scopes, rate limit, writes left today, open flags, today's spend and every agent's plan headroom

Needs usage:read · MCP only

No arguments.

usage.metrics

metrics: push readings per app (mrr, users, crashes, app_store_status), up to 100 at once; a repeated app + metric + as_of is stored once, so retries are safe

Needs metrics:write · REST only, not in MCP · REST POST /api/v1/metrics

ArgumentTypeNotes
metrics requiredobject[]Readings, 1 to 100

docs

docs.list

list: docs as titles and excerpts, newest first; filter by kind (doc, decision, guideline), app, issue or q (text match). kind=guideline lists the agent rules; kind=decision is the decisions log

Needs docs:read · REST GET /api/v1/docs

ArgumentTypeNotes
kind"doc" | "decision" | "guideline"doc (a page), decision (the decisions log) or guideline (agent rules)
appstringApp key like KID, or its uuid
issuestringIssue identifier like KID-4, or its uuid
qstringMatches the title or the text
limitinteger

docs.get

get: one doc with its full markdown text, app, linked ticket, decision status and version (the text version; pass it back as if_version). section gives that section's text only

Needs docs:read · REST GET /api/v1/docs/{id}

ArgumentTypeNotes
id requiredstring
sectionstringHeading text without the #s, e.g. "Plan"; "" is the text before the first heading
occurrenceintegerWhich one when the heading repeats; 1 is the first

docs.versions

versions: the doc's text versions, newest first (at most 50), with when and who

Needs docs:read · MCP only

ArgumentTypeNotes
id requiredstring
limitinteger

docs.version

version: the doc's full text as it was at a version (from docs.versions)

Needs docs:read · MCP only

ArgumentTypeNotes
id requiredstring
version requiredinteger

docs.put

put: add a doc (no id) or change one (id; only the fields you pass). Link it to an app or a ticket (a ticket implies its app). Decisions take decision_status and decided_on. Agent rules (kind guideline) need docs:admin

Needs docs:write · REST POST /api/v1/docs, PATCH /api/v1/docs/{id}

ArgumentTypeNotes
idstring
kind"doc" | "decision" | "guideline"doc (a page), decision (the decisions log) or guideline (agent rules)
titlestring
contentstringMarkdown. Raw HTML is shown as text
appstring | nullApp key or uuid; null makes it workspace-wide
issuestring | nullTicket like KID-4; null unlinks
decision_status"proposed" | "accepted" | "superseded" | "rejected"
decided_onstring | nullYYYY-MM-DD
if_versionintegerThe version you read; the save is refused (conflict) if the text changed since

docs.section_put

section_put: replace one section (its heading line through the line before the next heading) with content, heading included. Saved when that section is unchanged since if_version, even if others edited the rest; refused (conflict) otherwise

Needs docs:write · MCP only

ArgumentTypeNotes
id requiredstring
if_version requiredintegerThe version you read (docs.get gives it)
section requiredstringHeading text without the #s, e.g. "Plan"; "" is the text before the first heading
occurrenceintegerWhich one when the heading repeats; 1 is the first
content requiredstringThe new section in markdown, heading line included

docs.archive

archive: move a doc to the trash (a person can restore it from Settings › Trash)

Needs docs:write · destructive · REST DELETE /api/v1/docs/{id}

ArgumentTypeNotes
id requiredstring

help

help.get

get: how a session goes, a tool's actions, or one action's arguments (topic: issue or issue.finish)

Needs any valid key · REST GET /api/v1/help

ArgumentTypeNotes
topicstringA tool (issue) or tool.action (issue.finish); none for the overview

help.connect

connect: what a new agent is told on connect: how VOLAT works, this key's rules, the REST routes (REST only)

Needs any valid key · REST only, not in MCP · REST GET /api/v1/connect

No arguments.

search.query

query: ranked matches for q (words, "a phrase", or, -not; a ticket key like KID-4 comes first) across tickets, comments, docs, decisions, agent rules, ideas, agent sessions, run receipts, releases and apps; narrow with kinds, app and filters. One row per record, best first, up to 200 results: pass next_cursor back (same arguments) for the next page; changed_since_first_page means the workspace changed since page 1. complete is true only when the results ended on this page, nothing was cut at 200 and not_searched is empty; when it is false and you need every match, use search.list

Needs issues:read · REST GET /api/v1/search

ArgumentTypeNotes
q requiredstringWhat to look for
appstringApp key like KID, or its uuid
kinds"issue" | "comment" | "doc" | "decision" | "guideline" | "idea" | "session" | "receipt" | "release" | "app"[]Only these kinds
filtersanyNarrow by any of: apps (keys or ids; their rows plus workspace docs and ideas), states (status groups: triage, backlog, unstarted, started, review, completed, cancelled), priorities (0 to 4), assignees, authors, labels, releases (ids), types (bug, feature, chore), changed_by (who last changed it), created, updated, completed and content_changed ({from, to} ISO dates; from is included, to is not), archived (include, exclude or only)
sortstringrelevance, updated, created, completed: best first, or newest first by that date (completed lists only finished work)
limitinteger1 to 50 (default 20)
cursorstringnext_cursor from the previous page

search.list

list: every match page by page, newest first by created (default), updated or completed; q is optional (without it, everything the filters allow); same filters as query; pass next_cursor back (same arguments) until it is gone; sort=created is the full walk; under sort=updated a record edited mid-walk can be missed and the reply says so (changed_since_first_page, complete false); complete is true only on the last page when not_searched is empty

Needs issues:read · REST GET /api/v1/search/list

ArgumentTypeNotes
qstringWhat to look for
appstringApp key like KID, or its uuid
kinds"issue" | "comment" | "doc" | "decision" | "guideline" | "idea" | "session" | "receipt" | "release" | "app"[]Only these kinds
filtersanyNarrow by any of: apps (keys or ids; their rows plus workspace docs and ideas), states (status groups: triage, backlog, unstarted, started, review, completed, cancelled), priorities (0 to 4), assignees, authors, labels, releases (ids), types (bug, feature, chore), changed_by (who last changed it), created, updated, completed and content_changed ({from, to} ISO dates; from is included, to is not), archived (include, exclude or only)
sortstringrelevance, updated, created, completed: best first, or newest first by that date (completed lists only finished work)
limitinteger1 to 50 (default 20)
cursorstringnext_cursor from the previous page

search.changes

changes: what changed since a cursor, across tickets, comments, docs, ideas, sessions and receipts; since is the cursor from an earlier reply (without it the reply is only the cursor); events: created, updated (other fields), content_changed (title or text), moved (status), archived (restorable), restored, deleted (gone for good); more = ask again

Needs issues:read · REST GET /api/v1/search/changes

ArgumentTypeNotes
sincestring | integerOnly what changed after this: the cursor value from an earlier reply
limitintegerPage size, 1 to 100 (default 50)

search.activity

activity: what happened in the workspace, newest first, one line per burst; filter by actor (name), app, kind (tickets, releases, docs, approvals), from/to (YYYY-MM-DD) and q; older with before = next_cursor

Needs issues:read · REST GET /api/v1/activity

ArgumentTypeNotes
actorstringPerson or agent name, e.g. Claude
appstringApp key like KID, or its uuid
ticketstringHistory of one ticket, e.g. KID-4
kindstringtickets, releases, docs or approvals
fromstringFirst day, YYYY-MM-DD
tostringLast day, YYYY-MM-DD
qstringText within the log
beforestringnext_cursor from the previous page
limitintegerChanges to read, 1 to 100 (default 30)

feedback

feedback.push

push: store App Store reviews, in-app feedback or emails per app, up to 100 at once; a repeated app + source + source_id is stored once, so retries are safe

Needs feedback:write · REST only, not in MCP · REST POST /api/v1/feedback

ArgumentTypeNotes
items requiredobject[]Feedback items, 1 to 100

feedback.list

list: feedback newest first, by app, status, source or reply state (reply=approved lists replies a person approved and you may post now)

Needs feedback:read · REST only, not in MCP · REST GET /api/v1/feedback

ArgumentTypeNotes
appstringApp key like KID, or its uuid
status"pending" | "snoozed" | "accepted" | "duplicate" | "rejected"
source"app_store_review" | "in_app" | "email"
reply"none" | "pending" | "revision_requested" | "approved" | "posted" | "rejected" | "expired"
limitintegerPage size, 1 to 200 (default 50)
with_reviewerboolean | "0" | "1" | "true" | "false"Include the reviewer handle (personal data); only when you need it

feedback.reply

reply: attach a drafted reply; it becomes a send_external_message approval and nothing is sent until a person approves, then you post it and call posted

Needs feedback:write · REST only, not in MCP · REST POST /api/v1/feedback/{id}/reply

ArgumentTypeNotes
id requiredstringThe feedback item's id
text requiredstringThe reply, at most 4000 characters

feedback.posted

posted: you posted the approved reply yourself (VOLAT never posts); refused unless a person approved that exact text

Needs feedback:write · REST only, not in MCP · REST POST /api/v1/feedback/{id}/posted

ArgumentTypeNotes
id requiredstringThe feedback item's id