Hallo! Ich bin OPMedia AI. Wie kann ich dir helfen?
📁 Dateipfad erkannt — soll die Datei angehängt werden?
📎
🔌

API Test

Teste die OPMedia AI API interaktiv
Request POST
Enter = Senden, Shift+Enter = Neue Zeile
Bereit
Response
Formatiert
Raw JSON
HTML
🔍
Sende eine Anfrage um die Antwort hier zu sehen
🌐 Web-Integration Preview
☀️ 🌙
LIVE DEMO
🔒 meine-webseite.de/ai-assistant
Meine Web-App AI Assistant
🤖
Hallo! Wie kann ich dir helfen?
So sieht die API-Integration in einer echten Web-Anwendung aus. Nachrichten werden live an die API gesendet.
📄

API Dokumentation

Integriere OPMedia AI in deine eigene Website oder Anwendung

LIVE

🧰 Einbindungsassistent

Beantworte ein paar Fragen und erhalte massgeschneiderten Code fuer deine Integration.

🧰 Einbindungsassistent

🌐 Endpoint

POST https://n8n.lazybros.fun/webhook/aufgabe
Sende einen POST-Request mit JSON-Body an diesen Endpoint. Die AI verarbeitet deine Anfrage und gibt eine strukturierte JSON-Antwort zurueck. Keine Authentifizierung noetig fuer Web-Zugriff.

📥 Request

Header: Content-Type: application/json

FeldTypPflichtBeschreibung
aufgabe String Ja Die Frage oder der Auftrag an die AI. Das System erkennt automatisch den passenden Modus (10 Modi: Frage, Code, Datei, Recherche, Standort, Email, Planer, TempAgent, Komplex, Entwicklung).
chat_id String Ja Eindeutige User-ID (z.B. "kunde-123", "user-abc"). Wird fuer Session-Kontext verwendet — gleiche ID = fortlaufendes Gespraech (3-Tage-Speicher).
kanal String Optional Quelle: "web" (default) oder "api". Bestimmt das Antwort-Format.
datei Object Optional Datei-Upload als Objekt mit: data (Base64), file_name, mime_type, file_size. Max. 100 MB.
code String Optional JavaScript-Code fuer den Daten-Modus. Wird in einem temporaeren n8n-Workflow ausgefuehrt.
kontext String Optional Zusaetzlicher Kontext fuer die Verarbeitung

📤 Response

Die API antwortet mit einem JSON-Array mit einem Objekt. HTTP-Status 200 bei Erfolg.

FeldTypBeschreibung
nachrichtStringDie Hauptantwort der AI (Markdown-formatiert)
erfolgBooleantrue bei Erfolg, false bei Fehler
kanalStringAntwort-Kanal (z.B. "web")
chat_idStringZurueckgegebene User-ID
ttsBooleanOb Text-to-Speech aktiv ist
needsDownloadBooleanOb ein Datei-Download verfuegbar ist
Beispiel-Response
[{
  "nachricht": "Hallo! Ich bin OPMedia AI. Wie kann ich dir helfen?",
  "erfolg": true,
  "kanal": "web",
  "chat_id": "kunde-123",
  "tts": false,
  "needsDownload": false
}]

💻 Code-Beispiele

JavaScript
Python
cURL
PHP
JavaScript (fetch)
const response = await fetch('https://n8n.lazybros.fun/webhook/aufgabe', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    aufgabe: 'Was ist die Hauptstadt von Deutschland?',
    chat_id: 'mein-user-123',
    kanal:   'web'
  })
});

const data = await response.json();
const antwort = data[0].nachricht;
console.log(antwort);  // "Die Hauptstadt von Deutschland ist Berlin..."
Python (requests)
import requests

response = requests.post(
    'https://n8n.lazybros.fun/webhook/aufgabe',
    json={
        'aufgabe': 'Was ist die Hauptstadt von Deutschland?',
        'chat_id': 'mein-user-123',
        'kanal':   'web'
    }
)

data = response.json()
antwort = data[0]['nachricht']
print(antwort)  # "Die Hauptstadt von Deutschland ist Berlin..."
cURL
curl -X POST https://n8n.lazybros.fun/webhook/aufgabe \
  -H "Content-Type: application/json" \
  -d '{
    "aufgabe": "Was ist die Hauptstadt von Deutschland?",
    "chat_id": "mein-user-123",
    "kanal": "web"
  }'
PHP
$ch = curl_init('https://n8n.lazybros.fun/webhook/aufgabe');

curl_setopt_array($ch, [
    CURLOPT_POST           => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER     => ['Content-Type: application/json'],
    CURLOPT_POSTFIELDS     => json_encode([
        'aufgabe' => 'Was ist die Hauptstadt von Deutschland?',
        'chat_id' => 'mein-user-123',
        'kanal'   => 'web',
    ])
]);

$response = curl_exec($ch);
$data = json_decode($response, true);
echo $data[0]['nachricht'];  // "Die Hauptstadt von Deutschland ist Berlin..."

🧰 Schnellstart: Chat-Widget einbinden

Kopiere diesen Code in deine HTML-Seite. Das Widget bietet: Chat mit Markdown, Datei-Upload (📎), Chat-Verlauf (localStorage), Pfad-Erkennung, Typing-Indikator und XSS-Schutz.

HTML Widget (vollständig)
<!-- OPMedia AI Chat Widget v2 -->
<!-- Markdown-Support: marked.js einbinden -->
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
<script>
(function() {
  var API = 'https://n8n.lazybros.fun/webhook/aufgabe';

  // Stabile User-ID (bleibt ueber Sessions hinweg)
  var userId = localStorage.getItem('opm-user-id');
  if (!userId) {
    userId = 'w-' + Date.now() + '-' + Math.random().toString(36).substr(2,6);
    localStorage.setItem('opm-user-id', userId);
  }
  var opmFile = null;
  var pathHintShown = false;

  // Styles
  var css = document.createElement('style');
  css.textContent = `
    #opm-btn{position:fixed;bottom:20px;right:20px;width:56px;height:56px;
      border-radius:50%;background:#6c5ce7;border:none;color:#fff;font-size:24px;
      cursor:pointer;box-shadow:0 4px 20px rgba(108,92,231,0.4);z-index:9999;
      transition:transform .2s}
    #opm-btn:hover{transform:scale(1.1)}
    #opm-chat{position:fixed;bottom:90px;right:20px;width:400px;height:550px;
      background:#fff;border-radius:16px;box-shadow:0 8px 40px rgba(0,0,0,0.25);
      display:none;flex-direction:column;z-index:9999;font-family:-apple-system,
      sans-serif;overflow:hidden}
    #opm-chat.open{display:flex}
    @media(max-width:480px){#opm-chat{width:calc(100vw - 20px);
      height:calc(100vh - 100px);right:10px;bottom:80px}}
    #opm-head{padding:14px 16px;background:#6c5ce7;color:#fff;
      font-weight:700;font-size:15px;display:flex;align-items:center;
      justify-content:space-between}
    #opm-head button{background:none;border:none;color:rgba(255,255,255,0.7);
      font-size:18px;cursor:pointer;padding:0 4px}
    #opm-head button:hover{color:#fff}
    #opm-msgs{flex:1;overflow-y:auto;padding:12px;background:#fafafa}
    .opm-msg{margin:8px 0;padding:10px 14px;border-radius:12px;max-width:85%;
      font-size:14px;line-height:1.6;word-break:break-word}
    .opm-u{background:#6c5ce7;color:#fff;margin-left:auto;
      border-bottom-right-radius:4px}
    .opm-b{background:#fff;color:#333;border:1px solid #e8e8e8;
      border-bottom-left-radius:4px}
    .opm-b p{margin:0 0 6px}.opm-b p:last-child{margin:0}
    .opm-b code{background:#f0f0f0;padding:1px 5px;border-radius:3px;font-size:12px}
    .opm-b pre{background:#1e1e2e;color:#e8e8f0;padding:10px;border-radius:8px;
      overflow-x:auto;margin:6px 0;font-size:12px}
    .opm-b pre code{background:none;color:inherit;padding:0}
    .opm-b strong{font-weight:600}
    .opm-typing span{display:inline-block;width:6px;height:6px;background:#aaa;
      border-radius:50%;margin:0 2px;animation:opmDot 1.2s infinite}
    .opm-typing span:nth-child(2){animation-delay:.2s}
    .opm-typing span:nth-child(3){animation-delay:.4s}
    @keyframes opmDot{0%,80%,100%{opacity:.3;transform:scale(.8)}
      40%{opacity:1;transform:scale(1.1)}}
    #opm-file-bar{display:none;align-items:center;gap:6px;padding:6px 12px;
      background:#f0edff;font-size:12px;color:#6c5ce7;border-top:1px solid #e8e8e8}
    #opm-file-bar.visible{display:flex}
    #opm-file-bar .fn{flex:1;overflow:hidden;text-overflow:ellipsis;
      white-space:nowrap;font-weight:600}
    #opm-file-bar button{background:none;border:none;color:#e55;cursor:pointer;
      font-size:14px}
    #opm-path-hint{display:none;padding:6px 12px;background:#f0edff;
      font-size:11px;color:#6c5ce7;border-top:1px solid #e8e8e8;
      align-items:center;gap:6px}
    #opm-path-hint.visible{display:flex}
    #opm-path-hint button{background:#6c5ce7;color:#fff;border:none;
      border-radius:5px;padding:3px 10px;font-size:11px;cursor:pointer;
      font-weight:600}
    #opm-path-hint .x{background:none;color:#999;font-size:13px;padding:0 3px}
    #opm-foot{display:flex;padding:10px 12px;border-top:1px solid #eee;gap:6px;
      align-items:flex-end;background:#fff}
    #opm-foot button{flex-shrink:0;width:38px;height:38px;border:1px solid #ddd;
      border-radius:10px;background:#fff;cursor:pointer;font-size:16px;
      display:flex;align-items:center;justify-content:center;transition:all .15s}
    #opm-foot button:hover{border-color:#6c5ce7;color:#6c5ce7}
    #opm-foot button.has-file{border-color:#00c853;color:#00c853}
    #opm-foot textarea{flex:1;padding:9px 12px;border:1px solid #ddd;
      border-radius:10px;font-size:14px;outline:none;resize:none;
      font-family:inherit;min-height:38px;max-height:90px;line-height:1.4}
    #opm-foot textarea:focus{border-color:#6c5ce7}
    #opm-send{background:#6c5ce7!important;color:#fff!important;
      border:none!important;font-weight:700}
    #opm-send:disabled{opacity:.5;cursor:not-allowed}
  `;
  document.head.appendChild(css);

  // Button
  var btn = document.createElement('button');
  btn.id = 'opm-btn';
  btn.textContent = '💬';
  btn.onclick = function() {
    document.getElementById('opm-chat').classList.toggle('open');
  };
  document.body.appendChild(btn);

  // Chat-Container
  var c = document.createElement('div');
  c.id = 'opm-chat';
  c.innerHTML = '<div id="opm-head"><span>OPMedia AI</span>'
    + '<button onclick="document.getElementById(\\\'opm-chat\\\')'
    + '.classList.remove(\\\'open\\\')" title="Schliessen">&#10005;</button></div>'
    + '<div id="opm-msgs"></div>'
    + '<div id="opm-file-bar">&#128206; <span class="fn" id="opm-fn"></span>'
    + '<button onclick="opmRemoveFile()">&#10005;</button></div>'
    + '<div id="opm-path-hint">&#128193; Dateipfad erkannt &mdash; '
    + '<button onclick="document.getElementById(\\\'opm-fi\\\')'
    + '.click()">Datei w&auml;hlen</button>'
    + '<button class="x" onclick="opmDismissHint()">&#10005;</button></div>'
    + '<input type="file" id="opm-fi" style="display:none">'
    + '<div id="opm-foot">'
    + '<button id="opm-clip" onclick="document.getElementById(\\\'opm-fi\\\')'
    + '.click()" title="Datei anhaengen">&#128206;</button>'
    + '<textarea id="opm-txt" placeholder="Nachricht..." rows="1"></textarea>'
    + '<button id="opm-send" onclick="opmSend()">&#9654;</button></div>';
  document.body.appendChild(c);

  // Chat-Verlauf laden
  function loadHistory() {
    var h = JSON.parse(localStorage.getItem('opm-history') || '[]');
    var msgs = document.getElementById('opm-msgs');
    if (h.length === 0) {
      addMsg('Hallo! Ich bin **OPMedia AI**. Wie kann ich dir helfen?', false);
    } else {
      h.forEach(function(m) { addMsg(m.text, m.isUser, true); });
    }
    msgs.scrollTop = msgs.scrollHeight;
  }
  function saveHistory(text, isUser) {
    var h = JSON.parse(localStorage.getItem('opm-history') || '[]');
    h.push({ text: text, isUser: isUser, ts: Date.now() });
    // Max 100 Nachrichten behalten
    if (h.length > 100) h = h.slice(-100);
    localStorage.setItem('opm-history', JSON.stringify(h));
  }

  // Nachricht hinzufuegen (XSS-sicher)
  function addMsg(text, isUser, noSave) {
    var msgs = document.getElementById('opm-msgs');
    var div = document.createElement('div');
    div.className = 'opm-msg ' + (isUser ? 'opm-u' : 'opm-b');
    if (isUser) {
      div.textContent = text; // XSS-sicher
    } else if (typeof marked !== 'undefined') {
      div.innerHTML = marked.parse(text);
    } else {
      div.textContent = text;
    }
    msgs.appendChild(div);
    msgs.scrollTop = msgs.scrollHeight;
    if (!noSave) saveHistory(text, isUser);
    return div;
  }

  // Typing-Indikator
  function showTyping() {
    var div = document.createElement('div');
    div.className = 'opm-msg opm-b';
    div.id = 'opm-typing';
    div.innerHTML = '<div class="opm-typing"><span></span><span></span><span></span></div>';
    document.getElementById('opm-msgs').appendChild(div);
    div.parentElement.scrollTop = div.parentElement.scrollHeight;
  }
  function hideTyping() {
    var el = document.getElementById('opm-typing');
    if (el) el.remove();
  }

  // Datei-Anhang
  document.getElementById('opm-fi').addEventListener('change', function(e) {
    if (e.target.files.length) {
      opmFile = e.target.files[0];
      if (opmFile.size > 100*1024*1024) {
        addMsg('Datei zu gross! Max. 100 MB.', false);
        opmFile = null; return;
      }
      document.getElementById('opm-fn').textContent = opmFile.name;
      document.getElementById('opm-file-bar').classList.add('visible');
      document.getElementById('opm-clip').classList.add('has-file');
      opmDismissHint();
    }
  });
  window.opmRemoveFile = function() {
    opmFile = null;
    document.getElementById('opm-fi').value = '';
    document.getElementById('opm-file-bar').classList.remove('visible');
    document.getElementById('opm-clip').classList.remove('has-file');
  };
  window.opmDismissHint = function() {
    document.getElementById('opm-path-hint').classList.remove('visible');
    pathHintShown = true;
  };

  // Pfad-Erkennung + Enter-to-Send + Auto-Resize
  var txt = document.getElementById('opm-txt');
  var pathRe = /(?:[A-Za-z]:\\[^\s"<>|*?]+|\/(?:home|etc|var|tmp|Users)[^\s"<>|*?]+|~\/[^\s"<>|*?]+)/;
  txt.addEventListener('input', function() {
    this.style.height = 'auto';
    this.style.height = Math.min(this.scrollHeight, 90) + 'px';
    if (!pathHintShown && !opmFile && pathRe.test(this.value)) {
      document.getElementById('opm-path-hint').classList.add('visible');
    } else if (!pathRe.test(this.value)) {
      document.getElementById('opm-path-hint').classList.remove('visible');
    }
  });
  txt.addEventListener('keydown', function(e) {
    if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); opmSend(); }
  });

  // Senden (mit optionalem Datei-Upload)
  window.opmSend = async function() {
    var input = document.getElementById('opm-txt');
    var msg = input.value.trim();
    if (!msg && !opmFile) return;
    if (!msg && opmFile) msg = 'Analysiere diese Datei.';
    input.value = ''; input.style.height = 'auto';
    pathHintShown = false;
    document.getElementById('opm-path-hint').classList.remove('visible');
    document.getElementById('opm-send').disabled = true;

    var displayMsg = opmFile ? msg + ' 📎 ' + opmFile.name : msg;
    addMsg(displayMsg, true);
    showTyping();

    try {
      var payload = { aufgabe: msg, chat_id: userId, kanal: 'web' };

      // Datei als Base64 anhaengen
      if (opmFile) {
        var b64 = await new Promise(function(ok, fail) {
          var r = new FileReader();
          r.onload = function() {
            var s = r.result, i = s.indexOf(',');
            ok(i >= 0 ? s.substring(i+1) : s);
          };
          r.onerror = function() { fail(new Error('Lesefehler')); };
          r.readAsDataURL(opmFile);
        });
        payload.datei = {
          data: b64, file_name: opmFile.name,
          mime_type: opmFile.type || 'application/octet-stream',
          file_size: opmFile.size
        };
        opmRemoveFile();
      }

      var res = await fetch(API, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(payload)
      });
      var data = await res.json();
      if (Array.isArray(data)) data = data[0];
      hideTyping();
      var antwort = (data && (data.nachricht || data.ergebnis || data.fehler))
        || 'Keine Antwort erhalten.';
      addMsg(antwort, false);
    } catch(e) {
      hideTyping();
      addMsg('Fehler: ' + e.message, false);
    }
    document.getElementById('opm-send').disabled = false;
    document.getElementById('opm-txt').focus();
  };

  // Init: Verlauf laden
  loadHistory();
})();
</script>

🔒 Authentifizierung

Neue API-User muessen einmalig per Telegram freigeschaltet werden. Kein API-Key noetig — die Freischaltung erfolgt ueber die chat_id.

Erster Request
Sende eine Anfrage mit deiner chat_id. Du erhaeltst:
"Willkommen! Deine Anfrage wurde registriert. Ein Admin muss dich freischalten."
Admin-Benachrichtigung
Der Admin erhaelt automatisch eine Telegram-Nachricht:
"Neuer Beitrittsantrag: web-xxx — Freischalten mit: /accept web-xxx"
Freischaltung
Admin sendet /accept deine-chat-id im Telegram-Bot. Ab sofort funktioniert die API fuer diese chat_id.
Freigeschaltet
Alle weiteren Requests mit dieser chat_id werden normal verarbeitet. Die Freischaltung gilt dauerhaft.
Status-Antworten:
StatusAntwortBedeutung
new_user "Willkommen! ... Admin muss dich freischalten." Erstmalige Registrierung, wartet auf /accept
pending "Deine Anfrage wartet noch auf Freischaltung." Bereits registriert, noch nicht freigeschaltet
approved (Normale AI-Antwort) Freigeschaltet — voller Zugriff
blocked "Dein Zugang wurde gesperrt." Admin hat /reject oder /revoke ausgefuehrt

⚠️ Hinweise

  • Einmalige Freischaltung — Jede chat_id muss einmalig per Telegram freigeschaltet werden. Danach ist der Zugriff dauerhaft.
  • Chat-ID festlegen — Verwende eine stabile, eindeutige ID pro User (z.B. "meinapp-user-42"). Jeder Wechsel der chat_id erfordert neue Freischaltung.
  • Session-Kontext — Gleiche chat_id = fortlaufendes Gespraech (letzte 10 Nachrichten, 3 Tage Speicher).
  • Antwortzeit — Typisch 5-15 Sekunden (AI-Verarbeitung). Timeout auf mindestens 60 Sekunden setzen.
  • Antwort-Format — Die nachricht kann Markdown enthalten (Fett, Listen, Code-Bloecke).
  • Datei-Upload — Optional: datei-Objekt mit data (Base64), file_name, mime_type, file_size fuer Dateianalyse (max. 100 MB).
  • Auto-Routing — Das System erkennt automatisch den Modus: Recherche ("Suche im Internet..."), Standort ("Apotheken in..."), Email ("Sende Email an..."), Planer ("Erinnere mich..."), Datei-Analyse, Code-Ausfuehrung, Komplex-Analyse und mehr.
  • CORS — Requests von externen Domains sind erlaubt (Access-Control-Allow-Origin gesetzt).
📚

Execution-Archiv

System Online
OPMedia AI

Multi-Agent Infrastruktur. Kein API-Key. Self-Hosted.
14 Workflows in 7 Abteilungen, orchestriert durch n8n. Claude Code als LLM-Backend.

🔩 Architektur
👤
Du
n8n
Projektleitung
IF
Modus
n8n
Kommunikation
👤
Du
CC
Entwicklung
Claude Code via SSH
KI-Kernverarbeitung
📄
Fachabteilung
Dokumente, Daten,
Recherche, Standort
📧
Kommunikation
Email-Versand
Kundenkorrespondenz
📅
Sekretariat
Posteingang,
Terminplanung
Sonderaufgaben
Temp-Agenten,
Komplexe Analysen
🗃
Verwaltung
Archivierung,
Kundenhistorie, API
14
Workflows aktiv
7
Abteilungen
10
Modi (Auto-Routing)
4
Kommunikationskanaele
💬
✈️ Jetzt ausprobieren — Telegram Bot

Schreib dem Bot eine Nachricht auf Telegram und du bekommst eine Antwort direkt von Claude Code. Kein Account noetig, einfach loschatten.

✈️ @lazybros_n8n_bot oeffnen
💡 Probier zum Beispiel:
Schreibe mir ein Python Hello World Was ist Docker? Erklaere mir REST APIs
📡 Alle Kanaele
✈️

Telegram Bot

Schreib @lazybros_n8n_bot auf Telegram. Text, Sprache und Dateien — Claude antwortet in Sekunden. Inkl. Voice-Antwort (TTS).

{}

REST API

POST-Request an den Webhook. 10 Modi mit automatischem Routing: Fragen, Code, Recherche, Dateien, Standort, Email, Planer und mehr.

💬

Web-Chat

Direkt auf dieser Seite chatten — mit Datei-Upload. Oder das Widget in deine eigene Anwendung einbinden.

✉️

E-Mail

Posteingang wird automatisch verarbeitet. Ergebnisse per IONOS SMTP zugestellt. Auch als Aufgaben-Kanal nutzbar.

🚀 Live Test

Teste die API direkt — Fragen, Code, Datei-Analyse und Terminplanung in 4 Modi.

Stell Claude Code eine Frage — die Antwort kommt ueber die SSH-Kette von deiner lokalen Claude Code Instanz.

Fuehre JavaScript-Code direkt im Daten-Agent aus. Der Code wird in einem temporaeren n8n Workflow ausgefuehrt und das Ergebnis zurueckgegeben.

Hinweis: Code muss ein Array mit json-Objekten zurueckgeben: return [{json: {key: value}}];
Keine einfachen Anfuehrungszeichen verwenden — nutze doppelte Anfuehrungszeichen.

Erstelle Erinnerungen und wiederkehrende Tasks. Der Scheduler prueft alle 5 Minuten und sendet dir die Ergebnisse.

Zeitformate: in 30 Minuten | morgen um 9 | um 14:30 | jeden Tag um 9:00 | jeden Montag um 8:00
Verwaltung: Meine Aufgaben | Loesche Aufgabe 3

Lade eine Datei hoch — Claude analysiert den Inhalt und beantwortet deine Fragen dazu.

📂
Datei hierher ziehen oder klicken zum Auswaehlen
Max. 50 MB
Unterstuetzte Formate: TXT, CSV, PDF, JSON, MD, XML, HTML, ZIP, LOG, YAML — Code: PY, JS, TS, Java, SQL, C, C++, Go, Rust, Ruby, Swift, Kotlin, Shell
Claude Code denkt nach...
Du → n8n VPS → SSH Tunnel → Claude Code → Antwort
Antwort von Claude Code