{"openapi":"3.1.0","info":{"title":"EveryVisitor API","version":"1.0.0","description":"Read sites, scans and accessibility issues, and start scans, from your own tools.\n\nAvailable on the Agency Pro plan. Create a key under Settings → API keys and send it as `Authorization: Bearer psk_…`.\nEach key can make 60 requests per minute; the `X-RateLimit-Remaining` header shows what is left.\nResources in other organisations always return 404."},"servers":[{"url":"https://api.everyvisitor.app/v1"}],"tags":[{"name":"Sites","description":"Monitored websites."},{"name":"Issues","description":"Accessibility problems found by scans."},{"name":"Scans","description":"Scan runs and their results."}],"components":{"securitySchemes":{"apiKey":{"type":"http","scheme":"bearer","description":"An API key starting `psk_`. Scopes: `read`, `scan:write`."}},"schemas":{"Error":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable machine-readable code, e.g. NOT_FOUND."},"message":{"type":"string"},"details":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["code","message","details"],"additionalProperties":false}},"required":["error"],"additionalProperties":false},"Site":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"rootUrl":{"type":"string","format":"uri"},"platform":{"type":"string"},"clientName":{"type":["string","null"]},"status":{"type":"string","enum":["pending_verification","active","paused","error"]},"scanFrequency":{"type":"string","enum":["weekly","daily","manual"]},"pageLimit":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"standard":{"type":"string","enum":["wcag21aa","wcag22aa"]},"score":{"anyOf":[{"type":"integer","minimum":0,"maximum":100},{"type":"null"}]},"lastScanId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}]},"nextScanAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"openCritical":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"openSerious":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"createdAt":{"type":"string","format":"date-time"}},"required":["id","name","rootUrl","platform","clientName","status","scanFrequency","pageLimit","standard","score","lastScanId","nextScanAt","createdAt"],"additionalProperties":{},"description":"A monitored website."},"Issue":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"siteId":{"type":"string","format":"uuid"},"ruleId":{"type":"string","example":"image-alt"},"title":{"type":"string"},"impact":{"type":"string","enum":["critical","serious","moderate","minor"]},"wcagCriteria":{"type":"array","items":{"type":"string"},"example":["1.1.1"]},"wcagLevel":{"type":"string","enum":["A","AA"]},"templateKey":{"type":"string"},"selector":{"type":"string"},"htmlSnippet":{"type":["string","null"]},"status":{"type":"string","enum":["open","fixed","ignored"]},"isRegression":{"type":"boolean"},"occurrenceCount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"dueDate":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}]},"fixedAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"createdAt":{"type":"string","format":"date-time"}},"required":["id","siteId","ruleId","title","impact","wcagCriteria","wcagLevel","templateKey","selector","htmlSnippet","status","isRegression","occurrenceCount","dueDate","fixedAt","createdAt"],"additionalProperties":{},"description":"One accessibility problem, grouped across pages."},"Scan":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"siteId":{"type":"string","format":"uuid"},"trigger":{"type":"string","enum":["scheduled","manual","onboarding","api","plugin"]},"status":{"type":"string","enum":["queued","discovering","scanning","processing","completed","partial","failed","canceled"]},"queuedAt":{"type":"string","format":"date-time"},"startedAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"finishedAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"pagesPlanned":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"pagesScanned":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"score":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"counts":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"number"}},"errorCode":{"type":["string","null"]}},"required":["id","siteId","trigger","status","queuedAt","startedAt","finishedAt","pagesPlanned","pagesScanned","score","counts","errorCode"],"additionalProperties":{}},"CreateScan":{"type":"object","properties":{"standard":{"type":"string","enum":["wcag21aa","wcag22aa"]},"pagesPlanned":{"type":"integer","minimum":1,"maximum":100}},"additionalProperties":false,"description":"All fields optional; the site settings apply."}}},"paths":{"/sites":{"get":{"tags":["Sites"],"security":[{"apiKey":["read"]}],"operationId":"listSites","summary":"List sites","description":"Every site in the organisation with its latest score and open problem counts.","parameters":[{"name":"status","in":"query","schema":{"type":"string","enum":["pending_verification","active","paused","error"]}},{"name":"q","in":"query","description":"Search by name or URL.","schema":{"type":"string"}},{"name":"sort","in":"query","schema":{"type":"string","enum":["score","name","lastScan","openCritical"]}}],"responses":{"200":{"description":"The sites.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"sites":{"type":"array","items":{"$ref":"#/components/schemas/Site"}}}}}},"example":{"data":{"sites":[{"id":"01929b3e-5f0a-7c3d-9a1b-2c3d4e5f6a7b","name":"Oakhaus","rootUrl":"https://oakhaus.com","platform":"shopify","clientName":"Oakhaus Ltd","status":"active","scanFrequency":"weekly","pageLimit":250,"standard":"wcag22aa","score":82,"lastScanId":"01929b40-1111-7c3d-9a1b-2c3d4e5f6a7b","nextScanAt":"2026-10-27T02:00:00.000Z","openCritical":2,"openSerious":7,"createdAt":"2026-08-12T09:15:00.000Z"}]}}}}},"401":{"description":"Missing, invalid or revoked API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"API_KEY_INVALID","message":"This API key is not valid or has been revoked.","details":{}}}}}},"404":{"description":"Not found, or it belongs to another organisation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"NOT_FOUND","message":"Site not found.","details":{}}}}}},"429":{"description":"More than 60 requests in a minute. See the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"RATE_LIMITED","message":"Rate limit exceeded.","details":{"retryAfterSeconds":12}}}}}}}}},"/sites/{siteId}":{"get":{"tags":["Sites"],"security":[{"apiKey":["read"]}],"operationId":"getSite","summary":"Get a site","description":"Site detail with the latest scan summary and the score trend of the last 12 scans.","parameters":[{"name":"siteId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"The site.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"site":{"$ref":"#/components/schemas/Site"},"score":{"type":["integer","null"]},"trend":{"type":"array","items":{"type":"object"}}}}}},"example":{"data":{"site":{"id":"01929b3e-5f0a-7c3d-9a1b-2c3d4e5f6a7b","name":"Oakhaus","rootUrl":"https://oakhaus.com","platform":"shopify","clientName":"Oakhaus Ltd","status":"active","scanFrequency":"weekly","pageLimit":250,"standard":"wcag22aa","score":82,"lastScanId":"01929b40-1111-7c3d-9a1b-2c3d4e5f6a7b","nextScanAt":"2026-10-27T02:00:00.000Z","openCritical":2,"openSerious":7,"createdAt":"2026-08-12T09:15:00.000Z"},"score":82,"trend":[{"scanId":"01929b40-1111-7c3d-9a1b-2c3d4e5f6a7b","score":82,"date":"2026-10-20T02:31:00.000Z"}]}}}}},"401":{"description":"Missing, invalid or revoked API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"API_KEY_INVALID","message":"This API key is not valid or has been revoked.","details":{}}}}}},"404":{"description":"Not found, or it belongs to another organisation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"NOT_FOUND","message":"Site not found.","details":{}}}}}},"429":{"description":"More than 60 requests in a minute. See the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"RATE_LIMITED","message":"Rate limit exceeded.","details":{"retryAfterSeconds":12}}}}}}}}},"/sites/{siteId}/issues":{"get":{"tags":["Issues"],"security":[{"apiKey":["read"]}],"operationId":"listIssues","summary":"List issues for a site","parameters":[{"name":"siteId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"status","in":"query","description":"Comma-separated: open, regressed, needsReview, fixed, ignored.","schema":{"type":"string"}},{"name":"impact","in":"query","description":"Comma-separated: critical, serious, moderate, minor.","schema":{"type":"string"}},{"name":"wcag","in":"query","description":"A WCAG criterion such as 1.4.3.","schema":{"type":"string"}},{"name":"template","in":"query","schema":{"type":"string"}},{"name":"q","in":"query","schema":{"type":"string"}},{"name":"page","in":"query","schema":{"type":"integer","minimum":1,"default":1}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":200,"default":50}}],"responses":{"200":{"description":"A page of issues.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/Issue"}},"total":{"type":"integer"},"page":{"type":"integer"},"totalPages":{"type":"integer"}}}}},"example":{"data":{"items":[{"id":"01929b41-2222-7c3d-9a1b-2c3d4e5f6a7b","siteId":"01929b3e-5f0a-7c3d-9a1b-2c3d4e5f6a7b","ruleId":"image-alt","title":"Images must have alternative text","impact":"critical","wcagCriteria":["1.1.1"],"wcagLevel":"A","templateKey":"product","selector":".product-gallery img","htmlSnippet":"<img src=\"/cdn/shoe.jpg\">","status":"open","isRegression":false,"occurrenceCount":48,"dueDate":null,"fixedAt":null,"createdAt":"2026-09-02T02:14:00.000Z"}],"total":1,"page":1,"limit":50,"totalPages":1}}}}},"401":{"description":"Missing, invalid or revoked API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"API_KEY_INVALID","message":"This API key is not valid or has been revoked.","details":{}}}}}},"404":{"description":"Not found, or it belongs to another organisation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"NOT_FOUND","message":"Site not found.","details":{}}}}}},"429":{"description":"More than 60 requests in a minute. See the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"RATE_LIMITED","message":"Rate limit exceeded.","details":{"retryAfterSeconds":12}}}}}}}}},"/issues/{issueId}":{"get":{"tags":["Issues"],"security":[{"apiKey":["read"]}],"operationId":"getIssue","summary":"Get an issue","parameters":[{"name":"issueId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"The issue.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"issue":{"$ref":"#/components/schemas/Issue"}}}}},"example":{"data":{"issue":{"id":"01929b41-2222-7c3d-9a1b-2c3d4e5f6a7b","siteId":"01929b3e-5f0a-7c3d-9a1b-2c3d4e5f6a7b","ruleId":"image-alt","title":"Images must have alternative text","impact":"critical","wcagCriteria":["1.1.1"],"wcagLevel":"A","templateKey":"product","selector":".product-gallery img","htmlSnippet":"<img src=\"/cdn/shoe.jpg\">","status":"open","isRegression":false,"occurrenceCount":48,"dueDate":null,"fixedAt":null,"createdAt":"2026-09-02T02:14:00.000Z"}}}}}},"401":{"description":"Missing, invalid or revoked API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"API_KEY_INVALID","message":"This API key is not valid or has been revoked.","details":{}}}}}},"404":{"description":"Not found, or it belongs to another organisation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"NOT_FOUND","message":"Site not found.","details":{}}}}}},"429":{"description":"More than 60 requests in a minute. See the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"RATE_LIMITED","message":"Rate limit exceeded.","details":{"retryAfterSeconds":12}}}}}}}}},"/sites/{siteId}/scans":{"get":{"tags":["Scans"],"security":[{"apiKey":["read"]}],"operationId":"listScans","summary":"List scans for a site","description":"Newest first.","parameters":[{"name":"siteId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"The scans.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"scans":{"type":"array","items":{"$ref":"#/components/schemas/Scan"}}}}}},"example":{"data":{"scans":[{"id":"01929b40-1111-7c3d-9a1b-2c3d4e5f6a7b","siteId":"01929b3e-5f0a-7c3d-9a1b-2c3d4e5f6a7b","trigger":"api","status":"queued","queuedAt":"2026-10-21T10:00:00.000Z","startedAt":null,"finishedAt":null,"pagesPlanned":250,"pagesScanned":0,"score":null,"counts":{},"errorCode":null}]}}}}},"401":{"description":"Missing, invalid or revoked API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"API_KEY_INVALID","message":"This API key is not valid or has been revoked.","details":{}}}}}},"404":{"description":"Not found, or it belongs to another organisation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"NOT_FOUND","message":"Site not found.","details":{}}}}}},"429":{"description":"More than 60 requests in a minute. See the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"RATE_LIMITED","message":"Rate limit exceeded.","details":{"retryAfterSeconds":12}}}}}}}},"post":{"tags":["Scans"],"security":[{"apiKey":["scan:write"]}],"operationId":"startScan","summary":"Start a scan","description":"Queues a scan of a verified site. Needs the `scan:write` scope. API scans count toward the same daily allowance as manual scans.","parameters":[{"name":"siteId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateScan"},"example":{"pagesPlanned":100}}}},"responses":{"201":{"description":"Scan queued.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"scan":{"$ref":"#/components/schemas/Scan"}}}}},"example":{"data":{"scan":{"id":"01929b40-1111-7c3d-9a1b-2c3d4e5f6a7b","siteId":"01929b3e-5f0a-7c3d-9a1b-2c3d4e5f6a7b","trigger":"api","status":"queued","queuedAt":"2026-10-21T10:00:00.000Z","startedAt":null,"finishedAt":null,"pagesPlanned":250,"pagesScanned":0,"score":null,"counts":{},"errorCode":null}}}}}},"401":{"description":"Missing, invalid or revoked API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"API_KEY_INVALID","message":"This API key is not valid or has been revoked.","details":{}}}}}},"403":{"description":"The key lacks the scan:write scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"API_KEY_SCOPE","message":"This API key does not have the \"scan:write\" scope.","details":{}}}}}},"404":{"description":"Not found, or it belongs to another organisation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"NOT_FOUND","message":"Site not found.","details":{}}}}}},"409":{"description":"A scan is already running for this site.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"SCAN_IN_PROGRESS","message":"A scan is already running for this site.","details":{}}}}}},"422":{"description":"Site not verified, or the daily scan allowance is used up.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"PLAN_LIMIT","message":"You have used today’s manual scans for this site.","details":{}}}}}},"429":{"description":"More than 60 requests in a minute. See the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"RATE_LIMITED","message":"Rate limit exceeded.","details":{"retryAfterSeconds":12}}}}}}}}},"/scans/{scanId}":{"get":{"tags":["Scans"],"security":[{"apiKey":["read"]}],"operationId":"getScan","summary":"Get a scan","description":"Progress while running; score, counts and changes since the previous scan once finished.","parameters":[{"name":"scanId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"The scan.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"scan":{"$ref":"#/components/schemas/Scan"}}}}},"example":{"data":{"scan":{"id":"01929b40-1111-7c3d-9a1b-2c3d4e5f6a7b","siteId":"01929b3e-5f0a-7c3d-9a1b-2c3d4e5f6a7b","trigger":"api","status":"completed","queuedAt":"2026-10-21T10:00:00.000Z","startedAt":null,"finishedAt":null,"pagesPlanned":250,"pagesScanned":250,"score":84,"counts":{},"errorCode":null}}}}}},"401":{"description":"Missing, invalid or revoked API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"API_KEY_INVALID","message":"This API key is not valid or has been revoked.","details":{}}}}}},"404":{"description":"Not found, or it belongs to another organisation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"NOT_FOUND","message":"Site not found.","details":{}}}}}},"429":{"description":"More than 60 requests in a minute. See the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"RATE_LIMITED","message":"Rate limit exceeded.","details":{"retryAfterSeconds":12}}}}}}}}}}}