Integeri

Integeri Dokumentation

HTTP API v1 — Entwicklerdokumentation

Öffentliche JSON-Schnittstelle unter https://next.integeri.com/api/v1. Diese Seite: https://next.integeri.com/docs/api/v1Deutsch / English

Überblick

Die API ist für Maschine-zu-Maschine-Zugriffe über OAuth2 Client Credentials gedacht. Alle geschützten Routen erwarten Authorization: Bearer … und sollten mit Accept: application/json aufgerufen werden.

Authentifizierung

Token beziehen

POST https://next.integeri.com/oauth/token
Content-Type: application/json

{
  "grant_type": "client_credentials",
  "client_id": "<UUID des ApiClient> ",
  "client_secret": "<Secret des ApiClient> ",
  "scope": "*"
}

Antwort enthält u. a. access_token, token_type, expires_in.

HTTP-Status & Fehlerformat

JSON-Fehler für api/* und bei Accept: application/json

CodeTypische UrsacheBody (vereinfacht)
401Fehlendes/ungültiges Token{"message":"Unauthenticated."}
403Policy / Berechtigung / inaktiver Service-User{"message":"…"}
404Unbekannte Route oder Model{"message":"…"}
405Falsche HTTP-Methode{"message":"Method not allowed."}
422Validierung{"message":"…","errors":{…}}
429Rate Limit{"message":"Too many requests."}
500ServerfehlerIn Produktion generische Meldung; in Dev ggf. Detail

Listen: Pagination, Sortierung, Filter

Gemeinsame Query-Parameter für GET …/locations, GET …/teams, GET …/users .

ParameterBeschreibung
pageSeite
per_pageEinträge pro Seite, 1–100
sortKomma-getrennt; Feldname oder -feld für absteigend
stateactive oder inactive (Locations, Teams, Users)
searchTextsuche (je Ressource unterschiedlich; z. B. Kontaktname)

Erlaubte Sort-Felder

  • Locations: id, state, created_at, updated_at, order_position
  • Teams: id, state, created_at, updated_at, order_position
  • Users: id, state, username, created_at, updated_at

Zusätzliche Filter

  • GET /locations: include
  • GET /teams: location_id, include
  • GET /users: team_id, location_id, role, include
  • GET /courses: state (Standard active), search (Titel), type (siehe Endpunkt Courses)
  • GET /users/{user}/assigned-courses, GET /users/{user}/certificated-courses: keine Filter

Listen-Antwort: paginiertes JSON mit data, links, meta.

Optional: include

Komma-separierte Liste. Unbekannte Segmente werden ignoriert.

GETSegmenteWirkung (Kurz)
/locationsteamsLiefert eingebettete teams in der Location-Ressource
/teamsusers, instructionTeammitglieder bzw. wiederkehrende Schulung (Course)
/userslocationsZusatzfeld locations (dedupliziert über Team→Location)

Endpunkte: Auth

Basis: https://next.integeri.com/api/v1 — alle mit Bearer-Token.

GET /auth/me

200 — aktueller Service-User, OAuth-Client, Token-Metadaten

{
  "data": {
    "service_user": {
      "id": 1,
      "username": "…",
      "company_id": 1,
      "roles": ["company.admin", …]
    },
    "client": { "id": "…", "name": "…" },
    "token": {
      "expires_at": "2026-01-01T12:00:00+00:00",
      "scopes": ["*"]
    }
  }
}

POST /auth/logout

200 — aktuelles Access Token widerrufen

{ "message": "Token revoked." }

Endpunkte: Locations

PfadBeschreibungStatus
GET/locationsListe200
POST/locationsAnlegen201
GET/locations/{location}Detail200
PUT/PATCH/locations/{location}Aktualisieren200
POST/locations/{location}/deactivateDeaktivieren200
PUT/locations/order-positionsSortierung mehrerer Standorte200
PUT/locations/{location}/teams/order-positionsSortierung der Teams eines Standorts200

POST /locations — Body (Validierung)

  • name — required, string, max 255
  • description, street, zip_city, …
  • country — max 2 Zeichen
  • admin_user_ids[], trainer_admin_user_ids[] — optional, User-IDs der Firma

PATCH /locations/{id}

Felder wie Store, alle optional außerhalb von name-Pflicht bei vollem PUT gemäß Client.

PUT /locations/order-positions

Voraussetzung: Berechtigung zum Sortieren von Standorten. Body: {"locations": [{"id": 1, "order_position": 10}, …]} — sortiert Standorte der Firma

PUT /locations/{location}/teams/order-positions

Voraussetzung: Berechtigung zum Sortieren von Teams und Sicht auf den Standort. Body: {"teams": [{"id": 5, "order_position": 20}, …]}.

Endpunkte: Teams

PfadBeschreibungStatus
GET/teamsListe200
POST/teamsAnlegen201
GET/teams/{team}Detail200
PUT/PATCH/teams/{team}Aktualisieren200
POST/teams/{team}/deactivateDeaktivieren200
POST/teams/{team}/usersUser dem Team zuordnen200
DELETE/teams/{team}/users/{user}User aus Team lösen204

POST /teams — Body

  • name — required
  • location_id — required, existiert in locations
  • description, Kontakt-Felder, admin_user_ids[], trainer_admin_user_ids[] — optional

POST /teams/{team}/users

  • user_ids — required, Array von User-IDs
  • next_instruction_date — optional, Y-m-d
  • force — optional, boolean

Endpunkte: Users

PfadBeschreibungStatus
GET/usersListe200
POST/usersAnlegen201
GET/users/{user}Detail200
PUT/PATCH/users/{user}Aktualisieren200
POST/users/{user}/activateAktivieren200
POST/users/{user}/deactivateDeaktivieren200
POST/users/{user}/reset-passwordPasswort zurücksetzen200 JSON
PUT/users/{user}/rolesRollen synchronisieren200
POST/users/{user}/course-assignmentsBestehenden Kurs zuweisen201
POST/users/{user}/qualificationsQualifikation manuell hinterlegen201
GET/users/{user}/assigned-coursesOffene Kurszuweisungen (mit is_overdue)200
GET/users/{user}/certificated-coursesErledigte Kurse inkl. Zertifikat-URL200
GET/users/{user}/{assignment}/course/{course}-{lang}.pdf Zertifikat-PDF herunterladen 200

POST /users — Body (Auszug)

  • salutationm, f, d
  • first_name, last_name — required
  • email, mobile_number, username, password (min 8), language, birthday (Y-m-d), driving_classes (A,CE,D,...)
  • team_ids[], roles[] , send_credentials (boolean)
  • id — optional in Service-/Import-Flows; wird für die E-Mail-Unique-Prüfung als user_id interpretiert

Hinweis: Bei Bedarf wird der Benutzername aus Namen/Geburtstag abgeleitet; fehlender optionaler Schlüssel birthday ist erlaubt. bei 422 die errors prüfen.

PUT /users/{user}/roles

{ "roles": ["company.admin", "company.employee"] }

POST /users/{user}/reset-password

  • send_email — optional, boolean (Standard in der Regel true)

Ohne E-Mail-Versand kann die Antwort ein temporäres Passwort enthalten.

Endpunkte: Courses

Aktive Kurse, die dem aufrufenden Service-User sichtbar sind: Integeri-Kurse und die Kurse der eigenen Firma.

PfadBeschreibungStatus
GET/coursesListe aktiver Kurse (Pagination)200

Voraussetzung: Berechtigung zum Einsehen von Kursen. Query-Parameter: page, per_page (1–100), state (active/inactive, Standard active), search (Titel), type (optional, siehe unten).

GET /courses — Query-Parameter type

  • qualification — Qualifikation / manuelle Bestätigung durch Nutzer.
  • operator — nur Bediener-Schulungen .
  • trainer — nur Ausbilder-Schulungen .
  • operator_recurring — nur wiederkehrende Bediener-Unterweisungen .

Ohne type gilt nur die übliche Sichtbarkeitsregel (Integeri + eigene Firma). type schränkt die bereits sichtbaren Kurse weiter ein; Kombination mit search und state ist möglich.

Endpunkte: Content-Video (Prozess)

Legt ein Teleprompter-/Synthese-Video mit prompter_text an — entweder an einen bestehenden Inhaltsknoten angehängt oder als neuer Inhalt im Unterweisungskurs eines aktiven Basiskurses.

PfadBeschreibungStatus
POST/contentvideos/createVideo anlegen / optional neuer Inhalts- und Kursknoten unter Basiskurs201

Voraussetzung: Berechtigung zum Anlegen von Inhalten; der Ziel-Basiskurs muss zur Firma des Service-Users gehören (oder ein freigegebener Integeri-Basiskurs sein). Bei Berechtigungsfehler 403 oder Verstoß 422 unter errors.course_id.

POST /contentvideos/create — JSON-Body

  • prompter_text — Pflicht, String (max. 14000 Zeichen), wird als Prompter-Text des Videos gespeichert.
  • name — optional, String (max. 255 Zeichen). Titel des neuen Inhaltsknotens, wenn kein content_node_id gesetzt ist. Ohne Angabe wird der Titel aus dem Prompter-Text abgeleitet.
  • content_node_id — optional, positive ID. Wenn gesetzt, muss der Inhaltsknoten existieren; das Video wird dort verknüpft. Sonst wird ein neuer Inhaltsknoten im Zielkurs angelegt.
  • api_base_course_id — optional: positive ID einer API-Kollektion der Firma (muss in company.video_settings['api-courses'] registriert sein) oder -1 für eine neue Kollektion. Überschreibt die dem API-Client zugeordnete Kollektion. Ohne Angabe von course_id, api_base_course_id und team_id wird die dem OAuth-Client zugeordnete api_base_course_id verwendet.
  • course_id — optional, positive ID. Muss ein aktiver Basiskurs oder wiederkehrender Unterweisungskurs sein (z. B. teams.recurring_course_id über team_id).
  • team_id — optional, positive ID. Wenn gesetzt und weder course_id noch api_base_course_id (auch nicht -1) angegeben sind, wird der Unterweisungskurs des Teams (teams.recurring_course_id) als Zielkurs verwendet. Typischer Make.com-Flow: zuerst Team anlegen, dann Video mit team_id.

Fehler 422: unbekannte content_node_id; ungültiger/inaktiver Kurs; Kurs keine registrierte API-Kollektion (api_base_course_id); unbekanntes Team oder Team ohne Unterweisungskurs; Firmen-Mismatch; kein API-Client mit Kollektion; Basiskurs nicht zulässig. 403, wenn die Berechtigung zum Anlegen von Inhalten fehlt .

Erfolg 201, JSON data: content_node_video_id, content_node_id, course_id, course_node_id (nur gesetzt, wenn ein neuer Kursknoten angelegt wurde), estimated_video_length (geschätzte Videolänge in Sekunden aus dem Prompter-Text .

Endpunkte: Course-Assignments (pro User)

PfadBeschreibungStatus
POST/users/{user}/course-assignmentsBestehenden Kurs einem User zuweisen201
POST/users/{user}/qualificationsQualifikation manuell hinterlegen201
GET/users/{user}/assigned-coursesOffene Kurszuweisungen (mit is_overdue)200
GET/users/{user}/certificated-coursesErledigte Kurse inkl. Zertifikat-URL200
GET/users/{user}/{assignment}/course/{course}-{lang}.pdf Zertifikat-PDF herunterladen 200

POST /users/{user}/course-assignments

Voraussetzung: Berechtigung zum Anlegen von Kurszuweisungen und Sicht auf den Ziel-Benutzer. course_id wird gegen die Sichtbarkeit (eigene Firma oder freigegebener Integeri-Kurs) sowie state = active geprüft. Die Zuweisung startet mit Status assigned und Typ manual.

POST /api/v1/users/42/course-assignments
Content-Type: application/json
Authorization: Bearer …

{
  "course_id": 23,
  "deadline_date": "2026-06-30"   // optional, Y-m-d oder ISO-8601
}

Antwort 201: eine vollständige CourseAssignment-Ressource (siehe unten).

POST /users/{user}/qualifications

Voraussetzung: Berechtigung zum Anlegen von Kurszuweisungen und Sicht auf den Ziel-Benutzer. course_id muss ein aktiver Kurs mit Erlaube manuelle Qualifikation sein (Liste via GET /courses?type=qualification). Die Zuweisung wird mit state = success und type = approval angelegt. Datei-Uploads sind in der API v1 nicht enthalten (nur im Web-UI).

POST /api/v1/users/42/qualifications
Content-Type: application/json
Authorization: Bearer …

{
  "course_id": 15,
  "finish_date": "2024-06-01",   // optional, Y-m-d, max. heute
  "valid_period": "2y",          // optional, z. B. 30d, 6m, 2y; Pflicht, wenn Unternehmen die Gültigkeitsdauer selbst bestimmen kann
  "assignment_id": 99            // optional; bestehende approval-Zuweisung aktualisieren
}

Antwort 201: CourseAssignment-Ressource (state=success, assignment_type=approval).

Ablauf (empfohlen)

  1. Qualifikations-Kurse ermitteln: GET /courses?type=qualification (nur Kurse mit Erlaube manuelle Qualifikation).
  2. User-ID festlegen (z. B. aus GET /users oder Import).
  3. Qualifikation hinterlegen: POST /users/{user}/qualifications mit course_id und optional finish_date / valid_period.
  4. Ergebnis prüfen: Antwort enthält die neue Zuweisung; abgeschlossene Einträge erscheinen unter GET /users/{user}/certificated-courses mit entry_type = qualification_approval.

JSON-Body — Felder

FeldPflichtBeschreibung
course_idjaAktiver Qualifikations-Kurs (Erlaube manuelle Qualifikation), sichtbar für die Firma des Service-Users (Integeri-Kurs oder Firmenkurs).
finish_dateneinDatum der Qualifikation (Y-m-d), maximal heute. Fehlt die Angabe, wird das aktuelle Datum verwendet.
valid_periodbedingtGültigkeitsdauer, Format ^\d+[d|w|m|y]$ (z.B. 30d, 6m, 2y). Pflicht, Pflicht, wenn das Unternehmen die Gültigkeitsdauer selbst bestimmen kann; sonst wird die des Kurses übernommen.
assignment_idneinBestehende approval-Zuweisung desselben Users aktualisieren (Datum/Gültigkeit). Muss dem Ziel-User gehören und type = approval sein.

Verhalten & Voraussetzungen

  • Bei Neuanlage (ohne assignment_id): Zuweisung mit state = success, type = approval, result_percent = 100; es wird automatisch ein Zertifikat erzeugt .
  • Der Qualifikations-Kurs muss vollständig konfiguriert sein (mit Kursinhalt) . Sonst schlägt die Zertifikatserstellung fehl → Antwort 422 unter errors.qualification.
  • Bestehende gültige approval-Zuweisungen desselben Users für denselben Kurs werden bei Neuanlage auf valid_until = gestern gesetzt (ersetzt durch die neue Qualifikation).
  • Ist der Kurs eine Bedienerschulung, kann — wie in der integeri-Oberfläche — eine wiederkehrende Bediener-Unterweisung ausgelöst werden.

Nach erfolgreicher Anlage erscheint die Qualifikation in GET /users/{user}/certificated-courses (entry_type = qualification_approval, download_url falls Zertifikat-PDF vorhanden).

Fehlerfälle (422)

  • course_id — unbekannt, inaktiv, kein Qualifikations-Kurs, oder Kurs einer anderen Firma.
  • finish_date — ungültiges Datum oder liegt in der Zukunft.
  • valid_period — fehlt bei Kurs mit may_change_valid_period, oder Format ungültig.
  • assignment_id — Zuweisung existiert nicht, gehört nicht zum User, oder ist kein approval-Typ.
  • qualification — fachlicher Fehler bei der Qualifikationsanlage .

Maschinen-Voraussetzungen (Bediener-/Ausbilderschulung)

Wenn der zugewiesene Kurs eine Bedienerschulung oder Ausbilderschulung ist, werden die kurseigenen Voraussetzungen (Altersnachweis, vorgelagerte Qualifikation, Fitness-Status, etc.) für den Ziel-User geprüft.

Sind nicht alle Voraussetzungen erfüllt, antwortet die API mit 422 Unprocessable Entity. Die fehlgeschlagenen Bedingungen werden als bereits lokalisierte Textmeldungen unter errors.course_id ausgegeben:

{
  "message": "The given data was invalid.",
  "ok": 0,
  "id": 0,
  "errors": {
    "course_id": [
      "Die Altersüberprüfung (24 Jahre) des Anwenders ist nicht erfüllt.",
      "Der erfolgreiche Abschluss der Schulung 'Flurförderfahrzeuge/Stapler - Bediener' fehlt."
    ]
  }
}

Für Nicht-Maschinen-Kurse entfällt dieser zusätzliche Check.

GET /users/{user}/assigned-courses

Voraussetzung: Berechtigung zum Einsehen von Kurszuweisungen und Sicht auf den Ziel-Benutzer. Liefert alle offenen Zuweisungen (Status assigned, inprogress, done sowie success innerhalb laufender Gruppen-/Bedienerschulungen). Das Feld is_overdue markiert überfällige Einträge (deadline_date liegt in der Vergangenheit).

GET /users/{user}/certificated-courses

Voraussetzung: Berechtigung zum Einsehen abgeschlossener Kurse und Sicht auf den Ziel-Benutzer. Liefert abgeschlossene Zuweisungen als certificated_course-Ressourcen mit lokalisiertem state_label (wie Web-Zertifikatsliste, z. B. „Bestanden“ / „Teilgenommen“ — nicht roh success/failed). Das Feld download_url verweist auf die API-PDF-Route GET /users/{user}/{assignment}/course/{course}-{lang}.pdf (generierte Zertifikate) oder auf eine signierte Upload-Datei-URL — dieselben Regeln wie in der Web-Zertifikatsliste .

Hinweis: Wiederholungen und Gruppen-/Bedienerschulungen werden serverseitig dedupliziert

GET /users/{user}/{assignment}/course/{course}-{lang}.pdf

Voraussetzung: Berechtigung zum Einsehen abgeschlossener Kurse und Sicht auf den Ziel-Benutzer. Liefert das Zertifikat als PDF-Datei (dieselben Download-Regeln wie in der integeri-Oberfläche).

Nur für abgeschlossene Zuweisungen (state = success oder failed), deren user_id, assignment-ID und course-ID zur URL passen. {lang} ist ein zweistelliger Sprachcode (z. B. de, en).

GET /api/v1/users/42/99/course/15-de.pdf
Authorization: Bearer …

Antwort 200: PDF-Datei.

JSON-Ressourcen (Felder)

Vereinfachte Übersicht;

Location

id, type (= location), state, description, company_id, contact (Objekt), admin_user_ids, trainer_admin_user_ids, teams_count, optional teams bei include=teams, Zeitstempel.

Team

id, type (= team), state, description, location_id, contact, Zuweisungen, users_count, optional users / instruction, Zeitstempel.

User

id, type (= user), state, username, Kontakt-/Profilfelder, company_id, team_ids, roles, optional locations bei include=locations, Zeitstempel.

Course

id, type (= course), title, description, allow_user_approval_date (boolean), valid_period, number_of_questions, minimal_success_points, state, company_id (null für Integeri-Kurse).

CourseAssignment

Verwendet für POST /users/{user}/course-assignments, POST /users/{user}/qualifications und GET /users/{user}/assigned-courses.

  • id, type (= course_assignment), user_id
  • stateassigned, inprogress, done, success, failed, notshownup
  • assignment_typemanual, recurring, approval
  • deadline_date, valid_until, begin_date, finish_date (ISO-8601 bzw. Y-m-d)
  • result_percent — Prozent korrekt beantworteter Fragen, oder null
  • is_overdue — boolean, true wenn deadline_date < now()
  • course{id, title, short_type, scope_id, type}
  • trainer{id, full_name} oder null
  • creator{id, full_name} oder null
  • created_at, updated_at

CertificatedCourse

Verwendet für GET /users/{user}/certificated-courses (abgeschlossene Zuweisungen ).

  • id, user_id
  • entry_typecertificated_course (für manual), qualification_approval (für approval), operator_training (Gruppen-Bediener), trainer_training (Ausbilder-Kurs)
  • state_label — lokalisiertes Kurz-Ergebnis (Schulung/Unterweisung), kein rohes state
  • assignment_type — DB-Typ der Zuweisung
  • finish_date, valid_until, result_percent
  • is_group_operator_training — boolean
  • course{id, title, short_type}
  • download_url — API-PDF-URL (/api/v1/users/…/course/{course}-{lang}.pdf) oder signierte Upload-URL
  • created_at, updated_at

Referenzen