Gareth Wilson Gareth Wilson

Guide to Tanium Webhooks: Features and Best Practices

Published


Tanium webhooks are how endpoint data leaves Tanium Cloud for the rest of your stack. Tanium Connect can take the answer to a saved question, client status or an event and send it to an HTTP endpoint on a schedule, on demand or when the event fires. Security and IT teams use it to feed a SIEM, a data lake, a CMDB or their own automation with what Tanium knows about every endpoint.

This guide covers how Connect HTTP destinations work, what the request looks like, how to authenticate it with Header Authentication, the method, batching and network settings that trip people up, and the practices that make a Tanium receiver dependable.

What are Tanium webhooks?

In Tanium Connect, a connection pairs a source with a destination. The source decides what data is sent: usually information from Tanium such as a saved question, question log, client status or event. With an HTTP destination, Connect sends that data to a REST endpoint you specify, with the URL, method, headers and authentication you configure.

There's no fixed payload and no Tanium event type. The body is the source's rows, with the columns you choose, relabelled and typed as you like, in JSON by default or another Connect format. A connection runs on a schedule, when you run it manually, or, for an Event source, whenever the configured event is detected.

Tanium does not sign HTTP destination requests. The destination's Use Authentication setting offers several methods, and Header Authentication is the one built for a receiver you control: you choose an Auth Header Name and a Secret, and Connect sends that header on every request.

Tanium webhook features

FeatureDetails
ConfigurationModules > Connect > Overview > Connections > Create Connection, destination HTTP
SourcesSaved question, question log, client status, event and others
TriggersCron schedule, manual run, or an Event source with Listen for this Event
URLHTTPS only. The TLS certificate is validated, with optional Trust on First Use
MethodChosen from a Method drop-down. Batched sends are described as POST requests
HeadersAny extra headers with + Add Header, for example Content-Type: application/json
AuthenticationNone, Basic Authentication, OAuth2 Client Credentials, Header Authentication, IBM Cloud IAM API Key
Signature and timestampNone
FormatJSON by default, or another Connect format. Form data isn't supported
BatchingBy records or bytes, creating several requests. A batch size of 0 sends one request
TimeoutConfigurable per destination, in seconds
NetworkEgress allow list rule per destination FQDN and port. Two proxy IPs per Tanium Cloud instance
RetriesNot documented
LogsThe connection's Logs tab, with a row per run

Payloads

Because the source and columns are yours, Tanium has no event list to document. A saved-question source sending JSON produces rows keyed by the column labels you set in Configure Output > Columns. A body might look like this, although the exact shape depends on your format settings:

[
  {
    "Computer Name": "host-1.example.com",
    "IP Address": "10.0.0.5",
    "Operating System": "Windows Server 2022"
  }
]

You can change each column's Destination Label and force its Value Type to String, Numeric or Date/Time, with a default for numbers that can't be coerced and a format for dates. Use that to give your receiver stable, machine-friendly field names rather than display labels with spaces.

Tanium's own receiver examples, in Node.js, Python and Ruby, accept a POST with a JSON body and save it to a file. They're a reminder that the receiver only has to accept the data and answer quickly.

Inspect Tanium Connect requests as they arrive. Point an HTTP destination at a Hookdeck Inspect URL and click Run and Save to see exactly what your connection sends, with no account or setup required.

Setting up Tanium webhooks

Before a connection can reach your endpoint, add a network egress allow list rule for the destination's FQDN and port in your Tanium Account. If the endpoint is inside your network, allow inbound traffic from your Tanium Cloud instance's two proxy IP addresses. Pick a header name and a long random secret, for example X-Webhook-Secret with the output of openssl rand -hex 32.

  1. Go to Modules > Connect > Overview, find Connections and click Create Connection. Enter a name and description.
  2. Configure the source. You can't change the source type after the connection is created.
  3. Select HTTP as the destination and create a New destination with a unique name. Tanium recommends one destination per connection, because editing a shared destination affects every connection that uses it.
  4. Enter your HTTPS URL and choose the Method.
  5. Under Use Authentication, choose Header Authentication and enter your Auth Header Name and Secret.
  6. Optionally expand Advanced to set a batch size and a timeout.
  7. Configure filters, the format and columns, then a schedule or Listen for this Event.
  8. Click Save, or Run and Save to send immediately, and check the Logs tab.

With Hookdeck. Create a Hookdeck source with the Tanium type and use its URL as the destination URL. Enter the API Key Header (your Auth Header Name) and the API Key (your Secret) exactly as you set them, including any prefix. The source compares the whole value.

The Tanium source pre-selects POST but doesn't manage the method, because Connect lets you choose it. If your destination uses a method other than POST, such as PUT, allow that method on the Hookdeck source as well, or requests with it won't be accepted. Basic Authentication, OAuth2 Client Credentials and IBM Cloud IAM aren't covered by Hookdeck's Tanium source.

Securing Tanium webhooks

Look up your Auth Header Name case-insensitively and compare the whole value with your Secret, in constant time. Don't assume the method is POST: accept whichever method you chose on the destination.

const crypto = require('crypto');
const express = require('express');

const HEADER = (process.env.TANIUM_WEBHOOK_HEADER || 'X-Webhook-Secret').toLowerCase();
const EXPECTED = process.env.TANIUM_WEBHOOK_SECRET;

function safeEqual(received, expected) {
  const a = Buffer.from(received, 'utf8');
  const b = Buffer.from(expected, 'utf8');
  // timingSafeEqual throws on unequal lengths, so check first.
  return a.length === b.length && crypto.timingSafeEqual(a, b);
}

const app = express();

// Match the Method you chose on the destination.
app.all('/webhooks/tanium', express.raw({ type: '*/*', limit: '10mb' }), (req, res) => {
  if (!['POST', 'PUT', 'PATCH'].includes(req.method)) {
    return res.sendStatus(405);
  }

  const received = req.headers[HEADER]; // Node lower-cases header names
  if (!EXPECTED || typeof received !== 'string' || !safeEqual(received, EXPECTED)) {
    return res.sendStatus(401);
  }

  let rows;
  try {
    rows = JSON.parse(req.body.toString('utf8'));
  } catch {
    return res.sendStatus(400);
  }

  // rows is usually an array of objects keyed by your column labels.
  res.sendStatus(200);
});

The same check in Python:

import hmac
import os


def verify_tanium_request(headers) -> bool:
    secret = os.environ.get("TANIUM_WEBHOOK_SECRET")
    if not secret:
        return False  # never accept when unconfigured
    name = os.environ.get("TANIUM_WEBHOOK_HEADER", "X-Webhook-Secret")
    received = headers.get(name)  # case-insensitive in Starlette and Flask
    if not received:
        return False
    return hmac.compare_digest(received.encode("utf-8"), secret.encode("utf-8"))

A static header proves the sender knows the secret. It does not cover the body, and there is no timestamp, so a captured request can be replayed and still pass. Connect already requires HTTPS. Use a long random secret, and change it on the destination and in your environment together if it might have leaked.

Make Tanium webhooks production-ready. Hookdeck Event Gateway checks your Header Authentication value on every request, stores every batch durably, and delivers to your service at a rate it can handle.

Tanium webhook limitations and pain points

No documented retries

The Problem: If your endpoint is unavailable during a scheduled run, you can't rely on Connect to try that data again later.

Why It Happens: The HTTP destination page documents a timeout, but not retries or what counts as success. Connections scheduled during a Tanium Cloud maintenance window can also be interrupted or fail.

Workarounds:

  • Check the connection's Logs tab after any incident, and run the connection again manually if needed.
  • Schedule connections outside the Tanium Cloud maintenance window.

How Hookdeck Can Help: Hookdeck accepts and stores each request as soon as it arrives, then delivers to your service with retries you configure. Any batch that failed can be replayed without re-running the connection.

Large bursts from big sources

The Problem: A saved question across thousands of endpoints produces a large body, or a rapid series of batched requests, that can overwhelm a small receiver.

Why It Happens: With a batch size of 0, Connect sends everything in one request. With batching, it sends one request per batch until all the data is sent, and a single record larger than the byte limit still goes in full.

Workarounds:

  • Set a batch size so each request stays within your server's body limit.
  • Raise the body size limit on your receiver to match.

How Hookdeck Can Help: Hookdeck can deliver batches to your service with a max delivery rate, so a large run arrives at a pace your service can absorb.

Method and network mismatches

The Problem: A connection fails with every request, even though the URL and secret are right.

Why It Happens: The method on the destination doesn't match what the receiver accepts, or the destination FQDN and port aren't in your network egress allow list. A destination missing from the allow list shows a warning in Connect.

Workarounds:

  • Choose POST unless your receiver needs something else, and make the receiver accept the method you chose.
  • Add an egress allow list rule for every destination FQDN and port.

How Hookdeck Can Help: Hookdeck logs every request it receives, so you can tell a request that never arrived (an egress problem) from one that arrived with an unexpected method or header.

No event type or delivery ID

The Problem: Several connections sending to one endpoint are hard to tell apart, and a re-run sends the same rows again.

Why It Happens: The body is the source's rows. Tanium adds no event type, run ID or delivery ID to it.

Workarounds:

  • Give each connection its own endpoint path or its own destination header.
  • Upsert by a stable column, such as the computer name or ID, rather than appending.

How Hookdeck Can Help: Use one Hookdeck source per connection, or filters on the columns each connection sends, to route data to the right destination.

Best practices

Use one destination per connection

Tanium recommends it, and it keeps headers, secrets and methods from changing under another connection when you edit one.

Relabel columns for machines

Set Destination Label values such as computer_name and force Value Type where it matters, so your receiver gets stable keys and types.

Treat each run as a snapshot

Write rows as the current state of each endpoint, keyed by a stable identifier, so re-runs and repeated batches are harmless. See our guide to webhook idempotency.

Acknowledge fast and process asynchronously

Verify the header, store the body, respond within your destination's timeout, and load the rows from a background job. See why to process webhooks asynchronously.

Conclusion

Tanium Connect sends the rows of a saved question, event or other source to an HTTP destination with the method, headers and format you choose, unsigned and with no Tanium-defined event type. Use Header Authentication with a long random secret and compare it whole in constant time, make sure your receiver and any Hookdeck source accept the method you picked, set a batch size, and add the destination to your egress allow list.

Hookdeck Event Gateway checks the header, keeps every batch, and paces, retries and replays delivery to your service.

Get started with Hookdeck for free and handle Tanium webhooks reliably in minutes.


Gareth Wilson

Gareth Wilson

Product Marketing

Multi-time founding marketer, Gareth is PMM at Hookdeck and author of the newsletter, Community Inc.