Discord appelle deux choses différentes des "webhooks". L'une est une URL où poster des messages. L'autre est un endpoint d'interaction qui reçoit des POSTs signés à chaque commande slash. La première fonctionne sur localhost. La seconde non — c'est elle qui a besoin d'un tunnel.
Les deux variantes
Webhooks sortants : URLs vers lesquelles vous postez. Le trafic part de votre machine, aucun tunnel nécessaire.
Endpoints d'interaction : direction inverse. Vous enregistrez une URL ; Discord POST dessus à chaque /votrecommande. HTTPS obligatoire, réponse en moins de trois secondes, vérification Ed25519 sur chaque requête.
Pourquoi c'est plus strict que la moyenne
Discord ne demande pas seulement HTTPS — il prouve que vous contrôlez l'endpoint à l'enregistrement. Une interaction PING est envoyée, votre serveur doit répondre par un PONG signé. Une seule erreur Ed25519 et Discord refuse d'enregistrer l'URL.
Vous n'aurez pas la vérification Ed25519 du premier coup. Presque personne ne l'a.
Ed25519, le piège principal
Discord utilise Ed25519 (pas HMAC SHA-256) et fournit deux en-têtes :
X-Signature-Ed25519— signature en hexX-Signature-Timestamp— timestamp en secondes
Vous signez timestamp + rawBody avec la clé publique du dev portal.
import nacl from 'tweetnacl';
const valid = nacl.sign.detached.verify(
Buffer.from(timestamp + rawBody),
Buffer.from(signature, 'hex'),
Buffer.from(PUBLIC_KEY, 'hex'),
);
Encore une fois, la cause numéro un d'échec est un middleware qui parse le corps avant la vérification.
Étapes
- Démarrez le serveur HTTP de votre bot localement.
- Exécutez
npx portpreview 3000et copiez l'URL HTTPS. - Dans le portail développeur Discord, collez l'URL dans Interactions Endpoint URL.
- Sauvegardez. Discord envoie immédiatement un PING. Si Ed25519 passe, l'URL est enregistrée.
- Lancez une commande slash dans un serveur où votre bot est présent.
Trois secondes pour répondre
Discord exige une réponse en moins de trois secondes. Pour du traitement plus long, envoyez une réponse de type 5 (différée) puis PATCH l'interaction avec la vraie réponse plus tard.
Les webhooks sortants restent utiles
Pour envoyer des messages depuis du code local, l'URL webhook sortant suffit, sans tunnel. Nous l'utilisons pour des alertes de logs depuis nos runs locaux.
Quand passer à autre chose
Pour un bot avec quelques commandes, le tunnel suffit. Pour un bot public à des millions d'utilisateurs, un staging avec URL stable évite les re-vérifications à chaque rotation de session.
La fenêtre de trois secondes ressemble à celle de GitHub (dix secondes). Voir notre article retries et idempotence. Rejoignez la waitlist PortPreview.