REST API — Dokumentation
Mit der NormSafe REST API lassen sich Prüfungen, Kunden und Geräte aus eigenen Skripten, Excel-Makros oder Drittsystemen (z. B. ERP) abrufen. Schreiboperationen sind über die API aktuell nicht möglich — Daten werden ausschließlich in der App erfasst.
Authentifizierung
Alle Anfragen müssen den API-Key als Bearer-Token im Authorization-Header mitschicken. Der Key beginnt immer mit nsk_ und ist nach Erstellung nur einmalig im Klartext sichtbar.
Authorization: Bearer nsk_<dein-key>Fehlt der Header oder ist der Key ungültig/widerrufen, antwortet die API mit 401 Unauthorized.
Rate-Limiting
Jeder API-Key darf maximal 60 Anfragen pro Minute (gleitendes Fenster) absetzen. Bei Überschreitung antwortet die API mit 429 Too Many Requests. Warte kurz und versuche es dann erneut.
Basis-URL
https://normsafe.app/api/v1Alle Antworten sind JSON. Erfolgreiche Antworten haben HTTP-Status 200 und ein Feld data (Array). Fehlerantworten haben ein Feld error (String).
Endpunkte
/api/v1/inspectionsGibt alle Prüfungen deiner Organisation zurück — Gerätprüfungen (DGUV V3 / VDE 0701-0702), Anlagenprüfungen (VDE 0100-600), PV-Prüfungen und Wallbox-Prüfungen. Ergebnis wird nach inspected_at absteigend sortiert.
Query-Parameter
| since | ISO 8601 | Nur Prüfungen ab diesem Zeitpunkt zurückgeben, z. B. 2025-01-01T00:00:00Z |
| type | string | Filtert auf einen Typ: device, installation, pv oder wallbox |
| limit | integer | Anzahl Einträge (Standard 100, max 500) |
Beispielaufruf
curl -H "Authorization: Bearer nsk_..." \
"https://normsafe.app/api/v1/inspections?type=device&since=2025-01-01T00:00:00Z&limit=50"Antwortfelder (pro Eintrag)
| id | uuid | Eindeutige Prüfungs-ID |
| type | string | device | installation | pv | wallbox |
| inspected_at | ISO 8601 | Zeitpunkt der Prüfung |
| result | string | null | passed, failed, restricted oder null (noch nicht bewertet) |
| next_inspection_due | ISO 8601 | null | Nächster Prüftermin |
| object_name | string | Name des geprüften Objekts (Gerät / Anlage / String / Wallbox) |
| customer_name | string | Firmenname des Kunden |
| location_label | string | Standortbezeichnung |
Beispielantwort
{
"data": [
{
"id": "a1b2c3d4-...",
"type": "device",
"inspected_at": "2025-06-15T10:30:00.000Z",
"result": "passed",
"next_inspection_due": "2026-06-15",
"object_name": "Verlängerungskabel 25m",
"customer_name": "Musterbau GmbH",
"location_label": "Lager EG"
}
]
}/api/v1/customersGibt alle Kunden deiner Organisation alphabetisch sortiert zurück.
Query-Parameter
| limit | integer | Anzahl Einträge (Standard 100, max 500) |
Beispielaufruf
curl -H "Authorization: Bearer nsk_..." \
"https://normsafe.app/api/v1/customers"Antwortfelder (pro Eintrag)
| id | uuid | Kunden-ID |
| name | string | Firmenname |
| contact_person | string | null | Ansprechpartner |
| string | null | E-Mail-Adresse | |
| phone | string | null | Telefonnummer |
| created_at | ISO 8601 | Datum der Anlage in NormSafe |
/api/v1/devicesGibt alle ortsveränderlichen Geräte (DGUV V3) zurück, sortiert nach dem nächsten Prüftermin (überfälligste zuerst).
Query-Parameter
| limit | integer | Anzahl Einträge (Standard 100, max 500) |
Beispielaufruf
curl -H "Authorization: Bearer nsk_..." \
"https://normsafe.app/api/v1/devices?limit=200"Antwortfelder (pro Eintrag)
| id | uuid | Geräte-ID |
| name | string | Gerätename / Bezeichnung |
| inventory_no | string | Inventarnummer |
| device_type | string | Gerätetyp (z. B. power_tool, extension_cord) |
| protection_class | string | Schutzklasse: I, II oder III |
| next_inspection_due | ISO 8601 | null | Nächster Prüftermin |
| customer_name | string | Firmenname des Kunden |
| location_label | string | Standortbezeichnung |
Webhooks
Webhooks erlauben es, Push-Benachrichtigungen an eigene Systeme zu senden, sobald eine Prüfung abgeschlossen wird. Konfiguriert werden sie unter Einstellungen → Webhooks.
Events
| Event | Auslöser |
|---|---|
| inspection.created | Neue Prüfung wurde erfolgreich gespeichert |
| inspection.failed | Prüfung gespeichert mit Ergebnis „nicht bestanden" |
Payload-Format
POST https://deine-url.example.com/webhook
Content-Type: application/json
X-NormSafe-Signature: sha256=<hmac-hex>
{
"event": "inspection.failed",
"org_id": "uuid-...",
"timestamp": "2025-06-15T10:30:00.000Z",
"data": {
"id": "uuid-...",
"type": "device",
"object_id": "uuid-...",
"inspected_at": "2025-06-15T10:30:00.000Z",
"result": "failed",
"next_inspection_due": null
}
}Signatur-Verifikation
Jede Zustellung enthält den Header X-NormSafe-Signature: sha256=<hex>. Verifiziere ihn in deinem Empfänger, um sicherzustellen, dass die Anfrage tatsächlich von NormSafe stammt:
// Node.js-Beispiel
import { createHmac, timingSafeEqual } from "crypto";
function verifySignature(rawBody: string, secret: string, header: string): boolean {
const expected = "sha256=" + createHmac("sha256", secret).update(rawBody).digest("hex");
const a = Buffer.from(header);
const b = Buffer.from(expected);
if (a.length !== b.length) return false;
return timingSafeEqual(a, b);
}Verwende immer timingSafeEqual statt ===, um Timing-Angriffe zu vermeiden.
Wiederholungsversuche
Bei HTTP-Fehlercodes oder Verbindungsfehlern wiederholt NormSafe die Zustellung automatisch. Wiederholungen laufen gesammelt einmal täglich; jede Zustellung trägt den Header X-NormSafe-Delivery-Id, über den Empfänger doppelte Zustellungen erkennen können:
| Versuch | Verzögerung |
|---|---|
| 1 (sofort) | Beim Speichern der Prüfung |
| 2 | beim nächsten täglichen Verarbeitungslauf (05:00 UTC) |
| 3 (letzter) | am darauffolgenden Verarbeitungslauf |
Fehlercodes
| Status | Bedeutung |
|---|---|
| 200 OK | Anfrage erfolgreich |
| 401 Unauthorized | Fehlender, ungültiger oder widerrufener API-Key |
| 429 Too Many Requests | Rate-Limit überschritten (60 req/min) |
| 500 Internal Server Error | Datenbankfehler auf Serverseite |