Skip to main content

Setting Up Webhooks

1

Access Webhook Settings

Log into your Urtentic Dashboard, navigate to Integrations, and click Webhooks
2

Configure Endpoint

  • Endpoint URL: Your HTTPS endpoint (e.g., https://api.yourapp.com/webhooks/urtentic)
  • Secret Key: Auto-generated or custom webhook secret
  • IP Whitelist: Optional IP address restrictions
3

Test Connection

Click Test Endpoint, review the test payload, verify your endpoint responds with HTTP 200, and check signature verification

Implementing Webhook Endpoints

const express = require('express');
const crypto = require('crypto');
const app = express();

app.use('/webhooks/urtentic', express.raw({ type: 'application/json' }));

app.post('/webhooks/urtentic', (req, res) => {
  const signature = req.headers['x-urtentic-signature'];
  const timestamp = req.headers['x-urtentic-timestamp'];
  const payload = req.body;

  try {
    verifyWebhookSignature(payload, signature, process.env.WEBHOOK_SECRET, timestamp);
    const event = JSON.parse(payload);
    handleWebhookEvent(event);
    res.status(200).json({ received: true });
  } catch (error) {
    console.error('Webhook verification failed:', error.message);
    res.status(400).json({ error: 'Webhook verification failed' });
  }
});

function verifyWebhookSignature(payload, signature, secret, timestamp) {
  const currentTime = Math.floor(Date.now() / 1000);
  if (Math.abs(currentTime - timestamp) > 300) {
    throw new Error('Webhook timestamp too old');
  }
  const secretBytes = Buffer.from(secret, 'base64');
  const expectedSignature = crypto
    .createHmac('sha256', secretBytes)
    .update(payload, 'utf8')
    .digest('hex');
  if (signature.startsWith('sha256=')) signature = signature.substring(7);
  if (!crypto.timingSafeEqual(
    Buffer.from(signature, 'hex'),
    Buffer.from(expectedSignature, 'hex')
  )) {
    throw new Error('Invalid signature');
  }
}

function handleWebhookEvent(event) {
  switch (event.eventName) {
    case 'verification_completed':
      console.log(`Verification completed: ${event.flowId}`);
      break;
    case 'verification_abandoned':
      console.log(`Verification abandoned: ${event.flowId}`);
      break;
    case 'step_completed':
      console.log(`Step completed: ${event.step.stepId}`);
      break;
    default:
      console.log(`Unhandled event: ${event.eventName}`);
  }
}

app.listen(3000, () => console.log('Webhook server listening on port 3000'));

Monitoring & Maintenance

Webhook Health Monitoring

Monitor your webhook endpoint health:
  • Response Times: Track webhook processing performance
  • Success Rates: Monitor delivery success percentages
  • Error Patterns: Identify common failure modes
  • Retry Frequency: Track how often retries are needed

Logging Best Practices

function handleWebhookEvent(event) {
  const startTime = Date.now();
  try {
    console.log(`Processing webhook: ${event.eventName}`);
    processEvent(event);
    const duration = Date.now() - startTime;
    console.log(`Webhook processed successfully (${duration}ms)`);
  } catch (error) {
    console.error(`Webhook processing failed:`, error.message);
    throw error;
  }
}

Scaling Considerations

Queue Processing

Use message queues (RabbitMQ, SQS) for webhook processing

Load Balancing

Distribute webhook traffic across multiple servers

Database Optimization

Optimize queries for webhook handlers

Caching

Cache frequently accessed data to improve performance