The Reviseberg accessibility testing API brings findings into your own systems, webhooks let you react when a crawl finishes, and the pre-publish check lets your CI pipeline ask, before a release, whether a page meets your threshold. The findings are the same as in the app: axe-core rules on rendered pages, keyboard agent results and a WCAG 2.2 status for every criterion.
Three ways into your toolchain
| Route | What for | Available |
|---|---|---|
| REST API | Pull sites, open issues, score history and crawls into dashboards, ticketing or your own reports | with an API key: Starter 2, Growth 10 and Enterprise by agreement; none on the free account |
| Pre-publish check | Test a page of a preview or staging environment before release and fail the build when your threshold is missed | part of the REST API, same keys |
| Webhooks | React to finished crawls, new critical issues, score drops and outages | on every account, added by an Admin |
On top of that: the MCP server for coding agents, and CSV export. Enterprise also includes us wiring the pre-publish check into your CI with you.
REST API
The API speaks JSON at https://reviseberg.com/api/v1 and authenticates with an API key in the header Authorization: Bearer bz_…. An Admin creates the key in the app under Settings → API; it is shown exactly once, can be narrowed to particular sites and works until you revoke it.
| Endpoint | What it returns |
|---|---|
GET /api/v1/sites | The sites the key can see: ID, name, address, page limit, crawl schedule, last crawl |
GET /api/v1/issues?site=ID | The open issues from the latest completed crawl: rule, severity, WCAG level and criteria, occurrences, pages, points back and help link, plus a score |
GET /api/v1/sites/ID/scores | The score history across up to the last 90 completed crawls |
GET /api/v1/sites/ID/crawls | Recent runs with status, trigger, start and finish time – so you can see whether a run is done |
POST /api/v1/prepublish | Queues the check of one page (see below) |
GET /api/v1/prepublish/ID | The status and verdict of that check |
Issues prefixed qa: are quality (broken links, for example), seo: are search; everything else, including the agent's keyboard: rules, is accessibility.
curl -s "https://reviseberg.com/api/v1/sites" \
-H "Authorization: Bearer $REVISEBERG_API_KEY"
There is no separate API reference site yet; the table above is the complete list. The REST API does not start a crawl of the whole site – you do that in the app, on a schedule, or with the MCP server's run_scan tool.
A common use is creating tickets. There is no direct Jira, GitLab or GitHub Issues integration. With the API or a webhook you can build that bridge yourself – and decide which findings deserve a ticket.
Webhooks
Reviseberg sends an HTTP POST to an HTTPS address you choose when something happens. After every crawl exactly one message goes out, the most important one: crawl_failed, otherwise new_critical (new critical issues), otherwise score_drop (the score fell), otherwise scan_finished. Uptime monitoring adds uptime_down and uptime_up – once when a monitor goes down and once when it recovers, not at every check.
A webhook has one of two formats:
- Slack format:
{"text": "…"}– a line Slack and Microsoft Teams show as a message. - Generic:
event,title,text,url(the link to the report),site,dataandat. For a crawl,dataholds the score and the number of open and critical issues.
The address itself is the credential – as with Slack. Requests are not signed, so treat the address like a password. Reviseberg only accepts https://, shows the address truncated in the app, delivers each message once with a ten-second timeout, and records a failure on the webhook so you can see why a channel went quiet.
Pre-publish checks in GitHub Actions and GitLab CI
The pre-publish check tests one page before you publish: axe-core at both widths, without the keyboard agent and without a link check. Your pipeline sends the address, gets a check ID and polls until the verdict is in:
POST https://reviseberg.com/api/v1/prepublishwith{"url": "https://…"}answers202withcheck.id.GET https://reviseberg.com/api/v1/prepublish/IDreturnscheck.status(queued,running,doneorfailed) and, once it isdone, theverdict(passorfail), counts per severity, and the findings with rule, selector and message.- You set your threshold when you poll:
minSeverity(the lowest severity that counts, defaultminor) andmaxFailures(how many of those you tolerate, default0).
The verdict is deliberately a count, not a score: a gate that lets a build through because the number was still 91 is a gate nobody trusts. Cases axe-core cannot decide are reported and never counted as failures.
The address must belong to a site in your account – the same host or a subdomain of it, such as staging.example.com for example.com. A preview on an entirely different host is a site you add. If your staging environment sits behind a login, store that login on the site (the browser's password prompt, a login form, token headers or a proxy); it is stored encrypted and only ever sent to that host. The crawler identifies as RevisebergBot and honours robots.txt – a staging site that disallows every crawler has to allow it.
The logic lives in one small script that both CI systems share:
#!/usr/bin/env bash
# scripts/reviseberg-check.sh – check one page before release
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}" # count serious and critical only
MAX_FAILURES="${MAX_FAILURES:-0}" # how many of those you tolerate
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 # up to 10 minutes
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 · verdict: $(jq -r '.verdict' <<<"$RESULT")"
if [ "$(jq -r '.verdict' <<<"$RESULT")" != "pass" ]; then
echo "::error::Accessibility threshold not met for $PREVIEW_URL"; exit 1
fi
GitHub Actions (.github/workflows/accessibility.yml):
name: Accessibility before 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/checkout/"
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/checkout/"
MIN_SEVERITY: "serious"
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
Store the API key as an encrypted secret (GitHub) or a masked CI/CD variable (GitLab) – never in the repository. Each call checks one page; for several – home, product page, checkout – run the script once per page.
Thresholds that work
You set the threshold, not us. Three patterns work well:
- Let nothing serious through:
MIN_SEVERITY=serious,MAX_FAILURES=0. The build fails on any serious or critical finding on the page checked. A good start for the pages that carry revenue. - A ratchet: set
MAX_FAILURESto today's count and lower it after every improvement, so it can only move one way. - Zero tolerance for specific rules: read the
findingslist yourself and fail the build on particular rules, such as missing form labels (label) – barriers that lock people out completely.
The check does not compare against your live site; it counts what it finds on the page it checked. A passing check also does not mean the page conforms. It means the automated checks found nothing that breaks your threshold. Criteria that need human judgement stay "untested" – see our methodology.
axe-core in your build and Reviseberg: both
Component tests with axe-core (in Playwright or Jest, say) catch problems early, while you build. But they only see the states your tests create. Reviseberg tests the finished, rendered site across many pages, lets the keyboard agent walk your journeys, and keeps history, WCAG status and your accessibility statement up to date. The two complement each other.