Webhooks Guide

Vectis sends real-time notifications to your application when events occur. Configure webhook endpoints to receive order updates, inventory changes, and fulfillment events.

Setting Up Webhooks

Via Dashboard

  1. Navigate to Settings → Webhooks in your Vectis dashboard
  2. Click Add Webhook
  3. Enter your endpoint URL (must be HTTPS)
  4. Select the events you want to receive
  5. Save and copy your webhook secret

Via API

curl -X POST https://acme.vectisoms.app/api/webhooks \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://api.yoursite.com/webhooks/vectis",
    "events": ["order.created", "order.shipped"],
    "secret": "whsec_your_secret_here",
    "isActive": true
  }'

Event Types

Order Events

EventDescription
order.createdNew order received
order.updatedOrder details changed
order.cancelledOrder was cancelled
order.shippedAll packages shipped

Package Events

EventDescription
package.createdPackage created for order
package.shippedPackage shipped with tracking
package.deliveredPackage delivered

Inventory Events

EventDescription
inventory.adjustedStock level changed
inventory.low_stockItem fell below threshold

Webhook Payload

All webhooks include a consistent payload structure:

{
  "id": "evt_abc123",
  "type": "order.shipped",
  "timestamp": "2026-03-15T10:30:00Z",
  "data": {
    "orderId": "550e8400-e29b-41d4-a716-446655440000",
    "status": "shipped",
    "trackingNumbers": ["1Z999AA10123456784"]
  }
}

Verifying Signatures

All outbound webhooks are signed with HMAC-SHA256. Always verify signatures before processing webhook data.

Headers

Each webhook request includes:

  • X-Webhook-Signature: HMAC signature
  • X-Webhook-Timestamp: Unix timestamp (seconds)

Verification Process

  1. Concatenate: {timestamp}.{raw_request_body}
  2. Compute HMAC-SHA256 using your webhook secret
  3. Compare with X-Webhook-Signature header (timing-safe)
  4. Reject if timestamp is older than 5 minutes

Node.js Example

const crypto = require('crypto');

function verifyWebhook(payload, signature, timestamp, secret) {
  // Check timestamp freshness (5 minute window)
  const now = Math.floor(Date.now() / 1000);
  if (Math.abs(now - parseInt(timestamp)) > 300) {
    return false;
  }

  // Compute expected signature
  const signedPayload = `${timestamp}.${payload}`;
  const expected = crypto
    .createHmac('sha256', secret)
    .update(signedPayload)
    .digest('hex');

  // Timing-safe comparison
  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expected)
  );
}

// Express middleware
app.post('/webhooks/vectis', (req, res) => {
  const signature = req.headers['x-webhook-signature'];
  const timestamp = req.headers['x-webhook-timestamp'];
  const payload = req.rawBody; // Must be raw body, not parsed JSON

  if (!verifyWebhook(payload, signature, timestamp, process.env.WEBHOOK_SECRET)) {
    return res.status(401).json({ error: 'Invalid signature' });
  }

  const event = JSON.parse(payload);
  // Process event...

  res.status(200).json({ received: true });
});

Python Example

import hmac
import hashlib
import time

def verify_webhook(payload: bytes, signature: str, timestamp: str, secret: str) -> bool:
    # Check timestamp freshness
    now = int(time.time())
    if abs(now - int(timestamp)) > 300:
        return False

    # Compute expected signature
    signed_payload = f"{timestamp}.{payload.decode()}"
    expected = hmac.new(
        secret.encode(),
        signed_payload.encode(),
        hashlib.sha256
    ).hexdigest()

    # Timing-safe comparison
    return hmac.compare_digest(signature, expected)

Retry Behavior

Vectis retries failed webhook deliveries with exponential backoff:

AttemptDelay
1Immediate
21 minute
35 minutes
430 minutes
52 hours

A delivery is considered failed if:

  • Your endpoint returns a non-2xx status code
  • The request times out (30 seconds)
  • Connection cannot be established

After 5 failed attempts, the webhook is marked as failed and no further retries occur.

Best Practices

  1. Respond quickly — Return a 200 response immediately, then process asynchronously
  2. Handle duplicates — Use the event id to deduplicate (webhooks may be delivered more than once)
  3. Verify signatures — Never process unverified webhooks
  4. Use HTTPS — Webhook endpoints must use HTTPS
  5. Log everything — Store raw payloads for debugging

Testing Webhooks

Use the Test button in your dashboard to send a sample event to your endpoint. You can also use tools like webhook.site during development.

Managing Webhooks

List Webhooks

curl https://acme.vectisoms.app/api/webhooks \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN"

Delete Webhook

curl -X DELETE https://acme.vectisoms.app/api/webhooks/{id} \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN"