SaaS-Integrationen mit Claude Code: API-Keys, OAuth, Webhooks und Audit-Logs
Praxisleitfaden fuer SaaS-Integrationen mit Claude Code: API-Keys, OAuth, Webhooks, Retries, Secrets und Audit-Logs.
Wenn du mit Claude Code SaaS-Integrationen baust, ist die erste Frage nicht “welchen Endpoint rufe ich auf?”. Die erste Frage ist: Wie autorisiere ich sicher, wie wiederhole ich fehlgeschlagene Schritte ohne doppelte Nebenwirkungen, und wie kann ich spaeter erklaeren, wer was getan hat? Ohne diese Schicht wird selbst eine einfache Slack-Benachrichtigung schnell zu einem Sicherheits-, Abrechnungs- oder Betriebsproblem.
Dieser Leitfaden bringt API-Keys, OAuth, Webhooks, Rate Limits, Retries, Idempotenz, Audit-Logs, Secrets und Testumgebungen in eine Form, die gut zu Claude Code passt. Ein Webhook ist eine Nachricht, die ein SaaS-Dienst an deinen Server sendet. Idempotenz bedeutet, dass eine wiederholte Ausfuehrung kein doppeltes Ergebnis erzeugt. Ein Audit-Log ist das Protokoll, mit dem du Automatisierung spaeter nachvollziehen kannst.
Die Beispiele setzen Node.js 20 oder neuer voraus und sind so geschrieben, dass du sie direkt in ein kleines scripts/-Verzeichnis kopieren kannst.
Integrationsarchitektur
Claude Code sollte nicht der einzige Ort sein, an dem Integrationszustand lebt. Claude Code plant, generiert und startet Befehle; Tokens, Retry-Status und Audit-Historie gehoeren in den Connector-Code.
flowchart LR
A[Claude Code] --> B[CLI or MCP connector]
B --> C[Auth and secret store]
B --> D[Retry and rate-limit wrapper]
D --> E[SaaS API]
E --> F[Webhook receiver]
F --> G[Queue]
G --> H[Worker]
H --> I[Audit log]
Die kleinste sinnvolle Variante ist ein CLI-Wrapper, etwa node scripts/slack-notify.mjs, den Claude Code ausfuehrt. Wird der Workflow regelmaessig genutzt, lohnt sich ein MCP-Server, damit Eingabeschema, Berechtigungen und Fehlerbehandlung wiederverwendbar sind. Webhook-Empfaenger sind aufwendiger, aber notwendig, wenn Stripe, GitHub, Slack oder ein anderer SaaS-Dienst den Ablauf startet.
Vier konkrete Use Cases
Der erste Use Case ist Release-Betrieb. Claude Code liest unveroeffentlichte GitHub-Commits, erstellt Release Notes und postet eine kurze Zusammenfassung in Slack. Slack Incoming Webhooks sind schnell eingerichtet, aber fuer Loeschen, Threads oder komplexe Chat-Flows solltest du zur Slack Web API wechseln.
Der zweite Use Case ist Billing-Automatisierung. Ein Stripe-Webhook empfaengt checkout.session.completed, schreibt den Kunden in ein internes Tool und legt fehlgeschlagene Arbeit in eine Retry-Queue. Signaturpruefung, Idempotency Keys und strikte Trennung zwischen Test- und Live-Modus sind hier Pflicht.
Der dritte Use Case ist Support-Triage. Google Workspace OAuth erlaubt einem Backend, eine Support-CSV zu lesen; Claude Code klassifiziert die Zeilen; GitHub Issues werden fuer Engineering-Follow-up erstellt. Weil der Ablauf Nutzerdaten beruehrt, ist OAuth mit engen Read-only-Scopes sicherer als ein gemeinsamer API-Key.
Der vierte Use Case ist ein Audit-Dashboard. Jede von Claude Code angestossene SaaS-Aktion wird als NDJSON gespeichert, damit das Team Actor, Provider, Aktion, Ziel und Idempotency Key sehen kann. Das hilft schon lange bevor eine grosse Audit-Plattform eingefuehrt wird.
API-Key, OAuth, Webhook oder Connector?
| Methode | Einfache Erklaerung | Geeignet fuer | Worauf achten |
|---|---|---|---|
| API-Key | Gemeinsames Server-Geheimnis | Stripe-Serveraufrufe, interne Slack-Meldungen | Nur in Umgebungsvariablen oder Secret Manager speichern |
| OAuth | Nutzer oder Workspace erteilt Zugriff | Google Drive, GitHub Apps, nutzerspezifische Aktionen | Refresh Tokens und Scopes bewusst gestalten |
| Webhook | SaaS sendet ein Event an deinen Endpoint | Stripe-Zahlungen, GitHub-Issues, Slack-Events | Signaturen pruefen, Duplikate tolerieren, Reihenfolge nicht annehmen |
| CLI/MCP-Connector | Stabiles Tool fuer Claude Code | Runbooks, interne Ops, SaaS-uebergreifende Workflows | Validierung und Logs in den Connector legen |
Die Google-OAuth-2.0-Dokumentation beschreibt den Ablauf mit Access Token und Refresh Token. Auch bei GitHub und Slack brauchst du actor-bewusste Logs, denn “der Bot war es” reicht bei spaeterer Rechteanalyse nicht aus.
Checkliste fuer Umgebungsvariablen
Beginne mit .env.example und teile nur die Namen. Echte Werte bleiben aus Git heraus.
# .env.example
INTEGRATION_ENV=sandbox
SAAS_API_TOKEN=
SLACK_WEBHOOK_URL=
GITHUB_WEBHOOK_SECRET=
GOOGLE_CLIENT_ID=
GOOGLE_CLIENT_SECRET=
STRIPE_SECRET_KEY=sk_test_xxx
STRIPE_WEBHOOK_SECRET=whsec_xxx
AUDIT_LOG_PATH=logs/saas-audit.ndjson
# .gitignore
.env
.env.*
!.env.example
logs/
Pruefe vor der Ausfuehrung durch Claude Code:
- Live-Keys und Test-Keys liegen in getrennten Umgebungen.
- Secrets werden nie in Prompts eingefuegt.
Authorization-Header und Webhook-Secrets erscheinen nie in Fehlermeldungen.- OAuth-Scopes starten read-only und werden nur bei Bedarf erweitert.
- CI-Werte sind Secrets, keine normalen Repository-Variablen.
- Rotation von Keys wird mit Datum und Verantwortlichem dokumentiert.
Wrapper fuer Retries und Rate Limits
Ein Rate Limit ist die maximal erlaubte Aufruffrequenz eines Providers. GitHub REST APIs haben primaere und sekundaere Limits; bei Limitfehlern musst du Header respektieren. Slack antwortet mit 429 Too Many Requests und Retry-After. Dieses Verhalten gehoert in Code, nicht in spontane Prompts.
// scripts/saas-request.mjs
import crypto from "node:crypto";
import { pathToFileURL } from "node:url";
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
export async function saasRequest(url, options = {}) {
const {
method = "GET",
token = process.env.SAAS_API_TOKEN,
body,
idempotencyKey = method === "POST" ? crypto.randomUUID() : undefined,
maxRetries = 4,
headers = {},
} = options;
for (let attempt = 0; attempt <= maxRetries; attempt += 1) {
const res = await fetch(url, {
method,
headers: {
Accept: "application/json",
...(body ? { "Content-Type": "application/json" } : {}),
...(token ? { Authorization: `Bearer ${token}` } : {}),
...(idempotencyKey ? { "Idempotency-Key": idempotencyKey } : {}),
...headers,
},
body: body ? JSON.stringify(body) : undefined,
});
if (res.ok) return res;
const retryAfter = Number(res.headers.get("retry-after"));
const shouldRetry = [408, 409, 425, 429, 500, 502, 503, 504].includes(res.status);
if (!shouldRetry || attempt === maxRetries) {
const text = await res.text();
throw new Error(`SaaS request failed: ${res.status} ${text.slice(0, 200)}`);
}
const backoffMs = Number.isFinite(retryAfter)
? retryAfter * 1000
: Math.min(30000, 500 * 2 ** attempt);
await sleep(backoffMs);
}
throw new Error("unreachable");
}
if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
const url = process.argv[2];
if (!url) throw new Error("Usage: node scripts/saas-request.mjs <url>");
const res = await saasRequest(url);
console.log(await res.text());
}
Bei APIs wie Stripe, die Idempotency Keys unterstuetzen, kann derselbe POST sicher wiederholt werden. Fuer eigene Worker nimm einen Key wie provider + event_id + action und ueberspringe die Verarbeitung, wenn er bereits existiert.
Webhook-Signaturen pruefen
Webhooks sind oeffentliche HTTP-Eingaenge. Ohne Signaturpruefung kann jeder gefaelschte Events senden. GitHub verwendet X-Hub-Signature-256, Stripe Stripe-Signature. Wichtig ist, den Raw Body zu pruefen, bevor JSON geparst wird.
1. Raw Body lesen.
2. Signatur-Header lesen.
3. HMAC mit gemeinsamem Secret berechnen.
4. Timing-safe vergleichen.
5. Delivery ID als Idempotency Key speichern.
6. Schnell 202 zurueckgeben und schwere Arbeit in einer Queue verarbeiten.
// scripts/verify-github-webhook.mjs
import crypto from "node:crypto";
import http from "node:http";
const secret = process.env.GITHUB_WEBHOOK_SECRET;
if (!secret) throw new Error("Set GITHUB_WEBHOOK_SECRET");
function verifyGitHubSignature(rawBody, signatureHeader) {
const received = Array.isArray(signatureHeader)
? signatureHeader[0]
: signatureHeader ?? "";
const expected =
"sha256=" + crypto.createHmac("sha256", secret).update(rawBody).digest("hex");
const receivedBytes = Buffer.from(received);
const expectedBytes = Buffer.from(expected);
return (
receivedBytes.length === expectedBytes.length &&
crypto.timingSafeEqual(receivedBytes, expectedBytes)
);
}
http
.createServer(async (req, res) => {
const chunks = [];
for await (const chunk of req) chunks.push(chunk);
const rawBody = Buffer.concat(chunks);
if (!verifyGitHubSignature(rawBody, req.headers["x-hub-signature-256"])) {
res.writeHead(401);
res.end("invalid signature");
return;
}
const event = req.headers["x-github-event"];
const delivery = req.headers["x-github-delivery"];
console.log(JSON.stringify({ event, delivery, receivedAt: new Date().toISOString() }));
res.writeHead(202, { "Content-Type": "application/json" });
res.end(JSON.stringify({ ok: true }));
})
.listen(3000, () => console.log("Listening on http://localhost:3000"));
Bei Stripe ist in Produktion das offizielle SDK mit constructEvent() die bessere Wahl. Test- und Live-Webhook-Secrets unterscheiden sich, also bleibt STRIPE_WEBHOOK_SECRET umgebungsspezifisch.
Audit-Logs
Ein Audit-Log ist die Aufzeichnung, mit der du eine automatisierte Aktion spaeter erklaeren kannst. Claude-Code-Chatverlauf reicht nicht. Du brauchst Zeitstempel, Actor, Provider, Aktion, Ziel, Idempotency Key und Status.
{
"ts": "2026-06-03T09:15:00.000Z",
"actor": "claude-code",
"provider": "github",
"action": "create_issue",
"target": "owner/repo#123",
"idempotencyKey": "github:issue:customer-42:2026-06-03",
"status": "succeeded"
}
// scripts/audit-log.mjs
import { appendFile, mkdir } from "node:fs/promises";
import { dirname } from "node:path";
export async function writeAudit(event) {
const record = {
ts: new Date().toISOString(),
actor: event.actor ?? "claude-code",
provider: event.provider,
action: event.action,
target: event.target,
idempotencyKey: event.idempotencyKey,
status: event.status ?? "started",
};
const file = process.env.AUDIT_LOG_PATH ?? "logs/saas-audit.ndjson";
await mkdir(dirname(file), { recursive: true });
await appendFile(file, `${JSON.stringify(record)}\n`, "utf8");
}
if (process.argv[1]?.endsWith("audit-log.mjs")) {
await writeAudit({
provider: "slack",
action: "post_message",
target: "#release",
idempotencyKey: "demo-2026-06-03",
status: "succeeded",
});
}
NDJSON reicht fuer die erste Version. Spaeter kannst du die Datei in BigQuery, DuckDB oder ein Spreadsheet laden.
Typische Fallen
Eine haeufige Falle ist der Versuch, Webhooks direkt an localhost zu senden. GitHubs Troubleshooting weist darauf hin, dass Webhook-URLs oeffentlich erreichbar sein muessen. Nutze fuer lokale Tests einen Forwarding-Dienst und in Produktion HTTPS.
Eine zweite Falle ist Vertrauen in die Reihenfolge von Webhooks. Provider koennen Events verspaetet oder ausser Reihenfolge liefern. Nutze Event-Zeitstempel, Delivery IDs und den aktuellen Zustand der Ressource.
Das dritte Problem ist doppelte Arbeit durch Retries. Zahlungen, Issues, Slack-Posts und E-Mails sind sichtbar. Setze Idempotency Keys bei POST und speichere verarbeitete Delivery IDs im Worker.
Die vierte Falle sind zu breite OAuth-Scopes. Beginne mit Read-only, einem Ordner oder Workspace und kurzlebigen Tokens. Erweitere erst, wenn das Risiko klar ist.
Die fuenfte Falle ist das Einfuegen von Secrets in Claude Code. Bitte Claude Code, Umgebungsvariablennamen zu verwenden; echte Werte bleiben im Secret Manager, CI-Secret oder lokalen .env.
Wann ein Connector sinnvoll ist
Das erste Skript darf direkt und langweilig sein. Sobald Autorisierung, Pagination, Rate Limiting, Audit-Logging und Fehlerformatierung in drei Workflows wiederkehren, lohnt sich ein Connector.
Benenne die Abstraktion fachlich: sendMessage(), createTicket(), recordPaymentEvent(), writeAudit(). Ein duennes callSlackApi() ist fuer Claude Code weniger hilfreich als eine Funktion, die das Ziel des Workflows ausdrueckt.
Fuer benachbarte Details helfen Claude Code API Design Assistant und Claude Code API Testing. Fuer Security-Reviews lies vor Produktionszugriff Claude Code Security Best Practices.
Offizielle Referenzen
- Stripe: Webhook-Signaturen pruefen
- Stripe: Idempotent requests
- Slack: Incoming Webhooks
- Slack: Web API rate limits
- GitHub: Webhook deliveries validieren
- GitHub: REST API rate limits
- Google: OAuth 2.0 for Google APIs
Wenn Claude-Code-Integrationen in Teamprozesse kommen, bereite wiederverwendbare Vorlagen vor, bevor der erste Incident passiert. Praktische Checklisten findest du unter /products/, Team-Enablement unter /training/.
Im praktischen Test waren Integrationen mit Signaturpruefung, Idempotenz, Audit-Logs und getrennten Testumgebungen von Anfang an deutlich leichter zu erweitern. Selbst eine kleine Slack-Meldung wird verlaesslicher, wenn Fehler nachvollziehbar sind und bewusst erneut abgespielt werden koennen.
Kostenloses PDF: Claude-Code-Cheatsheet
E-Mail eintragen und eine Seite mit Befehlen, Review-Gewohnheiten und sicheren Workflows herunterladen.
Wir schützen Ihre Daten und senden keinen Spam.
Über den Autor
Masa
Engineer für praktische Claude-Code-Workflows und Team-Einführung.
Ähnliche Artikel
Claude Code Permission Safety Ladder: Zugriff kontrolliert erweitern
Von read-only zu begrenzten Änderungen, Prüfbefehlen und Deploy-Checks mit klarer Kontrolle.
Claude Code Small PR Proof Pack: kleine Änderungen reviewbar machen
Ein Proof Pack für Claude-Code-PRs: Diff, Checks, öffentliche URL, CTA-Pfad und Rollback.
Claude-Code-Review-Gate vor dem Commit
Vor dem Commit mit Claude Code prüfen: Diff, Build, öffentliche URL, Gumroad-Links, Beratung-CTA, fehlende Tests und fremde Dateien.