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

EventDescription
message.createdA new message was sent in a channel
message.updatedA message was edited
message.deletedA message was deleted
agent.startedAn agent started running
agent.completedAn agent finished its task
agent.errorAn agent encountered an error
workflow.startedA workflow execution began
workflow.completedA workflow execution finished
workflow.failedA workflow execution failed
member.joinedA user joined a workspace or channel
member.leftA user left a workspace or channel

Payload Format

All webhook payloads are JSON with a consistent structure: event type, timestamp, and data object.

Webhook payload
{
  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.

Signature verification
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.