{
  "components": {
    "schemas": {
      "Audit": {
        "properties": {
          "_links": {
            "$ref": "#/components/schemas/Links"
          },
          "createdAt": {
            "format": "date-time",
            "type": "string"
          },
          "domain": {
            "type": "string"
          },
          "error": {
            "description": "Why a failed audit failed",
            "oneOf": [
              {
                "$ref": "#/components/schemas/AuditError"
              },
              {
                "type": "null"
              }
            ]
          },
          "finishedAt": {
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "id": {
            "format": "uuid",
            "type": "string"
          },
          "issues": {
            "$ref": "#/components/schemas/Issues"
          },
          "phase": {
            "enum": [
              "queued",
              "discover",
              "crawl",
              "mobile",
              "finalise",
              "done"
            ],
            "type": "string"
          },
          "progress": {
            "$ref": "#/components/schemas/Progress"
          },
          "scores": {
            "description": "Null until the audit completes",
            "oneOf": [
              {
                "$ref": "#/components/schemas/Scores"
              },
              {
                "type": "null"
              }
            ]
          },
          "siteId": {
            "format": "uuid",
            "type": "string"
          },
          "startedAt": {
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "status": {
            "enum": [
              "queued",
              "running",
              "completed",
              "failed",
              "cancelled"
            ],
            "type": "string"
          },
          "url": {
            "description": "The start page",
            "type": "string"
          }
        },
        "required": [
          "id",
          "siteId",
          "domain",
          "url",
          "status",
          "phase",
          "progress",
          "issues",
          "scores",
          "startedAt",
          "finishedAt",
          "createdAt",
          "_links"
        ],
        "type": "object"
      },
      "AuditError": {
        "properties": {
          "code": {
            "type": "string"
          },
          "message": {
            "type": "string"
          }
        },
        "required": [
          "code",
          "message"
        ],
        "type": "object"
      },
      "AuditList": {
        "properties": {
          "audits": {
            "items": {
              "$ref": "#/components/schemas/Audit"
            },
            "type": "array"
          },
          "pagination": {
            "$ref": "#/components/schemas/Pagination"
          }
        },
        "required": [
          "audits",
          "pagination"
        ],
        "type": "object"
      },
      "AuditOptions": {
        "properties": {
          "categories": {
            "description": "Limit to these categories (default all)",
            "items": {
              "enum": [
                "seo",
                "accessibility",
                "security",
                "performance",
                "content",
                "structured-data"
              ],
              "type": "string"
            },
            "type": "array"
          },
          "keyword": {
            "description": "A target keyword for the content checks",
            "type": "string"
          },
          "maxDepth": {
            "description": "Link depth, up to the plan's",
            "type": "integer"
          },
          "maxPages": {
            "description": "Up to the plan's pages per audit (the default)",
            "type": "integer"
          },
          "mobile": {
            "description": "Also audit as a phone (default true where the plan allows)",
            "type": [
              "boolean",
              "null"
            ]
          },
          "path": {
            "description": "Start page path, with siteId",
            "type": "string"
          }
        },
        "type": "object"
      },
      "CreateAudit": {
        "properties": {
          "consent": {
            "description": "Required for an unverified site: you confirm you're allowed to audit it",
            "type": "boolean"
          },
          "options": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/AuditOptions"
              },
              {
                "type": "null"
              }
            ]
          },
          "siteId": {
            "description": "Audit one of your sites from its home page, or from options.path",
            "format": "uuid",
            "type": [
              "string",
              "null"
            ]
          },
          "url": {
            "description": "The page to start from. A site for its domain is added if you don't have one (within your plan's site limit)",
            "type": "string"
          }
        },
        "type": "object"
      },
      "CreateScan": {
        "properties": {
          "url": {
            "description": "A public page, like https://example.com/pricing",
            "type": "string"
          }
        },
        "required": [
          "url"
        ],
        "type": "object"
      },
      "Error": {
        "properties": {
          "error": {
            "$ref": "#/components/schemas/ErrorBody"
          }
        },
        "required": [
          "error"
        ],
        "type": "object"
      },
      "ErrorBody": {
        "properties": {
          "code": {
            "description": "Stable, machine-readable: see the error codes guide",
            "type": "string"
          },
          "message": {
            "description": "For people; may change",
            "type": "string"
          },
          "scope": {
            "description": "The scope the key lacks (missing_scope only)",
            "type": "string"
          }
        },
        "required": [
          "code",
          "message"
        ],
        "type": "object"
      },
      "Finding": {
        "properties": {
          "category": {
            "type": "string"
          },
          "device": {
            "enum": [
              "desktop",
              "mobile"
            ],
            "type": "string"
          },
          "helpUrl": {
            "type": "string"
          },
          "id": {
            "format": "uuid",
            "type": "string"
          },
          "message": {
            "type": "string"
          },
          "pageUrl": {
            "description": "Empty for site-wide findings",
            "type": "string"
          },
          "recommendation": {
            "type": "string"
          },
          "ruleId": {
            "description": "See the rule reference: /rules/{ruleId} on docs.kritano.com",
            "type": "string"
          },
          "ruleName": {
            "type": "string"
          },
          "selector": {
            "type": "string"
          },
          "severity": {
            "enum": [
              "critical",
              "serious",
              "moderate",
              "minor",
              "info"
            ],
            "type": "string"
          },
          "snippet": {
            "type": "string"
          },
          "status": {
            "enum": [
              "active",
              "acknowledged",
              "dismissed"
            ],
            "type": "string"
          },
          "wcag": {
            "description": "WCAG success criteria, e.g. 1.1.1",
            "items": {
              "type": "string"
            },
            "type": "array"
          }
        },
        "required": [
          "id",
          "ruleId",
          "ruleName",
          "category",
          "severity",
          "message",
          "pageUrl",
          "device",
          "status"
        ],
        "type": "object"
      },
      "FindingList": {
        "properties": {
          "findings": {
            "items": {
              "$ref": "#/components/schemas/Finding"
            },
            "type": "array"
          },
          "pagination": {
            "$ref": "#/components/schemas/Pagination"
          }
        },
        "required": [
          "findings",
          "pagination"
        ],
        "type": "object"
      },
      "FindingStatus": {
        "properties": {
          "status": {
            "description": "dismissed hides a finding (a false positive); acknowledged marks it as known",
            "enum": [
              "active",
              "acknowledged",
              "dismissed"
            ],
            "type": "string"
          }
        },
        "required": [
          "status"
        ],
        "type": "object"
      },
      "Info": {
        "properties": {
          "documentation": {
            "type": "string"
          },
          "key": {
            "$ref": "#/components/schemas/KeyInfo"
          },
          "limits": {
            "$ref": "#/components/schemas/Limits"
          },
          "plan": {
            "description": "The key owner's plan",
            "type": "string"
          },
          "scopes": {
            "description": "What this key may do",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "version": {
            "description": "The API version",
            "type": "string"
          }
        },
        "required": [
          "version",
          "plan",
          "limits",
          "key",
          "scopes",
          "documentation"
        ],
        "type": "object"
      },
      "Issues": {
        "properties": {
          "critical": {
            "type": "integer"
          },
          "total": {
            "type": "integer"
          }
        },
        "required": [
          "total",
          "critical"
        ],
        "type": "object"
      },
      "KeyInfo": {
        "properties": {
          "id": {
            "format": "uuid",
            "type": "string"
          },
          "name": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "name"
        ],
        "type": "object"
      },
      "Limits": {
        "properties": {
          "auditsPerMonth": {
            "type": "integer"
          },
          "auditsThisMonth": {
            "type": "integer"
          },
          "concurrentAudits": {
            "type": "integer"
          },
          "pagesPerAudit": {
            "type": "integer"
          },
          "requestsPerDay": {
            "description": "Per key, UTC days",
            "type": "integer"
          },
          "requestsPerMinute": {
            "description": "Per key",
            "type": "integer"
          },
          "scansPerDay": {
            "description": "One-page scans, UTC days",
            "type": "integer"
          },
          "scansToday": {
            "type": "integer"
          },
          "sites": {
            "type": "integer"
          }
        },
        "required": [
          "requestsPerMinute",
          "requestsPerDay",
          "concurrentAudits",
          "auditsPerMonth",
          "auditsThisMonth",
          "pagesPerAudit",
          "scansPerDay",
          "scansToday",
          "sites"
        ],
        "type": "object"
      },
      "Links": {
        "properties": {
          "app": {
            "description": "The audit in the Kritano app",
            "type": "string"
          },
          "findings": {
            "type": "string"
          },
          "self": {
            "type": "string"
          }
        },
        "required": [
          "self",
          "findings",
          "app"
        ],
        "type": "object"
      },
      "Pagination": {
        "properties": {
          "limit": {
            "type": "integer"
          },
          "page": {
            "type": "integer"
          },
          "pages": {
            "type": "integer"
          },
          "total": {
            "type": "integer"
          }
        },
        "required": [
          "page",
          "limit",
          "total",
          "pages"
        ],
        "type": "object"
      },
      "Progress": {
        "properties": {
          "pagesCrawled": {
            "type": "integer"
          },
          "pagesFailed": {
            "type": "integer"
          },
          "pagesFound": {
            "type": "integer"
          }
        },
        "required": [
          "pagesFound",
          "pagesCrawled",
          "pagesFailed"
        ],
        "type": "object"
      },
      "Scan": {
        "properties": {
          "_links": {
            "$ref": "#/components/schemas/ScanLinks"
          },
          "createdAt": {
            "format": "date-time",
            "type": "string"
          },
          "error": {
            "description": "Why a failed scan failed",
            "oneOf": [
              {
                "$ref": "#/components/schemas/AuditError"
              },
              {
                "type": "null"
              }
            ]
          },
          "finishedAt": {
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "id": {
            "format": "uuid",
            "type": "string"
          },
          "result": {
            "description": "Null until the scan completes",
            "oneOf": [
              {
                "$ref": "#/components/schemas/ScanResult"
              },
              {
                "type": "null"
              }
            ]
          },
          "status": {
            "enum": [
              "queued",
              "running",
              "completed",
              "failed"
            ],
            "type": "string"
          },
          "url": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "url",
          "status",
          "result",
          "createdAt",
          "finishedAt",
          "_links"
        ],
        "type": "object"
      },
      "ScanFinding": {
        "properties": {
          "category": {
            "type": "string"
          },
          "message": {
            "type": "string"
          },
          "recommendation": {
            "type": "string"
          },
          "ruleId": {
            "type": "string"
          },
          "ruleName": {
            "type": "string"
          },
          "selector": {
            "type": "string"
          },
          "severity": {
            "enum": [
              "critical",
              "serious",
              "moderate",
              "minor",
              "info"
            ],
            "type": "string"
          },
          "wcag": {
            "items": {
              "type": "string"
            },
            "type": "array"
          }
        },
        "required": [
          "ruleId",
          "ruleName",
          "category",
          "severity",
          "message"
        ],
        "type": "object"
      },
      "ScanLinks": {
        "properties": {
          "self": {
            "type": "string"
          }
        },
        "required": [
          "self"
        ],
        "type": "object"
      },
      "ScanResult": {
        "properties": {
          "finalUrl": {
            "description": "Where the page ended up after redirects",
            "type": "string"
          },
          "findings": {
            "description": "Worst first",
            "items": {
              "$ref": "#/components/schemas/ScanFinding"
            },
            "type": "array"
          },
          "httpStatus": {
            "type": "integer"
          },
          "overall": {
            "description": "The mean of the category scores",
            "type": [
              "integer",
              "null"
            ]
          },
          "scores": {
            "additionalProperties": {
              "type": "integer"
            },
            "description": "0–100 per category",
            "type": "object"
          }
        },
        "required": [
          "finalUrl",
          "httpStatus",
          "overall",
          "scores",
          "findings"
        ],
        "type": "object"
      },
      "Scores": {
        "properties": {
          "contentQuality": {
            "type": [
              "integer",
              "null"
            ]
          },
          "desktop": {
            "additionalProperties": {
              "type": "integer"
            },
            "type": "object"
          },
          "mobile": {
            "additionalProperties": {
              "type": "integer"
            },
            "type": "object"
          },
          "overall": {
            "description": "The mean of the desktop category scores",
            "type": [
              "integer",
              "null"
            ]
          }
        },
        "required": [
          "overall",
          "desktop"
        ],
        "type": "object"
      },
      "Site": {
        "properties": {
          "createdAt": {
            "format": "date-time",
            "type": "string"
          },
          "domain": {
            "type": "string"
          },
          "id": {
            "format": "uuid",
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "verified": {
            "description": "Unverified sites are audited 3 pages at a time, slowly",
            "type": "boolean"
          },
          "verifiedAt": {
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "id",
          "domain",
          "name",
          "verified",
          "verifiedAt",
          "createdAt"
        ],
        "type": "object"
      },
      "SiteList": {
        "properties": {
          "pagination": {
            "$ref": "#/components/schemas/Pagination"
          },
          "sites": {
            "items": {
              "$ref": "#/components/schemas/Site"
            },
            "type": "array"
          }
        },
        "required": [
          "sites",
          "pagination"
        ],
        "type": "object"
      }
    },
    "securitySchemes": {
      "apiKey": {
        "in": "header",
        "name": "X-API-Key",
        "type": "apiKey"
      },
      "bearer": {
        "description": "An API key: kt_live_\u003cid\u003e_\u003csecret\u003e",
        "scheme": "bearer",
        "type": "http"
      }
    }
  },
  "info": {
    "contact": {
      "name": "Kritano",
      "url": "https://kritano.com/contact"
    },
    "description": "The Kritano API runs audits and reads their results: the same sites, audits and findings as the app.\n\nAuthenticate with an API key from Settings → API keys in the app, sent as `Authorization: Bearer kt_live_…` (or an `X-API-Key` header). A key acts as you, limited to its scopes. API access comes with the Pro and Agency plans.\n\nRate limits are per key and depend on your plan; every response carries `X-RateLimit-Limit`, `X-RateLimit-Remaining` and `X-RateLimit-Reset`. Errors share one shape: `{\"error\": {\"code\": \"…\", \"message\": \"…\"}}`.",
    "title": "Kritano API",
    "version": "1.0.0"
  },
  "openapi": "3.1.0",
  "paths": {
    "/audits": {
      "get": {
        "description": "Needs the `audits:read` scope.",
        "operationId": "listAudits",
        "parameters": [
          {
            "in": "query",
            "name": "status",
            "required": false,
            "schema": {
              "enum": [
                "queued",
                "running",
                "completed",
                "failed",
                "cancelled"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only this site's audits",
            "in": "query",
            "name": "domain",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Only this site's audits",
            "in": "query",
            "name": "siteId",
            "required": false,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          },
          {
            "description": "From 1",
            "in": "query",
            "name": "page",
            "required": false,
            "schema": {
              "type": "integer"
            }
          },
          {
            "description": "Per page: default 20, at most 100",
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuditList"
                }
              }
            },
            "description": "OK",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests allowed a minute",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Left this minute",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "When the minute's count resets (Unix seconds)",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "No key, or the key is invalid, expired or revoked (key_required, key_invalid)"
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The key lacks a scope, or the plan doesn't allow it (missing_scope, plan_no_api, plan_limit)"
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Not found, or not yours (not_found)"
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Over the rate limit (rate_limited, rate_limited_daily)",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        },
        "summary": "List your audits, newest first",
        "tags": [
          "Audits"
        ],
        "x-kritano-scope": "audits:read"
      },
      "post": {
        "description": "Starts an audit of one of your sites, by `siteId` or by `url`. A `url` on a domain you haven't added adds it as a site (within your plan's site limit). The audit runs in the background: poll `GET /audits/{id}` until `status` is `completed`, `failed` or `cancelled`.\n\nNeeds the `audits:write` scope.",
        "operationId": "createAudit",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateAudit"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Audit"
                }
              }
            },
            "description": "Created",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests allowed a minute",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Left this minute",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "When the minute's count resets (Unix seconds)",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The request isn't valid (invalid_request, invalid_body)"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "No key, or the key is invalid, expired or revoked (key_required, key_invalid)"
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The key lacks a scope, or the plan doesn't allow it (missing_scope, plan_no_api, plan_limit)"
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Not found, or not yours (not_found)"
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The site already has an audit running, or the audit has finished (audit_running, audit_finished)"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The site isn't verified and consent wasn't given (consent_required)"
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Over the rate limit (rate_limited, rate_limited_daily)",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        },
        "summary": "Start an audit",
        "tags": [
          "Audits"
        ],
        "x-kritano-scope": "audits:write"
      }
    },
    "/audits/{id}": {
      "delete": {
        "description": "Needs the `audits:write` scope.",
        "operationId": "deleteAudit",
        "parameters": [
          {
            "description": "Audit id",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "No Content",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests allowed a minute",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Left this minute",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "When the minute's count resets (Unix seconds)",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The request isn't valid (invalid_request, invalid_body)"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "No key, or the key is invalid, expired or revoked (key_required, key_invalid)"
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The key lacks a scope, or the plan doesn't allow it (missing_scope, plan_no_api, plan_limit)"
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Not found, or not yours (not_found)"
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The site already has an audit running, or the audit has finished (audit_running, audit_finished)"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The site isn't verified and consent wasn't given (consent_required)"
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Over the rate limit (rate_limited, rate_limited_daily)",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        },
        "summary": "Delete a finished audit and its results",
        "tags": [
          "Audits"
        ],
        "x-kritano-scope": "audits:write"
      },
      "get": {
        "description": "Needs the `audits:read` scope.",
        "operationId": "getAudit",
        "parameters": [
          {
            "description": "Audit id",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Audit"
                }
              }
            },
            "description": "OK",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests allowed a minute",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Left this minute",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "When the minute's count resets (Unix seconds)",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "No key, or the key is invalid, expired or revoked (key_required, key_invalid)"
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The key lacks a scope, or the plan doesn't allow it (missing_scope, plan_no_api, plan_limit)"
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Not found, or not yours (not_found)"
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Over the rate limit (rate_limited, rate_limited_daily)",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        },
        "summary": "An audit's progress and scores",
        "tags": [
          "Audits"
        ],
        "x-kritano-scope": "audits:read"
      }
    },
    "/audits/{id}/cancel": {
      "post": {
        "description": "Needs the `audits:write` scope.",
        "operationId": "cancelAudit",
        "parameters": [
          {
            "description": "Audit id",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Audit"
                }
              }
            },
            "description": "OK",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests allowed a minute",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Left this minute",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "When the minute's count resets (Unix seconds)",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The request isn't valid (invalid_request, invalid_body)"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "No key, or the key is invalid, expired or revoked (key_required, key_invalid)"
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The key lacks a scope, or the plan doesn't allow it (missing_scope, plan_no_api, plan_limit)"
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Not found, or not yours (not_found)"
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The site already has an audit running, or the audit has finished (audit_running, audit_finished)"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The site isn't verified and consent wasn't given (consent_required)"
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Over the rate limit (rate_limited, rate_limited_daily)",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        },
        "summary": "Stop a queued or running audit",
        "tags": [
          "Audits"
        ],
        "x-kritano-scope": "audits:write"
      }
    },
    "/audits/{id}/export": {
      "get": {
        "description": "CSV is one row per finding. JSON is the audit, its pages and its findings.\n\nNeeds the `exports:read` scope.",
        "operationId": "exportAudit",
        "parameters": [
          {
            "description": "Audit id",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          },
          {
            "description": "Default json",
            "in": "query",
            "name": "format",
            "required": false,
            "schema": {
              "enum": [
                "json",
                "csv"
              ],
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "type": "string"
                }
              },
              "text/csv": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "description": "OK",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests allowed a minute",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Left this minute",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "When the minute's count resets (Unix seconds)",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "No key, or the key is invalid, expired or revoked (key_required, key_invalid)"
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The key lacks a scope, or the plan doesn't allow it (missing_scope, plan_no_api, plan_limit)"
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Not found, or not yours (not_found)"
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Over the rate limit (rate_limited, rate_limited_daily)",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        },
        "summary": "Download a completed audit",
        "tags": [
          "Exports"
        ],
        "x-kritano-scope": "exports:read"
      }
    },
    "/audits/{id}/findings": {
      "get": {
        "description": "Dismissed findings are included; filter with `status=active` to leave them out.\n\nNeeds the `findings:read` scope.",
        "operationId": "listFindings",
        "parameters": [
          {
            "description": "Audit id",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          },
          {
            "description": "`content` includes content-eeat and content-aeo",
            "in": "query",
            "name": "category",
            "required": false,
            "schema": {
              "enum": [
                "seo",
                "accessibility",
                "security",
                "performance",
                "content",
                "structured-data",
                "content-eeat",
                "content-aeo"
              ],
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "severity",
            "required": false,
            "schema": {
              "enum": [
                "critical",
                "serious",
                "moderate",
                "minor",
                "info"
              ],
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "status",
            "required": false,
            "schema": {
              "enum": [
                "active",
                "acknowledged",
                "dismissed"
              ],
              "type": "string"
            }
          },
          {
            "description": "From 1",
            "in": "query",
            "name": "page",
            "required": false,
            "schema": {
              "type": "integer"
            }
          },
          {
            "description": "Per page: default 20, at most 100",
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FindingList"
                }
              }
            },
            "description": "OK",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests allowed a minute",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Left this minute",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "When the minute's count resets (Unix seconds)",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "No key, or the key is invalid, expired or revoked (key_required, key_invalid)"
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The key lacks a scope, or the plan doesn't allow it (missing_scope, plan_no_api, plan_limit)"
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Not found, or not yours (not_found)"
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Over the rate limit (rate_limited, rate_limited_daily)",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        },
        "summary": "An audit's findings, worst first",
        "tags": [
          "Findings"
        ],
        "x-kritano-scope": "findings:read"
      }
    },
    "/audits/{id}/findings/{findingId}": {
      "patch": {
        "description": "A dismissed finding stays dismissed in later audits of the same site. Scores aren't changed: they're a record of the audit as it ran.\n\nNeeds the `findings:write` scope.",
        "operationId": "setFindingStatus",
        "parameters": [
          {
            "description": "Audit id",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "findingId",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/FindingStatus"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Finding"
                }
              }
            },
            "description": "OK",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests allowed a minute",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Left this minute",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "When the minute's count resets (Unix seconds)",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The request isn't valid (invalid_request, invalid_body)"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "No key, or the key is invalid, expired or revoked (key_required, key_invalid)"
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The key lacks a scope, or the plan doesn't allow it (missing_scope, plan_no_api, plan_limit)"
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Not found, or not yours (not_found)"
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The site already has an audit running, or the audit has finished (audit_running, audit_finished)"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The site isn't verified and consent wasn't given (consent_required)"
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Over the rate limit (rate_limited, rate_limited_daily)",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        },
        "summary": "Dismiss or acknowledge a finding",
        "tags": [
          "Findings"
        ],
        "x-kritano-scope": "findings:write"
      }
    },
    "/info": {
      "get": {
        "operationId": "getInfo",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Info"
                }
              }
            },
            "description": "OK",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests allowed a minute",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Left this minute",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "When the minute's count resets (Unix seconds)",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "No key, or the key is invalid, expired or revoked (key_required, key_invalid)"
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The key lacks a scope, or the plan doesn't allow it (missing_scope, plan_no_api, plan_limit)"
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Over the rate limit (rate_limited, rate_limited_daily)",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        },
        "summary": "Your key, plan and limits",
        "tags": [
          "Account"
        ]
      }
    },
    "/openapi.json": {
      "get": {
        "operationId": "getOpenAPI",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "description": "OK"
          }
        },
        "security": [],
        "summary": "This reference, as OpenAPI 3.1",
        "tags": [
          "Account"
        ]
      }
    },
    "/scans": {
      "post": {
        "description": "Loads one public page and scores it, without adding a site to your account: for a quick check of any address, such as an \"audit your site\" box. It runs in the background, usually in 5–20 seconds: poll `GET /scans/{id}` until `status` is `completed` or `failed`. A scan of the same URL in the last hour is returned instead of a new one (status 200, not 201), and doesn't count towards your daily scans.\n\nNeeds the `scans:run` scope.",
        "operationId": "createScan",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateScan"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Scan"
                }
              }
            },
            "description": "Created",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests allowed a minute",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Left this minute",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "When the minute's count resets (Unix seconds)",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The request isn't valid (invalid_request, invalid_body)"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "No key, or the key is invalid, expired or revoked (key_required, key_invalid)"
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The key lacks a scope, or the plan doesn't allow it (missing_scope, plan_no_api, plan_limit)"
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Over the rate limit (rate_limited, rate_limited_daily)",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        },
        "summary": "Scan one page",
        "tags": [
          "Scans"
        ],
        "x-kritano-scope": "scans:run"
      }
    },
    "/scans/{id}": {
      "get": {
        "description": "Needs the `scans:run` scope.",
        "operationId": "getScan",
        "parameters": [
          {
            "description": "Scan id",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Scan"
                }
              }
            },
            "description": "OK",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests allowed a minute",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Left this minute",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "When the minute's count resets (Unix seconds)",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "No key, or the key is invalid, expired or revoked (key_required, key_invalid)"
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The key lacks a scope, or the plan doesn't allow it (missing_scope, plan_no_api, plan_limit)"
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Not found, or not yours (not_found)"
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Over the rate limit (rate_limited, rate_limited_daily)",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        },
        "summary": "A scan's status and result",
        "tags": [
          "Scans"
        ],
        "x-kritano-scope": "scans:run"
      }
    },
    "/sites": {
      "get": {
        "description": "Needs the `audits:read` scope.",
        "operationId": "listSites",
        "parameters": [
          {
            "description": "From 1",
            "in": "query",
            "name": "page",
            "required": false,
            "schema": {
              "type": "integer"
            }
          },
          {
            "description": "Per page: default 20, at most 100",
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SiteList"
                }
              }
            },
            "description": "OK",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests allowed a minute",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Left this minute",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "When the minute's count resets (Unix seconds)",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "No key, or the key is invalid, expired or revoked (key_required, key_invalid)"
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "The key lacks a scope, or the plan doesn't allow it (missing_scope, plan_no_api, plan_limit)"
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Not found, or not yours (not_found)"
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Over the rate limit (rate_limited, rate_limited_daily)",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        },
        "summary": "List your sites",
        "tags": [
          "Sites"
        ],
        "x-kritano-scope": "audits:read"
      }
    }
  },
  "security": [
    {
      "bearer": []
    },
    {
      "apiKey": []
    }
  ],
  "servers": [
    {
      "url": "https://app.kritano.com/api/v1"
    }
  ],
  "tags": [
    {
      "name": "Account"
    },
    {
      "name": "Sites"
    },
    {
      "name": "Audits"
    },
    {
      "name": "Findings"
    },
    {
      "name": "Exports"
    },
    {
      "name": "Scans"
    }
  ]
}
