flowIQ for developers
flowIQ maps how teams actually work: captures (recorded walkthroughs and interviews) become step-by-step workflows, and multiple captures of the same process get synthesized into one process map. this page documents the hosted mcp server that lets ai agents read and act on that data.
hierarchy: workspace (organization) > teams > processes > captures.
getting started
- sign in at app.simplestuff.ai and open settings > api keys (click your name in the sidebar, then workspace settings).
- create a key. it starts with
fiq_and is shown once - store it somewhere safe. we only keep a hash. - connect an mcp client (below) or call the endpoint directly over json-rpc.
# quickest check: list the tools your key can call
curl -X POST https://app.simplestuff.ai/api/mcp \
-H "Authorization: Bearer fiq_YOUR_KEY" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}'authentication
every request needs an api key, sent as Authorization: Bearer fiq_... or X-API-Key: fiq_.... keys are user-wide: one key works across every workspace you are a member of, and each call can target a workspace via the workspace_id parameter.
- up to 10 active keys per user.
- revoking a key (settings > api keys) disables it immediately.
- keys inherit your permissions - nothing more. a key can never see workspaces you are not a member of.
connect a client
the mcp server lives at https://app.simplestuff.ai/api/mcp (streamable http, stateless - no session handshake required).
claude code
claude mcp add flowiq --transport http https://app.simplestuff.ai/api/mcp \
--header "Authorization: Bearer fiq_YOUR_KEY"claude desktop / other json config clients
{
"mcpServers": {
"flowiq": {
"type": "http",
"url": "https://app.simplestuff.ai/api/mcp",
"headers": {
"Authorization": "Bearer fiq_YOUR_KEY"
}
}
}
}cursor
// .cursor/mcp.json
{
"mcpServers": {
"flowiq": {
"url": "https://app.simplestuff.ai/api/mcp",
"headers": { "Authorization": "Bearer fiq_YOUR_KEY" }
}
}
}how scoping works
keys are user-wide, so the workspace is chosen per call. tools that operate at workspace level take an optional workspace_id:
- omit it and the call uses your first workspace - fine if you only have one.
- pass it explicitly when you belong to several.
list_workspacesreturns the ids. - membership is re-validated on every call. a
workspace_id, process or capture you cannot access answersnot_found- existence is never revealed across workspaces.
recommended flow for agents:
list_workspacesto see the options.list_teams/list_processesto find the process.list_captures+get_capturefor recorded detail,get_synthesisfor the merged process-level view.
tool reference
14 tools. reads mirror what a member sees in the app; writes are real and follow the same permission rules as the ui.
list_workspacesread
every workspace (organization) this key can act in, with your role in each. call this first; pass the chosen workspace_id to other tools.
params: none
list_teamsread
teams in a workspace. teams group related processes.
params: workspace_id? (uuid)
list_processesread
processes in a workspace, optionally filtered to one team. a process is a mapped piece of how the team works; its captures hold the recorded detail.
params: workspace_id? (uuid), team_id? (uuid)
get_processread
one process: name, team, whether a synthesis exists, and its capture list.
params: process_id (uuid)
list_capturesread
the captures (recorded workflow sessions) of a process.
params: process_id (uuid)
get_captureread
one capture: extracted workflow (steps, exceptions), status, duration, language. transcripts are omitted unless requested - they can be long.
params: capture_id (uuid), include_transcript? (boolean, default false)
get_synthesisread
the process-level synthesis: the merged view built from multiple captures (consensus steps, variations, open questions). fails with no_synthesis if none exists yet.
params: process_id (uuid)
list_membersread
members of a workspace with their names and roles.
params: workspace_id? (uuid)
create_processwrite
create a new process in a team. captures can then be recorded against it.
params: team_id (uuid), name (string, 1-120 chars)
create_teamwrite
create a new team in a workspace. the caller becomes its owner.
params: workspace_id? (uuid), name (string, 1-80 chars)
invite_memberwrite
invite someone to a team by email. new emails get a real invite email; existing accounts are added directly and notified in-app. allowed for a workspace owner/admin or a manager of that team.
params: team_id (uuid), email (string), role? (manager | member, default member)
update_capture_stepswrite
replace the step list of a capture you own. steps are objects with at least step_number and description. owner-only.
params: capture_id (uuid), steps (array of objects, min 1)
finalize_capturewrite
mark a capture as completed (reviewer sign-off) or reopen it. allowed for the capture owner or a manager of its process.
params: capture_id (uuid), finalized (boolean)
delete_capturedestructive
permanently delete a capture you own. irreversible - clients should confirm with the user first.
params: capture_id (uuid)
rate limits
| limit | value | behavior |
|---|---|---|
| calls per key per day | 1,000 | resets at midnight utc; over the limit answers http 429 |
| active keys per user | 10 | creating an 11th answers http 409 |
| request duration | 60s | long tool calls are cut off at the platform limit |
errors
| error | where | meaning |
|---|---|---|
| 401 invalid_api_key | http | missing, malformed, revoked, or unknown key |
| 429 rate_limit_exceeded | http | daily call budget spent; retry after midnight utc |
| 403 forbidden_origin | http | browser request from an origin we do not allow |
| *_not_found | tool result | the resource does not exist or your key cannot access it - deliberately the same answer |
| no_synthesis | tool result | the process has captures but no synthesis has been generated yet |
tool-level failures come back as mcp results with isError: true and a json body like {"error": "process_not_found"} - they are not http errors.