Webhook Setup Guide

    Configure webhooks to receive real-time notifications for link events

    Webhook Setup Guide

    Webhooks allow you to receive real-time notifications when events occur in your Smartlinks account.

    Overview

    Smartlinks can send webhook events to your server when:

    • A link is clicked
    • A new link is created
    • A link is updated or deleted
    • Analytics milestones are reached

    Creating a Webhook

    Step 1: Set Up Your Endpoint

    Create an endpoint on your server to receive webhook events:

    // Express.js example
    const express = require('express');
    const app = express();
    
    app.post('/webhooks/smartlinks', express.json(), (req, res) => {
      const event = req.body;
      
      console.log('Received webhook:', event.type);
      console.log('Data:', event.data);
      
      // Process the event
      handleWebhookEvent(event);
      
      // Acknowledge receipt
      res.status(200).json({ received: true });
    });
    
    app.listen(3000, () => {
      console.log('Webhook server running on port 3000');
    });
    

    Step 2: Register the Webhook

    Register your webhook endpoint with Smartlinks:

    async function registerWebhook(url, events) {
      const response = await fetch('https://api.smartlinks.io/v1/webhooks', {
        method: 'POST',
        headers: {
          'Authorization': `Bearer ${SMARTLINKS_API_KEY}`,
          'Content-Type': 'application/json'
        },
        body: JSON.stringify({
          url: url,
          events: events,
          active: true
        })
      });
      
      return await response.json();
    }
    
    // Register for link.clicked and link.created events
    registerWebhook('https://your-domain.com/webhooks/smartlinks', [
      'link.clicked',
      'link.created',
      'link.updated',
      'link.deleted'
    ]);
    

    Webhook Event Types

    link.clicked

    Triggered when someone clicks a short link:

    {
      "type": "link.clicked",
      "id": "evt_123abc",
      "created_at": "2024-01-15T10:30:00Z",
      "data": {
        "link_id": "link_456def",
        "short_url": "https://smrt.lnk/abc123",
        "destination_url": "https://example.com/page",
        "click": {
          "ip_address": "192.168.1.1",
          "user_agent": "Mozilla/5.0...",
          "referer": "https://google.com",
          "country": "US",
          "city": "New York",
          "device_type": "desktop"
        }
      }
    }
    

    link.created

    Triggered when a new link is created:

    {
      "type": "link.created",
      "id": "evt_789ghi",
      "created_at": "2024-01-15T10:30:00Z",
      "data": {
        "link_id": "link_456def",
        "short_url": "https://smrt.lnk/abc123",
        "destination_url": "https://example.com/page",
        "created_by": "user_123"
      }
    }
    

    Handling Webhooks

    Complete Event Handler

    function handleWebhookEvent(event) {
      switch (event.type) {
        case 'link.clicked':
          handleLinkClick(event.data);
          break;
        
        case 'link.created':
          handleLinkCreated(event.data);
          break;
        
        case 'link.updated':
          handleLinkUpdated(event.data);
          break;
        
        case 'link.deleted':
          handleLinkDeleted(event.data);
          break;
        
        default:
          console.log('Unhandled event type:', event.type);
      }
    }
    
    function handleLinkClick(data) {
      console.log(`Link ${data.link_id} clicked from ${data.click.country}`);
      
      // Example: Send to analytics
      analytics.track('Link Clicked', {
        linkId: data.link_id,
        country: data.click.country,
        device: data.click.device_type
      });
    }
    
    function handleLinkCreated(data) {
      console.log(`New link created: ${data.short_url}`);
      
      // Example: Send notification
      sendNotification(`New short link: ${data.short_url}`);
    }
    

    Verifying Webhook Signatures

    Security: Always verify webhook signatures to ensure requests are from Smartlinks.

    const crypto = require('crypto');
    
    function verifyWebhookSignature(payload, signature, secret) {
      const expectedSignature = crypto
        .createHmac('sha256', secret)
        .update(JSON.stringify(payload))
        .digest('hex');
      
      return crypto.timingSafeEqual(
        Buffer.from(signature),
        Buffer.from(expectedSignature)
      );
    }
    
    // In your webhook handler
    app.post('/webhooks/smartlinks', express.json(), (req, res) => {
      const signature = req.headers['x-smartlinks-signature'];
      const webhookSecret = process.env.WEBHOOK_SECRET;
      
      if (!verifyWebhookSignature(req.body, signature, webhookSecret)) {
        return res.status(401).json({ error: 'Invalid signature' });
      }
      
      // Process the event
      handleWebhookEvent(req.body);
      res.status(200).json({ received: true });
    });
    

    Testing Webhooks

    Local Testing with ngrok

    Use ngrok to expose your local server:

    # Install ngrok
    npm install -g ngrok
    
    # Expose your local port
    ngrok http 3000
    
    # Use the ngrok URL when registering webhooks
    # Example: https://abc123.ngrok.io/webhooks/smartlinks
    

    Manual Testing

    Test your webhook endpoint manually:

    curl -X POST https://your-domain.com/webhooks/smartlinks \
      -H "Content-Type: application/json" \
      -H "X-Smartlinks-Signature: test_signature" \
      -d '{
        "type": "link.clicked",
        "id": "evt_test",
        "created_at": "2024-01-15T10:30:00Z",
        "data": {
          "link_id": "link_test",
          "short_url": "https://smrt.lnk/test"
        }
      }'
    

    Error Handling & Retries

    Smartlinks will retry failed webhook deliveries:

    • 3 automatic retries with exponential backoff
    • Maximum retry interval: 1 hour
    • Webhooks are disabled after 10 consecutive failures
    // Ensure your endpoint responds quickly
    app.post('/webhooks/smartlinks', express.json(), async (req, res) => {
      // Acknowledge receipt immediately
      res.status(200).json({ received: true });
      
      // Process asynchronously
      processWebhookAsync(req.body).catch(error => {
        console.error('Error processing webhook:', error);
      });
    });
    
    async function processWebhookAsync(event) {
      // Your processing logic here
      await saveToDatabase(event);
      await triggerNotifications(event);
    }
    

    Best Practices

    • ✅ Respond with 200 status code quickly
    • ✅ Process events asynchronously
    • ✅ Verify webhook signatures
    • ✅ Implement idempotency using event IDs
    • ✅ Log all webhook events
    • ❌ Don't perform long-running operations synchronously
    • ❌ Don't expose your webhook secret

    Next Steps