Skip to main content

Webhooks

Receive real-time HTTP POST notifications when events occur on your TAGVU tags, batches, and orders.

Setup

1. Register a webhook URL

Navigate to your company dashboard at app.tag.vu/dashboard/settings/webhooks and add your HTTPS endpoint URL.

2. Select events

Choose which events to subscribe to. You can subscribe to all events or select specific ones.

3. Receive and verify

Each webhook includes a signature in the X-Tagvu-Signature header for verification.

Signature Verification

Every webhook request includes an HMAC-SHA256 signature. Verify it to ensure the request came from TAGVU.

import crypto from 'crypto';

function verifyWebhook(payload: string, signature: string, secret: string): boolean {
  const expected = crypto
    .createHmac('sha256', secret)
    .update(payload)
    .digest('hex');
  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expected)
  );
}

// In your webhook handler:
app.post('/webhooks/tagvu', (req, res) => {
  const signature = req.headers['x-tagvu-signature'] as string;
  const isValid = verifyWebhook(
    JSON.stringify(req.body),
    signature,
    process.env.TAGVU_WEBHOOK_SECRET
  );

  if (!isValid) {
    return res.status(401).json({ error: 'Invalid signature' });
  }

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

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

Retry Policy

  • Webhooks expect a 2xx response within 30 seconds.
  • Failed deliveries are retried with exponential backoff: 1min, 5min, 30min, 2h, 24h.
  • After 5 consecutive failures, the webhook is marked as disabled.
  • You can re-enable disabled webhooks from your dashboard.
  • Delivery logs are available for the last 7 days.

Event Types

tag.scanned

Fired when a tag is scanned by anyone. Includes location, device context, and tag status.

View payload example
{
  "event": "tag.scanned",
  "timestamp": "2026-03-27T10:30:00Z",
  "data": {
    "tag_id": "550e8400-e29b-41d4-a716-446655440000",
    "tag_code": "A1B2-C3D4-EF",
    "status": "active",
    "scan": {
      "id": "uuid",
      "location_text": "Brussels Central Station",
      "location_lat": 50.8453,
      "location_lng": 4.3570,
      "device_type": "mobile",
      "browser": "Chrome",
      "os": "Android"
    }
  }
}

tag.lost_mode_toggled

Fired when lost mode is enabled or disabled on a tag.

View payload example
{
  "event": "tag.lost_mode_toggled",
  "timestamp": "2026-03-27T10:30:00Z",
  "data": {
    "tag_id": "550e8400-e29b-41d4-a716-446655440000",
    "tag_code": "A1B2-C3D4-EF",
    "lost_mode_enabled": true,
    "reason": "Lost at the park"
  }
}

tag.claimed

Fired when a tag is claimed by a user using the claim PIN.

View payload example
{
  "event": "tag.claimed",
  "timestamp": "2026-03-27T10:30:00Z",
  "data": {
    "tag_id": "550e8400-e29b-41d4-a716-446655440000",
    "tag_code": "A1B2-C3D4-EF",
    "claimed_by": "user-uuid"
  }
}

tag.transferred

Fired when tag ownership is transferred to another user.

View payload example
{
  "event": "tag.transferred",
  "timestamp": "2026-03-27T10:30:00Z",
  "data": {
    "tag_id": "550e8400-e29b-41d4-a716-446655440000",
    "from_user": "user-uuid-1",
    "to_user": "user-uuid-2"
  }
}

tag.status_changed

Fired when a tag transitions between statuses (e.g., active to expired).

View payload example
{
  "event": "tag.status_changed",
  "timestamp": "2026-03-27T10:30:00Z",
  "data": {
    "tag_id": "550e8400-e29b-41d4-a716-446655440000",
    "previous_status": "active",
    "new_status": "expired",
    "reason": "Service period ended"
  }
}

batch.status_changed

Fired when a batch transitions through the production pipeline.

View payload example
{
  "event": "batch.status_changed",
  "timestamp": "2026-03-27T10:30:00Z",
  "data": {
    "batch_id": "uuid",
    "previous_status": "in_production",
    "new_status": "qc_pending",
    "quantity": 500
  }
}

order.status_changed

Fired when an order status changes (confirmed, shipped, delivered, etc.).

View payload example
{
  "event": "order.status_changed",
  "timestamp": "2026-03-27T10:30:00Z",
  "data": {
    "order_id": "uuid",
    "previous_status": "processing",
    "new_status": "shipped",
    "tracking_number": "1Z999AA1234567890"
  }
}

member.invited

Fired when a new member is invited to a company.

View payload example
{
  "event": "member.invited",
  "timestamp": "2026-03-27T10:30:00Z",
  "data": {
    "company_id": "uuid",
    "email": "new.member@example.com",
    "role": "operator",
    "invited_by": "user-uuid"
  }
}
Webhooks | TAGVU Developers