Skip to main content

Documentation Index

Fetch the complete documentation index at: https://developer.trackpilots.com/llms.txt

Use this file to discover all available pages before exploring further.

πŸ“‘ Reseller WebhooksReseller webhooks deliver real-time tracking events from all your child organisations to a single endpoint β€” giving you a unified event stream across your entire reseller network.

πŸ“Œ Overview

The Webhook page lets you configure webhook endpoints to receive tracking events from every organisation under your reseller account. It also includes a Live Desktop Event Feed β€” a real-time stream that lets you monitor incoming events directly in the dashboard without any external tooling. πŸ‘‰ Direct link: https://app.trackpilots.com/resellers/webhook

βž• Create a Webhook

  1. Go to Resellers β†’ Webhook
  2. Click Add Webhook
  3. Fill in the form:
FieldDescriptionRequired
Webhook NameA friendly name to identify this webhookβœ… Yes
Webhook URLYour HTTPS endpoint (e.g. https://yourdomain.com/reseller/events)βœ… Yes
EventsAt least one event type to subscribe toβœ… Yes
  1. Click Create Webhook
πŸ”’ HTTPS RequiredOnly public HTTPS URLs are accepted. Localhost, private IPs (10.x, 192.168.x, 172.16–31.x), and HTTP URLs are rejected for security reasons.

✏️ Edit a Webhook

Click the edit icon (✏️) on any webhook card to open the edit modal. You can update the webhook name, URL, and subscribed events. Click Update Webhook to save changes.

πŸ“‘ Supported Events

Subscribe to one or more of the following desktop tracking events:
Event NameTrigger
desktop.app_tracking.capturedFired when app/website usage is tracked on an employee’s desktop
desktop.screenshot_tracking.capturedFired when a screenshot is captured from an employee’s desktop
desktop.activity_tracking.capturedFired when an employee’s work mode or privacy mode status changes
Each event is delivered as a signed POST request to your webhook URL with the full event payload and security headers.

πŸ” Webhook Secret

Every webhook is assigned a unique secret key used to sign outgoing payloads. The secret is:
  • Partially masked in the UI (first8charsβ€’β€’β€’β€’β€’β€’β€’β€’β€’β€’β€’β€’β€’β€’β€’β€’β€’β€’β€’β€’β€’β€’β€’β€’)
  • Copyable via the πŸ“‹ copy button
  • Used to verify the x-webhook-signature header on incoming requests
See the Webhooks guide for the full HMAC SHA256 signature verification flow.

πŸ“‹ Webhook Card Fields

FieldDescription
Webhook NameDisplay name
Webhook URLEndpoint that receives events
Subscribed EventsBadge list of event types
SecretMasked API secret with copy button
CreatedDate the webhook was created

πŸ§‘β€πŸ’» Sample Webhook Receiver (Node.js + Express)

Below is the exact receiver implementation for the reseller webhook endpoint.
⚠️ Different from Standard WebhooksThe reseller webhook uses express.json() (parsed JSON body) β€” not express.raw(). The signature is computed against JSON.stringify(req.body), not the raw buffer. Using the wrong body type will cause all signature checks to fail.
import express from "express";
import crypto from "crypto";

const app = express();

// πŸ”” Reseller Webhook Endpoint
app.post(
  "/webhooks/reseller",
  express.json({ limit: "50mb" }),
  (req, res) => {
    try {
      // πŸ” Reseller webhook secret (set in your environment variables)
      const webhookSecret = process.env.RESELLER_WEBHOOK_SECRET;
      if (!webhookSecret) {
        console.error("❌ RESELLER_WEBHOOK_SECRET env var is not set");
        return res.status(500).send("Webhook secret not configured");
      }

      // Read signature headers
      const signature = req.headers["x-webhook-signature"];
      const timestamp = req.headers["x-webhook-timestamp"];
      if (!signature || !timestamp) {
        return res.status(400).send("Missing signature");
      }

      // πŸ” Build the payload string for signing
      // Note: sign against JSON.stringify(req.body), not the raw buffer
      const payloadToSign = `${timestamp}.${JSON.stringify(req.body)}`;

      const expectedSignature = crypto
        .createHmac("sha256", webhookSecret)
        .update(payloadToSign)
        .digest("hex");

      // πŸ›‘ Verify using constant-time comparison (prevents timing attacks)
      if (
        !crypto.timingSafeEqual(
          Buffer.from(signature, "hex"),
          Buffer.from(expectedSignature, "hex"),
        )
      ) {
        return res.status(401).send("Invalid signature");
      }

      // βœ… Verified β€” process the event
      const event = req.body;
      console.log("🎯 Verified Reseller Event:", JSON.stringify(event, null, 2));

      // Handle event types
      switch (event.event) {
        case "desktop.app_tracking.captured":
          // process app tracking data
          break;
        case "desktop.screenshot_tracking.captured":
          // process screenshot data
          break;
        case "desktop.activity_tracking.captured":
          // process work mode / privacy mode change
          break;
        default:
          console.log("Unknown event type:", event.event);
      }

      return res.status(200).json({ received: true });
    } catch (error) {
      console.error("❌ [Reseller Webhook] error:", error);
      return res.status(500).send("Webhook processing failed");
    }
  },
);

app.listen(3000, () => {
  console.log("πŸš€ Reseller webhook server running on http://localhost:3000");
});

πŸ” Signature Verification Formula

HMAC_SHA256(timestamp + "." + JSON.stringify(body), RESELLER_WEBHOOK_SECRET)
ComponentValue
timestampValue of the x-webhook-timestamp header
bodyThe parsed JSON request body
RESELLER_WEBHOOK_SECRETYour webhook secret (from the Reseller Webhook card)
Store the secret in an environment variable β€” never hardcode it in your source code.

πŸ—‘οΈ Delete a Webhook

Click the delete icon (πŸ—‘οΈ) on a webhook card, then confirm in the modal. Deletion is immediate and permanent β€” no further events will be delivered to that endpoint.

πŸ“Ί Live Desktop Event Feed

The Live Desktop Event Feed is a real-time dashboard panel that streams incoming tracking events from all your reseller organisations as they happen.
⚑ Real-Time via Socket.IOEvents are pushed over a persistent WebSocket connection. No page refresh is needed β€” new events appear instantly as they arrive from employee desktops across your organisations.
The feed only appears when at least one event type is configured in a webhook.

πŸ”Œ Connection Status

The top-right of the feed header shows:
BadgeMeaning
🟒 ConnectedWebSocket is live and receiving events
⚫ DisconnectedConnection lost β€” events are not streaming
πŸ”΄ LiveFeed is actively listening

πŸ—‚οΈ Event Tabs

Tabs are shown only for event types you have subscribed to in your webhooks:
TabColorEvent Type
Tracking EventπŸ”΅ Bluedesktop.app_tracking.captured
Screenshot Event🟠 Orangedesktop.screenshot_tracking.captured
Activity Event🟒 Greendesktop.activity_tracking.captured
The badge on each tab shows the total number of events received in that session.

πŸ“‹ Event Cards (Left Panel)

The left panel shows the latest 10 events for the selected tab. Each event card displays:
FieldDescription
Parent Organisation NameName of your reseller parent account
Reseller Organisation NameName of the child organisation that generated the event
UserIdID of the employee whose desktop sent the event
TeamIdID of the team the employee belongs to
TimestampExact date/time the event was received
Relative timeHuman-readable age (e.g. β€œ3 sec ago”, β€œ2 min ago”)
PayloadFull JSON event payload in a scrollable code block
Every ID field has a πŸ“‹ copy button for quick clipboard access. New Event Highlight: The most recently received card shows a β€œNew Event” badge (replacing the event type label) with a colored border highlight. Both disappear automatically after 3 seconds.

🌊 Live Pool (Right Panel)

The Live Pool is a chronological log of all incoming events across all tabs (max 30 entries). Each entry shows:
  • Event type with color-coded dot
  • Organisation name
  • Timestamp + relative time
  • β€œNew Event” badge on the far right for the most recent entry (disappears after 3 seconds)
Pause / Resume: Click the ⏸️ pause button to stop new entries from appearing in the pool (events still arrive in the background). Click ▢️ resume to restart live updates.

πŸ”” Toast Notifications

When a new event arrives, a toast notification appears in the top-right of the feed for 3 seconds showing:
  • Event type icon and name
  • Organisation name
  • Exact timestamp + relative time

βœ… Summary

FeatureDescription
Create webhookConfigure a URL + events to receive
Edit webhookUpdate name, URL, or subscribed events
Copy secretOne-click copy for HMAC signature verification
Live Event FeedReal-time stream of events from all organisations
Event tabsFilter feed by tracking / screenshot / activity
Event cardsFull event detail with copy buttons for all IDs
Live PoolCross-type chronological event log
Pause/ResumeControl live feed updates
New Event badgeVisual highlight for the latest event (auto-dismisses in 3s)

πŸ§ͺ Test Your Webhook Before Going LiveUse the built-in Simulations tool to send a signed test payload to your endpoint and verify it’s responding correctly before processing real events. πŸ‘‰ Reseller Simulations