Hello friends, I want to execute my workflow from an interface I developed using HTML, JS, and CSS. I tried configuring the Webhook node, but it always returns this error:
{
“code”: 404,
“message”: “The requested webhook “bbb32d58-2e90-4dc2-86e2-6a8ded7b82d8” is not registered.”,
“hint”: “Click the ‘Execute workflow’ button on the canvas, then try again. (In test mode, the webhook only works for one call after you click this button)”,
“stacktrace”: “ResponseError: The requested webhook “bbb32d58-2e90-4dc2-86e2-6a8ded7b82d8” is not registered.\n at TestWebhooks.getWebhookMethods (/usr/local/lib/node_modules/n8n/src/webhooks/test-webhooks.ts:185:37)\n at processTicksAndRejections (node:internal/process/task_queues:95:5)\n at TestWebhooks.executeWebhook (/usr/local/lib/node_modules/n8n/src/webhooks/test-webhooks.ts:80:22)\n at WebhookRequestHandler.handleRequest (/usr/local/lib/node_modules/n8n/src/webhooks/webhook-request-handler.ts:48:21)\n at /usr/local/lib/node_modules/n8n/src/webhooks/webhook-request-handler.ts:143:3”
}
This happens in both test mode and production. My code and n8n are running in WSL, so there should be no issue with routing.
How can I properly configure this webhook and respond to it from my interface?
this is my js script : class FlowRecomChat {
constructor() {
this.messagesContainer = document.getElementById("messagesContainer");
this.messageInput = document.getElementById("messageInput");
this.sendBtn = document.getElementById("sendBtn");
this.typingIndicator = document.getElementById("typingIndicator");
this.quickActions = document.getElementById("quickActions");
this.clearChatBtn = document.getElementById("clearChat");
// Générer un sessionId persistant
this.sessionId = localStorage.getItem("flowrecom_sessionId") || crypto.randomUUID();
localStorage.setItem("flowrecom_sessionId", this.sessionId);
this.init();
}
init() {
this.bindEvents();
this.showQuickActions();
}
bindEvents() {
if (!this.sendBtn || !this.messageInput) return console.error("Éléments DOM manquants");
// Envoi de message
this.sendBtn.addEventListener("click", () => this.sendMessage());
this.messageInput.addEventListener("keypress", (e) => {
if (e.key === "Enter") this.sendMessage();
});
// Actions rapides
document.querySelectorAll(".quick-action").forEach((btn) => {
btn.addEventListener("click", (e) => {
const message = e.currentTarget.dataset.message;
this.messageInput.value = message;
this.sendMessage();
});
});
// Effacer le chat
if (this.clearChatBtn) {
this.clearChatBtn.addEventListener("click", () => this.clearChat());
}
// Masquer/afficher les actions rapides selon la saisie
this.messageInput.addEventListener("focus", () => this.hideQuickActions());
this.messageInput.addEventListener("input", () => {
this.messageInput.value.trim()
? this.hideQuickActions()
: this.showQuickActions();
});
}
async sendMessage() {
const message = this.messageInput.value.trim();
if (!message) return;
this.addMessage(message, “user”);
this.messageInput.value = “”;
this.hideQuickActions();
this.showTyping();
try {
const response = await fetch("http://localhost:5678/webhook-test/bbb32d58-2e90-4dc2-86e2-6a8ded7b82d8", {
method: “POST”,
headers: { “Content-Type”: “application/json” },
body: JSON.stringify({
sessionId: this.sessionId,
question: message
})
});
const data = await response.json();
this.hideTyping();
// ✅ Utiliser la bonne clé "text"
const botResponse = Array.isArray(data) ? data\[0\]?.text || "Désolé, je n'ai pas compris la réponse." : "Erreur format webhook";
this.addMessage(botResponse, "bot");
} catch (err) {
this.hideTyping();
console.error("Erreur lors de l'envoi au webhook :", err);
this.addMessage("Erreur de communication avec le serveur.", "bot");
}
}
addMessage(content, sender) {
const messageDiv = document.createElement("div");
messageDiv.className = \`message ${sender}\`;
const time = new Date().toLocaleTimeString("fr-FR", {
hour: "2-digit",
minute: "2-digit",
});
messageDiv.innerHTML = \`
<div class="message-content">
${content}
<div class="message-time">${time}</div>
</div>
\`;
this.messagesContainer.appendChild(messageDiv);
this.scrollToBottom();
}
showTyping() {
if (this.typingIndicator) {
this.typingIndicator.style.display = "flex";
}
this.scrollToBottom();
}
hideTyping() {
if (this.typingIndicator) {
this.typingIndicator.style.display = "none";
}
}
showQuickActions() {
const userMessages = this.messagesContainer.querySelectorAll(".message.user");
if (userMessages.length === 0 && this.quickActions) {
this.quickActions.classList.add("show");
}
}
hideQuickActions() {
if (this.quickActions) {
this.quickActions.classList.remove("show");
}
}
clearChat() {
const welcomeMessage = this.messagesContainer.querySelector(".welcome-message");
this.messagesContainer.innerHTML = "";
if (welcomeMessage) {
this.messagesContainer.appendChild(welcomeMessage);
}
this.showQuickActions();
}
scrollToBottom() {
setTimeout(() => {
this.messagesContainer.scrollTop = this.messagesContainer.scrollHeight;
}, 100);
}
}
// Initialiser l’application avec animation
document.addEventListener(“DOMContentLoaded”, () => {
new FlowRecomChat();
const chatContainer = document.querySelector(“.chat-container”);
if (chatContainer) {
chatContainer.style.opacity = "0";
chatContainer.style.transform = "translateY(20px)";
setTimeout(() => {
chatContainer.style.transition = "all 0.5s ease";
chatContainer.style.opacity = "1";
chatContainer.style.transform = "translateY(0)";
}, 100);
}
});