{"openapi":"3.1.0","info":{"title":"ScanFix API","version":"2026-01","description":"ScanFix Website QA Infrastructure API — Programmatic website auditing, continuous monitoring, and CI/CD quality gates for agencies and developers.","contact":{"name":"ScanFix Developer Support","email":"api@scanfix.dev"}},"servers":[{"url":"/","description":"Current Environment API Server"}],"components":{"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","description":"API key provided as Bearer token in the Authorization header."},"ApiKeyAuth":{"type":"apiKey","in":"header","name":"x-api-key","description":"API key provided directly via the x-api-key header."}},"schemas":{"ApiEnvelope":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object"},"meta":{"type":"object"},"pagination":{"type":"object","properties":{"page":{"type":"integer"},"limit":{"type":"integer"},"total":{"type":"integer"},"has_more":{"type":"boolean"}}}}},"ApiError":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"request_id":{"type":"string"},"details":{"type":"object"}},"required":["code","message","request_id"]}}},"QualityGateConfig":{"type":"object","properties":{"minimum_score":{"type":"number","default":80},"maximum_critical":{"type":"number","default":0},"maximum_high":{"type":"number"},"maximum_regressions":{"type":"number"}}},"AutomationRule":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"trigger":{"type":"string","enum":["SCAN_COMPLETED","ISSUE_CREATED","ISSUE_REGRESSED","HEALTH_CHANGED","INCIDENT_CREATED","INCIDENT_RESOLVED"]},"is_enabled":{"type":"boolean"},"conditions":{"type":"array","items":{"type":"object"}},"actions":{"type":"array","items":{"type":"object"}}}}}},"security":[{"BearerAuth":[]},{"ApiKeyAuth":[]}],"paths":{"/api/v1/websites":{"get":{"summary":"List monitored websites","operationId":"listWebsites","parameters":[{"name":"client_id","in":"query","schema":{"type":"string"}},{"name":"search","in":"query","schema":{"type":"string"}},{"name":"page","in":"query","schema":{"type":"integer","default":1}},{"name":"limit","in":"query","schema":{"type":"integer","default":25}}],"responses":{"200":{"description":"Paginated list of websites"}}},"post":{"summary":"Register website","operationId":"createWebsite","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string"},"name":{"type":"string"},"client_id":{"type":"string"}},"required":["url"]}}}},"responses":{"201":{"description":"Website registered"}}}},"/api/v1/scans":{"get":{"summary":"List scans","operationId":"listScans","parameters":[{"name":"website_id","in":"query","schema":{"type":"string"}},{"name":"status","in":"query","schema":{"type":"string"}},{"name":"page","in":"query","schema":{"type":"integer"}},{"name":"limit","in":"query","schema":{"type":"integer"}}],"responses":{"200":{"description":"Paginated list of scans"}}},"post":{"summary":"Create scan job","operationId":"createScan","parameters":[{"name":"Idempotency-Key","in":"header","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"website_id":{"type":"string"},"url":{"type":"string"},"threshold":{"type":"number"},"wait":{"type":"boolean"},"max_pages":{"type":"integer"}}}}}},"responses":{"200":{"description":"Synchronous scan passed threshold"},"202":{"description":"Scan queued asynchronously"},"422":{"description":"Synchronous scan failed threshold"}}}},"/api/v1/scans/{id}":{"get":{"summary":"Get scan results","operationId":"getScan","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"format","in":"query","schema":{"type":"string","enum":["normalized","raw"]}}],"responses":{"200":{"description":"Scan results"},"404":{"description":"Scan not found"}}}},"/api/v1/scans/{id}/export":{"get":{"summary":"Export scan results (CSV or JSON)","operationId":"exportScan","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"format","in":"query","schema":{"type":"string","enum":["csv","json"],"default":"json"}},{"name":"type","in":"query","schema":{"type":"string","enum":["issues","summary","full"],"default":"issues"}}],"responses":{"200":{"description":"Export file stream"}}}},"/api/v1/quality-gates":{"post":{"summary":"Evaluate CI/CD Quality Gate","operationId":"evaluateQualityGate","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"scan_id":{"type":"string"},"website_id":{"type":"string"},"url":{"type":"string"},"config":{"$ref":"#/components/schemas/QualityGateConfig"}}}}}},"responses":{"200":{"description":"Quality gate passed"},"422":{"description":"Quality gate failed thresholds"}}}},"/api/v1/bulk-scans":{"get":{"summary":"List bulk scan batches","operationId":"listBulkScans","responses":{"200":{"description":"List of bulk scan batches"}}},"post":{"summary":"Create bulk scan batch","operationId":"createBulkScan","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"urls":{"type":"array","items":{"type":"string"}},"max_pages":{"type":"integer"}},"required":["urls"]}}}},"responses":{"202":{"description":"Batch queued for processing"}}}},"/api/v1/bulk-scans/{id}":{"get":{"summary":"Get bulk scan batch status","operationId":"getBulkScan","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Batch status and items"}}}},"/api/v1/automations":{"get":{"summary":"List automation rules","operationId":"listAutomations","responses":{"200":{"description":"List of rules"}}},"post":{"summary":"Create automation rule","operationId":"createAutomation","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutomationRule"}}}},"responses":{"201":{"description":"Automation rule created"}}}},"/api/v1/apps":{"get":{"summary":"List developer / partner OAuth applications","operationId":"listDeveloperApps","responses":{"200":{"description":"List of registered developer applications"}}},"post":{"summary":"Register developer OAuth application","operationId":"createDeveloperApp","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"callbackUrls":{"type":"array","items":{"type":"string"}},"allowedOrigins":{"type":"array","items":{"type":"string"}},"scopes":{"type":"array","items":{"type":"string"}},"environment":{"type":"string","enum":["live","test"]}},"required":["name","callbackUrls"]}}}},"responses":{"201":{"description":"Application registered with client credentials"}}}},"/api/v1/oauth/token":{"post":{"summary":"OAuth 2.0 Token Exchange","operationId":"exchangeOAuthToken","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"grant_type":{"type":"string","enum":["authorization_code"]},"client_id":{"type":"string"},"client_secret":{"type":"string"},"code":{"type":"string"},"redirect_uri":{"type":"string"}},"required":["grant_type","client_id","client_secret","code","redirect_uri"]}}}},"responses":{"200":{"description":"Bearer access token"}}}},"/api/v1/embed/config":{"get":{"summary":"List or retrieve embed configurations","operationId":"getEmbedConfig","responses":{"200":{"description":"Embed configuration details"}}},"post":{"summary":"Create embed configuration","operationId":"createEmbedConfig","responses":{"201":{"description":"Embed configuration and snippets"}}}},"/api/v1/embed/scan":{"post":{"summary":"Execute embedded audit scan with origin validation","operationId":"executeEmbedScan","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"config_id":{"type":"string"},"url":{"type":"string"}},"required":["config_id","url"]}}}},"responses":{"200":{"description":"Sanitized audit summary"},"403":{"description":"Origin disallowed by embed config"}}}},"/api/v1/webhooks/test":{"post":{"summary":"Dispatch test webhook event","operationId":"dispatchTestWebhook","responses":{"200":{"description":"Test ping delivery result"}}}},"/api/v1/websites/{id}/history":{"get":{"summary":"Retrieve historical health timeline and score snapshots","operationId":"getWebsiteHistory","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"range","in":"query","schema":{"type":"string","enum":["7d","30d","90d","6m","1y","all"]}}],"responses":{"200":{"description":"Historical health timeline and snapshots"}}}},"/api/v1/websites/{id}/technology-history":{"get":{"summary":"Retrieve detected technology changes and evolution history","operationId":"getWebsiteTechnologyHistory","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Chronological technology changes"}}}},"/api/v1/websites/{id}/issue-trends":{"get":{"summary":"Retrieve factual issue recurrence and persistence metrics","operationId":"getWebsiteIssueTrends","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Persistence metrics and recurring issues"}}}},"/api/v1/websites/{id}/benchmarks":{"get":{"summary":"Compare website scores against anonymous cohort benchmark","operationId":"getWebsiteCohortBenchmarks","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Cohort comparison or insufficient sample notice"}}}},"/api/v1/websites/{id}/investigate":{"post":{"summary":"Trigger on-demand AI root-cause regression investigation","operationId":"investigateWebsiteRegression","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Structured FACT, CORRELATION, and HYPOTHESIS analysis"}}}},"/api/v1/websites/{id}/privacy":{"get":{"summary":"Get benchmark opt-in status","operationId":"getWebsiteBenchmarkPrivacy","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Privacy settings"}}},"patch":{"summary":"Update benchmark opt-in status (purges on opt-out)","operationId":"updateWebsiteBenchmarkPrivacy","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"benchmark_opt_in":{"type":"boolean"}}}}}},"responses":{"200":{"description":"Updated privacy settings"}}}},"/api/v1/benchmarks":{"get":{"summary":"List published anonymous cohort benchmarks meeting minimum privacy sample size","operationId":"listPublishedBenchmarks","parameters":[{"name":"industry","in":"query","schema":{"type":"string"}},{"name":"type","in":"query","schema":{"type":"string"}},{"name":"size","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Published anonymous cohort benchmarks"}}}},"/api/v1/admin/data-quality":{"get":{"summary":"Get aggregation pipeline jobs, cohort sample sizes, and exclusions","operationId":"getAdminDataQuality","responses":{"200":{"description":"Data quality metrics and jobs"}}},"post":{"summary":"Trigger manual background aggregation pipeline execution","operationId":"triggerAggregationPipeline","responses":{"200":{"description":"Triggered aggregation job result"}}}},"/api/v1/roles":{"get":{"summary":"List built-in and custom roles with granular permissions","operationId":"listRoles","responses":{"200":{"description":"List of roles"}}},"post":{"summary":"Create custom role with explicit permissions (privilege escalation guarded)","operationId":"createCustomRole","responses":{"201":{"description":"Created custom role"}}}},"/api/v1/roles/{id}":{"get":{"summary":"Get role details","operationId":"getRole","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Role details"}}},"put":{"summary":"Update custom role","operationId":"updateCustomRole","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Updated custom role"}}},"delete":{"summary":"Archive custom role","operationId":"archiveCustomRole","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Role archived"}}}},"/api/v1/roles/assign":{"post":{"summary":"Assign role to organization user (escalation guarded)","operationId":"assignUserRole","responses":{"200":{"description":"Role assigned"}}}},"/api/v1/security/access-reviews":{"get":{"summary":"Get organization access review matrix (members, roles, sessions, keys)","operationId":"getAccessReview","responses":{"200":{"description":"Access review summary"}}},"post":{"summary":"Execute access review remediation (revoke session, revoke key, change role, remove member)","operationId":"executeAccessReviewAction","responses":{"200":{"description":"Remediation executed"}}}},"/api/v1/security/sso":{"get":{"summary":"Get SSO configuration and connections","operationId":"getSSOConfig","responses":{"200":{"description":"SSO configuration"}}},"post":{"summary":"Configure SAML 2.0 or OIDC enterprise SSO connection","operationId":"configureSSO","responses":{"201":{"description":"SSO connection saved"}}}},"/api/v1/security/domains":{"get":{"summary":"List verified organization domains","operationId":"listVerifiedDomains","responses":{"200":{"description":"List of domains"}}},"post":{"summary":"Register domain for DNS TXT verification","operationId":"registerDomain","responses":{"201":{"description":"Domain registered with verification token"}}}},"/api/v1/security/domains/{id}/verify":{"post":{"summary":"Trigger DNS TXT verification check","operationId":"verifyDomain","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Domain verification result"}}}},"/api/scim/v2/Users":{"get":{"summary":"SCIM 2.0 User List endpoint","operationId":"scimListUsers","responses":{"200":{"description":"SCIM ListResponse"}}},"post":{"summary":"SCIM 2.0 User Provisioning endpoint","operationId":"scimCreateUser","responses":{"201":{"description":"Provisioned SCIM User"}}}},"/api/scim/v2/Users/{id}":{"get":{"summary":"SCIM 2.0 Get User endpoint","operationId":"scimGetUser","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"SCIM User record"}}},"patch":{"summary":"SCIM 2.0 Update/Deactivate User endpoint","operationId":"scimPatchUser","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Updated SCIM User record"}}},"delete":{"summary":"SCIM 2.0 Deprovision User endpoint","operationId":"scimDeleteUser","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Deprovisioned"}}}},"/api/scim/v2/Groups":{"get":{"summary":"SCIM 2.0 Group List endpoint","operationId":"scimListGroups","responses":{"200":{"description":"SCIM Groups ListResponse"}}},"post":{"summary":"SCIM 2.0 Create Group endpoint","operationId":"scimCreateGroup","responses":{"201":{"description":"Provisioned SCIM Group"}}}},"/api/v1/security/scim/tokens":{"get":{"summary":"List dedicated SCIM bearer tokens","operationId":"listSCIMTokens","responses":{"200":{"description":"List of SCIM tokens"}}},"post":{"summary":"Generate dedicated SCIM bearer token","operationId":"generateSCIMToken","responses":{"201":{"description":"Generated token with raw secret shown once"}}}},"/api/v1/security/sessions":{"get":{"summary":"List active user sessions with device and approximate location","operationId":"listUserSessions","responses":{"200":{"description":"Active sessions"}}},"post":{"summary":"Revoke session or all other sessions","operationId":"revokeSession","responses":{"200":{"description":"Session revoked"}}}},"/api/v1/security/mfa":{"get":{"summary":"Get MFA status and recovery codes count","operationId":"getMFAStatus","responses":{"200":{"description":"MFA status"}}},"post":{"summary":"MFA actions: setup (generate secret), verify (activate), disable","operationId":"manageMFA","responses":{"200":{"description":"MFA operation result"}}}},"/api/v1/security/policies":{"get":{"summary":"Get organization security policies (SSO, MFA, IP allowlist, remediation governance)","operationId":"getSecurityPolicy","responses":{"200":{"description":"Security policy"}}},"put":{"summary":"Update organization security policies","operationId":"updateSecurityPolicy","responses":{"200":{"description":"Updated security policy"}}}},"/api/v1/security/audit":{"get":{"summary":"Search immutable audit logs with multi-field filtering","operationId":"searchAuditLogs","responses":{"200":{"description":"Paginated audit logs"}}}},"/api/v1/security/audit/export":{"get":{"summary":"Export immutable audit logs as CSV or JSON","operationId":"exportAuditLogs","responses":{"200":{"description":"Audit export file"}}}},"/api/v1/security/compliance/controls":{"get":{"summary":"Get compliance control readiness library and framework summaries (SOC 2, ISO 27001, GDPR)","operationId":"getComplianceControls","responses":{"200":{"description":"Compliance control readiness"}}}},"/api/v1/security/compliance/evidence":{"get":{"summary":"Get evidence center references for audit and procurement reviews","operationId":"getComplianceEvidence","responses":{"200":{"description":"Evidence items"}}}},"/api/v1/security/vulnerabilities":{"get":{"summary":"List internal vulnerability tracking items","operationId":"listVulnerabilities","responses":{"200":{"description":"Vulnerabilities list"}}},"post":{"summary":"Record or update internal vulnerability","operationId":"recordVulnerability","responses":{"201":{"description":"Recorded vulnerability"}}}},"/api/v1/security/dashboard":{"get":{"summary":"Get consolidated enterprise security posture overview","operationId":"getSecurityDashboard","responses":{"200":{"description":"Security posture metrics"}}}},"/api/v1/security/events":{"get":{"summary":"List security events (auth failure bursts, suspicious API usage, SSRF blocks)","operationId":"listSecurityEvents","responses":{"200":{"description":"Security events"}}}}}}