← All Posts

How to Debug and Format Webhook Payloads

Published on February 7, 2026

What Are Webhooks?

Webhooks are automated HTTP callbacks that are triggered when a specific event occurs in a system. Instead of your application repeatedly polling an API to check for new data (which is inefficient and slow), the service sends a POST request to your server with the event data as soon as it happens. This push-based approach is how modern applications stay in sync in real time.

For example, when a customer completes a payment on Stripe, Stripe sends a webhook to your server with the payment details. When someone pushes code to a GitHub repository, GitHub sends a webhook with information about the commits, branch, and author. Webhooks power integrations across thousands of services, from payment processors and CRMs to CI/CD pipelines and messaging platforms.

Understanding Webhook Payload Structure

A webhook payload is the JSON (or sometimes XML) body sent in the HTTP POST request. While every provider has its own schema, most webhook payloads share a common structure that includes an event type, a timestamp, and the actual data associated with the event:

{
  "id": "evt_1234567890",
  "type": "payment.completed",
  "created": 1738886400,
  "data": {
    "object": {
      "id": "pay_abc123",
      "amount": 2999,
      "currency": "usd",
      "customer": "cus_xyz789",
      "status": "succeeded"
    }
  }
}

The challenge with webhook payloads is that they can be deeply nested and contain dozens of fields. When you receive a webhook and need to quickly understand its structure, a formatter tool makes the data much easier to read and navigate.

Common Webhook Providers

Stripe Webhooks

Stripe sends webhooks for events like payment successes, failed charges, subscription changes, and invoice updates. Stripe payloads follow a consistent pattern with a top-level type field (like charge.succeeded or invoice.paid) and a nested data.object containing the full resource. Stripe payloads can be quite large, often exceeding 100 fields when you include nested customer, payment method, and metadata objects.

GitHub Webhooks

GitHub sends webhooks for repository events like pushes, pull requests, issues, releases, and deployments. The event type is specified in the X-GitHub-Event HTTP header rather than in the payload body. GitHub payloads include detailed information about the repository, the user who triggered the event, and the specific changes that were made:

{
  "action": "opened",
  "pull_request": {
    "number": 42,
    "title": "Fix login bug",
    "user": {
      "login": "octocat",
      "id": 1
    },
    "head": {
      "ref": "fix/login-bug",
      "sha": "abc123def456"
    },
    "base": {
      "ref": "main"
    }
  },
  "repository": {
    "full_name": "octocat/hello-world"
  }
}

Other Popular Providers

Slack sends webhooks for message events and interactive components. Shopify sends webhooks for orders, products, and customer updates. Twilio sends webhooks for incoming SMS messages and call status changes. Each provider has its own payload format, but they all share the same core concept: a JSON body describing what happened.

How to Use the PulpMiner Webhook Formatter

Paste your raw webhook payload into the input editor. The tool will automatically format the JSON with proper indentation, syntax highlighting, and collapsible sections for nested objects. You can expand and collapse sections to focus on the parts of the payload you care about.

The formatter also identifies the event type and timestamps, displaying them prominently so you can quickly understand what event triggered the webhook and when it occurred. If the payload contains Unix timestamps, the tool converts them to human-readable dates alongside the raw values.

Debugging Webhook Issues

When your webhook handler is not working as expected, the first step is always to inspect the raw payload. Common issues include expecting a field at the wrong nesting level, using the wrong event type string, not handling optional fields that may be null, and parsing timestamps incorrectly. By formatting the payload and reading it carefully, you can often identify the issue immediately.

Another common debugging technique is to compare payloads from different events. For example, a payment_intent.succeeded payload may have a different structure than a payment_intent.created payload. Using the formatter to inspect both side by side helps you understand the differences and write more robust handler code.

Best Practices for Handling Webhooks

  • Verify signatures: Most providers sign their webhooks with a secret key. Always verify the signature to ensure the payload has not been tampered with.
  • Respond quickly: Return a 200 status code immediately and process the webhook asynchronously. Most providers will retry if they do not receive a response within a few seconds.
  • Handle duplicates: Webhooks may be delivered more than once. Use the event ID to deduplicate and avoid processing the same event twice.
  • Log raw payloads: Store the raw webhook payload before processing it. This makes debugging much easier if something goes wrong.
  • Use a webhook testing tool: During development, use services like ngrok or localtunnel to expose your local server to the internet and receive real webhooks.

Need to extract data from websites?

PulpMiner turns any webpage into structured JSON data. No scraping code needed — just point, click, and get clean data.

Try PulpMiner Free

No credit card required