Einführung
Alle Endpunkte liegen unter dem /v1-Präfix, sprechen JSON und sind an
genau einen Bot gebunden. Ein Aufruf braucht immer einen API-Key.
ready zurück.
Authentifizierung
Jeder Aufruf braucht einen API-Key im Authorization-Header. Keys erzeugst
du im Dashboard unter Konnektoren → API-Zugriff. Jeder Key ist an einen Bot gebunden und trägt Scopes; fehlt ein Scope, antwortet
die API mit 403.
Authorization: Bearer rk_live_...
knowledge:read Wissensquellen lesen knowledge:write Wissen pushen, aktualisieren, löschen leads:read Kontaktanfragen lesen analytics:read Kennzahlen lesen tools:read Live-Tools lesen tools:write Live-Tools anlegen, ändern, löschen Basis-URL & Limits
https://api.ragnova.de Fehler
Fehler kommen als JSON mit maschinenlesbarem error-Code und optionaler
message.
invalid_input Ungültige oder fehlende Felder im Body. unauthorized Kein oder ungültiger API-Key im Header. forbidden Dem Key fehlt der nötige Scope. upgrade_required Der API-Zugriff ist ab dem Pro-Plan aktiv. not_found Ressource existiert nicht (oder anderer Bot). name_taken Tool-Name ist bereits vergeben. payload_too_large Inhalt über 256 KB. rate_limited Über 120 Anfragen/Minute für diesen Key. Knowledge
Inhalte in die Wissensbasis pushen und verwalten. Der Bot antwortet daraus.
/v1/knowledge knowledge:write Inhalt pushen oder syncen
Bettet den Inhalt synchron ein und macht ihn durchsuchbar. Mit externalId ist der Aufruf idempotent: ein erneuter Push mit derselben ID ersetzt die bestehende Quelle (alte Chunks werden entfernt).
content Pflicht Klartext, der eingebettet wird.
externalId ID im Kundensystem. Gleiche ID → idempotenter Upsert.
title Anzeigename der Quelle.
url Optionaler Quell-Link.
curl -X POST "https://api.ragnova.de/v1/knowledge" \ -H "Authorization: Bearer rk_live_..." \ -H "Content-Type: application/json" \ -d '{"externalId":"prod-123","title":"NodeMCU ESP8266","content":"Der NodeMCU ist ein WLAN-Mikrocontroller … Lieferzeit 1-2 Tage.","url":"https://shop.de/p/nodemcu"}'
const res = await fetch("https://api.ragnova.de/v1/knowledge", { method: "POST", headers: { Authorization: "Bearer rk_live_...", "Content-Type": "application/json", }, body: JSON.stringify({ "externalId": "prod-123", "title": "NodeMCU ESP8266", "content": "Der NodeMCU ist ein WLAN-Mikrocontroller … Lieferzeit 1-2 Tage.", "url": "https://shop.de/p/nodemcu" }), }); const data = await res.json();
import requests
res = requests.post(
"https://api.ragnova.de/v1/knowledge",
headers={"Authorization": "Bearer rk_live_..."},
json={
"externalId": "prod-123",
"title": "NodeMCU ESP8266",
"content": "Der NodeMCU ist ein WLAN-Mikrocontroller … Lieferzeit 1-2 Tage.",
"url": "https://shop.de/p/nodemcu"
},
)
data = res.json() {
"id": "b1e...",
"externalId": "prod-123",
"status": "ready",
"chunks": 3
} /v1/knowledge knowledge:read Wissensquellen listen
Alle über die API angelegten Quellen dieses Bots, neueste zuerst.
curl -X GET "https://api.ragnova.de/v1/knowledge" \ -H "Authorization: Bearer rk_live_..."
const res = await fetch("https://api.ragnova.de/v1/knowledge", { method: "GET", headers: { Authorization: "Bearer rk_live_...", }, }); const data = await res.json();
import requests
res = requests.get(
"https://api.ragnova.de/v1/knowledge",
headers={"Authorization": "Bearer rk_live_..."},
)
data = res.json() {
"data": [
{
"id": "b1e...",
"external_id": "prod-123",
"url": "https://shop.de/p/nodemcu",
"status": "ready",
"chunks": 3,
"created_at": "2026-07-01T10:00:00Z",
"updated_at": "2026-07-01T10:00:00Z"
}
]
} /v1/knowledge/{id} knowledge:read Quelle lesen
Liest eine Quelle. id ist die Quellen-UUID oder ext:<externalId> für die externe ID.
id Pflicht UUID oder ext:<externalId>.
curl -X GET "https://api.ragnova.de/v1/knowledge/b1e5f2a0-..." \ -H "Authorization: Bearer rk_live_..."
const res = await fetch("https://api.ragnova.de/v1/knowledge/b1e5f2a0-...", { method: "GET", headers: { Authorization: "Bearer rk_live_...", }, }); const data = await res.json();
import requests
res = requests.get(
"https://api.ragnova.de/v1/knowledge/b1e5f2a0-...",
headers={"Authorization": "Bearer rk_live_..."},
)
data = res.json() {
"id": "b1e...",
"external_id": "prod-123",
"url": "https://shop.de/p/nodemcu",
"status": "ready",
"chunks": 3
} /v1/knowledge/{id} knowledge:write Quelle löschen
Entfernt die Quelle samt aller Chunks. Idempotent per ext:<externalId>.
id Pflicht UUID oder ext:<externalId>.
curl -X DELETE "https://api.ragnova.de/v1/knowledge/b1e5f2a0-..." \ -H "Authorization: Bearer rk_live_..."
const res = await fetch("https://api.ragnova.de/v1/knowledge/b1e5f2a0-...", { method: "DELETE", headers: { Authorization: "Bearer rk_live_...", }, }); const data = await res.json();
import requests
res = requests.delete(
"https://api.ragnova.de/v1/knowledge/b1e5f2a0-...",
headers={"Authorization": "Bearer rk_live_..."},
)
data = res.json() {
"ok": true
} Leads
Vom Bot erfasste Kontaktanfragen abrufen (Nachricht, Rückruf, Termin).
/v1/leads leads:read Kontaktanfragen lesen
Anfragen des Bots, neueste zuerst.
limit Anzahl 1-200 (Default 100).
curl -X GET "https://api.ragnova.de/v1/leads" \ -H "Authorization: Bearer rk_live_..."
const res = await fetch("https://api.ragnova.de/v1/leads", { method: "GET", headers: { Authorization: "Bearer rk_live_...", }, }); const data = await res.json();
import requests
res = requests.get(
"https://api.ragnova.de/v1/leads",
headers={"Authorization": "Bearer rk_live_..."},
)
data = res.json() {
"data": [
{
"id": "9a...",
"type": "callback",
"name": "Erika Muster",
"email": "erika@example.com",
"phone": "+49 170 ...",
"message": "Bitte um Rückruf zu Angebot.",
"preferred_time": "vormittags",
"source_question": "Was kostet Variante B?",
"status": "new",
"created_at": "2026-07-02T08:30:00Z"
}
]
} Analytics
Aggregierte Kennzahlen des Bots der letzten 30 Tage.
/v1/analytics analytics:read Kennzahlen (30 Tage)
Gespräche, Antwortquote, Leads und CSAT als Momentaufnahme.
curl -X GET "https://api.ragnova.de/v1/analytics" \ -H "Authorization: Bearer rk_live_..."
const res = await fetch("https://api.ragnova.de/v1/analytics", { method: "GET", headers: { Authorization: "Bearer rk_live_...", }, }); const data = await res.json();
import requests
res = requests.get(
"https://api.ragnova.de/v1/analytics",
headers={"Authorization": "Bearer rk_live_..."},
)
data = res.json() {
"rangeDays": 30,
"conversations": 812,
"answered": 749,
"answeredRate": 92,
"leads": 37,
"csatRated": 120,
"csatPositiveRate": 88
} Live-Tools
Webhooks, die der Bot zur Laufzeit aufruft. Ragnova ruft deinen Endpoint SSRF-geprüft und HMAC-signiert auf — siehe Webhooks.
/v1/tools tools:read Live-Tools listen
Alle registrierten Tools dieses Bots.
curl -X GET "https://api.ragnova.de/v1/tools" \ -H "Authorization: Bearer rk_live_..."
const res = await fetch("https://api.ragnova.de/v1/tools", { method: "GET", headers: { Authorization: "Bearer rk_live_...", }, }); const data = await res.json();
import requests
res = requests.get(
"https://api.ragnova.de/v1/tools",
headers={"Authorization": "Bearer rk_live_..."},
)
data = res.json() {
"data": [
{
"id": "3c...",
"name": "bestellstatus",
"description": "Verfolgt eine Bestellung anhand von Bestellnummer und E-Mail.",
"endpoint_url": "https://shop.de/api/ragnova/order",
"method": "POST",
"auth_type": "bearer",
"enabled": true
}
]
} /v1/tools tools:write Tool registrieren
Registriert eine Live-Action. Das zurückgegebene signingSecret wird nur EINMAL ausgegeben — damit verifizierst du die Echtheit der Aufrufe.
name Pflicht z. B. bestellstatus.
description Pflicht Wann das Tool greift — der Router entscheidet danach.
endpointUrl Pflicht Dein Webhook.
method Default POST.
authType Auth deiner API. Default none.
authHeaderName Nur bei authType=header.
authSecret Verschlüsselt gespeichert, nie zurückgegeben.
timeoutMs 1000-10000, Default 5000.
parameters Bis 20 { name, description, required }.
curl -X POST "https://api.ragnova.de/v1/tools" \ -H "Authorization: Bearer rk_live_..." \ -H "Content-Type: application/json" \ -d '{"name":"bestellstatus","description":"Verfolgt eine Bestellung anhand von Bestellnummer und E-Mail.","endpointUrl":"https://shop.de/api/ragnova/order","authType":"bearer","authSecret":"sk_shop_...","parameters":[{"name":"order_id","description":"Bestellnummer","required":true},{"name":"email","description":"E-Mail des Kunden","required":true}]}'
const res = await fetch("https://api.ragnova.de/v1/tools", { method: "POST", headers: { Authorization: "Bearer rk_live_...", "Content-Type": "application/json", }, body: JSON.stringify({ "name": "bestellstatus", "description": "Verfolgt eine Bestellung anhand von Bestellnummer und E-Mail.", "endpointUrl": "https://shop.de/api/ragnova/order", "authType": "bearer", "authSecret": "sk_shop_...", "parameters": [ { "name": "order_id", "description": "Bestellnummer", "required": true }, { "name": "email", "description": "E-Mail des Kunden", "required": true } ] }), }); const data = await res.json();
import requests
res = requests.post(
"https://api.ragnova.de/v1/tools",
headers={"Authorization": "Bearer rk_live_..."},
json={
"name": "bestellstatus",
"description": "Verfolgt eine Bestellung anhand von Bestellnummer und E-Mail.",
"endpointUrl": "https://shop.de/api/ragnova/order",
"authType": "bearer",
"authSecret": "sk_shop_...",
"parameters": [
{
"name": "order_id",
"description": "Bestellnummer",
"required": true
},
{
"name": "email",
"description": "E-Mail des Kunden",
"required": true
}
]
},
)
data = res.json() {
"id": "3c...",
"name": "bestellstatus",
"signingSecret": "whsec_..."
} /v1/tools/{id} tools:read Tool lesen
Ein einzelnes Tool.
id Pflicht Tool-UUID.
curl -X GET "https://api.ragnova.de/v1/tools/b1e5f2a0-..." \ -H "Authorization: Bearer rk_live_..."
const res = await fetch("https://api.ragnova.de/v1/tools/b1e5f2a0-...", { method: "GET", headers: { Authorization: "Bearer rk_live_...", }, }); const data = await res.json();
import requests
res = requests.get(
"https://api.ragnova.de/v1/tools/b1e5f2a0-...",
headers={"Authorization": "Bearer rk_live_..."},
)
data = res.json() {
"id": "3c...",
"name": "bestellstatus",
"endpoint_url": "https://shop.de/api/ragnova/order",
"method": "POST",
"enabled": true
} /v1/tools/{id} tools:write Tool ändern
Partielles Update; nur gesendete Felder werden geändert (inkl. enabled-Toggle).
id Pflicht Tool-UUID.
curl -X PATCH "https://api.ragnova.de/v1/tools/b1e5f2a0-..." \ -H "Authorization: Bearer rk_live_..." \ -H "Content-Type: application/json" \ -d '{"enabled":false}'
const res = await fetch("https://api.ragnova.de/v1/tools/b1e5f2a0-...", { method: "PATCH", headers: { Authorization: "Bearer rk_live_...", "Content-Type": "application/json", }, body: JSON.stringify({ "enabled": false }), }); const data = await res.json();
import requests
res = requests.patch(
"https://api.ragnova.de/v1/tools/b1e5f2a0-...",
headers={"Authorization": "Bearer rk_live_..."},
json={
"enabled": false
},
)
data = res.json() {
"ok": true
} /v1/tools/{id} tools:write Tool löschen
Entfernt das Tool.
id Pflicht Tool-UUID.
curl -X DELETE "https://api.ragnova.de/v1/tools/b1e5f2a0-..." \ -H "Authorization: Bearer rk_live_..."
const res = await fetch("https://api.ragnova.de/v1/tools/b1e5f2a0-...", { method: "DELETE", headers: { Authorization: "Bearer rk_live_...", }, }); const data = await res.json();
import requests
res = requests.delete(
"https://api.ragnova.de/v1/tools/b1e5f2a0-...",
headers={"Authorization": "Bearer rk_live_..."},
)
data = res.json() {
"ok": true
} Webhooks — Tool-Aufruf verifizieren
Löst der Bot ein registriertes Live-Tool aus, sendet Ragnova einen POST an
deine endpointUrl. Verifiziere die Signatur, bevor du antwortest.
Antworte mit JSON (≤ 32 KB) innerhalb deines Timeouts — der Inhalt wird dem Bot als
geprüfter Kontext bereitgestellt.
X-Ragnova-Signature = "sha256=" + HMAC_SHA256(signingSecret, timestamp + "." + body)
import crypto from "node:crypto"; function verify(req, signingSecret) { const ts = req.headers["x-ragnova-timestamp"]; const sig = req.headers["x-ragnova-signature"]; const expected = "sha256=" + crypto .createHmac("sha256", signingSecret) .update(ts + "." + req.rawBody) .digest("hex"); return crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected)); }