Webhooks
Receive real-time HTTP notifications when events occur in your LVNG workspace. Webhooks let you build integrations that react to messages, agent activity, workflow completions, and more.
Event Types
| Event | Description |
|---|---|
message.created | A new message was sent in a channel |
message.updated | A message was edited |
message.deleted | A message was deleted |
agent.started | An agent started running |
agent.completed | An agent finished its task |
agent.error | An agent encountered an error |
workflow.started | A workflow execution began |
workflow.completed | A workflow execution finished |
workflow.failed | A workflow execution failed |
member.joined | A user joined a workspace or channel |
member.left | A user left a workspace or channel |
Payload Format
All webhook payloads are JSON with a consistent structure: event type, timestamp, and data object.
{
400">class="text-emerald-400">"event": 400">class="text-emerald-400">"message.created",
400">class="text-emerald-400">"timestamp": 400">class="text-emerald-400">"2024-03-15T10:30:00Z",
400">class="text-emerald-400">"data": {
400">class="text-emerald-400">"id": 400">class="text-emerald-400">"msg_550e8400-e29b-41d4-a716-446655440000",
400">class="text-emerald-400">"channel_id": 400">class="text-emerald-400">"ch_660e8400-e29b-41d4-a716-446655440000",
400">class="text-emerald-400">"content": 400">class="text-emerald-400">"Hello 400">from LVNG!",
400">class="text-emerald-400">"sender_id": 400">class="text-emerald-400">"usr_770e8400-e29b-41d4-a716-446655440000",
400">class="text-emerald-400">"message_type": 400">class="text-emerald-400">"user",
400">class="text-emerald-400">"created_at": 400">class="text-emerald-400">"2024-03-15T10:30:00Z"
}
}Verifying Signatures
Every webhook request includes an X-LVNG-Signature header containing an HMAC-SHA256 signature of the payload. Always verify this signature to ensure the request is from LVNG.
400">const crypto = require(400">class="text-emerald-400">'crypto');
400">function verifyWebhook(payload, signature, secret) {
400">const expected = crypto
.createHmac(400">class="text-emerald-400">'sha256', secret)
.update(payload)
.digest(400">class="text-emerald-400">'hex');
400">return crypto.timingSafeEqual(
Buffer.400">from(signature),
Buffer.400">from(expected)
);
}
400">class="text-zinc-500">// In your Express handler:
app.post(400">class="text-emerald-400">'/webhooks/lvng', (req, res) => {
400">const signature = req.headers[400">class="text-emerald-400">'x-lvng-signature'];
400">const isValid = verifyWebhook(
JSON.stringify(req.body),
signature,
process.env.WEBHOOK_SECRET
);
400">if (!isValid) {
400">return res.status(401).json({ error: 400">class="text-emerald-400">'Invalid signature' });
}
400">class="text-zinc-500">// Process the event
400">const { event, data } = req.body;
console.log(400">class="text-emerald-400">'Received event:', event, data);
res.status(200).json({ received: true });
});Best Practices
Respond quickly
Return a 2xx status code within 5 seconds. Process events asynchronously if needed.
Handle duplicates
Webhooks may be delivered more than once. Use the event ID for idempotency.
Verify signatures
Always validate the X-LVNG-Signature header before processing events.
Use HTTPS
Webhook endpoints must use HTTPS. HTTP endpoints will be rejected.