Developers

API Reference

REST v1 and MCP. Machine-readable spec: openapi.json

Authentication

Two auth modes accept all v1 endpoints:

  1. Browser session via NextAuth — used by the dashboard. teamId must be supplied as a query parameter.
  2. Personal Access Token via Authorization: Bearer qf_live_…. The token is bound to one team and a set of scopes at creation. Get one at Settings → API Keys.

Token plaintext follows the shape qf_<mode>_<prefix>_<secret>. Test-mode tokens use the qf_test_ prefix and bind to Stripe test products.

Scopes

ScopePurpose
jobs:readRead jobs and history.
jobs:writeCreate, update, move jobs.
stages:readRead pipeline stages.
stages:writeCreate or update stages.
tags:readRead tags.
tags:writeCreate or update tags.
members:readRead team membership list (email masked for tokens).
mcp:claimClaim / release / report progress on jobs.
mcp:assignAssign jobs to members. Requires the DIAMOND plan.
mcp:decideRequest a human decision on a job.
mcp:resolveResolve an open decision.
mcp:evidenceAttach evidence to a job.
team:readRead team metadata.
team:adminReserved — destructive verbs intentionally NOT bound to this scope today.

Endpoints

MethodPathScope
POST/api/auth/tokens
Issue a Personal Access Token. Returns plaintext ONCE.
session, owner+admin
GET/api/auth/tokens
List tokens for a team.
session, owner+admin
DELETE/api/auth/tokens/[id]
Soft-revoke a token (sets revokedAt).
session
GET/api/v1/jobs
List jobs (cursor-paginated, max 100/req).
jobs:read
POST/api/v1/jobs
Create a job in the first stage unless stageId is supplied.
jobs:write
GET/api/v1/jobs/[id]
Read a single job with tags + assignee.
jobs:read
PATCH/api/v1/jobs/[id]
Update title, description, priority, dueDate, poNumber, value.
jobs:write
POST/api/v1/jobs/[id]/move
Move a job to another stage with workflow validation.
jobs:write
POST/api/v1/jobs/[id]/assign
Assign a job to a team member (or null to unassign). DIAMOND plan.
mcp:assign
GET/api/v1/stages
List stages, ordered.
stages:read
POST/api/v1/stages
Create a stage (inserted before the final stage).
stages:write
PATCH/api/v1/stages/[id]
Rename, change SLA, change color.
stages:write
GET/api/v1/tags
List tags.
tags:read
POST/api/v1/tags
Create a tag.
tags:write
PATCH/api/v1/tags/[id]
Rename / recolor.
tags:write
GET/api/v1/members
List members with role + joinedAt.
members:read
GET/api/v1/audit-log
Read token-authed request log. Tokens cannot read this.
session, owner+admin
GET/api/health
Shallow liveness (no DB). Add ?deep=1 for DB + Stripe readiness. No auth.
public

Rate limits

  • Token-authed reads: 120 requests / minute per token.
  • Token-authed writes: 30 requests / minute per token (mutation tier).
  • Anonymous (newsletter, public boards): 20 / minute per IP.
  • Rate-limited responses return 429 with Retry-After and X-RateLimit-* headers.

Destructive operations

DELETE /api/teams/[id] requires session auth AND a body of { "confirm": "DELETE <team-slug>" } matched exactly. Tokens cannot delete teams. Bulk-delete and Stripe mutation are not exposed via the API at all.

Plans & limits

The API and MCP enforce the same plan matrix as the app. Reads and the agent-collaboration loop (claim, progress, evidence, decisions) are open on every plan; scale and premium capabilities are gated:

CapabilityMinimum plan
Create / move jobs (within active-job cap)FREE
Flag priorityPREMIUM
TagsPREMIUM
Assign jobs to membersDIAMOND

Exceeding a gate returns a structured upgrade hint (see Errors). Active-job caps: FREE 10 (up to 20 with referrals), PREMIUM 40, DIAMOND 150.

MCP server

Stdio MCP server published as qodflow-mcp. Point your AI client at it and pass QODFLOW_API_TOKEN as an env var (and QODFLOW_API_BASE=https://www.qodflow.com if overriding). Tools exposed:

  • Read: list_jobs, list_stages, list_tags, list_members, get_timeline, list_decisions, list_evidence
  • Write: create_job, update_job, move_job, assign_job (DIAMOND), create_tag, update_stage
  • Agent loop: claim_job, release_job, report_progress, request_human_decision, resolve_decision, attach_evidence

Destructive verbs are intentionally NOT exposed via MCP. See /security.

Errors

All errors follow the shape { success: false, error: { code, message, details? } }. Codes include UNAUTHORIZED, FORBIDDEN, INVALID_INPUT, NOT_FOUND, RATE_LIMIT_EXCEEDED, PLAN_LIMIT_REACHED, PLAN_UPGRADE_REQUIRED.

Plan and quota errors carry a machine-readable upgrade hint so an agent can relay it in-context:

{
  "success": false,
  "error": {
    "code": "PLAN_UPGRADE_REQUIRED",
    "message": "Feature \"assign_job\" requires the DIAMOND plan. You're on FREE.",
    "details": {
      "feature": "assign_job",
      "currentPlan": "FREE",
      "requiredPlan": "DIAMOND",
      "upgradeUrl": "https://www.qodflow.com/settings/billing",
      "docsUrl": "https://www.qodflow.com/api-docs#plans"
    }
  }
}