Grundlagen: Anmeldung, Formate, Blättern, Fehler
Anmeldung mit Token, Berechtigungen, Datenformate, Blättern mit Cursor, Abgleich mit updated_since, Rate-Limit und Fehlercodes der API.
Stand:
Alle Endpunkte liegen unter /api/public/v1 der App, z. B. https://app.revisio-app.net/api/public/v1. Die genaue
Adresse Ihrer Installation steht unter Verwaltung → API & Webhooks im Abschnitt Schnittstelle. Die API spricht
ausschließlich JSON über HTTPS.
Anmeldung#
Jede Anfrage trägt den Token eines API-Zugangs im Header:
GET /api/public/v1/customers HTTP/1.1
Host: app.revisio-app.net
Authorization: Bearer rvs_IhrToken
Accept: application/json
- Ein Token gehört zu genau einer Organisation. Datensätze anderer Organisationen sind nicht sichtbar und ergeben
404. - Revisio speichert nur einen Hash des Tokens. Ein verlorener Token lässt sich nicht wieder anzeigen; legen Sie einen neuen Zugang an und widerrufen Sie den alten.
- Abgelaufene und widerrufene Zugänge erhalten
401mit einer passenden Meldung. - Nach 30 fehlgeschlagenen Anmeldungen innerhalb einer Minute sperrt die API die IP-Adresse kurzzeitig (
429mitRetry-After).
Achtung
Der Token ist ein Passwort. Legen Sie ihn nur in der Konfiguration des Fremdsystems oder in einem Passwort-Tresor ab, nie im Quelltext, in Tickets oder in E-Mails. Für jedes Fremdsystem einen eigenen Zugang anlegen, dann lässt sich jeder einzeln widerrufen und im Protokoll zuordnen.
Berechtigungen#
Jeder Zugang hat eine oder mehrere Berechtigungen (Scopes). Fehlt die nötige, antwortet die API mit
403 insufficient_scope und nennt sie in error.details.required_scope.
| Scope | Bezeichnung in Revisio | Endpunkte |
|---|---|---|
read:master-data |
Stammdaten lesen | GET /customers, /sites, /assets, /order-types |
read:orders |
Aufträge lesen | GET /orders, GET /orders/{id} |
write:orders |
Aufträge anlegen und Status ändern | POST /orders, POST /orders/{id}/status |
read:reports |
Berichte lesen und herunterladen | GET /reports, GET /reports/{id}, PDF-Link |
read:faults |
Störungen lesen | GET /faults, GET /faults/{id}, GET /fault-categories |
write:faults |
Störungen anlegen | POST /faults |
Schreibende Berechtigungen schließen das Lesen nicht ein. Ein Fremdsystem, das Aufträge anlegt und danach abfragt,
braucht write:orders und read:orders.
Datenformate#
| Was | Format | Beispiel |
|---|---|---|
| IDs | ULID, 26 Zeichen, in Antworten klein geschrieben; in Filtern und Feldern auch groß | 01k7a3m9x2c4d5e6f7g8h9j0k1 |
| Zeitpunkte | ISO 8601 in UTC | 2026-10-08T07:13:22+00:00 |
| Datumswerte | JJJJ-MM-TT |
2026-10-08 |
| Aufzählungen | englischer Schlüssel, unabhängig von der Anzeige in Revisio | in_progress |
| Leere Werte | null |
"title": null |
| Zeichensatz | UTF-8, Umlaute unmaskiert | "Störung" |
Zeitpunkte in Anfragen (z. B. scheduled_start) dürfen eine Zeitzone tragen
(2026-11-03T08:00:00+01:00); Revisio rechnet sie nach UTC um. Ohne Angabe gilt UTC.
Einzelne Datensätze kommen in data:
{ "data": { "id": "01k7a3m9x2c4d5e6f7g8h9j0k1", "number": "K100231" } }
Listen und Blättern#
Listen (/customers, /sites, /assets, /orders, /reports, /faults) sind nach Änderungszeit und ID sortiert,
die ältesten Änderungen zuerst. Geblättert wird mit einem Cursor, nicht mit Seitenzahlen.
| Parameter | Bedeutung |
|---|---|
limit |
Einträge je Seite, 1 bis 200, Standard 50 |
cursor |
Wert aus meta.next_cursor der vorigen Seite, unverändert übergeben |
updated_since |
nur Datensätze, die seit diesem Zeitpunkt angelegt oder geändert wurden (ISO 8601) |
{
"data": [ { "id": "01k7a3m9x2c4d5e6f7g8h9j0k1", "updated_at": "2026-10-14T09:12:40+00:00" } ],
"meta": { "limit": 50, "has_more": true, "next_cursor": "eyJhdCI6IjIwMjYtMTAtMTRUMDk6MTI6NDAuMDAwMDAwWiIsImlkIjoiMDFrN2EzbTl4MmM0ZDVlNmY3ZzhoOWowazEifQ" },
"links": { "next": "https://app.revisio-app.net/api/public/v1/customers?cursor=eyJhdCI6..." }
}
Solange meta.has_more true ist, holen Sie mit links.next die nächste Seite. Weil nach Änderungszeit sortiert
wird, gehen beim Blättern keine Datensätze verloren und keiner kommt doppelt, auch wenn in der Zwischenzeit jemand
in Revisio arbeitet.
Regelmäßiger Abgleich#
Für einen Abgleich in festen Abständen merkt sich das Fremdsystem den Beginn des letzten Laufs:
- Startzeit des Laufs notieren.
- Liste mit
updated_since=<Beginn des letzten erfolgreichen Laufs>abrufen und bishas_more: falseblättern. - Jeden Datensatz anhand seiner
idanlegen oder aktualisieren. - Erst nach erfolgreichem Ende die notierte Startzeit als neuen Ausgangspunkt speichern.
Ziehen Sie vom Ausgangspunkt ein bis zwei Minuten ab, damit Änderungen, die genau während des Laufs gespeichert
wurden, sicher erfasst werden. Doppelt gelieferte Datensätze sind unschädlich, weil sie über die id zugeordnet
werden. Kombiniert mit Webhooks genügt ein seltener Abgleich, etwa
nächtlich, als Sicherheitsnetz.
Archivierte Kunden und Objekte bleiben in den Listen und tragen "status": "archived". Stillgelegte Anlagen haben
"status": "decommissioned". Gelöschte Datensätze (Papierkorb) erscheinen nicht mehr; welche das sind, meldet der
Webhook records.trashed, die Wiederherstellung records.restored.
Rate-Limit#
Standardmäßig sind 120 Anfragen je Minute und Zugang erlaubt; der Wert für Ihre Installation steht im Abschnitt
Schnittstelle. Jede Antwort trägt die Header X-RateLimit-Limit und X-RateLimit-Remaining. Bei Überschreitung
antwortet die API mit 429 rate_limited und nennt in Retry-After die Wartezeit in Sekunden. Warten Sie mindestens
so lange, bevor Sie es erneut versuchen.
Der PDF-Download über signierte Links ist zusätzlich auf 60 Abrufe je Minute und IP-Adresse begrenzt.
Fehler#
Fehler haben immer dieselbe Form:
{
"error": {
"code": "validation_failed",
"message": "Die Angaben sind ungültig.",
"details": { "asset_ids": ["Alle Anlagen eines Auftrags müssen zum selben Objekt gehören."] },
"request_id": "01k7e1f3g5h7j9k1m3n5p7q9r1"
}
}
code ist für Programme gedacht, message für Menschen. details fehlt, wenn es nichts zu ergänzen gibt. Geben Sie
bei Rückfragen an den Support die request_id an.
| HTTP | code |
Bedeutung | Was tun |
|---|---|---|---|
| 401 | unauthenticated |
Token fehlt, ist falsch, abgelaufen oder widerrufen | Token prüfen, ggf. neuen Zugang anlegen |
| 403 | insufficient_scope |
Berechtigung fehlt (details.required_scope) |
Zugang mit passender Berechtigung anlegen |
| 403 | invalid_signature |
PDF-Link ist abgelaufen oder verändert | Bericht erneut abrufen, neuen Link verwenden |
| 403 | forbidden |
Aktion für diesen Datensatz nicht erlaubt | – |
| 404 | not_found |
Datensatz oder Endpunkt gibt es nicht (oder er gehört zu einer anderen Organisation) | ID und Adresse prüfen |
| 405 | method_not_allowed |
falsche HTTP-Methode | Methode laut Beschreibung verwenden |
| 422 | validation_failed |
Eingaben ungültig, Felder in details |
Eingaben korrigieren, nicht unverändert wiederholen |
| 422 | invalid_transition |
Statuswechsel nicht erlaubt (details.allowed) |
erlaubten Status wählen |
| 429 | rate_limited |
zu viele Anfragen | Retry-After abwarten |
| 500 | server_error |
Fehler in Revisio | später erneut versuchen |
| 503 | unavailable, data_key_unavailable |
Dienst kurzzeitig nicht verfügbar | später erneut versuchen |
Bei 429, 500 und 503 darf das Fremdsystem die Anfrage mit wachsendem Abstand wiederholen. 4xx-Fehler außer
429 ändern sich durch Wiederholen nicht.
Versionen#
Die API trägt die Version im Pfad (/v1). Innerhalb von v1 kommen höchstens Felder, Filter, Endpunkte und
Webhook-Ereignisse hinzu; vorhandene Felder werden nicht umbenannt oder entfernt. Programmieren Sie den Empfang deshalb
so, dass unbekannte Felder ignoriert werden.
Protokoll#
Jede Änderung über die API (Auftrag angelegt, Status geändert, Störung gemeldet, PDF geladen) steht im Protokoll mit dem Namen des API-Zugangs. Unter Verwaltung → API & Webhooks zeigt Zuletzt genutzt den letzten Aufruf mit IP-Adresse.