Developers/Webhooks

Webhooks

Receive real-time HTTP POST notifications when events occur in your TrimLink account.

Overview

Webhooks allow you to receive real-time notifications when events happen in TrimLink. When an event occurs, we send an HTTP POST request to your configured endpoint with details about the event.

Configure webhooks in your Dashboard → Settings → API & Integrations.

Events

Subscribe to the events you want to receive notifications for:

EventDescription
link.createdA new link was created
link.clickedA link received a click
link.updatedA link was modified
link.deletedA link was deleted

Payload Format

All webhook payloads follow this structure:

Example: link.clicked
{
  "event": "link.clicked",
  "timestamp": "2026-01-31T12:00:00Z",
  "data": {
    "linkId": "clx123abc",
    "shortCode": "my-link",
    "clickedAt": "2026-01-31T12:00:00Z",
    "referrer": "https://twitter.com",
    "country": "US",
    "device": "mobile",
    "browser": "Chrome"
  }
}

Request Headers

Each webhook request includes these headers:

Webhook Headers
X-TrimLink-Signature: sha256=<signature>
X-TrimLink-Event: link.clicked
X-TrimLink-Delivery: <uuid>
X-TrimLink-Timestamp: <unix_timestamp>

Verifying Signatures

Always verify webhook signatures to ensure requests are from TrimLink and haven't been tampered with. Use your webhook secret (found in dashboard settings) to compute the expected signature.

Important: Never skip signature verification in production. This prevents attackers from sending fake webhook events to your endpoint.

const crypto = require('crypto');

function verifyWebhook(payload, signature, timestamp, secret) {
  const message = `${timestamp}.${JSON.stringify(payload)}`;
  const expectedSig = crypto
    .createHmac('sha256', secret)
    .update(message)
    .digest('hex');

  const expected = `sha256=${expectedSig}`;

  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expected)
  );
}

// Express.js example
app.post('/webhooks/trimlink', (req, res) => {
  const signature = req.headers['x-trimlink-signature'];
  const timestamp = req.headers['x-trimlink-timestamp'];

  if (!verifyWebhook(req.body, signature, timestamp, process.env.WEBHOOK_SECRET)) {
    return res.status(401).send('Invalid signature');
  }

  // Process the webhook
  const { event, data } = req.body;
  console.log(`Received ${event}`, data);

  res.status(200).send('OK');
});

Responding to Webhooks

Your endpoint should return a 2xx status code within 30 seconds to acknowledge receipt.

  • Success: Return 200, 201, or 204
  • Retry: Any other status triggers a retry
  • Timeout: No response within 30 seconds triggers a retry

Retry Policy

If your endpoint fails to respond successfully, we retry with exponential backoff:

  • 1st retry: 1 minute
  • 2nd retry: 5 minutes
  • 3rd retry: 30 minutes
  • 4th retry: 2 hours
  • 5th retry: 24 hours (final attempt)

After 5 failed attempts, the webhook is marked as failed and won't be retried.

Best Practices

  • Respond quickly: Return a 200 immediately, then process the event asynchronously
  • Handle duplicates: Use the delivery ID to deduplicate events that may be retried
  • Verify signatures: Always validate the signature before processing
  • Use HTTPS: Your webhook endpoint must use HTTPS for security