Barrierefreiheit in CI/CD: API, Webhooks und Pre-Publish-Check

Mit der Reviseberg-API holen Sie Barrierefreiheitsbefunde in Ihre eigenen Systeme, mit Webhooks reagieren Sie auf abgeschlossene Crawls, und mit dem Pre-Publish-Check fragt Ihre CI-Pipeline vor dem Release, ob eine Seite Ihre Schwelle einhält. Die Befunde sind dieselben wie in der App: axe-core-Regeln auf gerenderten Seiten, Ergebnisse des Tastatur-Agenten und ein WCAG-2.2-Status je Kriterium.

Drei Wege in Ihre Toolchain

Drei Wege in Ihre Toolchain
WegWofürVerfügbar
REST-APIWebsites, offene Issues, Score-Verlauf und Crawls in eigene Dashboards, Tickets oder Berichte übernehmenmit einem API-Schlüssel: Starter 2, Growth 10 und Enterprise nach Vereinbarung; im kostenlosen Konto keine
Pre-Publish-CheckEine Seite der Vorschau- oder Staging-Umgebung vor dem Release prüfen und den Build bei Überschreitung Ihrer Schwelle scheitern lassenTeil der REST-API, mit denselben Schlüsseln
WebhooksAuf abgeschlossene Crawls, neue kritische Issues, Score-Rückgänge und Ausfälle reagierenin jedem Konto, eingerichtet von einem Admin

Dazu kommen der MCP Server für Coding-Agenten und der CSV-Export. Enterprise enthält außerdem, dass wir den Pre-Publish-Check gemeinsam mit Ihnen in Ihre CI einbauen.

REST-API

Die API spricht JSON unter https://reviseberg.com/api/v1 und authentifiziert sich mit einem API-Schlüssel im Header Authorization: Bearer bz_…. Den Schlüssel legt ein Admin in der App unter Settings → API an; er wird genau einmal angezeigt, lässt sich auf einzelne Websites beschränken und gilt, bis Sie ihn widerrufen.

REST-API
EndpunktWas er liefert
GET /api/v1/sitesDie Websites, die der Schlüssel sehen darf: ID, Name, Adresse, Seitenlimit, Crawl-Rhythmus, letzter Crawl
GET /api/v1/issues?site=IDDie offenen Issues des letzten abgeschlossenen Crawls: Regel, Schweregrad, WCAG-Stufe und -Kriterien, Vorkommen, Seiten, Punkte zurück und Hilfe-Link, dazu ein Score
GET /api/v1/sites/ID/scoresDer Score-Verlauf über die letzten bis zu 90 abgeschlossenen Crawls
GET /api/v1/sites/ID/crawlsDie letzten Läufe mit Status, Auslöser, Start- und Endzeit – so sehen Sie, ob ein Lauf fertig ist
POST /api/v1/prepublishStellt die Prüfung einer Seite in die Warteschlange (siehe unten)
GET /api/v1/prepublish/IDStatus und Urteil dieser Prüfung

Issues mit dem Präfix qa: gehören zur Qualität (etwa defekte Links), seo: zur Suche; alle anderen, auch die keyboard:-Regeln des Agenten, zur Barrierefreiheit.

curl -s "https://reviseberg.com/api/v1/sites" \
  -H "Authorization: Bearer $REVISEBERG_API_KEY"

Eine eigene API-Referenz-Website gibt es noch nicht; diese Tabelle ist die vollständige Liste. Einen Crawl der ganzen Website startet die REST-API nicht – das tun Sie in der App, per Zeitplan oder über das Tool run_scan des MCP Servers.

Ein häufiger Einsatz: Tickets anlegen. Eine direkte Jira-, GitLab- oder GitHub-Issue-Integration gibt es nicht. Mit der API oder einem Webhook bauen Sie diese Brücke selbst – mit dem Vorteil, dass Sie bestimmen, welche Befunde ein Ticket wert sind.

Webhooks

Reviseberg sendet einen HTTP-POST an eine HTTPS-Adresse Ihrer Wahl, wenn etwas passiert. Nach jedem Crawl geht genau eine Nachricht hinaus, und zwar die wichtigste: crawl_failed, sonst new_critical (neue kritische Issues), sonst score_drop (der Score ist gefallen), sonst scan_finished. Für die Verfügbarkeitsüberwachung kommen uptime_down und uptime_up hinzu – je einmal beim Ausfall und bei der Erholung, nicht bei jeder Prüfung.

Ein Webhook hat eines von zwei Formaten:

  • Slack-Format: {"text": "…"} – eine Zeile, die Slack und Microsoft Teams als Nachricht anzeigen.
  • Generisch: event, title, text, url (der Link zum Bericht), site, data und at. Bei einem Crawl enthält data den Score und die Zahl der offenen und der kritischen Issues.

Die Adresse selbst ist der Zugang – wie bei Slack. Anfragen werden nicht signiert; behandeln Sie die Adresse deshalb wie ein Passwort. Reviseberg akzeptiert nur https://, zeigt sie in der App nur gekürzt an, stellt jede Nachricht einmal mit zehn Sekunden Zeitlimit zu und schreibt einen Fehler an den Webhook, damit Sie sehen, warum der Kanal still ist.

Pre-Publish-Check in GitHub Actions und GitLab CI

Der Pre-Publish-Check prüft eine Seite, bevor Sie veröffentlichen: axe-core in beiden Breiten, ohne Tastatur-Agent und ohne Linkprüfung. Ihre Pipeline schickt die Adresse, erhält eine Prüf-ID und fragt nach, bis das Urteil da ist:

  • POST https://reviseberg.com/api/v1/prepublish mit {"url": "https://…"} antwortet mit 202 und check.id.
  • GET https://reviseberg.com/api/v1/prepublish/ID liefert check.status (queued, running, done oder failed) und, sobald er done ist, verdict (pass oder fail), die Zählung je Schweregrad und die Befunde mit Regel, Selektor und Meldung.
  • Ihre Schwelle geben Sie beim Abfragen mit: minSeverity (ab welchem Schweregrad gezählt wird, Standard minor) und maxFailures (wie viele davon Sie hinnehmen, Standard 0).

Das Urteil ist bewusst ein Zählen und kein Score: Ein Tor, das einen Build durchlässt, weil die Zahl noch bei 91 lag, vertraut niemand. Fälle, die axe-core nicht entscheiden kann, werden gemeldet, aber nie als Fehler gezählt.

Die Adresse muss zu einer Website in Ihrem Konto gehören – derselbe Host oder eine Subdomain davon, etwa staging.example.com für example.com. Eine Vorschau auf einem ganz anderen Host legen Sie als eigene Website an. Liegt Ihre Staging-Umgebung hinter einem Login, hinterlegen Sie diesen an der Website (Browser-Passwortabfrage, Login-Formular, Token-Header oder ein Proxy); er wird verschlüsselt gespeichert und nur an diesen Host geschickt. Der Crawler meldet sich als RevisebergBot und hält sich an die robots.txt – eine Staging-Umgebung, die alle Crawler aussperrt, muss ihn zulassen.

Die Logik liegt in einem kleinen Skript, das beide CI-Systeme nutzen:

#!/usr/bin/env bash
# scripts/reviseberg-check.sh – eine Seite vor dem Release prüfen
set -euo pipefail
: "${REVISEBERG_API_KEY:?}" "${PREVIEW_URL:?}"
API="https://reviseberg.com/api/v1"
AUTH="Authorization: Bearer $REVISEBERG_API_KEY"
MIN_SEVERITY="${MIN_SEVERITY:-serious}"   # nur schwerwiegend und kritisch zählen
MAX_FAILURES="${MAX_FAILURES:-0}"         # wie viele davon Sie hinnehmen

CHECK=$(curl -sf -X POST "$API/prepublish" -H "$AUTH" \
  -H "Content-Type: application/json" \
  -d "{\"url\":\"$PREVIEW_URL\"}" | jq -r '.check.id')

for i in $(seq 1 60); do                  # bis zu 10 Minuten
  RESULT=$(curl -sf "$API/prepublish/$CHECK?minSeverity=$MIN_SEVERITY&maxFailures=$MAX_FAILURES" -H "$AUTH")
  STATUS=$(jq -r '.check.status' <<<"$RESULT")
  if [ "$STATUS" = "done" ] || [ "$STATUS" = "failed" ]; then break; fi
  sleep 10
done

jq -r '.findings[]? | "\(.severity)\t\(.rule)\t\(.selector)"' <<<"$RESULT"
echo "Status: $STATUS · Urteil: $(jq -r '.verdict' <<<"$RESULT")"
if [ "$(jq -r '.verdict' <<<"$RESULT")" != "pass" ]; then
  echo "::error::Barrierefreiheits-Schwelle nicht erreicht für $PREVIEW_URL"; exit 1
fi

GitHub Actions (.github/workflows/accessibility.yml):

name: Barrierefreiheit vor dem Release
on:
  pull_request:
  workflow_dispatch:
jobs:
  reviseberg:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Reviseberg Pre-Publish-Check
        run: bash scripts/reviseberg-check.sh
        env:
          REVISEBERG_API_KEY: ${{ secrets.REVISEBERG_API_KEY }}
          PREVIEW_URL: "https://staging.example.com/kasse/"
          MIN_SEVERITY: "serious"

GitLab CI (.gitlab-ci.yml):

reviseberg:
  stage: test
  image: alpine:3.20
  before_script:
    - apk add --no-cache bash curl jq
  script:
    - bash scripts/reviseberg-check.sh
  variables:
    PREVIEW_URL: "https://staging.example.com/kasse/"
    MIN_SEVERITY: "serious"
  rules:
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"

Den API-Schlüssel hinterlegen Sie als geschütztes Secret (GitHub) bzw. als maskierte CI/CD-Variable (GitLab), nie im Repository. Jeder Aufruf prüft eine Seite; für mehrere Seiten – Startseite, Produktseite, Kasse – rufen Sie das Skript mehrmals auf.

Schwellen, die sich bewähren

Die Schwelle legen Sie fest, nicht wir. Drei Muster haben sich bewährt:

  1. Nichts Schweres durchlassen: MIN_SEVERITY=serious, MAX_FAILURES=0. Der Build scheitert bei jedem schwerwiegenden oder kritischen Befund auf der geprüften Seite. Ein guter Start für die Seiten, die Umsatz tragen.
  2. Eine Ratsche: Setzen Sie MAX_FAILURES auf die heutige Zahl und senken Sie sie nach jeder Verbesserung. So geht es nur in eine Richtung.
  3. Null Toleranz für bestimmte Regeln: Werten Sie die Liste findings selbst aus und lassen Sie den Build bei bestimmten Regeln scheitern, etwa fehlenden Formular-Labels (label) – Barrieren, die Nutzende komplett aussperren.

Der Check vergleicht nicht mit dem Stand der Live-Website; er zählt, was er auf der geprüften Seite findet. Ein bestandener Check heißt auch nicht, dass die Seite konform ist. Er heißt, dass die automatischen Prüfungen nichts gefunden haben, was Ihre Schwelle verletzt. Kriterien, die ein Mensch beurteilen muss, bleiben „ungeprüft“ – mehr dazu in der Prüfmethodik.

axe-core im Build und Reviseberg: beides

Komponententests mit axe-core (z. B. in Playwright oder Jest) fangen Fehler früh, direkt beim Entwickeln. Sie sehen aber nur die Zustände, die Ihre Tests erzeugen. Reviseberg prüft die fertig gerenderte Website über viele Seiten, lässt den Tastatur-Agenten Ihre Nutzerreisen gehen und hält die Historie, den WCAG-Status und die Erklärung zur Barrierefreiheit aktuell. Beides ergänzt sich.

Den Einbau in Ihre CI mit uns besprechen

Häufige Fragen

Welche CI-Systeme werden unterstützt?

Jedes System, das ein Shell-Skript mit curl und jq ausführen kann. Beispiele für GitHub Actions und GitLab CI stehen oben; Jenkins, Bitbucket Pipelines oder Azure DevOps funktionieren nach demselben Muster.

Muss die Staging-Umgebung öffentlich sein?

Unser Crawler muss sie erreichen können. Ein Login, eine Browser-Passwortabfrage, Token-Header oder ein Proxy lassen sich an der Website hinterlegen. Einem VPN tritt der Crawler nicht selbst bei; dafür gibt es die Proxy-Option innerhalb Ihres Netzes.

Wie lange dauert der Check?

Er prüft eine Seite und steht in der Warteschlange vor wöchentlichen Crawls. Wie lange er auf einen freien Worker wartet, hängt von der Auslastung ab; das Skript oben wartet bis zu zehn Minuten.

Gibt es eine Jira- oder GitHub-Issues-Integration?

Nein. Über API und Webhooks lassen sich Tickets heute selbst anlegen.

Welche Tarife enthalten die API?

Jeder Tarif mit API-Schlüsseln: Starter 2, Growth 10 und Enterprise nach Vereinbarung; im kostenlosen Konto keine. Der Pre-Publish-Check ist Teil der API. Webhooks brauchen keinen Schlüssel.

Quellen

  1. GitHub Docs: Workflow-Syntax für GitHub Actions – https://docs.github.com/en/actions/writing-workflows/workflow-syntax-for-github-actions
  2. GitLab Docs: CI/CD-YAML-Syntax – https://docs.gitlab.com/ci/yaml/
  3. Deque: axe-core – https://github.com/dequelabs/axe-core
  4. W3C: WCAG 2.2 – https://www.w3.org/TR/WCAG22/

Weiterlesen

  • Prüfmethodik

    Unser Prüfverfahren offen erklärt: axe-core-Regeln, Tastatur-Agent, Status je WCAG-Kriterium, Score-Berechnung und die Grenzen der Automatisierung.

  • MCP Server

    Der Reviseberg MCP Server bringt WCAG-Befunde, Konformitätsstatus und Alt-Text-Vorschläge in Claude Code, Cursor, VS Code und claude.ai.

Sprechen wir darüber

Dreißig Minuten zu Ihrer Website, Ihren Fristen und dazu, was das Produkt für Sie klären kann – und was nicht.