Skip to content

Webhooks

A webhook sends tracker events to your server as they happen. For example, push each new conversion into your CRM at once, or send alerts to an on-call chat. Tab: Automation → Webhooks.

Webhooks tab with the list of subscriptions and the Add button
  1. Add webhook — opens the form with URL, events and secret.
Field What to enter
Target URL A public HTTPS address of your server. Local and private addresses are blocked.
Events One or more items from the list below.

The system generates the secret. It is shown once, right after creation. Copy it then. If it is lost, use “Rotate secret”: the old secret stops working immediately.

Event When it is sent
Conversion (conversion) A conversion was created or updated, for example a lead became a sale.
Offer disabled (offer_disabled) The system disabled an offer: failed health checks or a CR drop.
Domain banned (domain_banned) A domain was blocked and traffic moved to another domain.
Alert fired (alert_fired) An alert rule fired.
POST /your/endpoint HTTP/1.1
Content-Type: application/json
X-Webhook-Event: conversion
X-Webhook-Signature: 3f9a…c1d2
{"event":"conversion","data":{...},"timestamp":"2026-10-13T09:15:00.000Z"}

data fields per event:

  • conversion: conversionId, status, payout, currency, clickToken, offerId, isNew.
  • offer_disabled: offerId, name, reason, source (health_check or cr_threshold).
  • domain_banned: domainId, domain, reason, rotatedTo.
  • alert_fired: ruleName, metric, operator, threshold, value, sampleSize, scope, dimensionValue, action, firedAt.

X-Webhook-Signature is the HMAC-SHA256 of the raw request body, using your secret, as lowercase hex, with no prefix.

Compute the signature over the body exactly as it arrived, not over JSON you parsed and re-serialized. Whitespace and key order change the signature.

import crypto from 'node:crypto';
import express from 'express';
const SECRET = process.env.TG_WEBHOOK_SECRET;
const app = express();
// You need the raw body, so use express.raw, not express.json.
app.post('/telegfy', express.raw({ type: 'application/json' }), (req, res) => {
const expected = crypto.createHmac('sha256', SECRET).update(req.body).digest('hex');
const received = req.get('X-Webhook-Signature') ?? '';
const ok =
received.length === expected.length &&
crypto.timingSafeEqual(Buffer.from(received), Buffer.from(expected));
if (!ok) return res.status(401).end();
const event = JSON.parse(req.body.toString('utf8'));
// process idempotently: see "Retries" below
res.status(200).end();
});
  • A request counts as delivered when your server answers 2xx within 5 seconds.
  • Otherwise it is retried after 1, 5, 15 and 60 minutes. 5 attempts in total; after that the delivery is marked as failed.
  • A retry can arrive after you already processed the event (for example, when the response was lost on the network). Process events idempotently, for example by the key event + conversionId or event + ruleName + firedAt.

Owners, admins and editors create, change and delete webhooks. Viewers see the list.

/api/v1/webhooks — user session (JWT) only. API keys are not allowed. The secret is returned once, on creation and on rotation.