Raw markdown

Webhooks

Webhooks let Elaras notify your server when events happen in real time. Use them to sync conversations to your CRM, trigger automations, notify your team in Slack, or update your database when a lead is captured.

How webhooks work

  1. You register a webhook URL in the Elaras dashboard under Developer > Webhooks.
  2. When an event occurs, Elaras sends a POST request to your URL with a JSON payload and a signature header.
  3. Your server verifies the signature and processes the event.
  4. You respond with any 2xx status within 15 seconds.

If your server does not respond with 2xx, Elaras retries the delivery.

Configuring webhooks

Go to Developer > Webhooks in the Elaras dashboard and click Add webhook:

FieldDescription
URLYour publicly reachable HTTPS endpoint
SecretA secret you generate and store. Used to sign payloads — treat it like a password.
EventsChoose which events trigger this webhook (or select "All events")

Events

message.created

Fired when a new message is saved (user or AI response).

{ "event": "message.created", "chatbot_id": "cbt_abc123", "session_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "data": { "message_id": 42, "role": "assistant", "content": "We are open Monday to Friday, 9am to 5pm.", "credits_used": 3, "created_at": "2026-07-24T10:30:00Z" } }

session.started

Fired when a new session sends its first message.

{ "event": "session.started", "chatbot_id": "cbt_abc123", "session_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "data": { "started_at": "2026-07-24T10:29:55Z" } }

lead.captured

Fired when a user submits their email via the lead capture form or the SDK's submitLead() method.

{ "event": "lead.captured", "chatbot_id": "cbt_abc123", "session_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "data": { "email": "[email protected]", "name": "Jordan", "captured_at": "2026-07-24T10:31:00Z" } }

Payload structure

Every webhook payload shares this top-level shape:

FieldTypeDescription
eventstringEvent type (message.created, session.started, lead.captured)
chatbot_idstringThe chatbot's public key (cbt_...)
session_idstringSession UUID
dataobjectEvent-specific data

Signature verification

Elaras signs every webhook request with HMAC-SHA256 using your webhook secret. The signature is in the X-Elaras-Signature header:

X-Elaras-Signature: sha256=a1b2c3d4e5f6...

Always verify the signature before processing a webhook. This prevents malicious third parties from sending fake events to your endpoint.

Node.js

import crypto from 'crypto'; import express from 'express'; const app = express(); app.post('/webhooks/elaras', express.raw({type: 'application/json'}), (req, res) => { const signature = req.headers['x-elaras-signature']; const webhookSecret = process.env.ELARAS_WEBHOOK_SECRET; const expected = 'sha256=' + crypto .createHmac('sha256', webhookSecret) .update(req.body) .digest('hex'); if (!crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected))) { return res.status(401).send('Invalid signature'); } const payload = JSON.parse(req.body); switch (payload.event) { case 'message.created': console.log('New message:', payload.data.content); break; case 'session.started': console.log('New session:', payload.session_id); break; case 'lead.captured': console.log('Lead:', payload.data.email); // e.g. add to your CRM break; } res.status(200).send('ok'); });

PHP

<?php $rawBody = file_get_contents('php://input'); $signature = $_SERVER['HTTP_X_ELARAS_SIGNATURE'] ?? ''; $webhookSecret = getenv('ELARAS_WEBHOOK_SECRET'); $expected = 'sha256=' . hash_hmac('sha256', $rawBody, $webhookSecret); if (!hash_equals($expected, $signature)) { http_response_code(401); echo 'Invalid signature'; exit; } $payload = json_decode($rawBody, true); switch ($payload['event']) { case 'message.created': error_log('New message: ' . $payload['data']['content']); break; case 'session.started': error_log('New session: ' . $payload['session_id']); break; case 'lead.captured': error_log('Lead: ' . $payload['data']['email']); // Add to your CRM... break; } http_response_code(200); echo 'ok';

Retry behaviour

If your endpoint does not return a 2xx response (or times out after 15 seconds), Elaras automatically retries:

AttemptDelay after previous attempt
1st retry1 minute
2nd retry5 minutes
3rd retry15 minutes

After 3 failed retries (4 total attempts), the delivery is marked as failed and no further attempts are made. You can view failed deliveries and manually re-trigger them from Developer > Webhooks > Delivery log.

Responding

  • Respond with any 2xx status code (200, 204, etc.) to acknowledge receipt.
  • Respond within 15 seconds — process the event asynchronously if needed (queue it, then respond 200 immediately).
  • The response body is ignored by Elaras.

Security tips

  • Store your webhook secret in an environment variable — never hardcode it.
  • Use hash_equals() / timingSafeEqual() for comparison — never === or ==. This prevents timing attacks.
  • Only accept HTTPS endpoints.
  • Use a dedicated endpoint for Elaras webhooks rather than a shared route.