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
- You register a webhook URL in the Elaras dashboard under Developer > Webhooks.
- When an event occurs, Elaras sends a
POSTrequest to your URL with a JSON payload and a signature header. - Your server verifies the signature and processes the event.
- 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:
| Field | Description |
|---|---|
| URL | Your publicly reachable HTTPS endpoint |
| Secret | A secret you generate and store. Used to sign payloads — treat it like a password. |
| Events | Choose 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:
| Field | Type | Description |
|---|---|---|
event | string | Event type (message.created, session.started, lead.captured) |
chatbot_id | string | The chatbot's public key (cbt_...) |
session_id | string | Session UUID |
data | object | Event-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:
| Attempt | Delay after previous attempt |
|---|---|
| 1st retry | 1 minute |
| 2nd retry | 5 minutes |
| 3rd retry | 15 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.
