Back to blog

Webhook Endpoint Setup Guide: Step-by-Step Tutorial

Webhook endpoint setup guide for beginners and developers: create, verify, test, and troubleshoot webhooks with clear steps, examples, and fixes.

WG

WebhookGuide

April 22, 2026

Introduction: What this guide covers

A webhook only works when the receiving side is set up correctly, and that’s where many integrations break. This guide explains what a webhook endpoint is, how webhook endpoints work, how to set one up, how to verify signatures, and how to troubleshoot delivery problems in production.

It’s written for beginners learning the basics, backend developers wiring up a service, and teams integrating with a webhook provider such as Stripe, GitHub, Shopify, Slack, Twilio, or Zapier. If you need a refresher first, see what is a webhook and webhook endpoints explained.

The workflow is straightforward: choose an event source, create an endpoint URL, configure payloads and headers, verify signatures, test delivery, and troubleshoot failures. Along the way, you’ll work with HTTP and HTTPS, handle a POST request, parse JSON, inspect logs, and decide when to use a queue or background jobs so your app responds quickly.

What is a webhook endpoint?

A webhook endpoint is a public URL that accepts incoming HTTP requests when an event happens in another system. In most cases, the provider sends a POST request with a JSON payload and headers that identify the event type and source.

That differs from a standard API endpoint, which usually sends requests out to fetch data. Webhooks replace polling, where your app keeps asking for updates, with event-driven delivery.

For example, Stripe can POST a payment event to your receiver URL, and GitHub can POST a push event to your endpoint when code changes land. See webhook endpoints explained for the mechanics.

How webhook delivery works

A webhook delivery starts when an event occurs in the source system, such as a Stripe payment succeeding or a GitHub issue being opened. The provider sends an HTTP POST request to your endpoint URL with a payload that describes the event.

The request usually includes headers that tell your app what happened and how to verify it, such as event type, content type, timestamp, and signature metadata. Your server checks those headers, validates the signature, and parses the payload before processing it.

Return a fast 2xx status code when the delivery is accepted. Use a 4xx status code for bad input or failed validation, and expect 5xx responses or timeouts to trigger retry logic. Providers like GitHub and Stripe resend failed deliveries, so move heavy work to background jobs or a queue and respond within a few seconds. For setup details, see the webhook guide for developers.

Prerequisites before setting up a webhook endpoint

Confirm you have a public HTTPS endpoint URL, or a secure way to expose localhost during development. If you’re testing locally, use ngrok to tunnel requests to your machine without opening unsafe ports.

Make sure you can access the webhook provider dashboard or settings page for the event source. You’ll need it to register the endpoint URL, choose events, and retrieve signing secrets or test deliveries.

Prepare a receiver in a real stack such as Express, Django, Laravel, Ruby on Rails, or AWS Lambda. Before coding, review the expected payload shape, required headers, and signature verification rules so you can parse requests correctly.

Set up logs, request inspection, and a testing plan; the webhook testing checklist helps you verify delivery, retries, and error handling before production.

Step 1: Choose the event source and event types

Start by naming the event source that will send the webhook: Stripe for payments, GitHub for repository activity, Shopify for commerce events, Slack for workspace events, Twilio for messaging events, or Zapier for automation triggers. Then map each business action to an event, such as order.paid, issue.opened, form.submitted, or subscription.canceled.

Subscribe only to the events your app actually needs. Fewer events mean less noisy traffic, lower processing cost, and fewer duplicate deliveries to handle with idempotency.

Document the event list before coding so your receiver logic, tests, and provider settings stay aligned. If you need a broader planning reference, see the webhook guide for developers.

Step 2: Create the webhook endpoint URL

Create a dedicated route such as /webhooks/provider-name so webhook traffic stays separate from normal app routes. Keep the endpoint URL stable and publicly reachable over HTTPS so the provider can deliver requests reliably, whether you build it in Express, Django, Laravel, Ruby on Rails, or AWS Lambda. A hard-to-guess path can reduce casual noise, but it does not replace signature checks or other security controls; see webhook endpoints explained for the role of the receiving URL. Design the route to accept POST request traffic and parse JSON bodies safely, with strict validation before any downstream processing.

Step 3: Configure payloads, headers, and authentication

Document the exact payload format the webhook provider sends, usually JSON in UTF-8, and confirm the Content-Type your receiver expects, such as application/json. List the headers your app depends on: event type (X-Event-Type), request ID, timestamp, and any signature verification header such as X-Signature or Stripe-Signature. Store the secret token or shared secret in environment variables or a secret manager, never in source control.

For signature verification, the provider signs the payload with HMAC and your server recomputes the digest from the raw body, then compares it before processing. If the provider supports idempotency keys, record them so retries do not create duplicate orders or tickets. Capture all of this in your webhook documentation best practices so both systems agree on the contract.

Step 4: Handle and verify the webhook request in your application

Read the raw request body first; frameworks like Express or Django can normalize JSON and break signature verification. Use the shared secret token to verify the signature with HMAC before trusting the payload, as shown in the webhook guide for developers. Reject missing fields or malformed payload data with a 4xx status code.

Once the request is valid, return a fast 2xx status code and move heavy work to a queue or background jobs. That keeps the provider from retrying while your app processes email sends, database writes, or downstream API calls.

Use logs, event IDs, and idempotency checks to stop duplicate deliveries from creating duplicate records or actions. Run the webhook testing checklist to confirm repeated requests, bad signatures, and retry behavior all fail or succeed the way you expect.

Step 5: Test the webhook delivery end to end

Send a provider-side test event first: Stripe, GitHub, Shopify, Slack, Twilio, and Zapier all offer test deliveries or sandbox flows that hit your real endpoint URL. Confirm your app returns a 2xx status code, then inspect logs for the exact payload, headers, response time, and any signature fields.

Test locally with ngrok before deploying so you can watch requests arrive and compare them against your webhook testing checklist or testing checklist template. Use Postman to replay the same request manually while debugging.

Then break it on purpose: send an invalid signature, malformed JSON, a slow response, and a forced 5xx status code to confirm retry logic behaves as expected and failures are visible in logs.

Common webhook endpoint setup issues

If requests never arrive, check the endpoint URL first: a typo, wrong path, blocked port, missing HTTPS, or a firewall or proxy rule can stop delivery before your app sees it. Compare the provider dashboard URL with your deployed route, then inspect server and load balancer logs for blocked connections.

Signature failures usually come from the wrong secret token, reading the raw body after JSON parsing, or verifying with the wrong algorithm. Stripe and GitHub both require exact signature verification against the original request body and matching headers; a bad check should return a 4xx status code, not 5xx.

Malformed JSON or unexpected headers like a missing Content-Type can trigger parsing errors and early 4xx responses. Slow handlers cause timeouts, so the provider’s retry logic sends the event again; check response time in logs and keep processing fast.

Duplicate events are normal during retries, so use idempotency keys or event IDs to ignore repeats. For a quick checklist, use the webhook testing checklist.

Webhook security best practices and production checklist

Require HTTPS for every production webhook and reject insecure delivery attempts. Treat a secret URL as obscurity, not security: use signature verification with HMAC and a secret token as the primary trust check, like Stripe’s signed events or GitHub’s X-Hub-Signature-256. Add IP allowlisting and rate limiting when the provider supports them, but use them only as defense in depth.

Validate the incoming payload against the expected schema, enforce idempotency for retries, and keep downstream permissions minimal. For example, a webhook that creates support tickets should not also have billing access. Log request IDs, event types, and verification results, but never raw secrets or full sensitive payload data.

Document secret rotation and incident response steps, then verify go-live items from the webhook testing checklist and webhook documentation best practices: HTTPS, signature checks, retries, 2xx status code, monitoring, and alerting.

Webhook endpoint documentation and maintenance

Document the endpoint URL, supported event types, payload schema, required headers, and signature verification steps in one place so anyone can reproduce the integration. Include sample requests and sample responses that work in Postman or local tests, plus the exact retry logic, timeout expectations, idempotency rules, and where incident logs live. Keep secret handling explicit: note which signing secret is used, where it’s stored, and who can rotate it.

Version the endpoint or payload contract when the provider changes fields, renames event types, or alters delivery format; keep the old version until consumers migrate. Assign ownership for monitoring, documentation updates, and test maintenance, and tie changes to a checklist like webhook documentation best practices and the testing checklist template.

Conclusion: Webhook endpoint setup checklist

A reliable webhook integration follows the same workflow every time: choose the right event source and event types, create a stable endpoint URL, configure authentication and headers, verify the request in code, test delivery end to end, then harden the integration for production. The goal is not just to receive a request, but to process it safely, return a 2xx status code when handling succeeds, and keep the system resilient when delivery is retried.

Use this final checklist before you go live:

  • HTTPS is enabled on the endpoint URL.
  • Signature verification works with the provider’s secret or signing key.
  • Logs are visible and include request IDs, payload details, and failures.
  • Retry logic is understood, including how the provider behaves after non-2xx responses.
  • Idempotency is in place so duplicate deliveries do not create duplicate side effects.
  • The endpoint returns the correct 2xx status code after successful processing.

Run one last end-to-end test from the provider dashboard or a tool like Postman, then confirm the event appears in your application exactly once. If anything fails, check the raw request, headers, signature verification, and server logs before changing the provider settings.

For ongoing maintenance, keep your integration notes current with webhook documentation best practices and use the webhook testing checklist whenever you change code, secrets, or event subscriptions.