Home/Email API/Test a webhook

How to test a webhook

Inspect the payload before you write the handler, tunnel to localhost while you build it, and verify the signature before you trust it. Three stages, in that order.

Verified By George Hartley, Co-founder · Updated July 20, 2026

Stage one: see the payload

Before writing a line of handler code, point the webhook at a request bin, a throwaway URL that captures whatever arrives (webhook.site and friends exist exactly for this). Fire a test event and read the actual payload: field names, types, timestamp format. Real payloads beat documentation every time.

Stages two and three: localhost, then trust

While building the handler, tunnel production events to your machine: an ngrok-style tunnel gives your localhost a public URL, so real events hit your debugger. Send yourself a message, watch delivered fire, force a bounce with a bad address, watch that fire too.

Before production, test the paranoid paths: replay the same event twice and confirm nothing double-processes, send a payload with a wrong signature and confirm your handler rejects it. Nitrosend signs every event with HMAC-SHA256; a handler that skips verification is an open door with logging.

Test against events, not API responses. I once trusted a live response that read "sent: 0, failed: 2, status: completed" and shipped the campaign again as a resend. It was the third copy. The response told me the request finished. Only the event stream tells you what actually happened.

Test data shapes what you can test, too. QA on one of our re-engagement flows surfaced a 404 on the unsubscribe link, and the cause was the test path itself: the legacy test-send used recipients that weren't real contacts, so there was no contact to bind an unsubscribe token to. The fix was routing test sends through the real transactional endpoint with real contacts, so every link works because nothing is mocked. If your test path and your production path differ, you're testing the test path.

Full parameters and responses live in the REST API docs and the API reference.

Incoming webhook
{ "event": "delivered" … }
X-Nitrosend-Signature:
sha256=7f3a…c91e
Your server verifies
hmac_sha256(secret, body)
== header signature?
match → process ✓ no match → drop
Anyone can POST to a public URL. Only Nitrosend can sign with your secret. Same figure, second crop, works for /webhook-test.

Go deeper

The signature check and the rest of the hardening: how to secure webhooks. The mechanism itself: webhooks explained.

First send in thirty seconds.

Simple pricing. Unlimited contacts.

Every plan includes full stack emailing: Flows, Newsletter Campaigns and Transactional Email, plus our NitroWheel LLM and all agent integrations (Claude, ChatGPT, Codex, Cursor and others). Pay for what you send, not who you store.

Free
$0
forever
  • Emails 8,000then 500/mo
  • Email types Transactional & Marketing
  • AI actions 20/mo
  • Contacts Free & Unlimited
  • Brands 1
  • Seats 1
Start free
Ultra
$100
per month
  • Emails 125,000/month
  • AI actions 5,000/mo
  • Brands 5
  • Seats 10 · Domains 3
  • Frontier AI Included
  • Dedicated IP Available
Get started
Enterprise
$300
per month
  • AI actions Unlimited
  • Unlimited brands & domains Included
  • SSO / SAML Included
  • 99.9% SLA Included
Get started

Free forever. No credit card required. See full comparison →