splitforms.com
All articles/ GUIDES9 MIN READPublished June 28, 2026

Webhook Retry Strategy for Form Submissions (2026)

Design a reliable webhook retry strategy for form submissions — idempotency keys, exponential backoff, signature verification, dead-letter queues, and…

✶ Written by
splitforms.com / blog

Founder of splitforms — the form backend API for developers. Writes about form UX, anti-spam, and shipping web apps without backend code.

Why webhook retries matter

Webhooks sit in the exact place where teams expect software to be reliable: between a real user action and the system that needs to act on it. For form submissions, that means a website visitor asked for a quote, requested a demo, uploaded a file, or sent a support message. If the first webhook POST fails, the submission should not disappear.

The receiver can fail for boring reasons. A deployment restarts the API route. A CRM returns a temporary 502. A serverless function cold starts past the timeout. A rate limit briefly blocks traffic. None of those are good reasons to lose a lead.

A practical retry policy

Start with one immediate delivery attempt. If it fails with a retryable status, schedule retries with exponential backoff and jitter:

Attempt 1: immediately
Attempt 2: 30 seconds later
Attempt 3: 2 minutes later
Attempt 4: 10 minutes later
Attempt 5: 30 minutes later
Attempt 6: 2 hours later
Attempt 7: 12 hours later

The exact timing matters less than the shape. Fast retries catch momentary failures. Later retries catch outages and deploy mistakes. Jitter prevents hundreds of delayed requests from landing on the receiver at the same instant.

Which status codes should retry?

  • Retry: network errors, timeouts, 408, 409, 425, 429, and 5xx responses.
  • Do not retry by default: 400, 401, 403, 404, 410, and validation failures.
  • Review manually: repeated 429s, signature failures, and payload mapping errors.

Permanent failures should land in a dead-letter view with the request URL, response code, response body, attempt count, and a replay button. That gives the form owner a repair path without asking the original visitor to submit again.

Use idempotency keys on every event

Retry means duplicate delivery is possible. That is normal. The fix is to include a stable event ID or idempotency key in every webhook. The receiver stores that key after a successful write. If the same key arrives again, it returns 200 without creating a duplicate row.

// Receiver-side sketch
const eventId = request.headers.get("x-splitforms-event-id");

if (await alreadyProcessed(eventId)) {
  return Response.json({ ok: true, duplicate: true });
}

await createLead(payload);
await markProcessed(eventId);

return Response.json({ ok: true });

Sign the payload, then verify before processing

A webhook endpoint is public by design. Anyone can send a POST to it if they know the URL. HMAC signatures solve that by letting the receiver verify that the sender knew a shared secret and that the body was not changed in transit.

  • Use HTTPS only.
  • Sign the raw request body, not a parsed JSON object.
  • Include a timestamp and reject old payloads.
  • Compare signatures using a constant-time comparison.
  • Rotate webhook secrets when a URL or team member changes.

See the webhook docs for the splitforms signing contract.

Receiver checklist

  1. Return a 2xx response only after the downstream write succeeds.
  2. Keep the request handler fast; move slow CRM calls to a queue if needed.
  3. Log event ID, attempt number, response code, and duration.
  4. Use idempotency before creating records.
  5. Return clear 4xx errors for bad mapping or auth problems.
  6. Expose a manual replay path for recovered failures.

How splitforms handles form webhooks

splitforms sends signed webhooks on Starter and above, includes retry behavior for temporary failures, and keeps the original submission in the dashboard so the lead is not lost if a downstream system is unavailable. You can POST the same form to splitforms, receive the owner email, and route a signed JSON payload to your own API route, CRM proxy, or automation tool.

Start with the form to webhook guide, then read the full webhook documentation.

FAQ

How many times should a webhook retry?

Seven attempts is a practical default: one immediate delivery attempt, then retries over a widening window. That catches short deploys, temporary API failures, and rate limits without hammering the receiver forever.

Should webhooks retry on 4xx errors?

Usually no. A 400, 401, 403, or 404 means the receiver rejected the request because of configuration or auth. Retry 408, 409, 425, 429, and 5xx responses; send permanent 4xx failures to a dead-letter view.

Why do webhooks need idempotency keys?

Retries can deliver the same event more than once. An idempotency key lets the receiver detect duplicates and avoid creating the same CRM lead, support ticket, or database row twice.

Are signed webhooks enough for security?

Signed webhooks prove the payload came from the expected sender and was not changed in transit. You still need HTTPS, timestamp checks, replay protection, and secret rotation for a complete webhook security posture.

About the author
✻ ✻ ✻

Get your free contact form API key in 60 seconds.

500 free form submissions per month. No credit card. No SDK, no PHP, no plugin. Drop one POST endpoint in your form and submissions land in your dashboard and can notify your inbox on every plan.

Generate access key →Read the docs
founders pricing locked in · early access open