Testing webhooks can be challenging since they’re triggered by external events. This guide provides comprehensive strategies for testing your webhook implementations during development, staging, and production phases.

Testing strategies overview

Effective webhook testing involves multiple approaches:

Local development

Test on your development machine with tunneling tools

Staging environment

Test in production-like environment before going live

Production monitoring

Verify real-world performance with actual events

Automated testing

Include webhooks in your continuous integration pipeline

Local development testing

SDK Installation: Install the Rise SDK for secure webhook testing: npm install @riseworks/sdk

Setting up a local webhook endpoint

First, create a simple webhook endpoint for testing:
import express from 'express';
import { WebhookValidator } from '@riseworks/sdk';

const app = express();
app.use(express.raw({ type: 'application/json' }));

// Create validator with test secret
const validator = new WebhookValidator({
  secret: process.env.RISE_WEBHOOK_SECRET || 'test-secret',
  tolerance: 600 // 10 minutes
});

app.post('/webhook', async (req, res) => {
  const signature = req.headers['x-rise-signature'];

  console.log('📨 Webhook received:');
  console.log('Headers:', req.headers);
  console.log('Body:', req.body.toString());

  try {
    // Verify signature and get validated event
    const event = validator.validateEvent(req.body, signature);
    console.log('Success: Signature valid');

    console.log('Event details:');
    console.log('- Type:', event.event_type);
    console.log('- ID:', event.id);
    console.log('- Created:', new Date(event.created * 1000));

    res.status(200).json({ received: true });
  } catch (error) {
    console.error('Error: Error processing webhook:', error.message);
    res.status(400).send('Error processing webhook');
  }
});

const port = process.env.PORT || 3000;
app.listen(port, () => {
  console.log(`Webhook test server running on port ${port}`);
  console.log(`Webhook URL: http://localhost:${port}/webhook`);
});

Making your local endpoint accessible

Use tunneling tools to expose your local server to the internet:

Using Rise’s test webhook feature

The Rise app includes a built-in webhook testing tool:
1

Access test feature

Navigate to your webhook details page in the Rise app and click the “Test Webhook” button
2

Select event type

Choose an event type to simulate from the dropdown list (e.g., payment.sent, payment.group.created)
3

Choose version (optional)

If multiple event versions are available, select the version you want to test
4

Send test event

Click “Send Test Event” to deliver a test payload to your endpoint
5

Verify results

Check both the Rise app interface and your server logs to confirm the test was successful

Interpreting test results

The test interface shows:

Response status

HTTP status code returned by your endpoint (should be 200-299)

Response time

How long your endpoint took to respond (should be under 10 seconds)

Response body

What your endpoint returned (helpful for debugging)

Error details

Any connection or processing errors that occurred

Testing checklist

Before deploying your webhook implementation, verify all these aspects:

Functionality tests

Idempotency testing

Test that your webhook can safely handle duplicate events using the idempotency_key field:
// Test idempotency with duplicate events
async function testIdempotency() {
  const testEvent = {
    id: 'we-test123',
    object: 'event',
    created: Math.floor(Date.now() / 1000),
    event_type: 'payment.sent',
          event_version: '1.0',
    request_id: 'req_test789',
    idempotency_key: 'a1b2c3d4-e5f6-7890-abcd-ef1234567890', // UUID for duplicate detection
    payment: {
      nanoid: 'pa-test123',
      amount: '1000000',
      currency: 'USD',
      // ... other fields
    }
  };

  // Send the same event multiple times
  for (let i = 0; i < 3; i++) {
    const response = await fetch('http://localhost:3000/webhook', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'X-Rise-Signature': generateTestSignature(testEvent)
      },
      body: JSON.stringify(testEvent)
    });

    console.log(`Attempt ${i + 1}: ${response.status}`);
  }

  // Verify only one payment was processed using idempotency_key
  const processedEvents = await database.count('processed_webhooks', {
    idempotency_key: 'a1b2c3d4-e5f6-7890-abcd-ef1234567890'
  });
  console.log(`Event processed ${processedEvents} times (should be 1)`);
}

// Example idempotency handler implementation
function processWebhook(event) {
  const idempotencyKey = event.idempotency_key;

  // Check if already processed using idempotency_key
  const existingRecord = database.findByIdempotencyKey(idempotencyKey);
  if (existingRecord) {
    console.log(`Event ${idempotencyKey} already processed, skipping`);
    return { processed: false, status: "duplicate" };
  }

  // Process the event
  database.saveEvent({
    idempotency_key: idempotencyKey,
    event_type: event.event_type,
    processed_at: new Date(),
    event_data: event
  });

  // Trigger business logic
  handleBusinessLogic(event);

  return { processed: true, status: "success" };
}

Monitoring test webhook deliveries

Once your webhook is active, track its performance in the Rise app:
1

Navigate to webhook details

Go to your webhook details page in the Rise app
2

Access delivery history

Click on the “Delivery History” tab to see all webhook deliveries
3

Monitor key metrics

Track delivery success rates, response times, and error patterns
4

Set up alerts

Configure monitoring alerts for high failure rates or slow response times

Key metrics to track

Success rate

Target: >99%Percentage of successful first-attempt deliveries

Response time

Target: <2 secondsAverage time for your endpoint to respond

Error rate

Target: <1%Percentage of deliveries that ultimately fail
The delivery history shows:
  • Successful deliveries - Events delivered with 200 response
  • Failed deliveries - Events that couldn’t be delivered
  • Pending retries - Events waiting to be retried
  • Response details - HTTP status codes and response times

What’s next?

Now that you can test your webhooks effectively:
Testing tip: Test early, test often, and test everything. A well-tested webhook implementation prevents production surprises and ensures a reliable integration experience.