Entwicklerdoku

Schnittstelle für Entwickler

Eine REST-Schnittstelle je Team: Mitglieder, Trainings und Bewertungen lesen, Zuweisungen und Fälle verwalten, den freigegebenen Katalog und die Teamauswertung abrufen — und per Webhook benachrichtigt werden, wenn ein Training endet oder eine Bewertung fertig ist.

Diese Seite bringt dich in rund fünf Minuten zum ersten erfolgreichen Aufruf. Die vollständige Referenz listet jede Operation mit Parametern, Beispielantwort und möglichen Fehlern; die maschinenlesbare Fassung liegt unter openapi.v1.json (OpenAPI 3.1, aus demselben Code erzeugt wie diese Seiten).

Voraussetzungen

Die Schnittstelle ist Teil des Team- und des Enterprise-Pakets. Ein Administrator oder der Inhaber des Teams legt den ersten Schlüssel unter Team → Schnittstellen in der App an; das braucht das Teamrecht schnittstellen (standardmäßig nur beim Inhaber, von dort aus erteilbar).

Schnellstart

1

Schlüssel erzeugen

In der App unter Team → Schnittstellen → Schlüssel. Wähle die Vorlage „Nur lesen" für den ersten Versuch — der Geheimteil wird nur in diesem einen Moment angezeigt.

2

Ersten Aufruf machen

GET /me braucht keinen Scope und bestätigt, dass der Schlüssel gültig ist: Mandant, Scopes und die Datenschutzschalter des Teams.

curl https://app.sip.coach/api/public/v1/me \
  -H "Authorization: Bearer sipk_live_ab12cd34_…"
import httpx

antwort = httpx.get(
    "https://app.sip.coach/api/public/v1/me",
    headers={"Authorization": "Bearer sipk_live_ab12cd34_…"},
)
print(antwort.json())
const res = await fetch("https://app.sip.coach/api/public/v1/me", {
  headers: { Authorization: "Bearer sipk_live_ab12cd34_…" },
});
console.log(await res.json());
<?php
$context = stream_context_create(["http" => ["header" =>
    "Authorization: Bearer sipk_live_ab12cd34_…"]]);
$antwort = file_get_contents("https://app.sip.coach/api/public/v1/me", false, $context);
echo $antwort;

Antwort:

{
  "tenant_id": "6a9c3e3e-9b8e-4b7b-9e9d-2b7b1a2c3d4e",
  "kind": "team",
  "scopes": [
    "users:read",
    "trainings:read",
    "evaluations:read"
  ],
  "rate_limit_per_min": 600,
  "privacy": {
    "member_detail_enabled": true
  }
}
3

Weiterlesen

Mit einem Schlüssel der Vorlage „Lesen und Zuweisungen" liefert GET /users die Mitglieder, GET /trainings deren Trainings — Details und jede weitere Operation in der Referenz.

Authentifizierung

Jede Anfrage trägt den Schlüssel im Kopf Authorization: Bearer sipk_live_<Präfix>_<Geheimteil>. Der Schlüssel gehört dem Team, nicht einer Person; seine Scopes stehen bei der Erzeugung fest (eine Erweiterung braucht einen neuen Schlüssel). Widerruf wirkt sofort, eine Rotation überlappt den alten und den neuen Schlüssel für eine wählbare Frist.

ScopeErlaubt
users:read / users:writeMitglieder lesen / einladen, Rolle ändern, entfernen
trainings:readTrainings-Metadaten
evaluations:readBewertungen (Punktzahl, Dimensionen, Tipps — kein Transkript)
assignments:read / assignments:writeZuweisungen
cases:read / cases:writeTeam-Fälle
catalog:readKatalog im für das Team freigegebenen Umfang
analytics:readTeamauswertung (aggregiert)
webhooks:manageWebhook-Endpunkte

Die Oberfläche bietet beim Anlegen zusätzlich die Vorlagen „Nur lesen" (alle :read-Scopes) und „Lesen und Zuweisungen" (zusätzlich assignments:write) an, oder eine eigene Auswahl aus der Tabelle oben.

Mandant und Rechte

Der Mandant steht fest, sobald der Schlüssel erzeugt ist — kein Aufruf nennt eine Team-Kennung, weder im Pfad noch im Körper. Eine fremde Kennung liefert 404, genau wie eine erfundene: ob sie nie existiert hat oder einem anderen Team gehört, ist von außen nicht unterscheidbar.

Fehler

Jede Fehlerantwort folgt RFC 9457 (application/problem+json). code ist stabil und wird nie übersetzt; title richtet sich nach Accept-Language (de oder en).

{
  "type": "https://sip.coach/entwickler/api/fehler#insufficient_scope",
  "title": "Insufficient scope",
  "status": 403,
  "code": "insufficient_scope",
  "detail": "scope 'assignments:write' required",
  "request_id": "a7e8b2c1-4d3e-4f5a-9b6c-7d8e9f0a1b2c",
  "required_scope": "assignments:write"
}
StatusCodeWann
400bad_requestEine Abhängigkeit hat die Anfrage ohne eigenen Code abgelehnt; der Status richtet sich nach jener Abhängigkeit.
401unauthorizedSchlüssel fehlt, unbekannt, falsch, abgelaufen, widerrufen oder die IP ist nicht zugelassen — ein Code für alle Gründe.
403insufficient_scopeDer Scope für diese Operation fehlt; detail nennt ihn.
403privacy_restrictedDas Team hat Einzelwerte ausgeschaltet (member_detail_enabled).
403api_disabledMandant gesperrt oder beendet.
403vorgabe_gesperrtEine Vorgabe, die für den Empfänger gilt, sperrt diese Situation, Persönlichkeit oder Branche (nur bei Zuweisungen).
404not_foundNicht vorhanden oder einem anderen Mandanten gehörend — von außen nicht unterscheidbar.
409conflictDie E-Mail-Adresse gehört bereits einem Mitglied des Teams oder dessen Inhaber, oder ein gleichzeitiger zweiter Aufruf mit demselben Idempotency-Key läuft noch.
409seat_limit_reachedAlle Sitze des Teams sind belegt.
409last_adminDas Mitglied ist der letzte aktive admin; Rollenwechsel oder Entfernen würde das Team ohne Administrator zurücklassen.
409ownerDer Inhaber des Teams kann über die Schnittstelle weder entfernt noch in der Rolle geändert werden.
422validation_errorEine Query-, Pfad- oder Körperangabe ist ungültig. Ein beim Einlesen der Anfrage erkannter Formfehler trägt errors (eine Liste); ein von der Anwendung geprüfter Fachfehler trägt stattdessen field (genau ein Feldname).
422idempotency_mismatchIdempotency-Key wurde mit einem anderen Körper wiederverwendet.
422kombination_ungueltigDie Situation, Persönlichkeit oder Branche ist unbekannt, für das Team nicht sichtbar oder verletzt eine Katalogregel (nur bei Zuweisungen).
429rate_limitedGrenze erreicht; Retry-After nennt die Wartezeit in Sekunden.
500internalUnerwarteter Fehler; der Körper verrät bewusst keine Interna — request_id hilft beim Support.
503unavailableDie Schnittstelle ist vorübergehend nicht verfügbar.

Jeder Code mit Erklärung: Fehlercodes.

Grenzwerte und Idempotenz

120 Anfragen pro Minute je Schlüssel, zusätzlich eine je Mandant einstellbare Grenze (Vorgabe 600/Minute) — es gilt immer die engere der beiden. Jede Antwort trägt RateLimit-Limit, RateLimit-Remaining und RateLimit-Reset.

POST-Aufrufe akzeptieren einen Kopf Idempotency-Key (bis zu 100 Zeichen, 24 Stunden gültig): derselbe Schlüssel mit demselben Körper liefert die erste Antwort erneut, ohne die Aktion ein zweites Mal auszuführen; derselbe Schlüssel mit einem anderen Körper liefert 422 idempotency_mismatch.

Seitenteilung

Listenrouten (z. B. GET /users, GET /assignments) nehmen ?limit= (Vorgabe 50, höchstens 200) und ?cursor= entgegen und antworten mit einem Feld data (die Liste) und next_cursor. next_cursor ist ein undurchsichtiger Wert — nicht als Seitenzahl oder Versatz interpretieren, nur unverändert an den nächsten Aufruf zurückgeben; null heißt: keine weitere Seite.

{
  "data": [
    "…"
  ],
  "next_cursor": "eyJpZCI6ICI5ZjJhLi4uIn0="
}

Versionierung

Pfadversion v1. Innerhalb von v1 nur anfügende Änderungen (neue Felder, neue Routen, neue Ereignistypen) — ignoriere unbekannte Felder in der Antwort. Eine brechende Änderung erscheint als v2 neben v1, mindestens zwölf Monate parallel, angekündigt über die Kopfzeilen Deprecation/Sunset und eine Mail an jeden Administrator mit aktivem Schlüssel.

Datenschutz

Die Datenschutzschalter des Teams gelten für die Schnittstelle genauso wie für die Oberfläche. Ist member_detail_enabled aus, liefern personenbezogene Routen nur Aggregate oder 403 privacy_restricted, und Webhook-Körper enthalten weder Punktzahl noch user_id.

CRM-Verbindungen

Ein verbundenes CRM-System wird über die Oberfläche eingerichtet, unter Team → CRM-Verbindungen — nicht über diese Schnittstelle. Sobald eine Verbindung aktiv ist, liefert GET /crm/deals die synchronisierten Deals und GET /crm/objections den Einwandkatalog des Teams; beide Routen sind nur lesend, seitenweise wie jede andere Listenroute.

Weiter von hier