Gareth Wilson Gareth Wilson

Guide to Nexthink Webhooks: Features and Best Practices

Published


Nexthink webhooks push data out of Nexthink when something happens on your employees' devices. When an alert fires or an event matches a condition you define, Nexthink sends an HTTP request to a third-party tool, so you can open a ticket in your service desk, post to a chat channel, or start a workflow in your own service without anyone watching the Nexthink console.

This guide covers how Nexthink webhooks are built from credentials and templates, how to authenticate them, where they fall short, and how to receive them reliably.

What are Nexthink webhooks?

A Nexthink webhook is an outbound connector. It is closer to a configurable HTTP request than to a classic event subscription. You write the request yourself: the method, the path and the JSON body. Nexthink fills placeholders in the body from the alert or event that triggered it, and sends the request whenever the webhook's NQL condition matches.

Two objects make up the request:

  • A connector credential, created under Administration > Connector credentials, holds the instance URL (for example https://{host}:{port}/) and the authorization to send with it.
  • A webhook, created under Administration > Outbound connectors > Webhooks, holds the NQL condition, the credential to use, the method, a resource path appended to the credential's URL, and the payload template.

Nexthink does not sign these requests. The only authentication is the Authorization header that the credential produces. With the Bearer token type, that header is the Header prefix you set (usually Bearer) followed by the Token.

Nexthink webhook features

FeatureDetails
ConfigurationAdministration > Outbound connectors > Webhooks
PermissionsCentral Administrative privileges and the Integrations module
TriggerAn NQL condition matching an alert or event
MethodsPOST, PUT or PATCH, chosen per webhook
DestinationThe credential's instance URL plus the webhook's Resource path
PayloadYour own JSON template with {{variable_name}} placeholders
Event types and IDsNone defined by Nexthink
AuthenticationAuthorization header from the connector credential
Signature and timestampNone
DeliveryThrottled, so it may be delayed
Retries, timeout, delivery logNot documented; no central view of call status

The payload

Nexthink has no fixed payload and no list of event types. The body is the JSON you type into the webhook's Payload field, and the field only accepts JSON. You add placeholders from the NQL data model, and after you fill in the NQL conditions the page lists the Allowed placeholders for that webhook. For example, {{alert.monitor.name}} is the monitor's name and {{alert.alert.trigger_time}} is when the alert fired. Adding .as(format = text) makes values such as remote action outputs readable.

A template for alert notifications might look like this:

{
  "source": "nexthink",
  "type": "alert",
  "monitor": "{{alert.monitor.name}}",
  "triggered_at": "{{alert.alert.trigger_time}}"
}

Every field name here is your choice. Nexthink adds no event field, so if your receiver needs to tell one webhook from another, put a field like type in each template, or give each webhook its own Resource path.

Two documented behaviours affect how you parse the body. When a placeholder has an empty or invalid value, Nexthink cannot replace it and sends the literal {{variable_name}} text. And Send Test does not replace placeholders at all, so test requests carry the raw template.

See exactly what your template produces. Point a Nexthink credential at a Hookdeck Inspect URL and use Send Test to see the method, headers and body Nexthink sends, with no account or setup required.

Setting up Nexthink webhooks

Create a Bearer token credential

  1. Generate a long random token, for example with openssl rand -hex 32.
  2. Open Administration > Connector credentials and click New credential. If the option is missing from the menu, Nexthink says to ask its support team to enable it.
  3. Give it a name and choose Hypertext Transfer Protocol Secure (HTTPS) as the protocol.
  4. Set the URL address to your receiver's scheme and host, in the https://{host}:{port}/ format Nexthink asks for. The path goes in the webhook's Resource field instead.
  5. Choose Bearer token as the authorization type. Set Header prefix to Bearer and paste your token into Token.

Nexthink cannot test a credential when you save it. You find out whether it works when you send a test from a webhook.

Create the webhook

  1. Open Administration > Outbound connectors > Webhooks and click New webhook.
  2. Enter a Name and Description.
  3. Write the NQL Conditions that select the alerts or events to send.
  4. Select the credential you created.
  5. Choose the Method: POST, PUT or PATCH.
  6. Enter the Resource, the path Nexthink appends to the credential's URL. It can include key=value parameters and placeholders.
  7. Write the JSON Payload template.
  8. Click Send Test, then make sure the Active toggle is on.

Routing through Hookdeck

Create a Hookdeck source with the Nexthink type. Split its URL between the two Nexthink objects: the scheme and host go in the credential's URL address, and the path goes in the webhook's Resource.

The source has one field, Authorization Header. Choose the Bearer token credential type in Nexthink and paste the whole Authorization value into this field, including Bearer and the space after it, for example Bearer 3f9a.... Hookdeck compares the whole value. Basic and OAuth credential types are not covered by this source.

The source pre-selects POST as the allowed method but does not lock it. If your webhook uses PUT or PATCH, allow that method on the source as well.

Securing Nexthink webhooks

Compare the whole Authorization header with the value you expect, in constant time. Accept the methods your webhooks use, and allow an empty body.

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

// The whole header value, e.g. "Bearer 3f9a...".
const EXPECTED = process.env.NEXTHINK_AUTHORIZATION;

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();

app.all('/webhooks/nexthink', express.raw({ type: '*/*' }), (req, res) => {
  if (!['POST', 'PUT', 'PATCH'].includes(req.method)) {
    return res.sendStatus(405);
  }

  const received = req.get('authorization');
  if (!EXPECTED || typeof received !== 'string' || !safeEqual(received, EXPECTED)) {
    return res.sendStatus(401);
  }

  const raw = Buffer.isBuffer(req.body) ? req.body.toString('utf8') : '';
  let payload = null;
  if (raw.length > 0) {
    try {
      payload = JSON.parse(raw);
    } catch {
      return res.sendStatus(400);
    }
  }

  // Store the payload, then process it outside the request.
  res.sendStatus(200);
});

The same check in Python:

import hmac
import os

EXPECTED = os.environ.get("NEXTHINK_AUTHORIZATION", "")


def verify_nexthink_request(headers) -> bool:
    if not EXPECTED:
        return False  # never accept when unconfigured
    received = headers.get("authorization")
    if not received:
        return False
    # Compare bytes: compare_digest raises TypeError on a non-ASCII str.
    return hmac.compare_digest(received.encode("utf-8"), EXPECTED.encode("utf-8"))

A Bearer token proves the request came from someone who holds the token. It says nothing about the body, and with no signature or timestamp a captured request can be replayed. Keep the receiver on HTTPS, use a long random token, and if it might have leaked, put a new token in the credential and update your receiver at the same time.

Make Nexthink webhooks production-ready. Hookdeck Event Gateway checks the Authorization value on every request, records each delivery so you can see what Nexthink sent, and retries delivery to your service on your schedule.

Nexthink webhook limitations and pain points

No delivery log

The Problem: When a ticket never appears downstream, you cannot tell whether Nexthink sent the request or what came back.

Why It Happens: Nexthink's FAQ says there is currently no central place to see the status of the calls webhooks make. It recommends Send Test instead, and a test does not replace placeholders.

Workarounds:

  • Log every request your receiver gets, with headers and body.
  • Use Send Test to check the credential, method and resource, knowing the body will contain raw placeholders.

How Hookdeck Can Help: Every request to a Hookdeck source is recorded with its headers and body, so you can see each delivery as Nexthink sent it. Hookdeck answers Nexthink with a 200 either way, but a request with a missing or wrong Authorization value is recorded as failed verification and never reaches your service. Issues can notify you when deliveries to your service fail.

Retries are not documented

The Problem: If your receiver is down when an alert fires, the request may be lost.

Why It Happens: Nexthink's webhook documentation does not describe retries or a timeout.

Workarounds:

  • Keep the receiver simple and highly available, and return 200 as soon as the request is stored.
  • For alerts that matter, compare the alerts shown in Nexthink with what your receiver recorded.

How Hookdeck Can Help: Hookdeck accepts each request and stores it before forwarding, then delivers to your service with retries you configure, so your downtime does not drop alerts.

Removed credentials fail silently

The Problem: A webhook stops sending and still looks active.

Why It Happens: Nexthink's FAQ says a webhook whose credential has been removed will not process any requests and "will give a false impression that it is working".

Workarounds:

  • Delete the webhook before the credential it uses, as Nexthink recommends.
  • Alert on silence: if a receiver that normally gets traffic goes quiet, check the webhook.

How Hookdeck Can Help: Because every delivery is recorded per source, a gap in traffic is visible in the Hookdeck dashboard.

Placeholders can arrive unfilled

The Problem: Your receiver gets "{{alert.monitor.name}}" instead of a monitor name.

Why It Happens: Nexthink sends a placeholder as literal text when its value is empty or invalid, and always does so on Send Test.

Workarounds:

  • Treat any value that still starts with {{ as missing.
  • Only use placeholders listed under Allowed placeholders for the webhook's NQL condition.

How Hookdeck Can Help: A filter can hold back requests that still contain unfilled placeholders, and a transformation can replace them with null before your service sees them.

No event IDs

The Problem: You cannot tell a repeated request from a new one.

Why It Happens: Nexthink adds no ID or event type. The body only contains what your template puts in it.

Workarounds:

  • Include identifying placeholders in the template, such as the monitor name and {{alert.alert.trigger_time}}, and build an idempotency key from them. Nexthink's own PagerDuty example builds an incident key the same way, as incident_{{alert.alert.trigger_time}}.

How Hookdeck Can Help: Deduplication can drop requests whose body, or chosen fields, match one seen recently.

Throttled delivery

The Problem: Requests arrive later than the alert.

Why It Happens: Nexthink regulates how fast it sends to third-party tools so they are not overloaded, and says delivery "is not immediate and some delays may occur".

Workarounds:

  • Do not use the arrival time as the alert time. Put {{alert.alert.trigger_time}} in the template instead.

How Hookdeck Can Help: Hookdeck records when each request arrived, and you can set a max delivery rate on your side too, so a burst of alerts does not overload your service.

Best practices

Store the whole Authorization value

Keep the expected value exactly as Nexthink sends it, prefix and space included, and compare it whole. Do not strip Bearer in code.

Put a type field and an ID in every template

Since Nexthink defines neither, add your own type field to each webhook's payload, and include enough placeholders to identify the alert. That gives your receiver something to route on and to deduplicate with. See our guide to webhook idempotency.

Accept the methods you configured

If any webhook uses PUT or PATCH, make sure your receiver, and the Hookdeck source if you use one, accepts it.

Acknowledge fast and process asynchronously

Check the header, store the request, return 200, and do the work afterwards. See why to process webhooks asynchronously.

Conclusion

Nexthink webhooks are requests you design: you choose the method, the path and the JSON body, and Nexthink fills in placeholders and attaches the credential's Authorization header. That flexibility comes with gaps. There is no signature, no event ID, no documented retry policy and no delivery log. Check the whole header in constant time over HTTPS, put your own type and identifiers in each template, and treat unfilled placeholders as missing data.

Hookdeck Event Gateway checks the header, records every request, and retries delivery to your service, which gives you the delivery history Nexthink does not.

Get started with Hookdeck for free and handle Nexthink 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.