Getting Started with HookRelay#

HookRelay is a webhook delivery platform designed specifically for Next.js applications. It ensures your webhooks are delivered reliably, exactly once, with full observability—even in serverless environments like Vercel.

Why HookRelay?#

If you’ve ever experienced these problems with webhooks in Next.js:

  • “Stripe says the webhook was delivered, but my code didn’t run”
  • “The same webhook processed twice, causing duplicate charges”
  • “My webhook handler timed out, but I have no idea why”
  • “I can’t tell if a webhook actually succeeded or failed”

HookRelay solves all of these by acting as a reliable relay between webhook providers (like Stripe, GitHub, Shopify) and your Next.js application.

How It Works#

HookRelay Architecture

HookRelay sits between your webhook provider and your Next.js application, ensuring reliable delivery with automatic retries and full observability.

HookRelay sits between your webhook provider and your application, guaranteeing:

  • Guaranteed receipt - Once received, events are never lost
  • Exactly-once execution - Your handler runs once per event (unless explicitly replayed)
  • Automatic retries - Failed deliveries are retried with exponential backoff
  • Full visibility - See every event, attempt, and failure in the dashboard

Prerequisites#

  • A Next.js application (App Router recommended)
  • Node.js 18+ installed
  • An account with a webhook provider (Stripe, GitHub, Shopify, etc.)

Step 1: Create a HookRelay Account#

  1. Sign up at hookrelay.io
  2. Verify your email address
  3. You’ll be taken to the dashboard

Step 2: Install the SDK#

In your Next.js project, install the HookRelay SDK:

npm install @hookrelay/next
# or
pnpm add @hookrelay/next
# or
yarn add @hookrelay/next

Step 3: Create a Webhook Endpoint in HookRelay#

  1. In the HookRelay dashboard, navigate to Endpoints

  2. Click “Create Endpoint”

  3. Configure your endpoint:

    • Provider: Select your webhook provider (e.g., Stripe, GitHub, Shopify)
    • Forward URL: This will be your Next.js API route URL (we’ll create this next)
    • Provider Secret (optional): Your provider’s webhook signing secret for additional verification
  4. After creating, you’ll receive:

    • HookRelay Webhook URL: https://api.hookrelay.io/v1/webhooks/{endpoint-id}
    • HookRelay Secret: Used to verify webhooks in your Next.js app

Step 4: Create Your Next.js Webhook Handler#

Create a new API route in your Next.js app. For example, for Stripe webhooks:

// app/api/webhooks/stripe/route.ts
import { withHookRelay } from '@hookrelay/next';

export const POST = withHookRelay(
  async (event) => {
    const stripeEvent = event.payload;

    // Handle different event types
    switch (stripeEvent.type) {
      case 'checkout.session.completed':
        // Fulfill the order
        await fulfillOrder(stripeEvent.data.object);
        break;

      case 'customer.subscription.created':
        // Activate subscription
        await activateSubscription(stripeEvent.data.object);
        break;

      case 'invoice.payment_succeeded':
        // Record payment
        await recordPayment(stripeEvent.data.object);
        break;

      default:
        console.log(`Unhandled event type: ${stripeEvent.type}`);
    }
  },
  { provider: 'stripe' },
);

That’s it! The withHookRelay wrapper automatically:

  • Verifies the webhook signature
  • Ensures exactly-once execution
  • Reports success/failure back to HookRelay
  • Handles retries automatically

Step 5: Configure Environment Variables#

Add your HookRelay secret to your environment variables:

# .env.local
HOOKRELAY_SECRET=hr_secret_...

You can find your HookRelay secret in the endpoint details page in the dashboard.

Step 6: Update Your Forward URL#

  1. Deploy your Next.js application (or use a local tunnel like ngrok for development)
  2. Get your webhook handler URL (e.g., https://your-app.com/api/webhooks/stripe)
  3. In the HookRelay dashboard, update your endpoint’s Forward URL to point to this URL

Step 7: Configure Your Provider#

  1. In your provider’s dashboard (e.g., Stripe Dashboard), go to Webhooks
  2. Add a new webhook endpoint
  3. Use your HookRelay Webhook URL (from Step 3) as the endpoint URL
  4. Select the events you want to receive
  5. Save the webhook

Step 8: Test Your Integration#

  1. Trigger a test event from your provider (e.g., Stripe’s “Send test webhook”)
  2. Check the HookRelay dashboard’s Events page
  3. You should see the event appear with status “Received” → “Forwarded” → “Succeeded”
  4. Verify your Next.js handler executed correctly

Understanding the Event Object#

The event parameter in your handler contains:

{
  id: string; // HookRelay event ID
  provider: 'stripe'; // Provider name
  providerEventId: string; // Original provider event ID
  payload: StripeEvent; // The webhook payload (typed)
  receivedAt: string; // ISO timestamp
  attempt: number; // Delivery attempt number (1-based)
  replayed: boolean; // Whether this is a replayed event
}

Common Patterns#

Handling Multiple Event Types#

export const POST = withHookRelay(
  async (event) => {
    const stripeEvent = event.payload;

    if (stripeEvent.type === 'checkout.session.completed') {
      await handleCheckoutCompleted(stripeEvent);
    } else if (stripeEvent.type === 'customer.subscription.deleted') {
      await handleSubscriptionDeleted(stripeEvent);
    }
    // ... handle other types
  },
  { provider: 'stripe' },
);

Processing Asynchronously#

For long-running operations, return quickly and process in the background:

export const POST = withHookRelay(
  async (event) => {
    const stripeEvent = event.payload;

    // Return immediately
    if (stripeEvent.type === 'checkout.session.completed') {
      // Queue for background processing
      await queueOrderFulfillment(stripeEvent.data.object);
    }
  },
  { provider: 'stripe' },
);

Using Event Metadata#

export const POST = withHookRelay(
  async (event) => {
    console.log(`Processing event ${event.id}`);
    console.log(`Attempt ${event.attempt}`);
    console.log(`Replayed: ${event.replayed}`);

    // Use provider event ID for idempotency
    const providerEventId = event.providerEventId;
    // ... your logic
  },
  { provider: 'stripe' },
);

Next Steps#

Troubleshooting#

Webhook Not Appearing in Dashboard#

  • Verify your provider is sending to the correct HookRelay URL
  • Check that the endpoint exists and is active
  • Ensure your provider secret is correct (if configured)

Handler Not Receiving Events#

  • Verify your Forward URL is correct and publicly accessible
  • Check that HOOKRELAY_SECRET environment variable is set
  • Ensure your Next.js app is deployed and accessible
  • Check the Events page for delivery attempts and error messages

Signature Verification Failing#

  • Verify your HOOKRELAY_SECRET matches the secret shown in the endpoint details
  • Ensure you’re using the HookRelay secret, not the provider secret
  • Check that the secret is set in your environment variables

Need Help?#