Skip to content

Configure webhooks

Webhooks send HTTP POST requests to your server when events happen in your Topicary project, for example, when a topic is published or a publication target goes live. Use webhooks to trigger CI/CD pipelines, sync external systems, or build custom notifications.

Before you begin

This feature requires the Enterprise capability tier (the Business ). During the beta, every project is on the free Solo tier, so this feature is locked by default: go to Settings ▸ Billing and request Enterprise access to unlock it.

Only project members with the Admin can configure this feature. Authors and Reviewers do not have access to these settings.

Create a webhook

  1. Go to Settings in the sidebar.

  2. Open the Webhooks tab.

  3. Click Add Webhook.

  4. Enter the endpoint URL, the HTTPS URL where Topicary will send events.

  5. Select one or more event types from the list below.

  6. Click Create.

Topicary generates a signing secret for the webhook automatically. Copy it, you will need it to verify incoming requests.

Event types

Event

Fires when

topic.created

A topic is created

topic.updated

A topic's content or metadata changes

topic.published

A topic's status becomes Published (from any surface)

topic.deleted

A topic is deleted

topic.status_changed

A topic's status changes (Draft, Review, Published)

component.created

A component is created

component.updated

A component's content changes

component.deleted

A component is deleted

map.published

A publication target is published

map.unpublished

A publication target is unpublished

Payload format

Every webhook delivery is a POST request with a JSON body:

{
  "event": "topic.status_changed",
  "data": {
    "id": "topic_xyz789",
    "title": "Getting started",
    "status": "published"
  },
  "timestamp": "2026-06-09T14:30:00Z"
}

Request headers

Every webhook request includes the following headers:

Header

Value

Content-Type

application/json

X-Topicary-Signature

sha256=<hmac>

X-Topicary-Event

webhook

User-Agent

Topicary-Webhook/1.0

Verify signatures

Every request includes an X-Topicary-Signature header in the format sha256=<hex digest>. The hex digest is an HMAC-SHA256 signature of the raw request body using your webhook's signing secret. Verify this signature to confirm the request came from Topicary:

import crypto from "crypto";

function verifyWebhook(body, signatureHeader, secret) {
  const signature = signatureHeader.replace("sha256=", "");
  const expected = crypto
    .createHmac("sha256", secret)
    .update(body)
    .digest("hex");
  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expected)
  );
}

Always verify the signature before processing a webhook payload. Without verification, an attacker could send forged requests to your endpoint.

Retry behavior

If your endpoint returns a non-2xx status code or fails to respond within 10 seconds, Topicary retries the delivery. Each webhook is attempted up to 3 times total (the initial delivery plus two retries) with an exponential backoff between attempts:

Attempt

Scheduled after

Initial delivery

Immediately, when the event fires

1st retry

30 seconds after the initial failure

2nd retry

60 seconds after the 1st retry

Retries are processed by a background job, so the actual time between attempts can be slightly longer than the scheduled backoff. After the third failed attempt, the delivery is marked as failed. Check the delivery log to diagnose failures.

Delivery log

Each webhook has a delivery log showing recent requests:

  • Status: success (2xx), retrying, or failed

  • Timestamp: when the delivery was attempted

  • Response code: the HTTP status code your endpoint returned

  • Response time: how long your endpoint took to respond

Go to Settings > Webhooks, click a webhook, and open the Deliveries tab to view the log.

Rotate the signing secret

If a signing secret is compromised:

  1. Go to Settings > Webhooks and select the webhook.

  2. Click Rotate Secret.

  3. Update your endpoint to use the new secret.

After rotation, the old secret is immediately invalid. Update your verification code before rotating, or expect a brief window of failed signature checks.


See also

Was this page helpful?