{"version":"1.0","base_url":"/api/v1","auth":"Pass your API key in the X-Api-Key header (or ?api_key= query param). Endpoints marked auth:false are public.","slugs":"Organizations and projects each have a unique slug. For project-scoped endpoints, :project_id accepts either a numeric ID or the project slug (e.g., /api/v1/projects/my-project/spec/items). Slug matching is case-insensitive. Slugs are 3-60 lowercase alphanumeric characters or hyphens, auto-generated from the resource name on creation. Project responses include a slug field. Spec item responses include a url field with the slug-based path (/:org_slug/:project_slug/:permalink).","error_codes":{"not_found":"404 — Resource does not exist or is not accessible.","bad_request":"400 — Missing required parameter.","unprocessable_entity":"422 — Validation error or invalid argument.","plan_limit_exceeded":"403 — Monthly API call quota reached. Upgrade or wait for reset.","project_read_only":"403 — Project is read-only due to a plan downgrade. Upgrade to Pro to resume editing. Exports and reads are unaffected.","llm_timeout":"504 — LLM request timed out. Safe to retry.","internal_error":"500 — Unexpected server error."},"endpoints":[{"method":"GET","path":"/api/v1/ping","auth":false,"description":"Health check. Returns status, timestamp, and API version.","response":{"status":"ok","timestamp":"<iso8601>","version":"1.0"}},{"method":"GET","path":"/api/v1/health","auth":false,"description":"Health check. Returns status of all system components (database, worker, Stripe). HTTP 200 if healthy, 503 if degraded or down.","response":{"status":"ok|degraded|down","timestamp":"<iso8601>","version":"1.0","components":{"database":{"status":"ok|down","latency_ms":"<integer>"},"worker":{"status":"ok|degraded|down","last_heartbeat":"<iso8601|null>"},"stripe":{"status":"ok|down"}}}},{"method":"GET","path":"/api/v1/docs","auth":false,"description":"This endpoint. Returns full API documentation as JSON."},{"method":"GET","path":"/api/v1/settings","auth":true,"description":"Get organization settings (LLM config, GitHub token, etc.)."},{"method":"PATCH","path":"/api/v1/settings","auth":true,"description":"Update organization settings.","params":{"llm_provider":"anthropic|openai","llm_api_key":"string","llm_model":"string (optional)"}},{"method":"GET","path":"/api/v1/projects","auth":true,"description":"List all projects for the organization. Each project includes a slug field."},{"method":"POST","path":"/api/v1/projects","auth":true,"description":"Create a new project. A slug is auto-generated from the name if not provided. Slugs must be 3-60 lowercase alphanumeric characters or hyphens, with no leading or trailing hyphens, and must be unique within the organization.","params":{"name":"string (required)","description":"string","slug":"string (optional, auto-generated from name)"}},{"method":"GET","path":"/api/v1/projects/:project_id","auth":true,"description":"Get a single project. :project_id accepts either a numeric ID or the project's slug (e.g., /api/v1/projects/my-project)."},{"method":"GET","path":"/api/v1/projects/:project_id/spec/items","auth":true,"description":"List spec items. :project_id accepts numeric ID or project slug. Supports filters: ?type=functional|technical, ?state=inbox|draft|accepted|integrated, ?implementation_status=not_started|in_progress|implemented|verified|released, ?roots_only=true, ?parent_id=N, ?q=keyword (searches title+description), ?tag=tagname, ?has_review=true|false, ?review_verdict=ready|needs_refinement|major_gaps. Paginate with ?page=N&per=N (default 25, max 100). Response includes meta: {page, per, total}. Each item includes a url field with the slug-based path (/:org_slug/:project_slug/:permalink)."},{"method":"POST","path":"/api/v1/projects/:project_id/spec/items","auth":true,"description":"Create a spec item.","params":{"title":"string (required)","description":"string","type_of":"functional|technical","state":"draft|proposed|accepted|archived","parent_id":"integer (optional)"}},{"method":"GET","path":"/api/v1/projects/:project_id/spec/items/:id","auth":true,"description":"Get a single spec item."},{"method":"PATCH","path":"/api/v1/projects/:project_id/spec/items/:id","auth":true,"description":"Update a spec item.","params":{"title":"string","description":"string","state":"string","tags":"array"}},{"method":"DELETE","path":"/api/v1/projects/:project_id/spec/items/:id","auth":true,"description":"Delete a spec item."},{"method":"POST","path":"/api/v1/projects/:project_id/spec/items/:id/transition","auth":true,"description":"Transition a spec item to a new state.","params":{"state":"string (required)"}},{"method":"POST","path":"/api/v1/projects/:project_id/spec/items/:id/transition_implementation","auth":true,"description":"Transition a spec item's implementation status. Valid statuses: not_started→in_progress→implemented→verified→released.","params":{"implementation_status":"not_started|in_progress|implemented|verified|released (required)"}},{"method":"POST","path":"/api/v1/projects/:project_id/spec/items/bulk","auth":true,"description":"Bulk operation on multiple spec items. Supported actions: transition_implementation, transition, tag, delete.","params":{"action":"transition_implementation|transition|tag|delete (required)","item_ids":"array of integers (required)","params":"object with action-specific params (e.g. {implementation_status: 'implemented'} or {state: 'accepted'} or {tags: ['tag1','tag2']})"},"response":{"data":{"succeeded":"array of succeeded ids","failed":"array of {id, error}"}}},{"method":"GET","path":"/api/v1/projects/:project_id/stats","auth":true,"description":"Project stats dashboard: spec item counts by type/state/implementation, review coverage, tech coverage, and recent activity (last 24h).","response":{"data":{"type":"project_stats","spec_items":{"total":"N","by_type":"hash","by_state":"hash","by_implementation":"hash"},"reviews":{"tech_reviewed":"N","tech_unreviewed":"N","func_reviewed":"N","func_unreviewed":"N","avg_tech_score":"float","avg_func_score":"float","by_verdict":"hash"},"coverage":{"functional_with_tech":"N","functional_without_tech":"N"},"recent_activity":{"items_updated_24h":"N","reviews_24h":"N","agent_runs_24h":"N"}}}},{"method":"GET","path":"/api/v1/projects/:project_id/tech/items","auth":true,"description":"List technical spec items. Filter with ?state=, ?implementation_status=, ?func_item_id=N (tech items implementing a given functional item)."},{"method":"POST","path":"/api/v1/projects/:project_id/tech/items","auth":true,"description":"Create a technical spec item.","params":{"tech_item":{"title":"string (required)","description":"string","state":"string","implementation_status":"string","parent_id":"integer","tags":"string","priority":"integer","position":"integer","implements_item_id":"integer (optional — creates implements edge to functional item)"}}},{"method":"GET","path":"/api/v1/projects/:project_id/tech/items/:id","auth":true,"description":"Get a technical spec item. Response includes implements: list of functional items it covers."},{"method":"PATCH","path":"/api/v1/projects/:project_id/tech/items/:id","auth":true,"description":"Update a technical spec item.","params":{"tech_item":{"title":"string","description":"string","state":"string","implementation_status":"string","tags":"string"}}},{"method":"DELETE","path":"/api/v1/projects/:project_id/tech/items/:id","auth":true,"description":"Delete a technical spec item."},{"method":"GET","path":"/api/v1/projects/:project_id/tech/coverage","auth":true,"description":"Tech coverage report: for each functional item, shows how many tech items implement it, their implementation statuses, and whether it is covered."},{"method":"GET","path":"/api/v1/projects/:project_id/plans","auth":true,"description":"List all implementation plans for the project."},{"method":"POST","path":"/api/v1/projects/:project_id/plans","auth":true,"description":"Create a plan. Pass ?change_report_id=N to auto-populate from a cascade change report.","params":{"plan":{"title":"string (required)","description":"string"},"change_report_id":"integer (optional query param)"}},{"method":"GET","path":"/api/v1/projects/:project_id/plans/:id","auth":true,"description":"Get a plan with its plan_items and associated prompts."},{"method":"PATCH","path":"/api/v1/projects/:project_id/plans/:id","auth":true,"description":"Update a plan.","params":{"plan":{"title":"string","description":"string","state":"string"}}},{"method":"DELETE","path":"/api/v1/projects/:project_id/plans/:id","auth":true,"description":"Delete a plan."},{"method":"POST","path":"/api/v1/projects/:project_id/plans/:id/complete","auth":true,"description":"Mark a plan as complete.","params":{"commit_refs":"string","notes":"string"}},{"method":"POST","path":"/api/v1/projects/:project_id/plans/:id/generate_prompts","auth":true,"description":"Regenerate implementation prompts for a plan."},{"method":"GET","path":"/api/v1/projects/:project_id/prompts","auth":true,"description":"List all prompts for a project (across all plans). Filter by plan with ?plan_id=N."},{"method":"GET","path":"/api/v1/projects/:project_id/prompts/:id","auth":true,"description":"Get a single prompt.","response":{"data":{"id":"integer","type":"prompt","attributes":{"content":"string","sequence":"integer","token_count":"integer","plan_id":"integer","created_at":"iso8601"}}}},{"method":"GET","path":"/api/v1/projects/:project_id/graph/edges","auth":true,"description":"List dependency edges. Filter with ?source_id=N, ?target_id=N, ?edge_type=string.","params":{"source_id":"integer (optional)","target_id":"integer (optional)","edge_type":"implements|depends_on|etc (optional)"}},{"method":"POST","path":"/api/v1/projects/:project_id/graph/edges","auth":true,"description":"Create a dependency edge between two spec items.","params":{"dependency_edge":{"source_id":"integer (required)","target_id":"integer (required)","edge_type":"string (required)"}}},{"method":"GET","path":"/api/v1/projects/:project_id/graph/edges/:id","auth":true,"description":"Get a single dependency edge."},{"method":"PATCH","path":"/api/v1/projects/:project_id/graph/edges/:id","auth":true,"description":"Update a dependency edge.","params":{"dependency_edge":{"edge_type":"string"}}},{"method":"DELETE","path":"/api/v1/projects/:project_id/graph/edges/:id","auth":true,"description":"Delete a dependency edge."},{"method":"GET","path":"/api/v1/projects/:project_id/graph/dependencies/:item_id","auth":true,"description":"Get all items this item transitively depends on (outgoing dependency traversal)."},{"method":"GET","path":"/api/v1/projects/:project_id/graph/dependents/:item_id","auth":true,"description":"Get all items that transitively depend on this item (incoming dependency traversal)."},{"method":"GET","path":"/api/v1/projects/:project_id/graph/subgraph","auth":true,"description":"Get the connected subgraph around a spec item (both directions). Pass ?root=:item_id.","params":{"root":"integer (required)"}},{"method":"POST","path":"/api/v1/projects/:project_id/cascade/analyze","auth":true,"description":"Run cascade impact analysis for a spec item. Optionally mark the item dirty with a reason.","params":{"spec_item_id":"integer (required)","reason":"string (optional — marks item dirty if provided)"}},{"method":"GET","path":"/api/v1/projects/:project_id/cascade/dirty","auth":true,"description":"List spec items with a dirty/stale cascade status (ordered by dirty_since desc)."},{"method":"GET","path":"/api/v1/projects/:project_id/cascade/reports","auth":true,"description":"List change/cascade reports for a project. Filter with ?status=pending|approved|rejected."},{"method":"GET","path":"/api/v1/projects/:project_id/cascade/reports/:report_id","auth":true,"description":"Get a cascade report with its change_report_items."},{"method":"POST","path":"/api/v1/projects/:project_id/cascade/reports/:report_id/approve","auth":true,"description":"Approve a cascade report. Optionally approve only a subset of affected items.","params":{"item_ids":"array of integers (optional — approve subset)"}},{"method":"POST","path":"/api/v1/projects/:project_id/cascade/reports/:report_id/reject","auth":true,"description":"Reject a cascade report."},{"method":"GET","path":"/api/v1/projects/:project_id/snapshots/:id","auth":true,"description":"Get a snapshot with metadata (item_count, edge_count)."},{"method":"GET","path":"/api/v1/projects/:project_id/snapshots/:id/data","auth":true,"description":"Get the full data payload of a snapshot (all spec items and edges at the time of capture)."},{"method":"GET","path":"/api/v1/projects/:project_id/snapshots/:id/diff/:other_id","auth":true,"description":"Diff two snapshots. Returns added, removed, and changed spec items between snapshot :id and snapshot :other_id."},{"method":"GET","path":"/api/v1/projects/:project_id/linked_commits/:id","auth":true,"description":"Get a linked commit by id.","response":{"data":{"id":"integer","type":"linked_commit","attributes":{"sha":"string","short_sha":"string","message":"string","author":"string","committed_at":"iso8601","source":"string","agent_run_id":"integer","spec_item_id":"integer","files_changed_count":"integer","additions":"integer","deletions":"integer"}}}},{"method":"GET","path":"/api/v1/projects/:project_id/work_package/:item_id","auth":true,"description":"Full work package for an AI agent: item, functional requirements, dependencies, dependents, siblings, repo files, review, and agent history. Add ?include_codebase=true to include codebase context."},{"method":"POST","path":"/api/v1/projects/:project_id/work_package/:item_id/review","auth":true,"description":"Run an LLM tech review of one spec item. Synchronous. Requires LLM configured."},{"method":"POST","path":"/api/v1/projects/:project_id/work_package/review_all","auth":true,"description":"Queue a batch tech review job for all tech items needing review. Returns 202 with job_id. Poll /jobs/:id for status.","params":{"limit":"integer 1-50 (default 20)"},"response":{"data":{"job_id":"integer","status":"queued"}}},{"method":"POST","path":"/api/v1/projects/:project_id/work_package/:item_id/func_review","auth":true,"description":"Run an LLM functional quality review of one functional spec item. Synchronous."},{"method":"POST","path":"/api/v1/projects/:project_id/work_package/func_review_all","auth":true,"description":"Queue a batch functional review job for all functional items needing review. Returns 202 with job_id.","params":{"limit":"integer 1-50 (default 20)"},"response":{"data":{"job_id":"integer","status":"queued"}}},{"method":"POST","path":"/api/v1/projects/:project_id/work_package/:item_id/propose","auth":true,"description":"Generate an LLM improvement proposal for a spec item without applying it."},{"method":"POST","path":"/api/v1/projects/:project_id/work_package/:item_id/accept","auth":true,"description":"Accept the pending proposal for a spec item, applying the changes."},{"method":"POST","path":"/api/v1/projects/:project_id/work_package/:item_id/reject","auth":true,"description":"Reject the pending proposal for a spec item."},{"method":"POST","path":"/api/v1/projects/:project_id/work_package/apply_all","auth":true,"description":"Queue a batch refinement job (propose + optionally auto-accept) for items with actionable reviews. Creates a snapshot first for mass revert. Returns 202 with job_id and snapshot_id.","params":{"limit":"integer 1-25 (default 10)","auto_accept":"true|false"},"response":{"data":{"job_id":"integer","status":"queued","snapshot_id":"integer"}}},{"method":"POST","path":"/api/v1/projects/:project_id/work_package/:item_id/generate_tech","auth":true,"description":"Use LLM to propose technical spec items for a functional item."},{"method":"POST","path":"/api/v1/projects/:project_id/work_package/:item_id/create_tech","auth":true,"description":"Create tech items from proposals returned by generate_tech.","params":{"proposals":"array of {title, description}"}},{"method":"GET","path":"/api/v1/projects/:project_id/jobs","auth":true,"description":"List recent batch jobs (last 20). Filter with ?job_type=review_all|func_review_all|apply_all and ?status=queued|running|completed|failed."},{"method":"GET","path":"/api/v1/projects/:project_id/jobs/:id","auth":true,"description":"Get status and progress of a batch job.","response":{"data":{"id":"integer","job_type":"string","status":"queued|running|completed|failed","progress":"object","created_at":"iso8601","updated_at":"iso8601"}}},{"method":"GET","path":"/api/v1/projects/:project_id/graph","auth":true,"description":"Get the full dependency graph for a project (nodes + edges)."},{"method":"GET","path":"/api/v1/projects/:project_id/graph/impact","auth":true,"description":"Get impact analysis for a spec item. Pass ?item_id=N."},{"method":"GET","path":"/api/v1/projects/:project_id/snapshots","auth":true,"description":"List snapshots for a project."},{"method":"POST","path":"/api/v1/projects/:project_id/snapshots","auth":true,"description":"Create a snapshot of the current project state.","params":{"name":"string","description":"string"}},{"method":"POST","path":"/api/v1/projects/:project_id/snapshots/:id/restore","auth":true,"description":"Restore a project to a previous snapshot."},{"method":"GET","path":"/api/v1/projects/:project_id/audit","auth":true,"description":"List audit log entries for a project."},{"method":"GET","path":"/api/v1/projects/:project_id/inbox","auth":true,"description":"List inbox items for a project."},{"method":"POST","path":"/api/v1/projects/:project_id/inbox","auth":true,"description":"Create an inbox item.","params":{"title":"string (required)","content":"string","source":"string"}},{"method":"POST","path":"/api/v1/projects/:project_id/inbox/:id/triage","auth":true,"description":"Triage an inbox item (accept, reject, or escalate).","params":{"action":"accept|reject|escalate"}},{"method":"GET","path":"/api/v1/projects/:project_id/export/markdown","auth":true,"description":"Export project spec as Markdown."},{"method":"GET","path":"/api/v1/projects/:project_id/export/json","auth":true,"description":"Export project spec as JSON."},{"method":"GET","path":"/api/v1/projects/:project_id/export/html","auth":true,"description":"Export project spec as a self-contained HTML document with dark mode and print support."},{"method":"POST","path":"/api/v1/projects/:project_id/work_package/:item_id/record_run","auth":true,"description":"Record an agent run against a spec item.","params":{"session_key":"string","model":"string","provider":"string","status":"string","input_tokens":"integer","output_tokens":"integer","cost":"decimal","instruction_version":"integer (optional, which version of agent_instructions the agent was following)"}},{"method":"POST","path":"/api/v1/projects/:project_id/work_package/:item_id/link_commit","auth":true,"description":"Link a git commit to a spec item.","params":{"sha":"string (required)","message":"string","committed_at":"iso8601","source":"string","agent_run_id":"integer"}},{"method":"GET","path":"/api/v1/projects/:project_id/agent_instructions","auth":false,"description":"Get agent instructions for this project. Falls back to org-level instructions, then the default template. Supports ?format=markdown (or ?format=text) to get raw markdown. Auth optional — public by default.","response":{"data":{"id":"integer|null","type":"agent_instruction","attributes":{"content":"markdown string","version":"integer","scope":"project|org|default","updated_at":"iso8601|null","updated_by":"email|null"}}}},{"method":"PATCH","path":"/api/v1/projects/:project_id/agent_instructions","auth":true,"description":"Update or create project-level agent instructions. Auto-increments version and snapshots previous content.","params":{"content":"string (required, markdown)"}},{"method":"GET","path":"/api/v1/projects/:project_id/agent_instructions/versions","auth":true,"description":"List version history for project agent instructions. Paginated with ?page=N&per=N.","response":{"data":[{"id":"integer","version":"integer","updated_by":"email|null","created_at":"iso8601"}]}},{"method":"GET","path":"/api/v1/projects/:project_id/agent_instructions/versions/:version","auth":true,"description":"Get a specific version of the project agent instructions (including content for diffing).","response":{"data":{"id":"integer","version":"integer","content":"string","updated_by":"email|null","created_at":"iso8601"}}},{"method":"GET","path":"/api/v1/agent_instructions","auth":true,"description":"Get org-level default agent instructions. Falls back to the default template if none set."},{"method":"PATCH","path":"/api/v1/agent_instructions","auth":true,"description":"Update org-level default agent instructions.","params":{"content":"string (required, markdown)"}}]}