# Klickpfade über die API bearbeiten

Die REST-Endpunkte für Klickpfade, Anmeldeabläufe und Probeläufe, mit Beispielen, Rechten und Fehlercodes – für eigene Skripte ohne KI-Assistenten.

**Kurz gesagt**

- Alles, was über die API entsteht, ist ein Entwurf und läuft erst, wenn eine Person ihn im Reiter „Prüfung“ freigibt.
- Das Token gehört zu genau einer Website und braucht das Recht „Klickpfade bearbeiten“, das eine Administratorin erteilt.
- Fehler kommen mit stabilem „reason“, Schrittfehler zusätzlich mit Code, Schritt und Feld.

Dieser Artikel beschreibt die Endpunkte, über die eigene Skripte Klickpfade und die Schritte einer mehrstufigen Anmeldung entwerfen und ausprobieren. Ein KI-Assistent nutzt dieselben Regeln über den MCP-Server ([Anmeldung und Klickpfade beschreiben](https://barrierepruefung.de/hilfe/anmeldung-und-klickpfade#ki-assistent)). Die Schrittsprache selbst steht in [Anmeldung und Klickpfade beschreiben](https://barrierepruefung.de/hilfe/anmeldung-und-klickpfade#schritte).

## Token und Rechte

Sie brauchen ein Token, das an die Website gebunden ist und das Recht „Klickpfade bearbeiten“ trägt. Wie Sie es anlegen, steht in [Anmeldung und Klickpfade beschreiben](https://barrierepruefung.de/hilfe/anmeldung-und-klickpfade#ki-token). Mit dem Recht erhält das Token zwei Berechtigungen: `journeys:read` zum Lesen und Prüfen, `journeys:write` zum Speichern von Entwürfen und zum Starten von Probeläufen.

Jede Anfrage trägt das Token als Kopfzeile, die Basisadresse ist `https://barrierepruefung.de/api/v1`:

```text
Authorization: Bearer IHR_TOKEN
Accept: application/json
Accept-Language: de
```

`{site}` in den Pfaden ist die „Website-Kennung“ aus dem Reiter „Einbindung“. Für jede andere Website antwortet die API mit 404. Texte in Antworten folgen `Accept-Language` (`de` oder `en`). Schreibende Aufrufe nehmen optional `actor_name` an: den Namen, unter dem Ihr System die handelnde Person kennt. Er steht am Entwurf als Beleg, verantwortlich bleibt die Person, die das Recht erteilt hat.

## Endpunkte

| Methode | Pfad | Recht | Zweck |
| --- | --- | --- | --- |
| `GET` | `/sites/{site}/journeys` | lesen | alle Klickpfade mit Status, Schritten und Entwurf |
| `GET` | `/sites/{site}/journeys/{id}` | lesen | ein Klickpfad |
| `POST` | `/sites/{site}/journeys/pruefen` | lesen | Schritte prüfen, ohne zu speichern |
| `POST` | `/sites/{site}/journeys` | schreiben | neuen Klickpfad als Entwurf anlegen |
| `PUT` | `/sites/{site}/journeys/{id}/entwurf` | schreiben | Entwurf eines vorhandenen Klickpfads setzen |
| `DELETE` | `/sites/{site}/journeys/{id}/entwurf` | schreiben | Entwurf verwerfen, laufende Schritte bleiben |
| `GET` | `/sites/{site}/anmeldung` | lesen | Schritte der Anmeldung, ohne Zugangsdaten |
| `PUT` | `/sites/{site}/anmeldung/entwurf` | schreiben | Schritte einer mehrstufigen Anmeldung vorschlagen |
| `POST` | `/sites/{site}/probelaeufe` | schreiben | Probelauf starten |
| `GET` | `/sites/{site}/probelaeufe/{id}` | lesen | Stand und Ergebnis eines Probelaufs |

Das Schema der Schrittsprache steht ohne Token unter `https://barrierepruefung.de/api/v1/schema/klickpfad.json` und `https://barrierepruefung.de/api/v1/schema/anmeldeablauf.json` (JSON Schema 2020-12).

Freigeben und Löschen gibt es über die API nicht. Zugangsdaten auch nicht: Weder Benutzername, Passwort noch das Geheimnis für den Einmalcode, keine Anmeldedienste und keine Bestätigung dafür werden gesetzt oder ausgegeben.

## Schritte prüfen

`POST /sites/{site}/journeys/pruefen` mit `steps` und optional `stop_before` speichert nichts und antwortet immer mit 200. Ein ungültiger Pfad ist hier das Ergebnis:

```json
{
  "gueltig": false,
  "fehler": [
    {
      "code": "selektor_nicht_erlaubt",
      "schritt": 2,
      "feld": "selector",
      "text": "Schritt 2: Der Selektor enthält unerlaubte Zeichen. Erlaubt sind CSS-Selektoren, role=… und text=…."
    }
  ],
  "bereinigt": [
    {"action": "goto", "url": "/warenkorb"},
    {"action": "click", "selector": "xpath=//button"}
  ]
}
```

## Einen Entwurf speichern

`POST /sites/{site}/journeys` legt einen neuen Klickpfad an, mit `name`, `steps` und optional `stop_before`. Er hat danach keine laufenden Schritte, nur einen Entwurf. `PUT /sites/{site}/journeys/{id}/entwurf` setzt den Entwurf eines vorhandenen Pfads; dessen Name bleibt, die laufenden Schritte auch.

```json
{
  "name": "Bestellstrecke",
  "steps": [
    {"action": "goto", "url": "/warenkorb"},
    {"action": "click", "selector": "role=button[name=\"Zur Kasse\"]"}
  ],
  "stop_before": "role=button[name=\"Zahlungspflichtig bestellen\"]",
  "actor_name": "Build-Skript"
}
```

Die Antwort (201 beim Anlegen, sonst 200) beschreibt den Pfad:

```json
{
  "data": {
    "id": 42,
    "name": "Bestellstrecke",
    "status": "entwurf",
    "schritte": [],
    "stop_before": null,
    "entwurf": {
      "schritte": [
        {"action": "goto", "url": "/warenkorb"},
        {"action": "click", "selector": "role=button[name=\"Zur Kasse\"]"}
      ],
      "stop_before": "role=button[name=\"Zahlungspflichtig bestellen\"]",
      "von": {"weg": "api", "name": "Build-Skript", "token_name": "Build"},
      "am": "2026-10-30T09:15:00+00:00"
    },
    "freigegeben": null,
    "letzter_lauf": {
      "status": "gescheitert",
      "am": "2026-10-30T03:12:44+00:00",
      "lauf_id": "01JBX0A2C4E6G8H1J3K5M7N9P0",
      "seitdem_geaendert": false,
      "grund": null,
      "befund": {
        "code": "element_versteckt",
        "schritt": 2,
        "schritte": 2,
        "aktion": "click",
        "selektor": "role=button[name=\"Zur Kasse\"]",
        "viewport": "mobile",
        "befund": {"treffer": 1, "sichtbar": 0},
        "ueberschrift": "Schritt 2 von 2 gescheitert (click, Mobil, 390 px)",
        "erklaerung": "Der Selektor trifft ein Element, es ist aber nicht sichtbar.",
        "hinweis": "Wählen Sie ein Element, das in dieser Breite sichtbar ist, …"
      }
    },
    "freigabe_url": "…/websites/…/pruefung"
  }
}
```

`status` ist `entwurf`, `freigegeben` oder `freigegeben_mit_entwurf`. `letzter_lauf` ist `null`, solange der Pfad in keinem abgeschlossenen Lauf vorkam. Sonst steht dort der Stand im letzten Lauf: `status` ist `erfolgreich`, `gescheitert` oder `nicht_geprueft` (kein Scheitern des Pfads: Anmeldung, Drosselung, Frist, Budget oder Proxy verhinderten die Prüfung, der Grund steht in `grund`), `am` und `lauf_id` nennen den Lauf, `seitdem_geaendert` ist `true`, wenn der Pfad danach freigegeben wurde. Nur bei `gescheitert` ist `befund` gesetzt: `code` ist einer der Codes aus [Anmeldung und Klickpfade beschreiben](https://barrierepruefung.de/hilfe/anmeldung-und-klickpfade#klickpfad-scheitert), `schritt`, `schritte`, `aktion`, `selektor` und `viewport` sagen, wo, `befund` enthält die Messwerte (`treffer`, `sichtbar`, `erster_sichtbar`, `erster_bedienbar`, `abgeloest`, `navigiert`, `adresse`; je nach Code nicht alle), und `ueberschrift`, `erklaerung` und `hinweis` sind Texte in der Sprache der Anfrage. Verzweigen Sie an `code`, nicht an den Texten.

Unter `freigabe_url` gibt eine Person den Entwurf frei ([Anmeldung und Klickpfade beschreiben](https://barrierepruefung.de/hilfe/anmeldung-und-klickpfade#freigabe)).

Für eine mehrstufige Anmeldung schlägt `PUT /sites/{site}/anmeldung/entwurf` mit `schritte` die Schritte vor, mit Platzhaltern statt Zugangsdaten ([Anmeldung und Klickpfade beschreiben](https://barrierepruefung.de/hilfe/anmeldung-und-klickpfade#platzhalter)). Das geht nur, wenn im Reiter „Prüfung“ bereits ein Zugang dieser Art angelegt ist; sonst antwortet die API mit 404, bei einem einfachen Anmeldeformular mit `kein_ablauf`.

## Probeläufe

`POST /sites/{site}/probelaeufe` startet einen Probelauf und antwortet sofort mit 202. Er braucht genau eine Quelle:

- `{"journey_id": 42, "quelle": "entwurf"}` oder `"quelle": "freigegeben"`: ein gespeicherter Klickpfad. Ist ein Zugang aktiv, meldet sich der Probelauf wie eine Prüfung zuerst an.
- `{"anmeldung": "entwurf"}`: nur der Entwurf der Anmeldung.
- `{"schritte": [...], "stop_before": "…"}`: ungespeicherte Schritte, ohne Anmeldung.

Den Stand fragen Sie mit `GET /sites/{site}/probelaeufe/{id}` ab, bis `status` nicht mehr `wartet` oder `laeuft` ist:

```json
{
  "data": {
    "id": "01JBX3K7Q8M4V2N6P0R5S9T1W3",
    "status": "fertig",
    "quelle": "entwurf",
    "journey_id": 42,
    "mit_anmeldung": false,
    "erfolgreich": false,
    "grund": null,
    "schritte": [
      {"nr": 1, "viewport": "desktop", "action": "goto", "ok": true, "grund": null, "adresse": "https://www.example.org/warenkorb", "aria": "- main: …", "befund": null, "bild_url": "…"},
      {"nr": 2, "viewport": "desktop", "action": "click", "ok": false, "grund": "klick_abgelehnt:nicht_gefunden", "adresse": "https://www.example.org/warenkorb", "aria": "- main: …", "befund": {"code": "klick_abgelehnt:nicht_gefunden", "schritt": 2, "schritte": 2, "aktion": "click", "selektor": "role=button[name=\"Zur Kasse\"]", "viewport": "desktop", "befund": {"treffer": 0, "sichtbar": 0}, "ueberschrift": "…", "erklaerung": "…", "hinweis": "…"}, "bild_url": "…"}
    ],
    "anmeldung": null,
    "dauer_ms": 5120,
    "angelegt_am": "2026-10-30T09:16:00+00:00",
    "fertig_am": "2026-10-30T09:16:07+00:00",
    "loeschen_ab": "2026-10-31T09:16:00+00:00",
    "freigabe_hinweis": "Bevor dieser Pfad in Prüfungen läuft, muss eine Person ihn im Tab ‚Prüfung‘ freigeben: …"
  }
}
```

- `status`: `wartet`, `laeuft`, `fertig`, `gescheitert` (der Probelauf als Ganzes scheiterte, Grund in `grund`, etwa `start_fremder_host`, eine Fehlerseite des Proxys `proxy_fehler:…`, `budget_ueberschritten`, `abgelaufen` oder `scanner_veraltet` während einer Aktualisierung) oder `abgelehnt`.
- `erfolgreich`: `true` nur, wenn der Probelauf fertig ist, kein Schritt scheiterte und wirklich etwas gelang (ein Schritt mit `ok: true` oder, bei einem Probelauf nur der Anmeldung, eine gelungene Anmeldung); `null`, solange er läuft. Verzweigen Sie daran, nicht an `status`: Auch ein `fertig`er Probelauf kann an einem Schritt gescheitert sein.
- Ein Probelauf prüft jede Breite des Prüfprofils nacheinander und endet beim ersten Scheitern. `schritte` enthält einen Eintrag je Schritt und Breite; `viewport` ist `desktop`, `mobile` oder `reflow-320` (ältere Ergebnisse ohne Angabe gelten als `desktop`). Bei einem gescheiterten Schritt trägt `befund` dieselbe Form wie in `letzter_lauf`, mit `selektor`; sonst ist er `null`. Das Bild gehört zu Schritt und Breite.
- Je Schritt `ok`: `true`, `false` oder `null` für „nicht ausgeführt“. Nach dem ersten Fehlschlag endet der Probelauf. Die Gründe sind dieselben wie in einer Prüfung ([Anmeldung und Klickpfade beschreiben](https://barrierepruefung.de/hilfe/anmeldung-und-klickpfade#fehlergruende)); `stop_before` heißt, dass der Pfad vor dem Abbruchziel angehalten hat.
- `bild_url` ist eine signierte Adresse, die 10 Minuten gilt. Fragen Sie den Probelauf erneut ab, bekommen Sie eine neue.
- Liegt ein Schritt außerhalb Ihrer Domain, steht in `adresse` nur die Herkunft, `aria` und `bild_url` sind leer.
- Nach `loeschen_ab` sind Ergebnis und Bilder gelöscht.

Die Grenzen der Probeläufe stehen in [Anmeldung und Klickpfade beschreiben](https://barrierepruefung.de/hilfe/anmeldung-und-klickpfade#ki-grenzen).

## Fehler

Fehler kommen als `application/problem+json` mit `status`, `detail` (Satz in der Sprache der Anfrage) und, wo es eine gibt, einer stabilen Kennung `reason`. Verzweigen Sie an `reason`, nicht am Satz.

| Status | `reason` | Bedeutung |
| --- | --- | --- |
| 401 | – | Token fehlt oder ist ungültig. |
| 403 | `recht_fehlt` | Dem Token fehlt das Recht; `url` führt zum Reiter „Einbindung“. |
| 403 | `recht_erloschen` | Die Person, die das Recht erteilt hat, darf es nicht mehr. Lesen geht weiter. |
| 403 | `konto_geschlossen` | Das Konto der Organisation ist geschlossen. |
| 404 | – oder `nicht_gefunden` | Website, Klickpfad, Zugang oder Probelauf gibt es für dieses Token nicht. |
| 409 | `probelauf_laeuft` | Für diese Website läuft schon ein Probelauf. Er wird nicht eingereiht. |
| 422 | `schritte_ungueltig` | Mindestens ein Schritt ist ungültig; `fehler` nennt Code, Schritt und Feld. |
| 422 | `domain_nicht_bestaetigt` | Die Domain der Website ist nicht bestätigt. |
| 422 | `plan` | Der Plan erlaubt keine (weiteren) Klickpfade. |
| 422 | `kein_ablauf` | Der Zugang ist ein einfaches Anmeldeformular und hat keine Schritte. |
| 422 | `anmeldung_pausiert` | Die Anmeldung ist pausiert; probieren Sie zuerst einen neuen Anmeldeablauf aus. |
| 422 | `eingabe_ungueltig` | Die Eingabe des Probelaufs hat nicht die erwartete Form, etwa zwei Quellen. |
| 422 | – | Ein Feld fehlt oder hat die falsche Form; `errors` nennt es. |
| 429 | `grenze_erreicht` | Zu viele Probeläufe in der letzten Stunde; `wieder_ab` sagt, ab wann es wieder geht. |
| 429 | `anmeldung_gesperrt` | Probeläufe mit Anmeldung sind nach einer gescheiterten Anmeldung gesperrt; mit `wieder_ab`. |

Die Codes in `fehler[].code` bilden ein abgeschlossenes Verzeichnis:

| Code | Bedeutung |
| --- | --- |
| `aktion_unbekannt` | Die Aktion gibt es nicht. |
| `feld_fehlt` | Ein Pflichtfeld der Aktion fehlt. |
| `feld_kein_text` | Ein Feld ist kein Text. |
| `adresse_unvollstaendig` | Die Adresse ist unvollständig. |
| `schema_nicht_erlaubt` | Nur `http` und `https` sind erlaubt. |
| `adresse_fremd` | Die Adresse liegt nicht auf Ihrer Domain. |
| `selektor_nicht_erlaubt` | Der Selektor ist kein CSS, `role=…` oder `text=…`. |
| `taste_nicht_erlaubt` | Die Taste steht nicht in der Liste. |
| `zu_viele_schritte` | Mehr Schritte als erlaubt. |
| `keine_schritte` | Die Liste ist leer. |
| `stop_before_fehlt` | Der Pfad berührt eine Bestellung oder Zahlung und hat kein Abbruchziel. |
| `erster_schritt_nicht_eigen` | Der erste Schritt einer Anmeldung ist kein `goto` auf Ihre Domain. |
| `platzhalter_falsch` | Ein Platzhalter ist unbekannt oder steht an der falschen Stelle. |
| `platzhalter_fehlt` | Benutzername oder Passwort kommen in der Anmeldung nicht vor. |
| `einmalcode_ohne_geheimnis` | Der Einmalcode wird verwendet, aber kein Geheimnis ist hinterlegt. |
| `schritt_ungueltig` | Der Schritt ist kein gültiges Objekt. |
| `anmeldehost_ungueltig` | Ein Anmeldedienst ist kein gültiger Host. |
| `anmeldehost_eigen` | Ein Anmeldedienst liegt auf Ihrer eigenen Domain. |
| `zu_viele_anmeldehosts` | Mehr Anmeldedienste als erlaubt. |
| `anmeldehosts_unbestaetigt` | Die Anmeldedienste sind nicht bestätigt. |

---

Zuletzt gegen das Produkt geprüft: 2026-11-03 · https://barrierepruefung.de/hilfe/api-klickpfade
