API-Dokumentation
Drei Endpunkte, ein Authentifizierungs-Header, Abrechnung pro geliefertem Beleg. Hier steht alles, was Sie für die Integration brauchen — jedes Beispiel wurde gegen die Produktivumgebung ausgeführt.
Authentifizierung
Bearer-Token im Header. Ein unbekannter, ein deaktivierter und ein fehlender Schlüssel liefern dasselbe 401 — wir verraten nicht, woran es gescheitert ist.
Authorization: Bearer cyt_live_…Zwei Arten von Schlüsseln
Ein cyt_test_-Schlüssel nutzt denselben Korpus und liefert dieselben Antworten, wird aber nie abgerechnet — 100 Belege pro Monat für Integration und Fehlerbehandlung. Ein cyt_live_-Schlüssel bedient den Produktivbetrieb und zählt auf Ihr Paket. Der Schlüssel wird genau einmal bei der Ausgabe angezeigt; wir speichern nur seinen Hash.
Wofür Sie zahlen
Abrechnungseinheit ist der GELIEFERTE BELEG — ein Satz, dem wir eine Quelle mit Seitenzahl zuordnen konnten. Kein Treffer (found: false) ist kostenlos, ebenso HINTERGRUND-Material in /chapter-sources (Relevanz unter 7) — Sie zahlen nur für Quellen, die direkt zum Thema passen. Separat abgerechnet wird ein NEUES THEMA: Den Korpus für ein Gebiet aufzubauen, das wir noch nicht haben, dauert Minuten und kostet zwei Größenordnungen mehr — deshalb lösen Sie es bewusst mit harvestOnMiss aus. Über Ihr Paket hinaus funktionieren Aufrufe zu Mehrverbrauchspreisen weiter (auf die nächste Rechnung aufgeschlagen) — aber höchstens bis zu ZUSÄTZLICHEN 100 % des Pakets; danach gibt es 429 bis zum 1. des Monats oder bis zum Upgrade. Ihre Rechnung kann Sie also nie um mehr als das Doppelte des Pakets überraschen.
| Paket | Preis / Monat | Belege | Neue Themen | Mehrverbrauch |
|---|---|---|---|---|
| Test | kostenlos | 100 | 3 | — |
| Basic | 19 $ | 400 | 5 | 0,04 $ / 1,00 $ |
| Start | 49 $ | 1.200 | 15 | 0,04 $ / 1,00 $ |
| Pro | 99 $ | 3.000 | 40 | 0,04 $ / 1,00 $ |
Endpunkte
GET /usage
Paketstatus und Verbrauch im laufenden Monat. Kostet nichts und verbraucht nichts — der günstigste Weg zu prüfen, ob ein Schlüssel funktioniert.
curl -s -H "Authorization: Bearer $CYTADO_KEY" \
https://cytado.com/api/ext/usageimport os, requests
r = requests.get(
"https://cytado.com/api/ext/usage",
headers={"Authorization": f"Bearer {os.environ['CYTADO_KEY']}"},
timeout=60,
)
print(r.json())const r = await fetch("https://cytado.com/api/ext/usage", {
headers: { Authorization: `Bearer ${process.env.CYTADO_KEY}` },
});
console.log(await r.json());POST /find-source
Ein Satz rein, eine Quelle mit Seitenzahl raus. Der einzige kostenpflichtige Aufruf — und nur, wenn er etwas findet. Bis zu 60 Einträge pro Anfrage; der Überschuss wird AUSDRÜCKLICH verworfen. Das Feld hint ist das Thema der Arbeit: Ohne hint fragen wir „belegt diese Quelle diesen Satz?“, mit hint „könnte jemand, der DIESE Arbeit schreibt, sie zitieren?“. Jeder Treffer trägt wsparcie — stützt der GELIEFERTE Auszug selbst die Aussage: wprost (so zitieren), posrednie (lesen und einordnen), brak (der Auszug sagt das nicht — anderswo suchen), null (nicht bewertet).
curl -s -X POST https://cytado.com/api/ext/find-source \
-H "Authorization: Bearer $CYTADO_KEY" \
-H "Content-Type: application/json" \
-d '{
"items": [
{
"id": "a1",
"claim": "Procrastination is accompanied by guilt and psychological discomfort.",
"hint": "procrastination among university students"
}
],
"langs": [
"en"
],
"harvestOnMiss": false
}'import os, requests
r = requests.post(
"https://cytado.com/api/ext/find-source",
headers={"Authorization": f"Bearer {os.environ['CYTADO_KEY']}"},
json={
"items": [
{
"id": "a1",
"claim": "Procrastination is accompanied by guilt and psychological discomfort.",
"hint": "procrastination among university students"
}
],
"langs": [
"en"
],
"harvestOnMiss": False
},
timeout=600,
)
r.raise_for_status()
print(r.json())const r = await fetch("https://cytado.com/api/ext/find-source", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.CYTADO_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
"items": [
{
"id": "a1",
"claim": "Procrastination is accompanied by guilt and psychological discomfort.",
"hint": "procrastination among university students"
}
],
"langs": [
"en"
],
"harvestOnMiss": false
}),
});
if (!r.ok) throw new Error(`cytado ${r.status}: ${await r.text()}`);
console.log(await r.json());POST /chapter-sources
Ein Kapitelthema rein, eine Auswahl zitierfähiger Quellen raus, sortiert nach Themenabdeckung. Abgerechnet werden NUR Quellen direkt zum Thema (Relevanz >= 7) — und standardmäßig werden nur diese geliefert; Hintergrundmaterial (Relevanz 5–6, kostenlos) gibt es mit explizitem minRelevance: 5. Jede Quelle trägt wsparcie: Stützt der gelieferte Auszug selbst das Kapitel (wprost / posrednie / brak, null = nicht bewertet)? Das Feld chapter ist optional: Ohne es werden Quellen für das Thema als Ganzes ausgewählt, mit ihm werden die Bewertungen an dieses Kapitel gebunden. Das optionale Feld hint (Thema der gesamten Arbeit) filtert Quellen außerhalb des Themas heraus — wichtig bei allgemeinen Kapiteln wie „Methodik“, deren Überschrift zu allem passt; mit hint steigt die Standardschwelle für Hintergrundmaterial auf 6. limit ist auf 15 begrenzt; limit: 0 (oder negativ) ist ein kostenloser No-op ohne Ergebnis — praktisch für Schleifen nach dem Muster `limit: target - have`. Das Feld exclude listet bereits verwendete Quellen — die Abdeckung wird dann über den Rest berechnet, sodass aufeinanderfolgende Kapitel nicht immer dasselbe Material erhalten.
curl -s -X POST https://cytado.com/api/ext/chapter-sources \
-H "Authorization: Bearer $CYTADO_KEY" \
-H "Content-Type: application/json" \
-d '{
"topic": "screen time in preschool children",
"chapter": "Introduction",
"exclude": []
}'import os, requests
r = requests.post(
"https://cytado.com/api/ext/chapter-sources",
headers={"Authorization": f"Bearer {os.environ['CYTADO_KEY']}"},
json={
"topic": "screen time in preschool children",
"chapter": "Introduction",
"exclude": []
},
timeout=600,
)
r.raise_for_status()
print(r.json())const r = await fetch("https://cytado.com/api/ext/chapter-sources", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.CYTADO_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
"topic": "screen time in preschool children",
"chapter": "Introduction",
"exclude": []
}),
});
if (!r.ok) throw new Error(`cytado ${r.status}: ${await r.text()}`);
console.log(await r.json());Aufbau einer /find-source-Antwort
{
"results": [
{
"id": "a1", // twoje id, oddane bez zmian
"claim": "…", // echo tezy, o która pytales
"found": true,
"source": { // UWAGA: pola zrodla sa TUTAJ, nie plasko
"title": "…",
"authors": "…",
"year": 2021,
"url": "https://doi.org/10.12740/pp/95085",
"doi": "10.12740/pp/95085",
"page_from": 1088,
"page_to": 1090,
"snippet": "…",
"relevance": 9
}
},
{ "id": "a2", "claim": "…", "found": false }
],
"billing": { "citations_charged": 1, "topics_charged": 0 },
"harvested": 0
}Keine Quelle heißt schlicht: kein Feld source. Sechzig Einträge pro Anfrage sind kein Problem, rechnen Sie aber mit etwa 1,6 s pro Aussage — ein voller Stapel dauert ~95 s. Setzen Sie den Client-Timeout entsprechend; das Gateway erlaubt 800 s.
Antwortfelder, die man verstehen sollte
- found
- false bedeutet: Der Korpus hat nichts, was diese Aussage stützt. Wir liefern dann nicht den nächstbesten Treffer und berechnen nichts.
- page_from / page_to
- Die GEDRUCKTE Seitenzahl — die Seite, auf der Ihre Betreuerin oder Ihr Betreuer beim Prüfen der Fußnote landet, nicht die Blattnummer im PDF.
- page_from_label
- Nur bei ungewöhnlicher Paginierung gefüllt (z. B. „E136“). Ein leeres Label bei gefülltem page_from heißt „die gedruckte Seitenzahl ist einfach 152“, nicht „keine Paginierung“.
- relevance
- 9–10: direkt zu dieser Aussage und dieser Gruppe. 7–8: dasselbe Phänomen in verwandtem Kontext — anderer Beruf, anderes Alter oder anderes Land; zitierfähig, aber den Kontext kenntlich machen.
- doi
- Die reine DOI, sofern vorhanden, z. B. 10.36921/abc — ohne das Präfix https://doi.org/. Deduplizieren Sie darüber: Dasselbe Werk erreicht Sie auf mehreren Wegen, stabil ist nur die DOI.
- exclude (request)
- Quellen, die Sie bereits zitieren — URLs oder DOIs in beliebiger Form (10.x, doi:10.x und https://doi.org/10.x passen alle). Gefiltert wird VOR dem Rerank, Ausschließen macht den Aufruf also günstiger, nicht nur aufgeräumter. Gemessen an einer echten Abschlussarbeit: Ohne exclude waren 40–50 % der Antworten Werke, die schon im Literaturverzeichnis standen.
- claim
- Echo der gesendeten Aussage neben ihrer id — so brauchen Sie beim Setzen der Fußnoten keine eigene Zuordnung id→Satz.
- url
- Link zum Original — IMMER eine vollständige, klickbare Adresse (eine reine DOI wird als https://doi.org/… geliefert). JEDE gelieferte Quelle hat einen; bei mehr als der Hälfte des Korpus führt er zum Volltext, weil es Open-Access-Publikationen sind.
- snippet
- Ein kurzer Auszug im Rahmen des Zitatrechts. Volltexte von Quellen, die wir nicht weiterveröffentlichen dürfen, liefern wir nie — sondern den Link, unter dem Leser sie beim Verlag finden.
- billing
- Was genau diese Anfrage gekostet hat: citations_charged, already_paid (in diesem Thema bereits bezahlte Dokumente) und free_background — wie viele gelieferte Einträge kostenloses Hintergrundmaterial waren (Relevanz unter 7). Eine Null bei free_background heißt: Alles Gelieferte passte direkt zum Thema.
Limits und Fehler
- 401 unauthorized
- Unbekannter, deaktivierter oder fehlender Schlüssel.
- 400 invalid-json
- Der Request-Body ist kein gültiges JSON.
- 400 missing-items
- Das Pflichtfeld `items` (Array) fehlt.
- 400 unknown-field
- Unbekanntes Feld in der Anfrage — mit Vorschlag, wenn es nach einem Tippfehler aussieht (`min_relevance` → „meinten Sie minRelevance?“). Felder, die wir nicht kennen, ignorieren wir nicht stillschweigend: Ein Tippfehler im Parameternamen darf Sie nicht unbemerkt Geld kosten.
- 422 invalid_request
- Syntaktisch korrekt, aber ein ungültiger WERT in einem bekannten Feld — die Antwort nennt das Feld. Z. B. ein Thema kürzer als 8 oder länger als 4000 Zeichen, langs kein Array bekannter Codes, exclude kein Array von Strings, minRelevance keine Zahl.
- 429 rate_limited
- Limit überschritten. Retry-After gibt an, nach wie vielen Sekunden Sie es erneut versuchen können. Die Minutenbremse heißt „langsamer“, das Tageslimit „für heute Schluss“, die Mehrverbrauchsgrenze (Paket + 100 %) „bis zum 1. des Monats oder Upgrade“ — die Meldung unterscheidet die Fälle.
- 402
- Paket aufgebraucht bei einer Operation, die bezahlten Zugang erfordert.
Lange Operationen: Harvest und Polling
Einen vorhandenen Korpus auszulesen dauert Sekunden. Einen Korpus für ein Thema aufzubauen, das wir noch nicht haben, dauert 5–30 Minuten — wir laden die echten PDFs herunter und lesen sie. Darauf lässt sich nicht innerhalb einer einzigen HTTP-Anfrage warten: Auf unserer Seite steht ein nginx-Timeout, auf Ihrer ein Client-Timeout. Genau dafür gibt es den asynchronen Modus von /corpus: Sie stellen den Auftrag ein und fragen dann den Status ab.
# 1. Enqueue. Returns immediately.
curl -s https://cytado.com/api/ext/corpus \
-H "Authorization: Bearer $CYTADO_KEY" \
-H "Content-Type: application/json" \
-d '{"topic":"persuasion in advertising","langs":["en"],"minCoverage":6,"async":true}'
# {"jobId":82,"coverage":7,"coverageWprost":1,"corpusReady":false,"async":true}
# jobId = null -> corpus already sufficient, nothing was started, nothing billed.
# 2. Poll every 20-30 s. Free: polling is never billed.
curl -s https://cytado.com/api/ext/corpus/status \
-H "Authorization: Bearer $CYTADO_KEY" \
-H "Content-Type: application/json" \
-d '{"jobId":82,"topic":"persuasion in advertising","langs":["en"]}'
# {"jobId":82,"status":"running","ready":false,"coverage":9,"coverageWprost":4}
# status: queued | running | done | failed | unknown
# stop when "ready" is true, then call /chapter-sourcesFragen Sie alle 20–30 Sekunden ab und setzen Sie sich eine eigene Frist — der Status failed ist eine legitime Antwort, kein Verbindungsabbruch. Schlägt der Job fehl, bleibt der Korpus, wie er war, und Sie können mit dem arbeiten, was schon da ist.
Dasselbe in Python — zum Kopieren:
import os, time, requests
BASE = "https://cytado.com/api/ext"
HEAD = {"Authorization": f"Bearer {os.environ['CYTADO_KEY']}"}
def ensure_corpus(topic, langs=("pl", "en"), min_coverage=6, limit_s=1800):
"""Ensure the corpus covers a topic. Returns final coverage.
Blocks for up to limit_s. A harvest is billed once as a New topic;
polling is free. jobId None means the corpus was already sufficient
and nothing was started or charged.
"""
r = requests.post(f"{BASE}/corpus", headers=HEAD, timeout=120, json={
"topic": topic, "langs": list(langs),
"minCoverage": min_coverage, "async": True,
})
r.raise_for_status()
state = r.json()
if not state.get("jobId"):
return state.get("coverage", 0) # already covered, no charge
deadline = time.time() + limit_s
while time.time() < deadline:
time.sleep(25) # 20-30 s is the sane cadence
try:
s = requests.post(f"{BASE}/corpus/status", headers=HEAD, timeout=60,
json={"jobId": state["jobId"], "topic": topic,
"langs": list(langs)})
s.raise_for_status()
except requests.RequestException:
continue # transient: keep polling
state2 = s.json()
if state2.get("ready"): # done OR failed — both final
return state2.get("coverage", 0)
return state.get("coverage", 0) # our deadline, not an error
def chapter_sources(topic, chapter, used=(), limit=12):
"""Sources for one chapter. Pass previously used URLs/DOIs in 'used'
so the next chapter gets NEW material instead of the same top hits."""
r = requests.post(f"{BASE}/chapter-sources", headers=HEAD, timeout=600, json={
"topic": topic, "chapter": chapter, "langs": ["pl", "en"],
"limit": limit, "exclude": list(used),
})
r.raise_for_status()
return r.json()
ensure_corpus("persuasion in advertising")
data = chapter_sources("persuasion in advertising", "Chapter 1")
print(data["coverage"], data["coverageWprost"], data["billing"])Windows und PowerShell: Body als UTF-8 senden
PowerShell 5.1 kodiert bei Invoke-RestMethod -Body <String> den Body mit der System-Codepage, nicht als UTF-8. Nicht-ASCII-Zeichen — deutsche Umlaute, polnische Sonderzeichen, Kyrillisch — gehen verloren, bevor die Anfrage den Rechner verlässt. Das Thema kommt verstümmelt bei uns an, die Suche läuft auf dem falschen Text, und nichts weist darauf hin. Übergeben Sie BYTES statt eines Strings:
$body = @{ topic = "calibration of pressure transducers" } | ConvertTo-Json -Compress
$bytes = [System.Text.Encoding]::UTF8.GetBytes($body) # <-- required
Invoke-RestMethod -Uri "$BASE/corpus" -Method Post -Headers $h -Body $bytesPowerShell 7 und curl.exe machen das von sich aus richtig. Das Problem betrifft nur das mit Windows ausgelieferte PowerShell 5.1.
Folgekapitel: der Parameter exclude
Ohne exclude erhält Kapitel zwei dieselben Top-Quellen wie Kapitel eins — weil sie objektiv die besten sind. Übergeben Sie die URLs oder DOIs der bereits verwendeten Quellen; die Abdeckung wird dann über das berechnet, was für das NÄCHSTE Kapitel noch übrig ist, nicht über das ganze Thema.
curl -s https://cytado.com/api/ext/chapter-sources \
-H "Authorization: Bearer $CYTADO_KEY" \
-H "Content-Type: application/json" \
-d '{
"topic": "persuasion in advertising",
"chapter": "Chapter 2: emotional appeals",
"langs": ["en"],
"limit": 12,
"exclude": ["https://doi.org/10.1234/abc", "10.5678/def"]
}'
# {
# "sources": [ ... ],
# "coverage": 9, # documents still available (excluded ones removed)
# "coverageWprost": 5, # of which are squarely ON the topic, not adjacent
# "billing": { "citations_charged": 9, "already_paid": 3 }
# }coverageWprost ist wichtiger als coverage. Eine Lücke wie „coverage 6, coverageWprost 0“ bedeutet: Der Korpus enthält Material aus dem FACHGEBIET, aber nichts zu genau dieser Frage — das ist der Moment, einen Harvest zu starten, statt mit dem Vorhandenen zu schreiben.
Kosten prüfen, bevor Sie loslegen
Derselbe /corpus-Aufruf kann einen vorhandenen Korpus auslesen (Centbeträge) oder ihn von Grund auf aufbauen (neues Thema, mehrere Minuten). Was passiert, hängt vom Zustand des Korpus ab, den Sie von außen nicht sehen. Mit dryRun durchlaufen wir exakt dieselbe Prüfung und sagen Ihnen, was passieren WÜRDE — ohne einen Job anzulegen und ohne etwas abzurechnen.
curl -s https://cytado.com/api/ext/corpus \
-H "Authorization: Bearer $CYTADO_KEY" \
-H "Content-Type: application/json" \
-d '{"topic":"persuasion in advertising","langs":["en"],
"minCoverage":6,"dryRun":true}'
# {
# "dryRun": true,
# "coverage": 9,
# "coverageWprost": 5,
# "corpusReady": true,
# "wouldHarvest": false, # a real call would NOT start a harvest
# "wouldBill": null # ...and would bill nothing
# }
#
# When the corpus is thin:
# "wouldHarvest": true,
# "wouldBill": { "kind": "topic", "count": 1 }Die Vorschau ist kostenlos und unbegrenzt. Nutzen Sie sie als Entscheidungsschritt: erst dryRun, dann — wenn die Kosten passen — derselbe Aufruf ohne dieses Feld.
Testschlüssel und neue Themen
Ein cyt_test_-Schlüssel kann 3 NEUE THEMEN pro Monat aufbauen — genug, um den asynchronen Modus, das Polling und die Webhooks zu testen, also den schwierigsten Teil jeder Integration. Ist dieses Kontingent aufgebraucht, funktionieren Korpusabfrage und Verifizierung unverändert weiter; gesperrt ist nur der Aufbau eines Korpus für ein neues Thema, weil das die teuerste Operation der gesamten API ist. Für den Produktivbetrieb verwenden Sie einen cyt_live_-Schlüssel.
Ohne Postman: die Konsole im Panel
Alle drei Endpunkte — /corpus, /chapter-sources und /find-source — lassen sich direkt aus dem Panel aufrufen (Konto → API → Konsole), ohne Schlüssel einzufügen und ohne etwas einzurichten. Jedes Feld ist danach beschrieben, was es bewirkt, nicht nach seinem Typ. Darunter steht derselbe Aufruf als curl, fertig zum Kopieren in Ihren Code.
Die Kosten zeigen wir VOR dem Absenden an, aber je Endpunkt anders, weil sie jeweils anders entstehen. /corpus hat eine zweistufige Schaltfläche: Die erste prüft die Kosten und kann nichts abrechnen, die zweite — mit dem Preis darauf — erscheint erst unter der Antwort. /chapter-sources und /find-source nennen sofort eine Obergrenze, denn diese ergibt sich aus der Zahl, die Sie selbst eingeben: dem Quellenlimit bzw. der Anzahl der Aussagen. Achten Sie auf ein Feld: harvestOnMiss in /find-source kann mit einem Klick bis zu 24 neue Themen aufbauen, deshalb ist es standardmäßig deaktiviert.
maxNewTopics — die eigene Rechnung deckeln
In /find-source holt harvestOnMiss Quellen aus dem Web für Aussagen, die sich mit dem vorhandenen Korpus nicht klären lassen. Jeder solche Abruf ist ein NEUES THEMA — eine Position, die rund 25-mal teurer ist als ein Beleg. Ohne dieses Feld bauen wir höchstens 6 Themen pro Anfrage auf; die harte Obergrenze des Servers liegt bei 24. Mit maxNewTopics setzen Sie Ihr eigenes Limit — auch ein höheres, bis 24. Werte außerhalb des Bereichs schneiden wir auf 0–24 zu, statt die Anfrage abzulehnen.
{ "items": [...], "langs": ["en"],
"harvestOnMiss": true,
"maxNewTopics": 3 } # at most 3 new topics in this requestWas die Konsole NICHT ist
Die Konsole durchläuft denselben Code wie eine externe Anfrage — dieselben Limits, dieselbe Obergrenze für Testschlüssel, dieselbe Abrechnung, derselbe Logeintrag. Ein Aufruf aus dem Panel kostet genau so viel wie ein Aufruf von Ihrem Server; ein Gratismodus ist das nicht. Allerdings umgeht sie die HTTP-Schicht und deckt deshalb weder einen fehlerhaften Header noch einen Serialisierungsfehler im Body auf — wenn Sie ein Transportproblem debuggen, nehmen Sie den curl-Befehl unter dem Formular, denn nur der durchläuft den vollständigen Stack.
MCP-Server — für KI-Agenten
Die gesamte API steht auch als MCP-Server (Model Context Protocol) zur Verfügung — ein Agent verbindet sich einmal und erhält Tools, deren Beschreibungen ihm sagen, wann er sie aufrufen soll und was abgerechnet wird. Derselbe Schlüssel wie bei REST, dieselbe Abrechnung, derselbe Verbrauch im Panel. Transport: Streamable HTTP, zustandslos.
# Claude Code
claude mcp add cytado --transport http https://cytado.com/api/mcp \
--header "Authorization: Bearer $CYTADO_KEY"
# Claude API (MCP connector)
"mcp_servers": [{ "type": "url", "url": "https://cytado.com/api/mcp",
"name": "cytado", "authorization_token": "$CYTADO_KEY" }]
# stdio-only clients
npx -y mcp-remote https://cytado.com/api/mcp \
--header "Authorization: Bearer $CYTADO_KEY"ground_citation— Aussagen → eine verifizierte Quelle mit gedruckter Seite und Zitat oder ein ehrliches found:false; abgerechnet wie /find-sourceget_chapter_sources— Kapitelthema → Quellen mit seitengenau markierten Auszügen; abgerechnet wie /chapter-sourcescheck_corpus— kostenlose Vorschau der Abdeckung; mit provision:true startet ein Harvest im Hintergrund und liefert eine jobIdcheck_harvest_status— Harvest-Status (kostenlos); der Agent fragt ihn alle 30–60 s ab
MCP-Tools harvesten nie synchron — ground_citation antwortet in Sekunden aus dem Korpus, und das Nachladen neuer Themen läuft immer im Hintergrund über eine jobId. Die Abrechnungsregeln stehen direkt in den Tool-Beschreibungen, sodass der Agent weiß, was Geld kostet, bevor er etwas aufruft.
Verbindung im Chatfenster von claude.ai
Sie können cytado direkt in claude.ai als benutzerdefinierten Connector (custom connector) hinzufügen — dann stehen die Tools in einer normalen Unterhaltung zur Verfügung, ohne Terminal und ohne Code:
- Öffnen Sie in claude.ai Einstellungen → Connectors (in Team-/Enterprise-Plänen erledigt das der Organisationsinhaber in den Organisationseinstellungen) und klicken Sie auf „Add custom connector“.
- Als Server-URL geben Sie ein:
https://cytado.com/api/mcp - Fügen Sie im Abschnitt „Request headers“ einen Authorization-Header mit dem Wert „Bearer “ + Ihrem API-Schlüssel aus dem Panel (Konto → API) hinzu. Claude speichert den Wert sicher und sendet ihn bei jeder Anfrage mit.
- Klicken Sie in einer Unterhaltung auf „+“ → Connectors und aktivieren Sie cytado. Ab dann können Sie etwa schreiben: „Schreib einen Absatz über X und belege die Aussagen über cytado mit Quellen“ — der Agent ruft die Tools selbst auf.
Hinweis: Das Feld „Request headers“ in claude.ai ist eine Beta-Funktion, die schrittweise freigeschaltet wird — wenn Sie es nicht sehen, unterstützt Ihr Konto derzeit nur OAuth-Connectors. Eine OAuth-Anmeldung für cytado ist in Vorbereitung; bis dahin nutzen Sie Claude Code oder den MCP-Connector der Claude API (Beispiele oben). In ChatGPT fügen Sie den Connector analog im Entwicklermodus hinzu (Settings → Connectors), mit derselben URL und demselben Header.
HTTP-Benachrichtigungen (Webhooks)
Statt uns nach dem Stand Ihres Pakets zu fragen, nennen Sie uns eine URL, an die wir einen signierten POST senden: bei 80 % und 100 % des Pakets, beim Abschluss eines Abrechnungszeitraums, nach Ausstellung einer Rechnung und nach Abschluss eines Korpus-Harvests. URL und Secret legen Sie im Panel fest.
plan.80,plan.100— 80 % bzw. 100 % des Paketkontingents verbrauchtperiod.closed— ein Abrechnungszeitraum wurde abgeschlosseninvoice.issued— eine Rechnung wurde ausgestelltjob.completed,job.failed— Korpus-Harvest beendet; damit müssen Sie nicht in einer Schleife abfragen
POST https://your-app.example/cytado-hook
X-Cytado-Event: job.completed
X-Cytado-Timestamp: 1785858025
X-Cytado-Signature: 9f2c... # HMAC-SHA256 over "<timestamp>.<raw body>"
{
"event": "job.completed",
"at": 1785858025,
"data": {
"jobId": 83,
"topic": "persuasion in advertising",
"coverage": 15,
"coverageWprost": 10
}
}
# Verify in Node — sign the RAW body, never re-serialised JSON:
import { createHmac, timingSafeEqual } from "node:crypto";
const expected = createHmac("sha256", SECRET)
.update(`${req.headers["x-cytado-timestamp"]}.${rawBody}`)
.digest("hex");
const provided = req.headers["x-cytado-signature"];
const ok =
provided.length === expected.length &&
timingSafeEqual(Buffer.from(expected), Buffer.from(provided));Signieren Sie den ROHEN Body, nicht erneut serialisiertes JSON — eine andere Schlüsselreihenfolge ändert die Signatur. Lehnen Sie Anfragen ab, die älter als ein paar Minuten sind. Wir unternehmen pro Ereignis einen Zustellversuch: Der Webhook ist eine Bequemlichkeit, keine verbindliche Quelle — das bleiben das Panel und die Rechnung.
Änderungen an der API
Wir versionieren keine URLs. Stattdessen halten wir ein Versprechen: Felder verschwinden nie und ändern nie ihre Bedeutung, neue können jederzeit hinzukommen. Parsen Sie Antworten tolerant — ignorieren Sie ein unbekanntes Feld, statt es als Fehler zu behandeln.
- 2026-08-05 — chapter-sources: Das Feld chapter beeinflusst die Auswahl jetzt tatsächlich (vorher wurde es ignoriert), neuer Parameter minRelevance (5–10), abgerechnet werden NUR Quellen direkt zum Thema (Relevanz ≥ 7; Hintergrund kostenlos — siehe billing.free_background). Relevanzbewertungen werden einen Tag lang zwischengespeichert, ein identischer Aufruf liefert also dieselbe Auswahl und ein Retry kostet nicht doppelt. Die Feldnamen der Antworten sind jetzt englisch (billing, ready, url+doi, event/at/data); find-source akzeptiert exclude und gibt claim zurück. Ein unbekanntes Feld in der Anfrage liefert jetzt 400 unknown-field mit Vorschlag, statt still ignoriert zu werden.
- 2026-08-04 — neu: coverageWprost (/corpus, /corpus/status, /chapter-sources) und der Block billing in /chapter-sources (damals unter dem Namen rozliczenie).
- 2026-08-04 — die Abrechnung umfasst jetzt /chapter-sources und /corpus; für dasselbe Dokument im selben Thema zahlen Sie einmal.
Was sich gefahrlos wiederholen lässt
- /corpus/status
- Uneingeschränkt — diese Aufrufe berühren den Korpus nicht und werden nie abgerechnet.
- /chapter-sources
- Gefahrlos. Dokumente, die Sie in diesem Thema bereits bezahlt haben, werden nicht erneut berechnet — Sie sehen sie unter billing.already_paid.
- /corpus (async: true)
- Gefahrlos innerhalb eines 30-Minuten-Fensters: Ein wiederholter Auftrag für dasselbe Thema liefert DIESELBE jobId und rechnet kein zweites Thema ab.
- /find-source
- Ein Retry nach einem Timeout kann gelieferte Belege doppelt abrechnen — wenn Sie automatisch wiederholen, merken Sie sich, was bereits zurückgekommen ist.
Mit einem Testschlüssel starten
100 Belege pro Monat, ohne Abrechnung und ohne Kreditkarte. Den Schlüssel erstellen Sie selbst im Panel, direkt nach der Registrierung.
Konto erstellen