How to Use Hookdeck.com to Test and Debug Webhooks

How to Use Hookdeck to Test and Debug Webhooks

With the introduction of more easily accessible no-code tools like N8N, webhooks have become a “must-have” when deciding which service to choose. But then you have to test what they return! This piece aims to help with that.

Contents

Webhooks are the backbone of modern web applications, enabling real-time communication between services. But testing and debugging them can be a nightmare, especially when you’re dealing with third-party services, local development environments, or unreliable network connections.

What Is a Webhook and How Does It Work?

What is a webhook?

A webhook is essentially a “reverse API call” – instead of your application polling another service for updates, the external service pushes data to your application when something interesting happens.

Think of it like this: instead of constantly asking “Are we there yet?” on a road trip, webhooks are like getting a text message when you arrive at your destination.

Here’s the typical webhook flow:

  1. Setup: You provide a webhook URL to an external service
  2. Event occurs: Something happens in the external service (user signs up, payment processed, form submitted)
  3. Notification: The service sends an HTTP POST request to your webhook URL with event data
  4. Processing: Your application receives and processes the webhook payload

This real-time communication pattern is crucial for building responsive applications that need to react immediately to external events.

Real-World Webhook Examples

Let’s look at some common webhook use cases that you’ll encounter as a developer:

FormBear

FormBear is a modern form management platform that sends webhooks whenever forms are submitted. This is perfect for triggering automated workflows like:

  • Sending welcome emails to new subscribers
  • Creating leads in your CRM
  • Triggering Slack notifications for support requests
  • Updating analytics dashboards in real-time

When a user submits a FormBear form, you’ll receive a webhook payload like this:

{
  "id": "b8bf41bf-d634-41e1-bad2-a50754045215",
  "data": {
    "fields": {
      "name": "Sarah Johnson",
      "email": "sarah@example.com",
      "message": "I'd love to learn more about your services!"
    },
    "submission_id": "sub_1753966250344"
  },
  "form": {
    "id": "contact-form-123",
    "name": "Contact Form"
  },
  "event": "form.submitted",
  "metadata": {
    "ip_address": "192.168.1.100",
    "user_agent": "Mozilla/5.0...",
    "submitted_at": "2025-01-15T14:30:45.344Z"
  }
}

Stripe

Stripe is the gold standard for payment processing, and their webhooks are crucial for building reliable payment flows. Stripe sends webhooks for dozens of different events, but some of the most important ones include:

Payment Events:

  • invoice.payment_succeeded – A payment was successfully processed
  • invoice.payment_failed – A payment attempt failed
  • payment_intent.succeeded – One-time payment completed successfully

Subscription Events:

  • customer.subscription.created – New subscription started
  • customer.subscription.updated – Subscription plan changed
  • customer.subscription.deleted – Subscription canceled

Customer Events:

  • customer.created – New customer account created
  • customer.updated – Customer information changed

Here’s a real example of an invoice.payment_succeeded webhook that Stripe would send when a customer successfully pays their subscription:

{
  "object": {
    "id": "in_1Rql02frY8V0rQXKfgb",
    "object": "invoice",
    "account_name": "Your Stripe Account",
    "amount_due": 4900,
    "amount_paid": 4900,
    "amount_remaining": 0,
    "billing_reason": "subscription_create",
    "currency": "gbp",
    "customer": "cus_Sm48uvqLyN",
    "customer_email": "hello@yourdomain.dev",
    "status": "paid",
    "lines": {
      "data": [
        {
          "id": "il_1RqlrYQCM8ViOeXS",
          "amount": 4900,
          "currency": "gbp",
          "description": "1 × Pro (at £49.00 / month)",
          "period": {
            "end": 1756603816,
            "start": 1753925416
          }
        }
      ]
    },
    "hosted_invoice_url": "https://invoice.stripe.com/i/acct_1RqLqYQCM8V0/test_...",
    "invoice_pdf": "https://pay.stripe.com/invoice/acct_1RqLqXQCM8V0/test_.../pdf"
  }
}

This webhook tells you that customer hello@yourdomain.dev just successfully paid £49.00 for a Pro subscription. In your application, you might use this to:

  • Upgrade the user’s account to Pro features immediately
  • Send a confirmation email with the invoice PDF link
  • Update your analytics to track monthly recurring revenue
  • Sync with your CRM to mark the customer as an active subscriber
  • Grant access to premium features or content

The beauty of Stripe webhooks is their reliability – even if your server is down when the payment processes, Stripe will keep retrying the webhook delivery.

GitHub

GitHub webhooks are the backbone of modern DevOps workflows, automatically triggering actions when code changes occur. The most common webhook is the push event, which fires whenever commits are pushed to a repository.

The push webhook is incredibly detailed, containing information about:

  • What changed: Before/after commit SHAs and the full diff
  • Who made the change: Author and pusher information
  • Where it happened: Repository, branch, and organization details
  • Commit details: All commits in the push (up to 2048 commits)

Here’s what a typical push webhook payload looks like when someone pushes new code:

{
  "ref": "refs/heads/main",
  "before": "6113728f27ae82b1a177c8d03f9e96edf246",
  "after": "0d1a26e67d8f5e1f6ba5c57fc3c71ac0fd1c",
  "created": false,
  "deleted": false,
  "forced": false,
  "base_ref": null,
  "compare": "https://github.com/octocat/Hello-World/compare/6113728f27ae...0d1a26e67d8f",
  "commits": [
    {
      "id": "0d1a26e67d8f5eaf1f6ba5c57fc3c7d91ac0fd1c",
      "tree_id": "f9d2a07e9488b91af2641b26b9407fe22a451433",
      "message": "Fix user authentication bug",
      "author": {
        "name": "Sarah Johnson",
        "email": "sarah@example.com",
        "username": "sarahj"
      },
      "url": "https://github.com/octocat/Hello-World/commit/0d1a26e67d8f5eaf1f6ba5c57fc3c7d91ac0fd1c",
      "added": ["src/auth.js"],
      "removed": [],
      "modified": ["README.md", "package.json"]
    }
  ],
  "head_commit": {
    "id": "0d1a26e67d8f5eaf1f6ba5c57fc3c7d91ac0fd1c",
    "message": "Fix user authentication bug",
    "author": {
      "name": "Sarah Johnson",
      "email": "sarah@example.com"
    }
  },
  "repository": {
    "id": 1296269,
    "name": "Hello-World",
    "full_name": "octocat/Hello-World",
    "html_url": "https://github.com/octocat/Hello-World",
    "default_branch": "main"
  },
  "pusher": {
    "name": "sarahj",
    "email": "sarah@example.com"
  }
}

This webhook tells you that Sarah Johnson just pushed a commit to the main branch that:

  • Fixed a user authentication bug
  • Added a new src/auth.js file
  • Modified the README and package.json files

In practice, you’d use this webhook to:

  • Trigger CI/CD pipelines: Automatically run tests, build the app, and deploy to staging
  • Update project management: Create deployment tickets or update issue status
  • Send notifications: Alert the team in Slack about new deployments
  • Run security scans: Automatically scan new code for vulnerabilities
  • Update documentation: Regenerate API docs or deployment guides

The beauty of GitHub’s webhook system is that it gives you enough detail to make intelligent decisions about what actions to take based on the specific changes.

Testing Webhooks with Hookdeck: Step-by-Step

Let’s walk through setting up Hookdeck to test webhooks from FormBear (you can apply these same steps to any webhook provider).

Step 1: Set Up Your Hookdeck Project

Navigate to hookdeck.com and create a free account. You’ll land on the getting started page where you can create your first connection.

The interface is clean and intuitive – you’ll see options to create connections for routing events through Hookdeck’s infrastructure.

Step 2: Create an Event Source

Click “Create a connection” to set up your first webhook source. You’ll need to:

  1. Choose Source Type: Select “Webhook” since we’re receiving HTTP requests from FormBear
  2. Name Your Source: Use a descriptive name like “formbear-prod” or “contact-form-webhooks”
  3. Configure Authentication: Leave this disabled for now (you can add signature verification later)

The source represents the producer of your webhooks – in this case, FormBear’s form submission events.

Step 3: Get Your Webhook URL

Once you create the source, Hookdeck generates a unique URL for receiving webhooks. It will look something like:

https://hkdk.events/x31mwm3dg0tje9

This URL is what you’ll provide to FormBear (or any other service) to start receiving webhooks. Copy this URL – you’ll need it in the next step.

Step 4: Send Test Webhooks

Now let’s configure FormBear to send webhooks to your Hookdeck URL:

  1. Log into FormBear: Navigate to your FormBear dashboard
  2. Go to Webhooks: Click on the “Webhooks” section in the sidebar
  3. Create New Webhook: Click “Create Webhook” or similar button
  4. Configure the Webhook:
    • URL: Paste your Hookdeck URL
    • Events: Select “form.submitted” and any other events you want to monitor
    • Name: Give it a descriptive name like “Hookdeck Test”
  5. Test the Webhook: Use FormBear’s built-in test feature to send a sample webhook

You’ll need a FormBear account to follow along exactly, but you can use any webhook-enabled service or even send manual POST requests with curl to test the same concepts.

Step 5: Monitor and Debug

Return to your Hookdeck dashboard and you should see the webhook request appear in your “Requests” view. Hookdeck provides detailed information about each request:

  • Request Details: Method, headers, query parameters
  • Payload: Full JSON body with syntax highlighting
  • Response: Status codes and response bodies
  • Timing: Request duration and retry attempts
  • Routing: Which destinations received the webhook

You can click on any request to see complete details, making debugging much easier than parsing server logs.