Webhooks

Receive real-time notifications for fingerprint events.

Webhooks are available on Builder plans and above. See Pricing to upgrade.

Overview

Configure webhooks to receive HTTP POST notifications when fingerprint events occur in real time — without polling the API.

Event Types

EventDescription
visit.newA device is identified for the first time
visit.returningA previously seen device visits again
visit.flaggedA visit triggered one or more risk factors
threat.detectedBot probability exceeded 0.7 on a visit

Webhook Payload

All events share the same payload structure. The event field identifies the type.

json
{ "event": "visit.returning", "timestamp": 1712000003000, "data": { "visitorId": "iq_01hns3k6tez83695a6t714s6n1", "visitCount": 5, "botProbability": 0.05, "country": "US", "riskFactors": [] } }

Payload Fields

event string

The event type. One of visit.new, visit.returning, visit.flagged, or threat.detected.

timestamp number

Unix timestamp (milliseconds) when the event occurred on the FingerprintIQ edge.

data object

Event data specific to the fingerprint event.

Signature Verification

All webhook deliveries include an X-FIQ-Signature header containing an HMAC-SHA256 signature computed over the raw request body. Always verify this signature before processing the event.

import crypto from 'crypto';

function verifyWebhook(rawBody, signature, webhookSecret) {
  const expected = crypto
    .createHmac('sha256', webhookSecret)
    .update(rawBody)
    .digest('hex');

  // Use timingSafeEqual to prevent timing attacks
  return crypto.timingSafeEqual(
    Buffer.from(signature, 'hex'),
    Buffer.from(expected, 'hex')
  );
}

// Express example
app.post('/webhooks/fingerprintiq', express.raw({ type: 'application/json' }), (req, res) => {
  const sig = req.headers['x-fiq-signature'];
  if (!verifyWebhook(req.body, sig, process.env.FIQ_WEBHOOK_SECRET)) {
    return res.status(401).send('Invalid signature');
  }
  const event = JSON.parse(req.body);
  // handle event
  res.status(200).send('OK');
});

Always use crypto.timingSafeEqual (Node.js) or crypto.subtle (Web Crypto) for signature comparison. A simple string comparison (===) is vulnerable to timing attacks that can leak your webhook secret.

Delivery and Retries

FingerprintIQ delivers webhooks with the following guarantees:

  • Deliveries time out after 5 seconds — your endpoint must respond within this window
  • Events are retried up to 3 times with exponential backoff (1s, 5s, 25s) on non-200 responses or timeouts
  • Respond with 2xx as quickly as possible and process the event asynchronously (e.g., push to a queue)

Return a 200 OK immediately and process webhook events in a background job or queue. This prevents timeouts if your processing logic involves database writes or external API calls.

Ask a question... ⌘I