Gareth Wilson Gareth Wilson

Guide to Document360 Webhooks: Features and Best Practices

Published


Document360 webhooks send knowledge base activity to your own systems. When an article is published, a category is deleted or a workflow status changes, a webhook notification channel can send the event to your service, so you can purge a content cache, start a review workflow in another tool, or keep an audit trail outside Document360.

This guide covers how webhook channels and notification mapping fit together, how to authenticate requests with a secret header, what the payloads look like, and the practices that make a Document360 receiver dependable.

What are Document360 webhooks?

Document360 sends notifications through channels, such as email, Slack, Microsoft Teams and Webhook. Setting one up takes two steps:

  1. Create a Webhook notification channel with your URL, method and headers.
  2. Under Notification mapping, turn on the events you want and map them to the channel.

A channel with no mapped events sends nothing. All events are off by default, and Document360 notes that "enabling a toggle without a mapped channel will not deliver notifications".

Document360 doesn't sign webhook requests. To tell a real request from a forged one, add a secret header to the channel and check it on your side.

Document360 webhook features

FeatureDetails
ConfigurationSettings > Knowledge base portal > Notifications > Channels > New channel > Webhook
Event mappingNotifications > Notification mapping, Owner or Admin role
MethodPOST or PUT, chosen per channel
FormatJSON, with display-label keys such as "Article name"
Custom headersKey-value pairs
Authorization key fieldHeader name not documented
EventsAbout 200, grouped into modules
Signature and timestampNone
HistoryA Notification history tab
Retries, timeout, source IPsNot documented

Events and payloads

The Notification mapping tab groups events into modules: Documentation editor, Drive, Knowledge base portal settings, Knowledge base site settings, Knowledge base widget settings, Users & security settings, Tools settings, Knowledge base site, AI notifications, Analytics, and All comments notification. You can turn on everything, a whole module, or individual events, then map them to one or more channels.

Some commonly used events:

ModuleEvents
Documentation editorArticle created, Article published, Article deleted, Article settings updated, Article slug updated, Article workflow status updated, Category created, Category published, Category deleted
DriveFolder added, Folder renamed, Folder deleted, File(s) added, File(s) updated, File(s) deleted
Knowledge base portal settingsWorkspace created, Workspace updated, Workspace deleted, Notification channel deleted

The payload is JSON, and its keys are display labels with spaces. This is Document360's example for a deleted article:

{
  "Knowledge base name": "My Knowledge Base",
  "Event": "Article deleted",
  "User": "John Doe",
  "User email": "johndoe@example.com",
  "Logged on (UTC)": "02/13/2026 10:57:16",
  "Article name": "Getting Started Guides",
  "Article id": "24a4e58a-9d64-453c-8f00-4159eb94b82e",
  "Language": "English",
  "Project version id": "0644e0fe-2ae1-4d16-a993-98b81524d5c4",
  "Language code": "en",
  "Slugs": [
    { "language": "en", "slug": "getting-started" },
    { "language": "fr", "slug": "demarrer" },
    { "language": "de", "slug": "erste-schritte" }
  ]
}

A few details to plan for:

  • Event holds the event's display name. Fields that don't apply to an event are left out, and non-article events carry their own fields, such as Extension, Widget setting name or Folder name.
  • Logged on (UTC) isn't ISO 8601. The example above puts the month first, so parse it with an explicit MM/DD/YYYY HH:mm:ss format.
  • Slugs, on delete events, lists the article's slug in every language, which is what you need to purge a cache.
  • The docs' other sample payload names its event "Article settings saved", while the event list calls it "Article settings updated". Match event names against real deliveries, not the docs.

Inspect Document360 webhooks as they arrive. Point a Webhook channel at a Hookdeck Inspect URL to see each event's exact headers and body, with no account or setup required.

Setting up Document360 webhooks

Choose a header name and a long random value first, for example Authorization and Bearer followed by the output of openssl rand -hex 32.

  1. Go to Settings > Knowledge base portal, select Notifications, and on the Channels tab click New channel.
  2. Select Webhook.
  3. Enter a Friendly name, such as Cache-ArticleDeletes.
  4. Choose a Request method, POST or PUT.
  5. Enter your HTTPS endpoint in Webhook URL, and choose the Request content format.
  6. Click Add under Authorization key and add your header as a key-value pair. Document360 doesn't say which header its separate Authorization key field fills in, so use a key-value header you name yourself.
  7. Click Save.
  8. Open the Notification mapping tab, turn on the events you need, and map them to the channel with Map to channel.

To route through Hookdeck, create a source with the Document360 type and use its URL as the webhook URL. Enter the header's name in API Key Header and its exact value, including any Bearer prefix, in API Key. The source has POST selected, so if you chose PUT on the channel, allow PUT in the source's allowed HTTP methods as well.

Securing Document360 webhooks

Read the header you added, case-insensitively, and compare its whole value with the one you stored, in constant time. Accept both methods if you're not sure which one the channel uses.

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

const HEADER = (process.env.DOCUMENT360_WEBHOOK_HEADER || 'Authorization').toLowerCase();
const SECRET = process.env.DOCUMENT360_WEBHOOK_SECRET; // the exact, whole header value

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

function handleDocument360(req, res) {
  const received = req.get(HEADER);
  if (!SECRET || typeof received !== 'string' || !safeEqual(received, SECRET)) {
    return res.sendStatus(401);
  }

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

  // event['Event'] is the display name, e.g. "Article deleted".
  res.sendStatus(200);
}

const app = express();

app
  .route('/webhooks/document360')
  .post(express.raw({ type: '*/*' }), handleDocument360)
  .put(express.raw({ type: '*/*' }), handleDocument360);

The same check in Python:

import hmac
import os

HEADER = os.environ.get("DOCUMENT360_WEBHOOK_HEADER", "Authorization")
SECRET = os.environ.get("DOCUMENT360_WEBHOOK_SECRET", "")


def verify_document360_request(headers) -> bool:
    if not SECRET:
        return False  # fail closed when unconfigured
    received = headers.get(HEADER)  # Starlette and Flask headers are case-insensitive
    if not received:
        return False
    # Compare bytes: compare_digest raises TypeError on a non-ASCII str.
    return hmac.compare_digest(received.encode("utf-8"), SECRET.encode("utf-8"))

A static header authenticates the sender, not the body. It can't detect a modified payload, and with no signed timestamp a captured request can be replayed and still pass. Serve the endpoint over HTTPS only, use a long random value, and replace it on the channel and in your receiver if it might have leaked.

Make Document360 webhooks production-ready. Hookdeck Event Gateway checks your secret header on every Document360 event, stores each one durably, and lets you replay any delivery after a fix.

Document360 webhook limitations and pain points

No signature

The Problem: Anyone who learns the header value can send convincing events, and a changed body goes unnoticed.

Why It Happens: Document360 computes nothing over the body. The header you add is sent unchanged on every request.

Workarounds:

  • Use a long random value, HTTPS only, and keep the header out of your logs.
  • Before a destructive action, such as purging content, confirm the change through the Document360 API or portal.

How Hookdeck Can Help: Hookdeck's Document360 source compares the header you name with the exact value you enter. Hookdeck answers Document360 with a 200 either way, but a request with a missing or wrong value is recorded as failed verification and never reaches your destination.

Events stop without warning

The Problem: Notifications you relied on stop arriving.

Why It Happens: Deleting a channel means "any events mapped to it silently stop delivering". An event switched on without a mapped channel never sends anything, and some actions don't fire the event you'd expect: an article created through Word import doesn't send Article created.

Workarounds:

  • Map the Notification channel deleted event to a channel you watch.
  • After changing mappings, check the Notification history tab.

How Hookdeck Can Help: Hookdeck's request log shows when events last arrived from Document360, and Hookdeck issues can notify you about failed deliveries to your service.

Delivery behaviour is undocumented

The Problem: You can't tell whether an event sent during your outage will arrive later.

Why It Happens: Document360 doesn't document a timeout or retry policy for webhook channels.

Workarounds:

  • Respond with 200 as soon as the header checks out, and do the work afterwards.
  • After an outage, review the Notification history and re-sync from the API.

How Hookdeck Can Help: Hookdeck accepts each event as soon as it arrives, stores it, and delivers it to your service with retries you configure, so a short outage on your side doesn't depend on Document360 retrying.

Display-label payloads

The Problem: Parsers break on keys with spaces, a field is missing, or a date is read the wrong way round.

Why It Happens: Keys are labels like "Logged on (UTC)", fields vary by event, and the date format puts the month first.

Workarounds:

  • Map the payload to your own field names in one place, and treat every field except Event as optional.
  • Parse dates with an explicit format.

How Hookdeck Can Help: Hookdeck transformations can rename keys and normalise dates before events reach your service, and filters can route events by their Event value.

Best practices

Scope channels by purpose

Document360 recommends scoping each channel to a focused set of events. A channel for cache purges and another for workflow automation are easier to debug than one channel for everything.

Store the full header value

Keep the exact value, prefix included, as one string and compare it whole. Put the name and value in configuration, not code.

Deduplicate on the event, object and time

There is no event ID. Build a key from Event, the object's ID (such as Article id) and Logged on (UTC), and store it before acting. See our guide to webhook idempotency.

Acknowledge fast and process asynchronously

Check the header, store the event, return 200, and purge caches or call other APIs afterwards. See why to process webhooks asynchronously.

Conclusion

Document360 sends knowledge base events through a Webhook notification channel, as JSON with display-label keys, once you map events to the channel, authenticated only by a header you add. Use a key-value header you name yourself, compare it whole in constant time, accept the method your channel uses, and watch for channels being deleted, which stops their events without warning.

Hookdeck Event Gateway sits in front of your receiver, checks the header, and keeps every event until your service has processed it.

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