For developers

Webhook replay window checker

Decode a webhook-timestamp header into its exact UTC time and tolerance window, and check whether a clock reading falls inside or outside it.

Free, no accountIn your browser

Unix seconds, exactly as the webhook-timestamp header carries it.

Unix seconds, or a UTC time ending in "Z" - left blank, only the window's bounds are shown.

Try

Result

Tolerance window bounds for this timestamp

A clock reading anywhere from 2025-10-13T11:55:31Z to 2025-10-13T12:05:31Z would still accept this timestamp as fresh, against the reference library's 5-minute window.

  • Info

    This window is quoted, not chosen by us

    The Standard Webhooks specification itself sets no figure for how far a webhook-timestamp may drift from a receiver's clock - it only says a receiver should reject anything outside "some allowable tolerance." The 5-minute window shown here is the JavaScript reference library's own WEBHOOK_TOLERANCE_IN_SECONDS (5 * 60); a different verifying library is free to enforce a different figure.

  • Info

    A retried delivery keeps its id, not a fresh one

    A failed delivery is retried with the same webhook-id up to 14 hours after its first attempt, so a receiver that records the ids it has already handled and skips repeats needs no narrow window of its own - the id, not a tight clock match, is what stops it acting twice.

Tolerance window

webhook-timestamp
1760356831 (2025-10-13T12:00:31Z)
Earliest accepted clock reading
1760356531 (2025-10-13T11:55:31Z)
Latest accepted clock reading
1760357131 (2025-10-13T12:05:31Z)
  • Only the JavaScript reference library's own figure is shown. The specification sets no figure of its own, so a different Standard Webhooks library, or code written against it directly, can enforce a wider or narrower window than this.

What this is

This webhook replay window checker decodes a webhook-timestamp header into the exact UTC moment it names and the tolerance window a verifying library builds around it, then checks whether a clock reading you give falls inside that window or past it.

A webhook-timestamp header is always Unix seconds (`packages/events/src/signing.ts:18`, where `signWebhook` converts a delivery's own `Date` into exactly that before signing it) - never milliseconds, never an ISO string. This page decodes those seconds into an absolute UTC time, then builds the window a verifying library checks a clock reading against before it rejects a delivery as too old or too new.

Our own webhooks guide tells a receiver to "always verify" a delivery and notes that "libraries also reject timestamps that are too old" (`apps/web/content/docs/(guides)/webhooks.mdx:106-107`) - but states no figure of its own for how old is too old. The 300-second window shown here is the Standard Webhooks JavaScript reference library's own default, not a number ResellerHQ sets; a different verifying library, or code written against the specification directly, is free to use a different one.

How to read the result

With no clock reading given, the window's own bounds are shown: any clock reading between those two UTC times would still be accepted as fresh by the reference library. Give a clock reading - Unix seconds, or a UTC time ending in "Z" - to check one specific moment against that window instead: inside it is a success, outside it is a warning, never a danger, because a stale timestamp says the two clocks disagree, not that the signature itself was forged.

A retried delivery keeps the same webhook-id on every attempt, so a receiver that has already recorded the ids it has handled needs no narrow clock match of its own to avoid acting twice - the id, not this window, is what actually stops a duplicate.

"Verifying one of our webhooks" explains why this window exists at all: a stale webhook-timestamp is what stops a captured, legitimately signed delivery from being replayed later, a different threat from the duplicate-retry problem webhook-id solves, and it sets this page's 300-second default against our own retry schedule.

Common mistakes

What goes wrong most often, and how to tell.

  • Treating "outside the window" as proof of a forged signatureA timestamp outside the tolerance window only means the two clocks being compared disagree by more than the reference library allows - it says nothing about whether the HMAC signature itself is correct. Check the signature separately before deciding anything was forged.
  • Assuming 300 seconds is a number ResellerHQ enforcesThe Standard Webhooks specification itself states no figure, only "some allowable tolerance," and our own webhooks guide repeats that without a number of its own. The 300 seconds shown here belongs to the JavaScript reference library; a different verifying library is free to use a wider or narrower window.

Questions

What people ask about this tool.

  • With no clock reading typed in, there is nothing yet to compare the timestamp against - only the window a verifying library would check a reading against. Filling in "Your receiver's clock" turns that window into an actual inside-or-outside answer for one specific moment.
  • It belongs to the Standard Webhooks JavaScript reference library's own `WEBHOOK_TOLERANCE_IN_SECONDS` constant, not to the specification or to ResellerHQ. Our own webhooks guide says only that "libraries also reject timestamps that are too old," with no figure of its own - a different verifying library, or code written directly against the specification, can use a different one entirely.
  • No - it only means a clock reading you gave disagrees with the webhook-timestamp by more than the window allows, which a verifying library would report as "Message timestamp too old" or "too new." That can be genuine staleness, a clock out of sync on one side, or a slow network; it proves nothing about the signature, which this tool does not check at all.
  • A time with no trailing "Z" has no timezone attached to it, and handing that straight to a date parser reads it as local time on whatever machine runs the check - your own browser's timezone, not a fixed value - which would make this tool's answer depend on where it happens to run. Typing Unix seconds, or a UTC time that ends in "Z", avoids that entirely.

Sources

Every fixed value here comes from the provider’s own documentation. These pages change, so each says the day it was last read.

Use it from the API

The same check, as one request.

Request
curl -X POST https://resellerhq.com/api/tools/webhook-replay-window-checker \
  -H "Content-Type: application/json" \
  -d '{"timestamp":"","clock":""}'
Response
{
  "tool": "webhook-replay-window-checker",
  "input": {
    "timestamp": "",
    "clock": ""
  },
  "result": {
    "verdict": {
      "tone": "neutral",
      "headline": "Nothing to check yet",
      "summary": "Paste the webhook-timestamp value and this works out its tolerance window as you type."
    },
    "findings": [],
    "parts": []
  }
}

Build on the same API this tool is part of: numbers, domains and mailboxes, one key.

Read the API

Company names and logos are trademarks of their owners, shown only to identify each service.