Back to blog

How to set up webhook notifications for shipping updates

·6 min read

Polling-based monitoring has a downside: there's always a delay between an event occurring and your notification. Webhooks solve this problem by pushing events to your endpoint in real time.

This article shows how to set up webhook notifications for shipment updates — from basic configuration to signature verification and retry logic.

What are webhooks?

Webhooks are HTTP callbacks: when an event occurs, the server sends an HTTP POST request to a URL you define. In the context of shipment monitoring, this means: as soon as a shipment's status changes, your system is immediately informed.

json
{
  "event": "shipment.exception",
  "timestamp": "2026-01-15T14:32:00Z",
  "data": {
    "trackingNumber": "00340434161094042684",
    "carrier": "DHL",
    "customerRef": "ORDER-4521",
    "status": "DELIVERY_FAILED",
    "previousStatus": "IN_TRANSIT",
    "priority": "HIGH",
    "description": "Delivery attempt failed - recipient not available",
    "location": "Berlin, DE"
  }
}

Setting up webhooks

Setup involves three steps: create an endpoint, configure the URL, verify signatures.

1. Create an endpoint

Your webhook endpoint must accept HTTP POST requests with JSON payloads and respond with a 200 status. Any other status code will be treated as a failed delivery attempt and automatically retried.

typescript
// Express example: acknowledge immediately, process async
import express from 'express';
import { addToQueue } from './queue';

const app = express();
app.use(express.json());

app.post('/webhooks/shipping', async (req, res) => {
  // 1. Verify signature (see below)
  if (!verifySignature(req)) {
    return res.status(401).send('Invalid signature');
  }

  // 2. Enqueue for async processing
  await addToQueue('shipping-events', req.body);

  // 3. Acknowledge immediately
  res.status(200).json({ received: true });
});

2. Configure the URL

Register your webhook URL via the ShipTriage API or dashboard. You can also set a secret used to sign payloads.

3. Verify signatures

Every webhook payload includes an X-ShipTriage-Signature header with an HMAC-SHA256 signature. Verify this signature to ensure the payload actually came from ShipTriage.

typescript
import crypto from 'crypto';

function verifySignature(req: express.Request): boolean {
  const signature = req.headers['x-shiptriage-signature'] as string;
  if (!signature) return false;

  const payload = JSON.stringify(req.body);
  const expected = crypto
    .createHmac('sha256', process.env.WEBHOOK_SECRET!)
    .update(payload)
    .digest('hex');

  // Use timingSafeEqual to prevent timing attacks
  // Check length first -- timingSafeEqual throws if lengths differ
  if (signature.length !== expected.length) return false;

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

Retry logic

If your endpoint is unreachable or returns an error, ShipTriage automatically retries delivery with exponential backoff: after 1, 5, and 30 minutes.

Integration examples

Slack integration

Forward webhook events to a Slack channel to instantly inform your team about shipment issues.

Microsoft Teams

Use incoming webhooks in Teams to receive shipment notifications in your operations channel.

Custom system

Process webhook events in your own backend to update shipment data in your OMS, CRM, or customer support system.

Real-time notifications for your shipments

Webhooks, email, Slack, Teams, Telegram, Discord, and PagerDuty — all included.

Get started free