CI/CD REST API

Integrate Kuality into your CI pipeline to gate builds on quality thresholds, report coverage, and track test debt over time.

Authentication

All endpoints require a Bearer token issued from your Organization settings page. Include it as an HTTP header:

Authorization: Bearer ku_xxxxxxxxxxxxxxxxxxxx

Rate limit: 60 requests per minute per organization. Excess requests return HTTP 429.

Scans

POST /api/v1/scans

Queue a scan. Returns immediately with a scan_id; poll GET /api/v1/scans/:id for completion.

Request body

{
  "target": "https://example.com",
  "scan_type": "a11y"
}

Response 201

{
  "scan_id": "0193ab21-...",
  "status": "queued",
  "target": "https://example.com",
  "scan_type": "a11y",
  "poll_url": "https://kuality.io/api/v1/scans/0193ab21-..."
}

Test types

web a11y ssl headers tech cms api jsaudit cookie brokenlinks webvitals seo formaudit
GET /api/v1/scans/:id

Poll a scan for completion. Returns report details including score and finding counts. Recommended poll interval: 5–10 seconds.

{
  "scan_id": "0193ab21-...",
  "report_id": "0193ab22-...",
  "status": "completed",
  "scan_type": "a11y",
  "target": "https://example.com",
  "score": 84.0,
  "high": 0,
  "medium": 2,
  "low": 5,
  "total": 7,
  "started_at": "2026-04-17T11:58:00Z",
  "completed_at": "2026-04-17T12:00:00Z",
  "report_url": "https://kuality.io/reports/0193ab22-.../a11y"
}

Reports

Reports are produced by completed scans. Use these endpoints to list historical reports, fetch detailed findings, or export JUnit XML for CI consumers.

GET /api/v1/reports

List completed reports for your organization. Optional query params: scan_type , target , limit (max 100, default 20), offset .

Response 200

{
  "reports": [
    {
      "id": "0193ab22-...",
      "scan_type": "a11y",
      "target": "https://example.com",
      "state": "completed",
      "score": 84.0,
      "high": 0, "medium": 2, "low": 5, "total": 7,
      "created_at": "2026-04-17T12:00:00Z"
    }
  ],
  "limit": 20,
  "offset": 0
}
GET /api/v1/reports/:report_id

Retrieve a single report with the full findings array.

Response 200

{
  "report": {
    "id": "0193ab22-...",
    "scan_type": "a11y",
    "target": "https://example.com",
    "state": "completed",
    "score": 84.0,
    "high": 0, "medium": 2, "low": 5, "total": 7,
    "created_at": "2026-04-17T12:00:00Z",
    "started_at": "2026-04-17T11:58:00Z",
    "completed_at": "2026-04-17T12:00:00Z",
    "findings": [ /* …array of finding objects… */ ]
  }
}
GET /api/v1/reports/:report_id/junit

Returns the report rendered as a JUnit XML test suite — each finding becomes a <testcase> , with high/critical findings marked as <error> and lower-severity findings as <failure> . Compatible with Jenkins, GitHub Actions test reporters, GitLab MR widgets, and CircleCI's Tests tab.

Targets

GET /api/v1/targets

List the verified targets (sites) configured for your organization.

Response 200

{
  "targets": [
    {
      "id": "0193aa10-...",
      "url": "https://example.com",
      "verified": true,
      "added_at": "2026-03-01T10:00:00Z"
    }
  ]
}

Scores

GET /api/v1/scores

Latest Kuality Score per target and scan type. Filter with ?scan_type=a11y to narrow to a single check.

Response 200

{
  "scores": [
    {
      "target": "https://example.com",
      "scan_type": "a11y",
      "score": 91.0,
      "last_scanned": "2026-04-17T12:00:00Z"
    }
  ]
}

Quality Gates

Gate CI deployments on Kuality scores and finding counts. HTTP 200 means all checks passed; HTTP 422 means one or more gates failed. Active alert rules in your organization are also evaluated automatically.

POST /api/v1/gates/evaluate

Evaluates the latest completed test scores for the given target and test types against configured thresholds. Omit scan_types to evaluate all tests, omit target to evaluate all targets.

Request body

{
  "target": "https://example.com",
  "scan_types": ["a11y", "webvitals", "headers"],
  "score_threshold": 70,
  "max_high": 0,
  "max_medium": 5
}

Response 200 — all passed

{
  "status": "pass",
  "passed": true,
  "overall_score": 88.3,
  "summary": { "total_checks": 3, "passed_checks": 3, "failed_checks": 0 },
  "checks": [
    { "scan_type": "a11y", "score": 91.0, "high": 0, "passed": true },
    { "scan_type": "webvitals", "score": 87.5, "high": 0, "passed": true },
    { "scan_type": "headers", "score": 86.4, "high": 0, "passed": true }
  ]
}

Response 422 — gate failed

HTTP 422 — one or more gates failed:
{
  "status": "fail",
  "passed": false,
  "overall_score": 61.2,
  "checks": [
    { "scan_type": "a11y", "score": 58.0, "high": 2, "passed": false,
      "reasons": ["score 58 below threshold 70", "2 high-severity findings (max: 0)"] }
  ]
}

GitHub Actions — gate step

- name: Quality gate
  run: |
    curl -sf -X POST KUALITY_URL/api/v1/gates/evaluate \
      -H "Authorization: Bearer KUALITY_TOKEN" \
      -H "Content-Type: application/json" \
      -d '{"target":"STAGING_URL","score_threshold":70,"max_high":0}'

The -sf flags make curl silent and cause it to exit non-zero on any HTTP ≥ 400 (including the 422 returned when a gate fails), which fails the CI step.

Coverage

POST /api/v1/coverage

Upload test coverage data from your CI run.

{
  "project": "my-app",
  "branch": "main",
  "commit_sha": "abc123",
  "statements_pct": 87.4,
  "branches_pct": 72.1,
  "lines_pct": 88.9,
  "changed_files": ["src/auth.ts", "src/api.ts"]
}
GET /api/v1/coverage

Retrieve the latest coverage summary for your organization.

Mutations & Test Debt

POST /api/v1/mutations

Upload mutation testing results (e.g. from Stryker, mutmut).

{
  "project": "my-app",
  "branch": "main",
  "killed": 142,
  "survived": 18,
  "timeout": 3,
  "score": 88.2
}
POST /api/v1/test-debt

Report test debt metrics (skipped tests, TODO counts, flaky tests).

{
  "project": "my-app",
  "branch": "main",
  "skipped": 4,
  "flaky": 2,
  "todo_count": 11,
  "debt_score": 7.5
}

Public endpoints (no auth)

GET /api/v1/badge?target=example.com&type=web

Returns a shields.io-compatible SVG badge with the current Kuality Score. Embed in your README:

![Kuality Score](https://kuality.io/api/v1/badge?target=example.com&type=web)
GET /api/v1/score-graph?target=example.com

Returns a JSON array of score/date tuples for embedding score history charts.

GET /api/openapi.json

Full OpenAPI 3.1 specification of the CI/CD API. Feed it to your client-generator of choice (openapi-generator, swagger-codegen) to produce a typed SDK in any language.

GitHub Actions example

Gate your PR builds on a minimum Kuality Score. Add this step to your workflow:

- name: Run Kuality tests
  uses: kuality-io/action@v1
  with:
    api-key: ${{ secrets.KUALITY_API_KEY }}
    url: ${{ vars.STAGING_URL }}
    types: a11y,webvitals,seo
    fail-on: high
    score-threshold: 70

Download the full workflow template: kuality-scan.yml

GitLab CI

Add a Kuality quality gate to your GitLab merge request pipelines. Set KUALITY_API_KEY and STAGING_URL as CI/CD variables (Settings → CI/CD → Variables). Mark the API key as masked.

stages:
  - quality

kuality-test:
  stage: quality
  image: golang:alpine
  before_script:
    - apk add --no-cache curl tar
    - curl -fsSL https://github.com/kuality-io/cli/releases/latest/download/kuality_latest_linux_amd64.tar.gz | tar xz
    - mv kuality /usr/local/bin/
  script:
    - kuality test "$STAGING_URL" --type web --fail-on high --format junit > kuality-report.xml
  artifacts:
    when: always
    reports:
      junit: kuality-report.xml

Download the full template: kuality-gitlab-ci.yml

The --format junit flag outputs JUnit XML, which GitLab natively displays in the merge request "Test summary" widget. The --fail-on high flag exits non-zero to block the pipeline if high-severity findings are detected.

Jenkins Pipeline

Add a Kuality quality gate to your Jenkins pipeline. Store your API key as a Jenkins credential (Manage Jenkins → Credentials) with ID kuality-api-key. Set STAGING_URL as a pipeline parameter.

pipeline {
    agent any
    environment {
        KUALITY_API_KEY = credentials('kuality-api-key')
    }
    stages {
        stage('Kuality Test') {
            steps {
                sh 'curl -fsSL https://github.com/kuality-io/cli/releases/latest/download/kuality_latest_linux_amd64.tar.gz | tar xz'
                sh './kuality test "$STAGING_URL" --type web --fail-on high --format junit > kuality-report.xml'
            }
            post {
                always { junit 'kuality-report.xml' }
            }
        }
    }
}

Download the full template: Jenkinsfile-kuality

The junit post-build step publishes JUnit XML results natively in Jenkins. Failed tests appear as test failures in the build report.

CircleCI

Add a Kuality quality gate to your CircleCI workflows. Set KUALITY_API_KEY and STAGING_URL as environment variables (Project Settings → Environment Variables).

version: 2.1
jobs:
  kuality-test:
    docker:
      - image: cimg/base:current
    steps:
      - run:
          name: Install Kuality CLI
          command: |
            curl -fsSL https://github.com/kuality-io/cli/releases/latest/download/kuality_latest_linux_amd64.tar.gz | tar xz
            sudo mv kuality /usr/local/bin/
      - run:
          name: Run Kuality test
          command: kuality test "$STAGING_URL" --type web --fail-on high --format junit > kuality-report.xml
      - store_test_results:
          path: kuality-report.xml

Download the full template: kuality-circleci.yml

The store_test_results step makes JUnit XML results available in the CircleCI "Tests" tab. The store_artifacts step preserves the raw report for download.

Version 1.0.0