REST-API · v1

Integriere ProbeTailor in Minuten

REST-Endpunkte mit Bearer-Token-Auth + signierte Outbound-Webhooks. cURL-, JavaScript- und Python-Beispiele inklusive — und Live-Test direkt aus der Doku.


Quickstart

Drei Schritte vom Account zum ersten erfolgreichen Aufruf.

  1. 1
    API-Key erstellen
    Unter Einstellungen → API-Schlüssel einen neuen Schlüssel anlegen. Das Plaintext-Secret wird einmalig angezeigt.
  2. 2
    Request senden
    Authorization-Header setzen und einen GET-Request gegen /api/v1/me schießen.
  3. 3
    Webhooks abonnieren
    Optional: Webhook-URL eintragen und Events wählen. Wir signieren jeden Versand per HMAC-SHA256.
  4. 4
    Schnittstelle als OpenAPI
    Alle Adressen unter /api/v1 mit Scopes, Rümpfen und Webhook-Ereignissen stehen maschinenlesbar unter /api/v1/openapi.json — zum Erzeugen eines Clients oder für ein Werkzeug wie Postman.
# 1) Verifizieren, dass dein Key tickt
curl https://app.probetailor.com/api/v1/me \
  -H "Authorization: Bearer sb_<dein_key>"

# 2) Templates auflisten
curl https://app.probetailor.com/api/v1/templates?limit=10 \
  -H "Authorization: Bearer sb_<dein_key>"

Authentifizierung

Alle Endpunkte erwarten einen Bearer-Token im Authorization-Header.

Beim Anlegen eines API-Keys bekommst du einen Plaintext-Token im Format sb_<prefix>_<secret>. Der Server speichert nur den SHA-256-Hash — du musst den Token sicher aufbewahren.

Authorization: Bearer sb_<prefix>_<secret>
  • read — GET auf Templates, Members, Workspace-Metadaten.
  • write — Reserviert für zukünftige POST/PUT/DELETE-Endpunkte (Templates, Invites).

Endpunkte

Alle Endpunkte unter /api/v1. JSON-Responses, paginiert via limit-Parameter.

Logge dich ein, um Endpunkte direkt aus der Doku zu testen.
GET/api/v1/me

Gibt das aktive Tenant + Scope-Info des API-Keys zurück. Perfekt für eine 'API-Key gültig?'-Probe.

curl https://app.probetailor.com/api/v1/me \
  -H "Authorization: Bearer sb_<key>"
Beispiel-Response
{
  "tenant": {
    "id": "f9c8…",
    "name": "Acme GmbH",
    "slug": "acme",
    "subscription_tier": "Trial",
    "created_at": "2026-…"
  },
  "api_key": { "id": "8a2b…", "scopes": ["read"] }
}
GET/api/v1/templates

Listet alle Mail-Templates des Workspaces. Optional: ?limit=1-100 und ?category=Onboarding|Transactional|Marketing|System|Custom.

curl "https://app.probetailor.com/api/v1/templates?limit=50&category=Onboarding" \
  -H "Authorization: Bearer sb_<key>"
Beispiel-Response
{
  "data": [
    {
      "id": "ab12…",
      "name": "Willkommens-Mail",
      "category": "Onboarding",
      "default_locale": "de-DE",
      "subject": "Willkommen bei {{workspace_name}}…",
      "variables": [
        { "name": "first_name", "label": "Vorname", "example": "Anna" }
      ],
      "is_default": true,
      "updated_at": "2026-…"
    }
  ],
  "count": 1
}
GET/api/v1/templates/{id}

Detail-View eines einzelnen Templates inklusive aller Locale-Übersetzungen (Subject + Markdown-Body).

curl https://app.probetailor.com/api/v1/templates/ab12… \
  -H "Authorization: Bearer sb_<key>"
GET/api/v1/members

Listet alle Workspace-Mitglieder mit Rolle, Beitrittsdatum, E-Mail und Anzeigename.

curl https://app.probetailor.com/api/v1/members \
  -H "Authorization: Bearer sb_<key>"
POST/api/v1/systeme/{system}/katalog

Testkatalog eines geprüften Systems hochladen (tests.json je Vorhaben). Scope: test.katalog.sync. Gleicher Stand → 200 unveraendert, neuer Stand → 201 mit version_id, ungültige Datei → 422 mit vorhaben, pfad, meldung.

curl -X POST https://app.probetailor.com/api/v1/systeme/tailor-plattform/katalog \
  -H "Authorization: Bearer sb_<key>" \
  -H "Content-Type: application/json" \
  --data '{"commit_sha":"1a4d14c","dateien":{"belegfluss":{…}}}'
POST/api/v1/ci-laeufe

Ergebnisse automatischer Tests als CI-Läufe melden — je Welle ein abgeschlossener Lauf. Scope: test.ci. lauf_ref macht den Aufruf idempotent (gleicher lauf_ref → 200, nichts doppelt). Zwei Wege: JSON mit ergebnisse je Fall, oder der Testbericht selbst als Rumpf mit ?format=junit|pytest|cucumber|robot|testng|playwright|cypress|auto und system, lauf_ref in der Adresse (höchstens 4 MB). Zuordnung im Bericht über die Annotation pt:<fall_id> oder einen Testnamen, der mit der Fall-Kennung beginnt; Tests ohne Fall stehen in ohne_fall, unbekannte Fälle in unbekannt. Kommandozeile: npx @clouddna/probetailor upload.

curl -X POST https://app.probetailor.com/api/v1/ci-laeufe \
  -H "Authorization: Bearer sb_<key>" \
  -H "Content-Type: application/json" \
  --data '{"system":"tailor-plattform","lauf_ref":"gh-123","commit_sha":"1a4d14c","ergebnisse":[{"fall_id":"BF4-T03","status":"failed","fehler":"…"}]}'

# oder den Testbericht selbst (Format am Inhalt erkannt)
curl -X POST "https://app.probetailor.com/api/v1/ci-laeufe?format=auto&system=tailor-plattform&lauf_ref=gh-123" \
  -H "Authorization: Bearer sb_<key>" \
  --data-binary @report.xml
GET/api/v1/sap/calm/{system}/testcases

SAP Cloud ALM, Test Automation: Cloud ALM ruft ProbeTailor als Testwerkzeug auf. Scope: test.sap; Anmeldung Bearer oder Basic mit dem Schlüssel als Passwort. Die Fälle des aktiven Katalogs als Testfälle (testCaseId ist die Fall-ID, url führt zum Fall).

curl -u "calm:sb_<key>" "https://app.probetailor.com/api/v1/sap/calm/tailor-plattform/testcases"
GET/api/v1/sap/calm/{system}/testdatavariants

SAP Cloud ALM, Test Automation. Scope: test.sap. Ein Testdatenvariant je Fall mit derselben Kennung; ?testCaseId= grenzt ein. ProbeTailor führt jeden Fall mit seinen eigenen Testdaten aus.

curl -u "calm:sb_<key>" "https://app.probetailor.com/api/v1/sap/calm/tailor-plattform/testdatavariants"
POST/api/v1/sap/calm/{system}/testcases/execute

SAP Cloud ALM, Test Automation. Scope: test.sap. Fälle starten. Rumpf: Liste mit testCaseId (oder { testCases: [...] }). Je Fall ein Job; er ist fertig, sobald der Fall nach dem Start in ProbeTailor ein Ergebnis hat.

curl -X POST -u "calm:sb_<key>" "https://app.probetailor.com/api/v1/sap/calm/tailor-plattform/testcases/execute" \
  -H "Content-Type: application/json" --data '[{"testCaseId":"BF4-T03"}]'
GET/api/v1/sap/calm/{system}/job/status

SAP Cloud ALM, Test Automation. Scope: test.sap. Stand der Jobs (?jobID=, mehrere mit Komma): running, finished oder unknown, mit percentage.

curl -u "calm:sb_<key>" "https://app.probetailor.com/api/v1/sap/calm/tailor-plattform/job/status"
GET/api/v1/sap/calm/{system}/testcases/executionhistory

SAP Cloud ALM, Test Automation. Scope: test.sap. Letztes Ergebnis je Fall: PASS als successful, FAIL und BLOCKED als failed, Message mit Zeit, Notiz und Link zum Lauf (höchstens 1000 Zeichen). ?testCaseId= oder ?jobID= grenzen ein.

curl -u "calm:sb_<key>" "https://app.probetailor.com/api/v1/sap/calm/tailor-plattform/testcases/executionhistory"
POST/api/v1/sap/calm/{system}/scopechanged

SAP Cloud ALM, Test Automation. Scope: test.sap. Cloud ALM meldet eine Änderung am Scope; die Antwort bestätigt nur — der nächste Abgleich holt die Testfälle.

curl -X POST -u "calm:sb_<key>" "https://app.probetailor.com/api/v1/sap/calm/tailor-plattform/scopechanged" \
  -H "Content-Type: application/json" --data '{}'
POST/api/v1/sap/calm/{system}/createtestcase

SAP Cloud ALM, Test Automation. Scope: test.sap. Neuen Fall im Vorhaben cloud-alm anlegen (name, description); die Review-Regel des Systems gilt. Antwort: id und url.

curl -X POST -u "calm:sb_<key>" "https://app.probetailor.com/api/v1/sap/calm/tailor-plattform/createtestcase" \
  -H "Content-Type: application/json" --data '{"name":"Bestellung freigeben","description":"…"}'
POST/api/v1/files

Datei hochladen (multipart/form-data, Feld file). Scope: write. Legt die Datei im documents-Bucket an und gibt id, path, sha256, bytes zurück.

curl -X POST https://app.probetailor.com/api/v1/files \
  -H "Authorization: Bearer sb_<key>" \
  -F "file=@beleg.pdf"
GET/api/v1/files/{id}

Metadaten/Status einer hochgeladenen Datei. Scope: read.

curl https://app.probetailor.com/api/v1/files/ab12… \
  -H "Authorization: Bearer sb_<key>"
GET/api/v1/service-desk/tickets

Service Desk (Modul „Service-Desk-Schnittstelle“): Vorgänge lesen (Scope read; status, channel, limit, before) und mit POST anlegen (Scope write; title, description, kind, severity, impact_scope, customer_ref, reporter_email, external_ref — mit external_ref ohne Doppel). Interne Notizen nie. Felder: docs/SERVICE-DESK-API.md.

curl "https://app.probetailor.com/api/v1/service-desk/tickets?status=New&limit=20" \
  -H "Authorization: Bearer sb_<key>"

curl -X POST "https://app.probetailor.com/api/v1/service-desk/tickets" \
  -H "Authorization: Bearer sb_<key>" -H "Content-Type: application/json" \
  -d '{"title":"Export bricht ab","severity":"High","external_ref":"crm-4711"}'
GET/api/v1/service-desk/tickets/{nummer}

Ein Vorgang mit seinem öffentlichen Gespräch (Antworten, Rückfragen, Antworten des Melders) — ohne interne Notizen, ohne Namen von Bearbeitern.

curl https://app.probetailor.com/api/v1/service-desk/tickets/ST-2026-0001 \
  -H "Authorization: Bearer sb_<key>"
GET/api/v1/usage

KI-Kosten und Token, aggregiert über einen Zeitraum. Scope: read. Parameter: from/to (YYYY-MM-DD, Vorgabe laufender Monat), unit_id, document_id, group_by = feature | unit | day | none (Vorgabe feature). Beträge in cost_cents als US-Cent; die Preise stammen aus dem Vercel AI Gateway.

curl "https://app.probetailor.com/api/v1/usage?from=2026-09-01&group_by=feature" \
  -H "Authorization: Bearer sb_<key>"

Webhooks

Outbound POST-Requests an deinen Endpunkt bei wichtigen Workspace-Events.

Jeder Versand trägt eine HMAC-Signatur im X-SaaSBase-Signature Header, identisch zum Stripe-Format:

X-SaaSBase-Signature: t=<unixSeconds>,v1=<hmac-sha256-hex>

Signierter Payload ist <unixSeconds>.<rawBody>

Verfügbare Events

Subscribe pro Webhook gezielt nur die Events, die dich interessieren — oder '*' für alle.

EventWann?
invite.created
Beim Anlegen einer neuen Einladung im Workspace.
invite.accepted
Wenn jemand die Einladung annimmt und Member wird.
invite.revoked
Wenn ein Owner/Admin die Einladung widerruft.
member.role_changed
Wenn die Rolle eines Members geändert wird.
template.created
Wenn ein neues Mail-Template angelegt wurde.
template.updated
Wenn ein Template gespeichert wurde (Meta oder Inhalt).
template.deleted
Wenn ein Template gelöscht wurde.
service_desk.ticket.created
Service Desk: ein Vorgang ist neu (Portal, Mail, App, API).
service_desk.ticket.replied
Service Desk: öffentliche Antwort, Rückfrage oder Antwort des Melders — nie interne Notizen.
service_desk.ticket.status_changed
Service Desk: gelöst, zugewiesen oder zusammengeführt.
pt.lauf.gestartet
Ein Testlauf beginnt (im Portal, im geprüften System oder über die MCP-Schnittstelle).
pt.lauf.abgeschlossen
Ein Testlauf ist abgeschlossen, auch ein CI-Lauf.
pt.ergebnis.bewertet
Ein Fall wurde bewertet: PASS, FAIL, BLOCKED oder NOT RUN, mit Lauf und Katalogstand.
pt.befund.erfasst
Ein Fall steht auf FAIL oder BLOCKED — mit Notiz und Link zum Fall, für Teams-, Slack- oder Ticket-Automatik.
pt.abnahme.entschieden
Die Abnahme einer Welle ist erteilt oder verweigert, mit Begründung.

Signatur verifizieren

Im Receiver: Header parsen, HMAC neu berechnen, mit timingSafeEqual vergleichen. Timestamp-Drift > 5 Min verwerfen (Replay-Schutz).

import { createHmac, timingSafeEqual } from "node:crypto";

function verify(rawBody, header, secret) {
  const parts = Object.fromEntries(header.split(",").map(kv => kv.split("=")));
  const t = parseInt(parts.t, 10);
  if (Math.abs(Math.floor(Date.now() / 1000) - t) > 300) return false;
  const expected = createHmac("sha256", secret)
    .update(`${t}.${rawBody}`).digest("hex");
  const a = Buffer.from(expected, "hex");
  const b = Buffer.from(parts.v1, "hex");
  return a.length === b.length && timingSafeEqual(a, b);
}

Fehlercodes

Standard-HTTP-Codes. Body bei Fehlern: {"error": "<message>"}.

StatusMeaningHint
200OKRequest erfolgreich.
400Bad RequestUngültige Parameter oder Body.
401UnauthorizedBearer-Token fehlt, ungültig oder widerrufen. Auch: fehlender Scope.
404Not FoundRessource existiert nicht oder gehört nicht zu deinem Tenant.
500Server ErrorUnerwarteter Fehler. Hilf uns bitte mit Support-Ticket.

Bereit zum Loslegen?

Hol dir deinen ersten API-Key in 30 Sekunden — und integriere ohne Discovery-Call.