[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"public-branding":3,"content-de-webhooks":8,"public-ads-config":517},{"siteName":4,"primaryColor":5,"accentColor":6,"faviconUrl":7,"logoUrl":7},"KiroCloud","#ffffff","#888888","",{"id":9,"title":10,"author":11,"body":12,"category":507,"description":508,"extension":509,"lastUpdated":11,"meta":510,"navigation":341,"order":512,"path":513,"readTime":11,"seo":514,"stem":515,"__hash__":516},"docs\u002Fdocs\u002Fde\u002Fwebhooks.md","Webhooks",null,{"type":13,"value":14,"toc":498},"minimark",[15,20,24,29,32,79,83,86,112,116,123,297,301,304,315,320,463,467,494],[16,17,19],"h1",{"id":18},"webhooks-event-streams","Webhooks & Event Streams",[21,22,23],"p",{},"Mit Webhooks kannst du externe Systeme (z. B. deinen eigenen Bot-Monitoring-Dienst, Alerting-Tools oder interne Statusseiten) automatisch benachrichtigen lassen, sobald relevante Ereignisse für deine Instanzen in KiroCloud eintreten. Dies ermöglicht dir, auf Events in Echtzeit zu reagieren, ohne die REST-API wiederholt abfragen zu müssen (Polling).",[25,26,28],"h2",{"id":27},"_1-webhook-registrieren","1. Webhook registrieren",[21,30,31],{},"Webhooks werden direkt in deinem Benutzer-Dashboard konfiguriert:",[33,34,35,44,50,56,62,73],"ol",{},[36,37,38,39,43],"li",{},"Gehe im Dashboard zu ",[40,41,42],"strong",{},"Einstellungen > Webhooks & Benachrichtigungen",".",[36,45,46,47,43],{},"Klicke auf ",[40,48,49],{},"Webhook hinzufügen",[36,51,52,55],{},[40,53,54],{},"Name",": Eine eindeutige Bezeichnung (z. B. \"Discord Alerting Service\").",[36,57,58,61],{},[40,59,60],{},"Ziel-URL",": Die HTTPS-Adresse deines Servers, an die KiroCloud die POST-Requests senden soll.",[36,63,64,67,68,72],{},[40,65,66],{},"Subscribed Events",": Wähle die Ereignisse aus, über die du benachrichtigt werden möchtest (z. B. ",[69,70,71],"code",{},"bot.crashed",").",[36,74,75,78],{},[40,76,77],{},"Signing Secret"," (Empfohlen): Ein geheimer Schlüssel, mit dem KiroCloud die Payload signiert. So validierst du, dass die Anfrage authentisch ist.",[25,80,82],{"id":81},"_2-verfügbare-ereignisse","2. Verfügbare Ereignisse",[21,84,85],{},"KiroCloud bietet folgende Event-Typen für deine verwalteten Instanzen:",[87,88,89,94,100,106],"ul",{},[36,90,91,93],{},[69,92,71],{}," - Wird ausgelöst, wenn ein von dir gehosteter Discord-Bot unerwartet beendet wird oder wegen Speichermangels stoppt.",[36,95,96,99],{},[69,97,98],{},"bot.started"," - Wird ausgelöst, wenn ein Discord-Bot erfolgreich gestartet wurde.",[36,101,102,105],{},[69,103,104],{},"ticket.created"," - Wird ausgelöst, wenn ein neues Support-Ticket zu deinem Account erstellt wird.",[36,107,108,111],{},[69,109,110],{},"ticket.updated"," - Wird ausgelöst, wenn ein Support-Ticket beantwortet oder aktualisiert wird.",[25,113,115],{"id":114},"_3-payload-struktur","3. Payload-Struktur",[21,117,118,119,122],{},"Wenn ein abonniertes Ereignis eintritt, sendet KiroCloud einen HTTP ",[69,120,121],{},"POST","-Request an deine Ziel-URL. Der Body ist als JSON-Objekt formatiert:",[124,125,129],"pre",{"className":126,"code":127,"language":128,"meta":7,"style":7},"language-json shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","{\n  \"event\": \"bot.crashed\",\n  \"timestamp\": \"2026-10-09T00:00:00.000Z\",\n  \"data\": {\n    \"botId\": \"00000000-0000-0000-0000-000000000000\",\n    \"name\": \"MyCommunityBot\",\n    \"exitCode\": 1,\n    \"reason\": \"Process exited with code 1\"\n  }\n}\n","json",[69,130,131,140,167,188,203,226,247,265,285,291],{"__ignoreMap":7},[132,133,136],"span",{"class":134,"line":135},"line",1,[132,137,139],{"class":138},"sMK4o","{\n",[132,141,143,146,150,153,156,159,162,164],{"class":134,"line":142},2,[132,144,145],{"class":138},"  \"",[132,147,149],{"class":148},"spNyl","event",[132,151,152],{"class":138},"\"",[132,154,155],{"class":138},":",[132,157,158],{"class":138}," \"",[132,160,71],{"class":161},"sfazB",[132,163,152],{"class":138},[132,165,166],{"class":138},",\n",[132,168,170,172,175,177,179,181,184,186],{"class":134,"line":169},3,[132,171,145],{"class":138},[132,173,174],{"class":148},"timestamp",[132,176,152],{"class":138},[132,178,155],{"class":138},[132,180,158],{"class":138},[132,182,183],{"class":161},"2026-10-09T00:00:00.000Z",[132,185,152],{"class":138},[132,187,166],{"class":138},[132,189,191,193,196,198,200],{"class":134,"line":190},4,[132,192,145],{"class":138},[132,194,195],{"class":148},"data",[132,197,152],{"class":138},[132,199,155],{"class":138},[132,201,202],{"class":138}," {\n",[132,204,206,209,213,215,217,219,222,224],{"class":134,"line":205},5,[132,207,208],{"class":138},"    \"",[132,210,212],{"class":211},"sBMFI","botId",[132,214,152],{"class":138},[132,216,155],{"class":138},[132,218,158],{"class":138},[132,220,221],{"class":161},"00000000-0000-0000-0000-000000000000",[132,223,152],{"class":138},[132,225,166],{"class":138},[132,227,229,231,234,236,238,240,243,245],{"class":134,"line":228},6,[132,230,208],{"class":138},[132,232,233],{"class":211},"name",[132,235,152],{"class":138},[132,237,155],{"class":138},[132,239,158],{"class":138},[132,241,242],{"class":161},"MyCommunityBot",[132,244,152],{"class":138},[132,246,166],{"class":138},[132,248,250,252,255,257,259,263],{"class":134,"line":249},7,[132,251,208],{"class":138},[132,253,254],{"class":211},"exitCode",[132,256,152],{"class":138},[132,258,155],{"class":138},[132,260,262],{"class":261},"sbssI"," 1",[132,264,166],{"class":138},[132,266,268,270,273,275,277,279,282],{"class":134,"line":267},8,[132,269,208],{"class":138},[132,271,272],{"class":211},"reason",[132,274,152],{"class":138},[132,276,155],{"class":138},[132,278,158],{"class":138},[132,280,281],{"class":161},"Process exited with code 1",[132,283,284],{"class":138},"\"\n",[132,286,288],{"class":134,"line":287},9,[132,289,290],{"class":138},"  }\n",[132,292,294],{"class":134,"line":293},10,[132,295,296],{"class":138},"}\n",[25,298,300],{"id":299},"_4-sicherheit-signaturprüfung-hmac-sha256","4. Sicherheit & Signaturprüfung (HMAC-SHA256)",[21,302,303],{},"Um Man-in-the-Middle-Angriffe oder gefälschte Requests zu verhindern, signiert KiroCloud jede Webhook-Anfrage im HTTP-Header:",[124,305,309],{"className":306,"code":307,"language":308,"meta":7,"style":7},"language-http shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","X-Kiro-Signature: sha256=a1b2c3d4e5f6...\n","http",[69,310,311],{"__ignoreMap":7},[132,312,313],{"class":134,"line":135},[132,314,307],{},[316,317,319],"h3",{"id":318},"validierungsbeispiel-in-nodejs-express","Validierungsbeispiel in Node.js \u002F Express:",[124,321,325],{"className":322,"code":323,"language":324,"meta":7,"style":7},"language-javascript shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","import crypto from 'node:crypto';\nimport express from 'express';\n\nconst app = express();\nconst WEBHOOK_SECRET = 'dein_signing_secret';\n\n\u002F\u002F Der rohe Request-Body wird für die Signaturprüfung benötigt\napp.post('\u002Fwebhook', express.json({ verify: (req, res, buf) => { req.rawBody = buf; }}), (req, res) => {\n  const signature = req.headers['x-kiro-signature'];\n  if (!signature) {\n    return res.status(401).send('Missing signature');\n  }\n\n  const hash = crypto.createHmac('sha256', WEBHOOK_SECRET)\n                     .update(req.rawBody)\n                     .digest('hex');\n  const expectedSignature = `sha256=${hash}`;\n\n  if (crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expectedSignature))) {\n    console.log('Webhook verifiziert! Event:', req.body.event);\n    res.status(200).send('OK');\n  } else {\n    res.status(401).send('Invalid signature');\n  }\n});\n","javascript",[69,326,327,332,337,343,348,353,357,362,367,372,377,383,388,393,399,405,411,417,422,428,434,440,446,452,457],{"__ignoreMap":7},[132,328,329],{"class":134,"line":135},[132,330,331],{},"import crypto from 'node:crypto';\n",[132,333,334],{"class":134,"line":142},[132,335,336],{},"import express from 'express';\n",[132,338,339],{"class":134,"line":169},[132,340,342],{"emptyLinePlaceholder":341},true,"\n",[132,344,345],{"class":134,"line":190},[132,346,347],{},"const app = express();\n",[132,349,350],{"class":134,"line":205},[132,351,352],{},"const WEBHOOK_SECRET = 'dein_signing_secret';\n",[132,354,355],{"class":134,"line":228},[132,356,342],{"emptyLinePlaceholder":341},[132,358,359],{"class":134,"line":249},[132,360,361],{},"\u002F\u002F Der rohe Request-Body wird für die Signaturprüfung benötigt\n",[132,363,364],{"class":134,"line":267},[132,365,366],{},"app.post('\u002Fwebhook', express.json({ verify: (req, res, buf) => { req.rawBody = buf; }}), (req, res) => {\n",[132,368,369],{"class":134,"line":287},[132,370,371],{},"  const signature = req.headers['x-kiro-signature'];\n",[132,373,374],{"class":134,"line":293},[132,375,376],{},"  if (!signature) {\n",[132,378,380],{"class":134,"line":379},11,[132,381,382],{},"    return res.status(401).send('Missing signature');\n",[132,384,386],{"class":134,"line":385},12,[132,387,290],{},[132,389,391],{"class":134,"line":390},13,[132,392,342],{"emptyLinePlaceholder":341},[132,394,396],{"class":134,"line":395},14,[132,397,398],{},"  const hash = crypto.createHmac('sha256', WEBHOOK_SECRET)\n",[132,400,402],{"class":134,"line":401},15,[132,403,404],{},"                     .update(req.rawBody)\n",[132,406,408],{"class":134,"line":407},16,[132,409,410],{},"                     .digest('hex');\n",[132,412,414],{"class":134,"line":413},17,[132,415,416],{},"  const expectedSignature = `sha256=${hash}`;\n",[132,418,420],{"class":134,"line":419},18,[132,421,342],{"emptyLinePlaceholder":341},[132,423,425],{"class":134,"line":424},19,[132,426,427],{},"  if (crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expectedSignature))) {\n",[132,429,431],{"class":134,"line":430},20,[132,432,433],{},"    console.log('Webhook verifiziert! Event:', req.body.event);\n",[132,435,437],{"class":134,"line":436},21,[132,438,439],{},"    res.status(200).send('OK');\n",[132,441,443],{"class":134,"line":442},22,[132,444,445],{},"  } else {\n",[132,447,449],{"class":134,"line":448},23,[132,450,451],{},"    res.status(401).send('Invalid signature');\n",[132,453,455],{"class":134,"line":454},24,[132,456,290],{},[132,458,460],{"class":134,"line":459},25,[132,461,462],{},"});\n",[25,464,466],{"id":465},"_5-fehlertoleranz-retry-verhalten","5. Fehlertoleranz & Retry-Verhalten",[87,468,469,480,487],{},[36,470,471,472,475,476,479],{},"KiroCloud erwartet einen HTTP-Statuscode im Bereich ",[69,473,474],{},"2xx"," (z. B. ",[69,477,478],{},"200 OK",") innerhalb von 5 Sekunden.",[36,481,482,483,486],{},"Antwortet dein Endpunkt mit ",[69,484,485],{},"5xx"," oder läuft in ein Timeout, unternimmt das System automatische Wiederholungsversuche mit exponentiellem Backoff (bis zu 3 Versuche).",[36,488,489,490,493],{},"Im Dashboard kannst du über die Schaltfläche ",[40,491,492],{},"„Test-Ping senden“"," jederzeit die Erreichbarkeit deines Endpunkts überprüfen.",[495,496,497],"style",{},"html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}",{"title":7,"searchDepth":142,"depth":142,"links":499},[500,501,502,503,506],{"id":27,"depth":142,"text":28},{"id":81,"depth":142,"text":82},{"id":114,"depth":142,"text":115},{"id":299,"depth":142,"text":300,"children":504},[505],{"id":318,"depth":169,"text":319},{"id":465,"depth":142,"text":466},"api","Erhalte HTTP-Benachrichtigungen über deine Bot- und Ticket-Ereignisse in Echtzeit","md",{"icon":511},"i-lucide-webhook",0,"\u002Fdocs\u002Fde\u002Fwebhooks",{"title":10,"description":508},"docs\u002Fde\u002Fwebhooks","7PEWWY6Id8WCOgbfzdREFvwm9qI9wRTdqk2K1ZIfhKY",{"enabled":341,"clientPubId":518,"docsSlotId":7,"newsSlotId":7,"guidesSlotId":7,"dashboardSlotId":7,"docsEnabled":341,"newsEnabled":341,"guidesEnabled":341,"dashboardEnabled":341},"ca-pub-9454065621077312"]