> ## Documentation Index
> Fetch the complete documentation index at: https://docs.livingsecurity.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Webhooks Integration

> Send Living Security event data to custom webhook endpoints for SIEM integration, ticketing systems, and custom automation.

<Info>
  The Webhooks integration is coming soon. This documentation describes upcoming functionality.

  Self-service webhook configuration is not currently exposed in **Settings → Integrations**. **Settings → Developer Hub → Webhooks** is a non-functional preview only: endpoints are stored in the browser and no production events are delivered. Contact your account manager for availability of supported webhook configuration.
</Info>

Webhooks allow Living Security to send real-time event data to your custom endpoints. Use webhooks to integrate with SIEM platforms, ticketing systems, data warehouses, and custom automation playbooks.

## Overview

When configured, Living Security sends HTTP POST requests to your endpoint whenever selected events occur. Each webhook payload includes:

* Event type and timestamp
* Relevant entity data (user, training, playbook)
* Organization context
* Cryptographic signature for verification

## Supported Events

| Event Category | Events                                                                            |
| -------------- | --------------------------------------------------------------------------------- |
| Training       | `training.assigned`, `training.started`, `training.completed`, `training.overdue` |
| Users          | `user.created`, `user.updated`, `user.deactivated`                                |
| Playbooks      | `playbook.started`, `playbook.completed`, `playbook.paused`                       |

## Webhook Payload Format

All webhooks use a consistent JSON payload structure:

```json theme={null}
{
  "id": "evt_abc123",
  "type": "training.completed",
  "timestamp": "2024-01-15T10:30:00Z",
  "organization_id": "org_xyz789",
  "data": {
    "user_id": "usr_456",
    "user_email": "john.doe@example.com",
    "training_id": "trn_789",
    "training_name": "Security Awareness 101",
    "score": 85,
    "completed_at": "2024-01-15T10:30:00Z"
  }
}
```

## Configuring a Webhook

<Steps>
  <Step title="Prepare your endpoint">
    Create an HTTPS endpoint that:

    * Accepts POST requests
    * Responds with 2xx status within 30 seconds
    * Handles JSON request bodies
    * Verifies webhook signatures (recommended)
  </Step>

  <Step title="Navigate to webhook settings">
    When the Developer Hub preview is enabled for your organization, open **Settings → Developer Hub → Webhooks** to explore the upcoming UI. The legacy **Settings → Integrations → Outbound → Webhooks** navigation path is no longer shown in the dashboard menu.

    <Warning>
      The Developer Hub webhooks page is a prototype. Creating endpoints there does not configure production webhook delivery.
    </Warning>
  </Step>

  <Step title="Add your webhook endpoint">
    Click **Add endpoint** and configure:

    <ParamField body="endpoint" type="string" required>
      Your webhook URL. Must be HTTPS in production.
    </ParamField>

    <ParamField body="description" type="string" required>
      A friendly name for this endpoint (for example, "SIEM Integration").
    </ParamField>

    <ParamField body="events" type="array" required>
      Select which events trigger this webhook.
    </ParamField>

    Click **Create endpoint**. Living Security generates a signing secret once after creation — copy and store it securely before closing the dialog. You cannot retrieve the full secret again later.
  </Step>

  <Step title="Test and verify">
    Click **Send Test Event** to verify your endpoint receives webhooks correctly.

    <Check>
      Your endpoint returns a 200 status and the webhook shows as "active".
    </Check>
  </Step>
</Steps>

## Verifying Webhook Signatures

Living Security signs all webhook payloads using HMAC-SHA256. Verify signatures to ensure webhooks are authentic:

<CodeGroup>
  ```javascript Node.js theme={null}
  const crypto = require('crypto');

  function verifyWebhookSignature(payload, signature, secret) {
    const expected = crypto
      .createHmac('sha256', secret)
      .update(payload, 'utf8')
      .digest('hex');
    
    return crypto.timingSafeEqual(
      Buffer.from(signature),
      Buffer.from(`sha256=${expected}`)
    );
  }

  // In your webhook handler
  app.post('/webhook', (req, res) => {
    const signature = req.headers['x-ls-signature'];
    const isValid = verifyWebhookSignature(
      JSON.stringify(req.body),
      signature,
      process.env.WEBHOOK_SECRET
    );
    
    if (!isValid) {
      return res.status(401).send('Invalid signature');
    }
    
    // Process the webhook
    console.log('Received event:', req.body.type);
    res.status(200).send('OK');
  });
  ```

  ```python Python theme={null}
  import hmac
  import hashlib

  def verify_webhook_signature(payload: bytes, signature: str, secret: str) -> bool:
      expected = hmac.new(
          secret.encode('utf-8'),
          payload,
          hashlib.sha256
      ).hexdigest()
      
      return hmac.compare_digest(signature, f'sha256={expected}')

  # In your webhook handler
  @app.route('/webhook', methods=['POST'])
  def handle_webhook():
      signature = request.headers.get('X-LS-Signature')
      is_valid = verify_webhook_signature(
          request.data,
          signature,
          os.environ['WEBHOOK_SECRET']
      )
      
      if not is_valid:
          return 'Invalid signature', 401
      
      # Process the webhook
      event = request.get_json()
      print(f"Received event: {event['type']}")
      return 'OK', 200
  ```
</CodeGroup>

## Retry Policy

Living Security retries failed webhook deliveries with exponential backoff:

| Attempt | Delay      |
| ------- | ---------- |
| 1       | Immediate  |
| 2       | 1 minute   |
| 3       | 5 minutes  |
| 4       | 30 minutes |
| 5       | 2 hours    |

After 5 failed attempts, the webhook is marked as failing and notifications are paused.

## Common Integrations

<CardGroup cols={2}>
  <Card title="Splunk" icon="chart-line">
    Forward events to Splunk HEC for security analytics and dashboards.
  </Card>

  <Card title="ServiceNow" icon="ticket">
    Create incidents or tasks automatically based on training events.
  </Card>

  <Card title="Jira" icon="list-check">
    Track training compliance as Jira issues for team visibility.
  </Card>

  <Card title="Custom Data Warehouse" icon="database">
    Stream events to your data warehouse for custom reporting.
  </Card>
</CardGroup>

## Troubleshooting

<AccordionGroup>
  <Accordion title="Webhooks not being received">
    * Verify your endpoint is publicly accessible
    * Check firewall rules allow traffic from Living Security IPs
    * Ensure your endpoint responds within 30 seconds
    * Review your server logs for incoming requests
  </Accordion>

  <Accordion title="Signature verification failing">
    * Ensure you're using the raw request body for verification (not parsed JSON)
    * Verify the secret matches exactly (no extra whitespace)
    * Check you're comparing the full signature including the `sha256=` prefix
  </Accordion>

  <Accordion title="Webhook marked as failing">
    * Check your endpoint health and availability
    * Review error responses in the webhook delivery logs
    * Fix the underlying issue, then click **Retry** to resume deliveries
  </Accordion>
</AccordionGroup>

## Best Practices

<Tip>
  Process webhooks asynchronously. Accept the webhook with a 200 response immediately, then process it in a background job. This prevents timeouts and ensures reliable delivery.
</Tip>

* Always verify webhook signatures before processing
* Implement idempotency—webhooks may be delivered more than once
* Log all incoming webhooks for debugging
* Set up monitoring and alerting for webhook processing failures
* Use a webhook management service (like Svix or Hookdeck) for complex routing needs
