Add a Webhook Endpoint

How to Add a Webhook Endpoint

Overview

In order to start listening to chargeback events, you will need to configure your webhook endpoints. Adding an endpoint is as simple as providing a URL that you control and selecting the event types that you want to listen to.

Adding Your First Endpoint

Step 1: Prepare Your Endpoint URL

Your endpoint should be:

  • Publicly accessible - We need to be able to reach it from our servers
  • HTTPS enabled - For security, we only support HTTPS endpoints
  • POST request handler - Your endpoint should accept POST requests
  • Fast responding - Should return a response within 15 seconds

Example endpoint URLs:

https://api.yourcompany.com/webhooks/chargebacks
https://yourapp.com/api/v1/chargeback-webhooks
https://webhook-handler.yoursite.com/chargebacks

Step 2: Configure Event Types

When adding an endpoint, you can choose which events to receive:

  • All events (Recommended for testing): If you don't specify any event types, your endpoint will receive all events, regardless of type. This is helpful for getting started and testing.

  • Specific events (Recommended for production): Select only the events you need:

    • chargeback.created - New chargeback notifications
    • chargeback.updated - Chargeback data updates

Step 3: Add Through Dashboard

  1. Navigate to the Webhooks section in your dashboard
  2. Click "Add Endpoint"
  3. Enter your endpoint URL
  4. Select desired event types (or leave empty for all events)
  5. Save your configuration

Testing Before Production

If your endpoint isn't quite ready to start receiving live events, you have a couple of options:

Option 1: Use a Test URL

You can use services like:

  • ngrok - Create a tunnel to your local development server
  • webhook.site - Generate a temporary URL for testing
  • RequestBin - Inspect incoming webhook requests

Option 2: Svix Play Integration

Press the "with Svix Play" button to have a unique URL generated for you. You'll be able to view and inspect webhooks sent to your Svix Play URL, making it effortless to get started without setting up your own endpoint immediately.

Endpoint Implementation Example

Here's a basic NestJS controller example for handling webhook events:

import { Controller, Post, Body, Headers, HttpCode, HttpStatus } from '@nestjs/common';
import { WebhookEvent, ChargebackDto } from './interfaces/webhook.interface';

@Controller('webhooks/chargebacks')
export class WebhookController {
  
  @Post()
  @HttpCode(HttpStatus.OK)
  async handleWebhook(
    @Body() event: WebhookEvent,
    @Headers() headers: Record<string, string>
  ) {
    try {
      // Verify webhook signature (see signature verification section)
      this.verifyWebhookSignature(JSON.stringify(event), headers);
      
      // Process the event based on type
      switch (event.event) {
        case 'chargeback.created':
          await this.handleChargebackCreated(event.data);
          break;
        case 'chargeback.updated':
          await this.handleChargebackUpdated(event.data);
          break;
        default:
          console.log(`Unhandled event type: ${event.event}`);
      }
      
      // Return success status
      return { received: true };
      
    } catch (error) {
      console.error('Webhook processing failed:', error);
      throw error; // This will return a 5xx status code
    }
  }
  
  private async handleChargebackCreated(chargeback: ChargebackDto) {
    // Your business logic for new chargebacks
    console.log(`New chargeback created: ${chargeback.id}`);
    // Save to database, trigger notifications, etc.
  }
  
  private async handleChargebackUpdated(chargeback: ChargebackDto) {
    // Your business logic for updated chargebacks
    console.log(`Chargeback updated: ${chargeback.id}`);
    // Update database, notify relevant parties, etc.
  }
  
  private verifyWebhookSignature(payload: string, headers: Record<string, string>) {
    // Implementation details in the Signature Verification section
  }
}

Best Practices

1. Idempotency

Always design your webhook handler to be idempotent. You may receive the same event multiple times due to retries, so ensure your system can handle duplicate events gracefully.

// Example: Check if event was already processed
const existingWebhook = await this.webhookLogService.findByWebhookId(event.webhookId);
if (existingWebhook) {
  return { received: true, status: 'already_processed' };
}

2. Asynchronous Processing

For complex workflows, consider processing webhooks asynchronously to respond quickly:

@Post()
@HttpCode(HttpStatus.OK)
async handleWebhook(@Body() event: WebhookEvent) {
  // Quickly validate and queue the event
  await this.webhookQueue.add('process-chargeback-event', event);
  
  // Respond immediately
  return { received: true, queued: true };
}

3. Logging and Monitoring

Log all webhook events for debugging and monitoring:

// Log the incoming webhook for audit trail
this.logger.log({
  message: 'Webhook received',
  event: event.event,
  webhookId: event.webhookId,
  merchantUuid: event.merchantUuid,
  timestamp: event.timestamp
});

Security Considerations

  • Always verify signatures (detailed in the next section)
  • Use HTTPS only for your webhook endpoints
  • Disable CSRF protection for webhook routes
  • Validate payload structure before processing
  • Rate limit your webhook endpoints if necessary