Doku
REST-API
Programmatischer, nur lesender Zugriff auf deine Berichte und KI-Sichtbarkeitsdaten über team-gebundene API-Schlüssel.
Was die REST-API ist
Die CrunchJunkie REST-API bietet programmatischen, nur lesenden Zugriff auf dieselben Daten wie die App und der MCP-Connector — deine Kunden, Berichte und deren Live-Daten sowie KI-Sichtbarkeits-Kennzahlen — über einfaches HTTPS mit JSON-Antworten. Sie ist für Server, Cronjobs, Data-Warehouses und No-Code-Tools wie Zapier oder Make gedacht: überall dort, wo du deine CrunchJunkie-Zahlen brauchst, ohne dass jemand durchs Dashboard klickt.
Zwei Dinge sind bewusst so gebaut. Sie ist nur lesend: jeder v1-Endpunkt liest, keiner schreibt — ein geleakter Schlüssel kann also nie etwas ändern, löschen oder Budget ausgeben. Und sie ist team-gebunden: ein Schlüssel gehört zu genau einem Workspace und gibt nur dessen Daten zurück. Verfügbar in den Tarifen Pro, Agency und Scale. (Der MCP-Connector ist in jedem bezahlten Tarif enthalten.)
Einen API-Schlüssel erstellen
Öffne Einstellungen → REST-API. Nur Inhaber oder Admins eines Workspace können Schlüssel erstellen oder widerrufen — ein Schlüssel kann den gesamten Workspace lesen, das ist also keine Mitglieder-Aktion.
Gib dem Schlüssel einen Namen (z. B. „Zapier Produktion“) und klicke auf Erstellen. Der vollständige Schlüssel — er sieht aus wie cj_live_ab12cd34.xxxx… — wird genau einmal angezeigt. Kopiere ihn und bewahre ihn sicher auf (Passwort-Manager, das Zugangsdaten-Feld deines Tools); wir behalten nur einen Hash und können ihn dir nicht erneut zeigen. Verlierst du ihn, widerrufe ihn und erstelle einen neuen.
Widerrufen wirkt sofort: klicke bei einem Schlüssel auf Widerrufen, und jede Integration, die ihn nutzt, funktioniert ab der nächsten Anfrage nicht mehr. Schlüssel laufen nicht von selbst ab, außer du setzt ein Ablaufdatum. Ein Schlüssel gehört dem Workspace, aber wenn ein Mitglied geht, werden die Schlüssel, die es darin erstellt hat, mit widerrufen: wenn du es unter Einstellungen → Team entfernst (das Entfernen fragt vorher nach und sagt, wie viele) und wenn es sein eigenes Konto löscht (die Bestätigung sagt, wie viele). Die Schlüssel bleiben hier als widerrufen gelistet.
Eine Anfrage stellen
Die Basis-URL ist https://app.crunchjunkie.io/api/v1. Sende deinen Schlüssel als Bearer-Token im Authorization-Header:
curl -H "Authorization: Bearer cj_live_ab12cd34.xxxx…" https://app.crunchjunkie.io/api/v1/clients
Jede Antwort ist JSON. Erfolg sieht so aus: { "data": … , "meta": { … } }; ein Fehler so: { "error": { "code": "…", "message": "…" } } mit dem passenden HTTP-Status (401 nicht authentifiziert, 403 falscher Scope oder Tarif, 404 nicht gefunden, 429 Rate-Limit, 500 Serverfehler).
Endpunkte
v1 ist nur lesend und spiegelt die MCP-Lese-Tools, die Zahlen stimmen also exakt mit der App überein:
• GET /api/v1/clients — deine Kunden, ihre verbundenen Anbieter und Berichtsanzahl.
• GET /api/v1/reports?clientId=… — deine Berichte (IDs für die Aufrufe unten). Berichte unter „Gelöscht“ fehlen darin; mit includeDeleted=true werden sie mit aufgeführt, markiert mit deleted: true.
• GET /api/v1/reports/{id} — die Definition eines Berichts (Widgets, Zeitraum-Konfiguration).
• GET /api/v1/reports/{id}/data?datePreset=…&comparePreset=… — die live zusammengestellten Daten des Berichts (KPIs, Charts, Tabellen). Eine Voreinstellung wird wie in der App in der Zeitzone des Workspaces aufgelöst, und die Antwort enthält den aufgelösten dateRange. Mit brandFilter=branded oder brandFilter=nonbranded liest du seine Search-Console-Widgets und jedes andere Widget, das Suchanfragen oder Keywords zählt, nur für diese Gruppe.
• GET /api/v1/ai-visibility/projects?clientId=… — deine KI-Sichtbarkeits-Projekte.
• GET /api/v1/ai-visibility/projects/{id}/metrics?dateFrom=…&dateTo=…&model=…&market=…&source=…&limit=…&offset=… — KI-Sichtbarkeit über ganze UTC-Tage (standardmäßig die letzten 30, höchstens 180): jede Marke gepoolt über alle Antworten (Antworten, die sie nennen, ÷ Antworten, mit den Antworten als n und der ±-Fehlermarge), der Kunde je Engine und die Snapshot-Zeilen dahinter, jede mit Engine-Bezeichnung und Quelle. Sentiment liegt auf 0–100 mit 50 als neutral, Position 1 heißt zuerst genannt; beide sind null, mit avgPositionMentions / sentimentMentions und einem Grund, wenn weniger als 10 Erwähnungen dahinterstehen; meta.note nennt die Pooling-Regel. Ein Aufruf liefert höchstens 5.000 Snapshot-Zeilen (limit, 1 bis 5.000; ohne Angabe 500); blättere mit offset, bis du meta.total Zeilen hast.
• GET /api/v1/ai-visibility/projects/{id}/prompts?days=…&activeOnly=…&q=… — die verfolgten Prompts, jeder mit seiner Sichtbarkeit, gepoolt über seine Antworten im Zeitraum, und den Antworten als n. activeOnly=true (Standard) listet die Prompts, die die Scans stellen; activeOnly=false nimmt pausierte Prompts dazu, markiert mit active: false, deren gespeicherte Antworten erhalten bleiben. Die API ändert nie einen Prompt. Ein Prompt, der in der App oder über den MCP-Connector gelöscht wurde, ist mit allen gespeicherten Antworten weg; diese Liste enthält ihn dann nicht mehr, auch nicht für frühere Zeiträume.
• GET /api/v1/ai-visibility/projects/{id}/answers?scanJobId=…&days=…&model=…&promptId=…&market=…&brandMentioned=…&source=…&includeText=…&limit=…&offset=… — die KI-Antworten hinter diesen Zahlen, eine je Prompt, Engine und Durchlauf, die neueste zuerst: die ID der Antwort, der Scan, aus dem sie stammt (scanJobId), wann sie lief, die Engine mit dem Modell, das der Anbieter gemeldet hat, der Markt, der Prompt mit Kategorie und Tags, und für deine Marke und jeden erfassten Wettbewerber, ob die Antwort ihn nennt, an welcher Position und mit welchem Sentiment (0–100, 50 ist neutral), dazu die URLs, die sie zitiert, und die, die sie nur abgerufen hat, wo die Engine das unterscheidet, und ein Auszug von 280 Zeichen. includeText=true fügt den ganzen Text hinzu (bis zu 30.000 Zeichen; eine Seite enthält dann höchstens 25 Antworten, sonst 100, ohne Angabe 50). Mit scanJobId bekommst du jede Antwort, die dieser eine Scan gespeichert hat, unabhängig vom Datum; eine Antwort mit superseded: true wurde später am selben Tag auf derselben Engine noch einmal gefragt und zählt nicht mehr. Eine Antwort kann auch nach deinem Abruf noch superseded werden, wenn später am selben Tag neu gescannt wird; lies die Scans eines Tages deshalb noch einmal, bevor du ihn poolst. Ohne scanJobId bekommst du die Antworten, die die Zahlen im Zeitraum zählen (standardmäßig 30 Tage, 1 bis 180; außerhalb davon ein 400). Bilde Raten selbst als Antworten, die die Marke nennen, ÷ alle Antworten, nie als Durchschnitt von Raten je Prompt oder Engine, sonst weichen deine Zahlen von der App ab. Für einen Abgleich nach jedem Scan lies nach scanJobId: Das ist günstig, und die Liste eines beendeten Scans ändert sich nicht mehr. Eine Liste über einen Zeitraum steht mit der neuesten Antwort zuerst, ein Scan, der während des Blätterns endet, verschiebt also die Offsets; nimm answerId als Schlüssel deiner Zeilen. market=de-DE liest einen einzelnen Markt, genau so, wie er im locale jeder Antwort steht (derselbe Wert, den /metrics als market nimmt); ein Markt ohne Antworten im Zeitraum liefert eine leere Liste, und meta.note nennt die Märkte, die welche haben. Blättere mit meta.nextOffset; ein limit außerhalb seines Bereichs ist ein 400.
• GET /api/v1/ai-visibility/projects/{id}/scans?status=…&limit=…&offset=… — die Scans eines Projekts, der neueste zuerst: ID, Status (queued, running, done, stopped, error), was ihn gestartet hat, wann er begann und endete, die Engines und Märkte, die Prompts, die Durchläufe je Prompt, die geplanten Prüfungen und die gespeicherten Antworten. Damit holst du ein scan.completed nach, das dein Endpunkt verpasst hat.
In /reports/{id}/data ist prev einer KPI-Metrik der Wert des Vergleichszeitraums. Er ist null, wenn es nichts zum Vergleichen gibt: kein Vergleichszeitraum, keine früheren Daten für diese Metrik, ein Vergleichszeitraum, den die Quelle nicht liefern konnte, oder eine Zahl, die es nur im heutigen Stand gibt (Katalogzahlen, Bewertungszahlen, Follower-Zahlen). Er ist eine Zahl, auch 0, wenn der Vergleichszeitraum gemessen wurde: 0 ist eine echte vorherige 0, von der es keine prozentuale Veränderung gibt. Jedes KPI-Widget trägt prevNull: true; meta.note sagt dasselbe. Der Wert (value) einer KPI ist null, wenn es keine Zahl gibt: Das Lesen ist fehlgeschlagen, oder der Wert lässt sich nicht berechnen (zum Beispiel Kosten pro Conversion bei 0 Conversions). Er steht nie für 0.
Ein Search-Console- oder Rank-Tracking-Diagramm in /reports/{id}/data kann googleUpdates enthalten: die Google-Ranking-Updates, die in seinem Zeitraum liefen, aus Googles Search Status Dashboard (Name, Link, Beginn und Ende als Tage nach US-Pazifikzeit, Ende null, solange der Rollout läuft). Sie zeigen nur den Zeitpunkt, keine Ursache, und meta.googleUpdates sagt das, sobald ein Diagramm sie enthält.
Ein Google-Ads-Donut nach Gerät oder Netzwerk mit einer Rate, einem Anteil oder einem Durchschnitt (CTR, CPC, Anteil an möglichen Impressionen, Kosten pro Conversion, ROAS) hat in /reports/{id}/data und im MCP-Tool get_report_data keine Segmente: Sein emptyReason ist „gads_not_summable“, weil ein solcher Wert je Gerät kein Teil einer Summe ist. Eine Google-Ads-Karte mit einer solchen Metrik trägt notSummable: true, und die Werte ihrer Länder sind die eigene Rate jedes Landes, nie Anteile zum Aufaddieren. meta.gadsNotSummable sagt das für einen solchen Donut und meta.geoNotSummable für eine Karte jeder Quelle (auch eine Google-Analytics-Karte von Nutzern oder einer Rate), und die aiNote des Widgets nennt die Metrik. Ein Donut jeder anderen Quelle verhält sich seit 3.187 genauso: Eine Rate, ein Durchschnitt, ein Verhältnis, die Reichweite oder einzelne Nutzer (CTR, ROAS, Absprungrate, durchschnittliche Position, Nutzer, Besucher) haben keine Segmente und den emptyReason „not_summable“, und meta.donutNotSummable sagt das. Ein Donut einer Anzahl oder eines Betrags zeigt seine 9 größten Segmente und ein „Sonstige“ mit dem Rest, damit seine Segmente jede Zeile ergeben, die die Quelle liefert (Google Analytics liefert bis zu 10.000 Zeilen, Matomo und Piwik PRO bis zu 1.000; Zeilen darüber hinaus stehen in keinem Segment).
Spaltennamen von Tabellen (cols) bleiben englische Kennungen; Anzeigezellen stehen in der Sprache des Berichts, so wie der Bericht sie druckt – seit dem 14. Oktober 2026 auch die Zellen Typ und Quelle der Tabelle Zitierte URLs und die Zellen Problem der Tabelle Quellenzustand (vorher englisch), in /reports/{id}/data wie im MCP-Tool get_report_data.
Ein KI-Sichtbarkeits-Widget zu Quellen oder Zitaten in /reports/{id}/data (und im MCP-Tool get_report_data), das Antworten weggelassen hat, deren URLs aus dem Modellgedächtnis stammen und nicht aus einer Suche, nennt ihre Zahl: memoryExcluded an Tabelle, Donut oder Diagramm, fromMemory an jeder betroffenen KPI-Kennzahl. Diese Antworten stehen weder im Zähler noch im Nenner; die Endpunkte für Zitate und Content-Lücken nennen dieselbe Zahl als answersFromMemoryExcluded. Jede Tabelle der KI-Sichtbarkeit mit Vergleich kann außerdem withinMargin tragen, die Zellen [Zeile, Spalte], deren Veränderung nicht mindestens doppelt so groß ist wie ihre Fehlermarge: in der Markentabelle (Brand) der Vergleich einer Zelle, in der Prompt-Tabelle die Zelle „Δ Visibility“, in den Tag-Tabellen ihre Δ-Spalten und die Veränderung unter einem Wert. Der Bericht zeigt sie grau mit „~“, lies eine solche Veränderung also als unverändert – lies dafür dieses Feld, nicht das „~“ im Text.
Die maschinenlesbare OpenAPI-3.1-Spezifikation liegt unter https://app.crunchjunkie.io/api/v1/openapi.json — importiere sie in Postman, Insomnia oder deinen Codegen.
Stabilität und Versionen
v1 ist ein Vertrag, auf dem du aufbauen kannst. Innerhalb von v1 kommt nur etwas hinzu: ein neuer Endpunkt, ein neuer optionaler Parameter, ein neues Feld in einer Antwort oder einer Webhook-Nutzlast oder ein neuer Wert in einer Liste wie den Engine-IDs, den Scan-Status oder answerEnd. Wir entfernen kein Feld, benennen keines um und ändern weder seinen Typ noch seine Bedeutung. Schreib deine Integration also so, dass sie unbekannte Felder ignoriert und Engine-IDs, Status und ähnliche Werte als offene Menge behandelt. Eine Änderung, die das brechen würde, kommt als neue Version (v2) neben v1. Wir kündigen sie mindestens sechs Monate vorher per E-Mail an die Inhaber jedes Workspaces an, der einen API-Schlüssel oder einen Webhook-Endpunkt nutzt, und v1 läuft nach dem Start von v2 noch mindestens sechs Monate weiter. Jede Erweiterung steht im Changelog, und die OpenAPI-Datei unter /api/v1/openapi.json beschreibt immer, was die API heute liefert.
Rate-Limits, Paginierung und Genauigkeit
Jeder Schlüssel hat ein Token-Bucket-Rate-Limit; überschreitest du es, bekommst du einen 429 mit einem Retry-After-Header, der dir sagt, wie viele Sekunden du warten musst. Große Sammlungen geben die neuesten Zeilen mit meta.total und einem meta.truncated-Flag zurück, damit eine begrenzte Seite nie als vollständige Menge ausgegeben wird — grenze nach Datum oder Modell ein, um ältere Daten zu erreichen.
Ein Genauigkeitshinweis, der zählt, wenn du eigene Aggregate berechnest: KI-Sichtbarkeits-Kennzahlen folgen dem Metrik-Vertrag — poole eine Rate, indem du die Zähler und die Läufe summierst und EINMAL teilst (Σ visibilityCount ÷ Σ totalRuns), nie durch Mitteln von Prozentwerten pro Zeile, und halte jeden Markt (Locale) als eigene Population. Die App macht das für dich; mach es nachgelagert genauso, und deine Zahlen stimmen mit unseren überein.
Erste Schritte Reporting Berichtsvorlagen Filter, Dimensionen & Vergleiche Berichte teilen & versenden White-Label & Branding Metrik-Glossar KI-Sichtbarkeit Eigene KI-API-Schlüssel Wahrnehmung KI-Shopping-Sichtbarkeit GEO-Audit KI-Crawler & Crawlbarkeit KI-Traffic aus GA4 Rank-Tracker SEO-Audit Keyword-Recherche Links Monitoring Signale & Automatisierungen Integrationen Data Studio Mit Claude & ChatGPT verbinden (MCP) Claude verbinden Claude Code verbinden ChatGPT verbinden Cursor verbinden VS Code verbinden Webhooks Single Sign-on (SSO) Konto & Abrechnung Daten, Datenschutz & Sicherheit Der Crunch-Assistent Freunde empfehlen FAQ