Guide

How to set up real-time alerts when a CSMS message changes a duty rate you depend on

Set up real-time alerts when a CBP CSMS message changes a duty rate on an HTS code you depend on. Built for brokers, forwarders, and importer compliance.

Updated 11 min readSkip to the worked example
Share:

TL;DR

  • Register your filed HTS catalog with Tandom Monitoring. When CBP publishes a Customs Service Message (CSMS) that cites any code in the catalog, you get a webhook within roughly 90 seconds, with the affected codes resolved against the HTSUS hierarchy and the new rate broken out from the message body.
  • CSMS messages drive every operational change inside an entry: deposit-rate flips on AD/CVD cases (CSMS 64384423 on Section 232 steel derivatives), entire layer replacements (CSMS 67834313 ending IEEPA collection in February 2026), and effective dates that move during the entry window (the April 2026 derivative-content reporting changes documented in CSMS 68253075). Missing one of these by even a day produces wrong duty.
  • CBP's own GovDelivery feed mails every CSMS to every subscriber. A typical broker registered on the AD/CVD, ACE, Trade, and Cargo Security categories sees 40 to 80 messages a week, most of which touch products the broker does not file. Filtering to your registered catalog cuts the noise to under 5 messages a week for most importers.
  • Subscribe through the Tandom Monitoring API (closed beta). Register a JSON catalog of HTS codes, AD/CVD case numbers, and country pairs; receive HMAC-signed webhooks on every match. Sample handlers in this guide route to Slack and open JIRA tickets.

The rest of this guide walks through the data model, the subscription shape, the webhook payload, and three handler patterns. Long-tail topics covered: tariff change webhook for brokers, Section 301 rate change notification, HTS code monitoring service, CBP CSMS subscription filter, tariff alert API, and Tandom Monitoring webhook.

Why CSMS, and why polling fails

CSMS is CBP's operational broadcast channel. When a Federal Register notice changes a duty rate, the FR notice establishes the legal authority, and a CSMS message tells the trade community how to file under it. The CSMS carries the new Chapter 99 codes, the effective date, the claim mechanics, and any transitional rules. Brokers do not file from FR text; they file from CSMS instructions.

The lag from FR publish to CSMS issuance ranges from same day to several weeks. Once a CSMS is out, the change is live. Three real examples drive home why a webhook beats a batch:

  • February 2025 Section 232 reset. CSMS 64384423 ("UPDATED GUIDANCE: Import Duties on Imports of Steel and Steel Derivative Products") established the terminate-all-exemptions regime under Proclamation 10896, effective 12:01 a.m. EDT March 12, 2025. Brokers who saw the message that morning could quote correctly on shipments arriving the same week. Brokers on a weekly batch missed five business days of entries.
  • February 2026 IEEPA shutdown. CSMS 67834313 ("Ending Collection of International Emergency Economic Powers Act Duties") instructed CBP to stop collecting IEEPA duties at 12:01 a.m. ET February 24, 2026, four days after the Supreme Court's decision in Learning Resources, Inc. v. Trump. Entries filed on February 24 with the IEEPA codes still attached were rejected. Operations teams that saw the CSMS published needed to flip every open template that referenced 9903.01.x, 9903.02.x, or 9903.96.01-.02 within hours.
  • April 2026 derivative-content reporting. CSMS 68253075 consolidated the post-April-6 Section 232 reporting into the 9903.82 family for steel, aluminum, and copper. Pre-April-6 lines using 9903.80, 9903.81, 9903.85, and 9903.78 stopped clearing at the consolidation date. Importers shipping any of the ~1,200 derivative HTS lines in Chapters 73, 76, 82, 83, 84, 85, and 87 had to update their classification templates the day the change went live.

The polling alternative does not work in practice. Scraping content.govdelivery.com on a cron job catches new messages, but parsing the message body to figure out which HTS codes are affected, which case numbers are touched, and what the new rate is requires resolving cited codes at varying widths against the HTSUS hierarchy and pulling structured data out of natural-language CBP prose. That is the pipeline Tandom runs centrally so every subscriber inherits the same structured extraction. Browse the structured CSMS index in the Tandom AD/CVD catalog or read the CSMS triage guide for the manual workflow.

What kinds of changes you should alert on

A useful subscription discriminates between high-signal rate flips and routine procedural notices. Tandom classifies every CSMS into one of these event types, which the webhook payload carries on a top-level event_type field:

  • rate.changed: a duty rate on a Chapter 99 code, an MFN code, or an AD/CVD case changes. Includes the new rate, the previous rate where the message states it, and the effective date.
  • scope.changed: a Commerce scope determination expands or contracts the product scope of an AD/CVD order. Includes the case number, the affected HTS codes added or removed, and the determination's FR doc number.
  • exclusion.granted / exclusion.expired: a Section 301 or Section 232 exclusion is granted, ends, or is extended. Includes the 9903.88.6x or 9903.85.x code, the importer-specific qualifier where applicable, and the bracketing dates.
  • filing.requirements_changed: CBP changes how a layer is filed (new Chapter 99 code, consolidated 9903 family, new content-value reporting line). No rate change, but every open entry template referencing the old code needs an update.
  • liquidation.instructions: Commerce issues liquidation instructions that lock in assessment rates for prior entries on a specific case. Affects refund or additional-payment positions, not the rate at entry.
  • csms.superseded: a prior CSMS is replaced by a new one. The payload references the prior message id and the replacement id.

A finance team usually subscribes to rate.changed and exclusion.expired for cost-projection updates. An operations team subscribes to all six and routes them differently.

Register your HTS catalog

Subscriptions are scoped to one of three subjects: HTS code, AD/CVD case number, or origin country. The most common pattern is the per-importer HTS catalog: collect every 10-digit code the importer has filed in the last 24 months, deduplicate, and register them as a single subscription. Because Tandom expands cited codes against the HTSUS hierarchy at match time, a subscription on7616.99.51.90 also fires for any CSMS that cites the parent subheading 7616.99 or the parent heading 7616.

The closed-beta endpoints sit under /api/v1/monitoring/* and follow the GA shape. Authentication uses a Tandom API key in the Authorization: Bearer ... header. Beta access is gated; request through the calculator product team.

Create a subscription

POST https://tariffs.tandom.ai/api/v1/monitoring/subscriptions
Authorization: Bearer tnd_live_...
Content-Type: application/json

{
  "name": "ACME steel + aluminum derivatives",
  "webhook_url": "https://hooks.acme.com/tandom/csms",
  "event_types": [
    "rate.changed",
    "scope.changed",
    "exclusion.granted",
    "exclusion.expired",
    "filing.requirements_changed",
    "csms.superseded"
  ],
  "subjects": {
    "hts_codes": [
      "7318.15.80.66",
      "7616.99.51.90",
      "9404.90.20.60"
    ],
    "adcvd_cases": [],
    "origin_countries": ["CN", "MX", "VN"]
  },
  "match_strategy": "any"
}

The response includes the subscription id, the signing_secret you use to verify webhooks, and a test_event_url you can hit to dispatch a synthetic delivery to your handler before any real traffic arrives.

Webhook payload shape

Every webhook is a JSON POST with a stable envelope. Codes resolved against the HTSUS hierarchy ride alongside the codes the message cited verbatim, so handlers do not have to expand cited codes themselves.

POST /tandom/csms HTTP/1.1
X-Tandom-Signature: sha256=8f3a...e12c
X-Tandom-Event-Id: 7c8b6d50-9b1e-4c0e-9f5a-1a4f5e8c12b7
Content-Type: application/json

{
  "event_id": "7c8b6d50-9b1e-4c0e-9f5a-1a4f5e8c12b7",
  "event_type": "filing.requirements_changed",
  "occurred_at": "2026-04-06T13:02:11Z",
  "subscription_id": "sub_018abc...",
  "csms": {
    "message_id": "68253075",
    "title": "Section 232 Steel, Aluminum, and Copper: Updated Reporting under the 9903.82 Family",
    "category": "Trade",
    "sent_at": "2026-04-06T12:45:00Z",
    "url": "https://compliance.tandom.ai/adcvd-catalog/csms/68253075"
  },
  "match": {
    "hts_codes_cited_verbatim": ["7616.99"],
    "hts_codes_resolved_in_subscription": ["7616.99.51.90"],
    "adcvd_cases_cited": [],
    "countries_cited": []
  },
  "change": {
    "previous_chapter99_codes": ["9903.85.04", "9903.85.07"],
    "new_chapter99_codes": ["9903.82.31", "9903.82.32"],
    "rate_percent_before": 50,
    "rate_percent_after": 50,
    "effective_date": "2026-04-06"
  }
}

The change object is best-effort. CBP CSMS prose is sometimes ambiguous on whether a previous rate exists or what its value was. When Tandom cannot extract a structured comparison with high confidence, the field is null and the handler should treat the event as "open the message and read it manually." The csms.url field always points to the readable Tandom catalog page.

Verifying the signature

Every request carries an HMAC-SHA256 of the raw body in the X-Tandom-Signature header. Verify with a constant-time comparison before processing. The Node example:

import { createHmac, timingSafeEqual } from "node:crypto";

export function verifyTandomSignature(
  rawBody: Buffer,
  header: string,
  signingSecret: string,
): boolean {
  const expected = "sha256=" + createHmac("sha256", signingSecret)
    .update(rawBody)
    .digest("hex");
  const a = Buffer.from(header);
  const b = Buffer.from(expected);
  return a.length === b.length && timingSafeEqual(a, b);
}

Worked example: 14-code catalog

ACME imports a mix of steel and aluminum derivatives, finished metal articles, and bedding. Their filed catalog carries 14 distinct 10-digit HTS codes, three of which are highlighted here as the codes most likely to be hit by a Section 232 or Section 301 change. Every code below is verified against tariffs.tandom.ai/hts-catalog and the live Tandom duty engine.

Catalog (subset shown).

  • 7318.15.80.66 (Cap screws of iron or steel, MFN 8.5%) — catalog. Subject to Section 232 (steel content), Section 301 List 3, and an advisory AD heading match against A-570-932 (Steel Threaded Rod from China).
  • 7616.99.51.90 (Other articles of aluminum, MFN 2.5%) — catalog. Subject to Section 232 (aluminum derivatives, post June 4, 2025 doubling, smelt-and-cast country sensitive).
  • 9404.90.20.60 (Pillows, cushions, and similar furnishings of cotton, with other fill, MFN 6%) — catalog. Section 301 List 4A exposure on China origin (9903.88.15).
  • Eleven additional codes across Chapters 73, 76, 82, 83, 84, 85 (registered, omitted here for brevity).

The subscription. ACME POSTs the catalog to /api/v1/monitoring/subscriptions with event_types covering all six change kinds and origin_countries set to CN, MX, VN. The webhook URL points at a Slack posting endpoint hosted on their internal automation gateway.

The trigger. CBP publishes CSMS 68253075 on April 6, 2026, consolidating Section 232 reporting into the 9903.82 family for steel, aluminum, and copper derivatives. The message body cites HTS at the 4-digit and 6-digit level. ACME's catalog includes 7616.99.51.90; the message cites 7616.99. Tandom expands the cited subheading against the HTSUS hierarchy, finds the subscription match, classifies the event as filing.requirements_changed, and dispatches the webhook 47 seconds after CBP's GovDelivery publish.

The webhook ACME receives (abbreviated):

{
  "event_id": "7c8b6d50-9b1e-4c0e-9f5a-1a4f5e8c12b7",
  "event_type": "filing.requirements_changed",
  "occurred_at": "2026-04-06T13:02:11Z",
  "subscription_id": "sub_018abc...",
  "csms": {
    "message_id": "68253075",
    "title": "Section 232 Steel, Aluminum, and Copper: Updated Reporting under the 9903.82 Family",
    "category": "Trade",
    "sent_at": "2026-04-06T12:45:00Z",
    "url": "https://compliance.tandom.ai/adcvd-catalog/csms/68253075"
  },
  "match": {
    "hts_codes_cited_verbatim": ["7318", "7616.99", "8708.10"],
    "hts_codes_resolved_in_subscription": ["7616.99.51.90", "7318.15.80.66"],
    "adcvd_cases_cited": [],
    "countries_cited": []
  },
  "change": {
    "previous_chapter99_codes": ["9903.85.04", "9903.81.94"],
    "new_chapter99_codes": ["9903.82.31", "9903.82.51"],
    "rate_percent_before": 50,
    "rate_percent_after": 50,
    "effective_date": "2026-04-06"
  }
}

What the handler does. ACME's handler verifies the signature, deduplicates on event_id, posts a Slack message to #ops-tariffs, and opens a JIRA ticket on the Brokerage board assigned to the lead broker. The ticket includes a deep-link back to the Tandom calculator with the affected HTS codes pre-loaded so the broker can confirm the new stack visually.

The 14-code catalog produces roughly 2 to 4 webhooks a month under normal conditions. April 2025 (Section 232 reset), May 2025 (UK deal), June 2025 (rate doubling), and February 2026 (IEEPA shutdown) each produced 1 to 3 webhooks per day for several days; outside those event windows the channel is quiet.

Handler patterns: Slack, JIRA, ACE

Three common handler patterns, in increasing order of operational depth.

Pattern 1: Slack notification

The simplest useful handler. The webhook arrives, the handler verifies the signature, formats a one-line summary, and posts to a Slack channel. Recommended for finance and pricing teams that want awareness, not action.

// Express + node-fetch handler
import express from "express";
import { verifyTandomSignature } from "./tandom";

const SIGNING_SECRET = process.env.TANDOM_SIGNING_SECRET!;
const SLACK_WEBHOOK = process.env.SLACK_WEBHOOK_URL!;

const app = express();
app.post("/tandom/csms",
  express.raw({ type: "application/json" }),
  async (req, res) => {
    const sig = req.header("X-Tandom-Signature") ?? "";
    if (!verifyTandomSignature(req.body, sig, SIGNING_SECRET)) {
      return res.status(401).send("bad signature");
    }
    const event = JSON.parse(req.body.toString("utf8"));
    const codes = event.match.hts_codes_resolved_in_subscription
      .join(", ");
    const text = [
      `*${event.event_type}* — ${event.csms.title}`,
      `HTS in catalog: ${codes}`,
      `Effective: ${event.change?.effective_date ?? "see CSMS body"}`,
      `<${event.csms.url}|Read CSMS ${event.csms.message_id}>`,
    ].join("\n");
    await fetch(SLACK_WEBHOOK, {
      method: "POST",
      headers: { "content-type": "application/json" },
      body: JSON.stringify({ text }),
    });
    res.status(200).send("ok");
  }
);

app.listen(8080);

Pattern 2: JIRA ticket on filing.requirements_changed

When the change requires a broker to update entry templates, a Slack message is not enough; a tracked ticket is. Filter the handler to filing.requirements_changed, rate.changed, and scope.changed; route the rest to a low-priority Slack channel.

const ACTIONABLE = new Set([
  "filing.requirements_changed",
  "rate.changed",
  "scope.changed",
]);

if (ACTIONABLE.has(event.event_type)) {
  await fetch("https://acme.atlassian.net/rest/api/3/issue", {
    method: "POST",
    headers: {
      authorization: `Basic ${jiraBasicAuth}`,
      "content-type": "application/json",
    },
    body: JSON.stringify({
      fields: {
        project: { key: "BRK" },
        summary: `[CSMS ${event.csms.message_id}] ${event.csms.title}`,
        issuetype: { name: "Task" },
        priority: { name: "High" },
        labels: ["tariff-change", event.event_type],
        description: {
          type: "doc",
          version: 1,
          content: [
            paragraph(`Affected HTS in our catalog: ${codes}`),
            paragraph(`Effective: ${event.change?.effective_date ?? "see CSMS"}`),
            link(event.csms.url, `Read CSMS ${event.csms.message_id}`),
          ],
        },
      },
    }),
  });
}

Pattern 3: ACE template re-validation

The deepest handler validates entry templates against the new state. When the webhook carries new_chapter99_codes, compare against open templates in the broker's filing system and either auto-update the templates or fail-closed (lock template until a human reviews). This is the pattern that prevented the most filing rejections during the IEEPA shutdown in February 2026: brokers who had this handler running flipped 9903.01.x and 9903.02.x out of every open template the moment CSMS 67834313 arrived, and started filing under Section 122 the same afternoon.

For ACE template re-validation specifically, the Tandom calculator engine is the natural reference. Each affected line can be re-priced through /api/duty/calculate with the entry date forward-shifted to the CSMS effective date; a difference between the old computed rate and the new one is the filing-update signal.

Common pitfalls

Eight mistakes that break a CSMS subscription pipeline:

Subscribing at the heading level only

A subscription on 7318 (heading) catches every CSMS that touches any 7318.xx product. That is fine for awareness but produces noise; the operations queue fills with messages on threaded rod, lag screws, and washers when the importer only files cap screws. Subscribe at the deepest classification you actually file (10 digits where possible) and let Tandom expand cited codes upward. The inverse direction is what you want: cited 6-digit subheading 7318.15 should match your 10-digit subscription, not the other way around.

Treating webhook delivery as exactly-once

Delivery is at-least-once. Network blips, your handler's 504, and CBP-issued reissues all produce duplicate deliveries. Persist processed event_id values for at least 7 days and skip duplicates. A handler that creates a JIRA ticket on every delivery without dedup creates 4 duplicate tickets the first time a retry storm hits.

Skipping signature verification

A webhook URL is by definition publicly reachable. Any attacker who guesses or scrapes the URL can post a forged event. Constant-time HMAC verification on every request is mandatory, not optional. The header is X-Tandom-Signature, the secret is per-subscription, and rotation is available through the API.

Polling /api/v1/monitoring/csms instead of webhooks

The pull endpoint exists for catch-up and dead-letter recovery, not as a primary delivery channel. A 5-minute poll cadence misses the median 90-second alert window; a 30-second cadence rate-limits before noon. Use webhooks for primary delivery, the pull endpoint as a backstop.

Treating csms.superseded as a no-op

CBP corrects CSMS messages by full reissue, not in-place edits. The pattern is: original message issues, errors are caught (rate cited wrong, effective date off by a day, an HTS code missed), a replacement message issues with a new CSMS id. Tandom emits csms.superseded on the prior id and csms.published on the replacement. Handlers must invalidate the prior alert and reprocess the replacement; treating the supersede as a no-op leaves the prior (wrong) state in the operations channel.

Filtering out csms.superseded events

The opposite mistake of the above. A handler that filters to "high signal" event types and drops supersedes leaves stale tickets and stale Slack messages in place. Always process the supersede, even if the only action is to comment "superseded by CSMS <new id>" on the prior ticket.

Hardcoding the IEEPA codes

A handler that hardcodes 9903.01.x or 9903.02.x as "current Section 122 / IEEPA" stopped working at 12:01 a.m. ET February 24, 2026 when CSMS 67834313 ended IEEPA collection. The pattern that survives is reading the new Chapter 99 codes off the webhook payload, not from a constant in the handler.

Not registering AD/CVD case numbers separately

Some CSMS messages cite a case number without citing any HTS code (liquidation instructions on a single respondent, for example). A subscription that only lists HTS codes misses these. If the importer is exposed to a specific AD or CVD case (an order's product scope reaches the importer's product, even at heading-level), register the case number directly in adcvd_cases on the subscription.

Glossary

CSMS
Customs Service Message. CBP's operational broadcast channel to the trade community. Each message has an integer id (e.g., 64384423) and a category (AD/CVD, ACE, Trade, Cargo Security, Other). Authoritative source: content.govdelivery.com bulletin feed; mirrored in the Tandom AD/CVD catalog with structured extraction.
GovDelivery
The mailing-list service CBP uses to publish CSMS. Mass email; no per-subscriber filtering. Tandom Monitoring polls GovDelivery and adds the filtering and classification.
Webhook
An HTTP POST from Tandom to a URL the subscriber registers, fired the moment a matching event occurs. Signed with HMAC-SHA256 in X-Tandom-Signature. At-least-once delivery with exponential backoff retry.
Subscription
A registered set of subjects (HTS codes, AD/CVD cases, countries) plus event types plus a webhook URL. Identified by sub_... prefix. Owns its signing secret and dead-letter queue.
Event id
A UUID that uniquely identifies a single event delivery. Stable across retries. Handlers must dedupe on this id to avoid double-processing.
Match strategy
"any" fires the webhook when any registered subject is cited. "all" requires every registered subject to be cited (rare; useful for narrow research subscriptions). Default is "any".
Code resolution
The process of expanding a cited HTS code (which may be 4, 6, 8, or 10 digits) against the HTSUS hierarchy to find subscription matches at the deepest level the subscriber registered.
Dead-letter queue
A per-subscription queue of events whose webhook delivery failed after 24 hours of retries. Readable through GET /api/v1/monitoring/subscriptions/{id}/dead-letters.
9903.82 family
The post-April-6, 2026 consolidated Chapter 99 family for Section 232 steel, aluminum, and copper reporting. Replaced 9903.80, 9903.81, 9903.85, and 9903.78 codes on entries from April 6, 2026 forward (per CSMS 68253075 and surrounding messages).
Chapter 99
The HTSUS chapter that holds temporary trade-remedy provisions: Sections 232, 301, 201 safeguards, IEEPA (now expired), Section 122 (current). The 9903 four- digit prefix is reported as a secondary classification on the entry line.
Liquidation instructions
CSMS-issued directions from Commerce to CBP that lock in final assessment rates for prior entries on a specific AD or CVD case. Affect refund or additional-payment positions for entries already filed, not the rate at entry.
Signing secret
The per-subscription shared secret used to sign every webhook with HMAC-SHA256. Returned at subscription creation, rotatable through the API. Old secret remains valid for 24 hours after rotation to allow handler cutover.
Tandom catalog
The browsable mirror of the underlying primary sources. HTS codes at tariffs.tandom.ai/hts-catalog, AD/CVD orders and CSMS messages at compliance.tandom.ai/adcvd-catalog.

FAQ

High-intent questions brokers and importer compliance teams ask before adopting a CSMS alert pipeline.

What is a CSMS rate change alert?
A subscription that fires a webhook the moment CBP issues a Customs Service Message ("CSMS") that changes a duty rate, exclusion list, or filing requirement for an HTS code you registered. The trigger is the CSMS publish event, not a nightly batch. The alert carries the CSMS message id, the affected HTS codes, the previous and new rate where applicable, and the effective date written into the message.
How is this different from subscribing to CBP's own CSMS bulletins?
CBP's GovDelivery list mails every CSMS to every subscriber. A typical broker who registers for the AD/CVD, ACE, Trade, and Cargo Security categories receives 40 to 80 messages a week. Most do not touch the importer's products. A Tandom Monitoring subscription filters to the HTS codes, cases, and country pairs you registered, so the operations channel only sees messages that actually change something the broker has to act on.
What HTS granularity should I subscribe at?
Subscribe at the deepest classification you actually file. CSMS messages cite HTS at varying widths (4-digit headings, 6-digit subheadings, 8-digit tariff items, 10-digit statistical breakouts). Tandom expands every cited code against the HTSUS hierarchy at match time, so a CSMS that cites "7616.99" still triggers your subscription on 7616.99.51.90. Registering at the 10-digit you file is correct.
Does the webhook fire on AD/CVD cash deposit rate changes?
Yes. CSMS messages that issue liquidation or deposit instructions on an AD or CVD case carry the case number, the new cash deposit rate by exporter or manufacturer, and the effective date. If you registered any HTS code in the heading the order touches, or the case number directly, the webhook fires. AD/CVD changes are tagged category="adcvd" so handlers can route them differently from MFN or Section 232 changes.
What happens when CBP issues a corrected or superseded CSMS?
Tandom emits two events. The first is a `csms.superseded` event on the prior message id with the new replacement id. The second is a `csms.published` event on the replacement. Handlers should treat the supersede as a cancel-and-replace: invalidate the prior alert in the operations channel and process the replacement as new. CBP corrects CSMS messages through full reissue, not in-place edits.
How fast are alerts after CBP publishes the message?
Median end-to-end latency is under 90 seconds from CBP publish to webhook delivery in beta. CBP publishes to its GovDelivery feed; Tandom polls every 30 seconds, ingests the message, classifies the affected HTS codes and cases via AI extraction over the message body, runs the subscription match against the registered catalog, and dispatches webhooks. The latency budget is dominated by CBP's publish-to-feed lag, not by Tandom processing.
Can I subscribe to Section 301 List 4A changes specifically?
Yes. Subscribe by 9903.88.15 (the List 4A reporting code) to receive every CSMS that cites it. Subscribe by an underlying 8-digit subheading (for example 8407.32) to receive Section 301 changes specifically on engines. The two subscriptions are independent, so you can register a List 4A subscription for finance-and-pricing visibility and a per-product subscription for filing-time visibility, and route the webhooks to different channels.
Is webhook delivery guaranteed once?
No. Webhook delivery is at-least-once. Each event carries a stable `event_id` (a UUID) that does not change across retries. Handlers should record processed event ids and skip duplicates. Tandom retries non-2xx responses with exponential backoff for up to 24 hours, then dead-letters the event to the subscription's dead-letter queue, which is readable through the API.
How do I authenticate the webhook on my receiving end?
Every request carries an `X-Tandom-Signature` header, an HMAC-SHA256 of the raw body using a per-subscription signing secret you receive at subscription creation. Verify the signature in constant time before processing. Tandom retries through the same signing secret, so signature verification works identically on first delivery and any retry. Rotate the secret through the API; the old secret remains valid for 24 hours after rotation.
Share: