{"openapi":"3.1.0","info":{"title":"Fixie API","version":"1.0.0","description":"REST API for running Fixie scans, opening fix PRs, and reading workspace usage."},"servers":[{"url":"/"}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"API Key","description":"Use a Fixie API key in the Authorization header: Bearer fxie_live_..."}},"schemas":{"ApiError":{"type":"object","required":["error"],"properties":{"error":{"type":"string"}}},"UsageSummary":{"type":"object","required":["planTier","planStatus","periodStart","scansUsed","fixPrsUsed","combinedOperationsUsed","includedMonthlyOperations","includedMonthlyFixPrs","remainingOperations","remainingFixPrs","apiRateLimitPerMinute"],"properties":{"planTier":{"type":"string","enum":["BUILDER","TEAM","GROWTH","ENTERPRISE"]},"planStatus":{"type":"string","enum":["NONE","PENDING","ACTIVE"]},"periodStart":{"type":"string","format":"date-time"},"scansUsed":{"type":"integer"},"fixPrsUsed":{"type":"integer"},"combinedOperationsUsed":{"type":"integer"},"includedMonthlyOperations":{"type":["integer","null"]},"includedMonthlyFixPrs":{"type":["integer","null"]},"remainingOperations":{"type":["integer","null"]},"remainingFixPrs":{"type":["integer","null"]},"apiRateLimitPerMinute":{"type":"integer"}}},"VulnerabilityFinding":{"type":"object","required":["id","ruleId","title","severity","description","line","snippet","suggestedFix","plainEnglish","businessImpact","fixSummary","timeToFix","filePath"],"properties":{"id":{"type":"string"},"ruleId":{"type":"string"},"title":{"type":"string"},"severity":{"type":"string","enum":["CRITICAL","HIGH","MEDIUM"]},"description":{"type":"string"},"line":{"type":"integer"},"snippet":{"type":"string"},"suggestedFix":{"type":"string"},"plainEnglish":{"type":"string"},"businessImpact":{"type":"string"},"fixSummary":{"type":"string"},"timeToFix":{"type":"string"},"filePath":{"type":"string"}}},"ScanRequest":{"type":"object","required":["repoFullName"],"properties":{"repoFullName":{"type":"string","pattern":"^[a-zA-Z0-9_.-]+/[a-zA-Z0-9_.-]+$"},"model":{"type":"string","enum":["ollama/qwen2.5-coder:7b","ollama/llama3.1:latest","ollama/deepseek-coder-v2","anthropic/claude-sonnet-4-6","openai/gpt-4o","gemini/gemini-1.5-pro"]}},"example":{"repoFullName":"octo-org/example-repo","model":"ollama/qwen2.5-coder:7b"}},"ScanResponse":{"type":"object","required":["success","scannedCount","vulnerabilities","usage"],"properties":{"success":{"type":"boolean"},"scannedCount":{"type":"integer"},"error":{"type":"string"},"vulnerabilities":{"type":"array","items":{"$ref":"#/components/schemas/VulnerabilityFinding"}},"usage":{"$ref":"#/components/schemas/UsageSummary"}}},"FixPrRequest":{"type":"object","required":["repoFullName","finding"],"properties":{"repoFullName":{"type":"string","pattern":"^[a-zA-Z0-9_.-]+/[a-zA-Z0-9_.-]+$"},"model":{"type":"string","enum":["ollama/qwen2.5-coder:7b","ollama/llama3.1:latest","ollama/deepseek-coder-v2","anthropic/claude-sonnet-4-6","openai/gpt-4o","gemini/gemini-1.5-pro"]},"finding":{"$ref":"#/components/schemas/VulnerabilityFinding"}},"example":{"repoFullName":"octo-org/example-repo","model":"ollama/qwen2.5-coder:7b","finding":{"id":"finding_123","ruleId":"express_sql_injection","title":"Unsanitized SQL query","severity":"HIGH","description":"User-controlled input flows into a SQL string without parameterization.","line":42,"snippet":"db.query(`select * from users where id = ${req.query.id}`)","suggestedFix":"Use parameterized queries instead of string interpolation.","plainEnglish":"An attacker can change the query by editing request input.","businessImpact":"This can expose or alter production data.","fixSummary":"Swap the raw query for a prepared statement.","timeToFix":"15-30 minutes","filePath":"src/routes/users.ts"}}},"FixPrResponse":{"type":"object","required":["success","usage"],"properties":{"success":{"type":"boolean"},"prUrl":{"type":"string"},"prNumber":{"type":"integer"},"prIsDraft":{"type":"boolean"},"explanation":{"type":"string"},"appliedChanges":{"type":"array","items":{"type":"string"}},"validation":{"type":"object","required":["status","summary","commands","hasTestSuite","regressionClaim","notes"],"properties":{"status":{"type":"string","enum":["passed","failed","unavailable","timed_out"]},"summary":{"type":"string"},"commands":{"type":"array","items":{"type":"object","required":["kind","command","source","label"],"properties":{"kind":{"type":"string","enum":["test","typecheck","lint"]},"command":{"type":"string"},"source":{"type":"string","enum":["package_json","github_actions","gitlab_ci","circleci"]},"label":{"type":"string"}}}},"hasTestSuite":{"type":"boolean"},"regressionClaim":{"type":"string"},"workflowRunUrl":{"type":"string"},"failedJobs":{"type":"array","items":{"type":"string"}},"notes":{"type":"array","items":{"type":"string"}}}},"error":{"type":"string"},"usage":{"$ref":"#/components/schemas/UsageSummary"}}}}},"security":[{"bearerAuth":[]}],"paths":{"/api/v1/scans":{"post":{"operationId":"createScan","summary":"Run a repository scan","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScanRequest"}}}},"responses":{"200":{"description":"Scan completed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScanResponse"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/v1/fix-prs":{"post":{"operationId":"createFixPr","summary":"Open a fix PR for a grounded finding","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FixPrRequest"}}}},"responses":{"200":{"description":"Fix PR flow completed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FixPrResponse"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/v1/usage":{"get":{"operationId":"getUsage","summary":"Read the current monthly usage summary","responses":{"200":{"description":"Current usage snapshot","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UsageSummary"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}}}}