Skip to content

Complete guide to testing webhooks locally with Volley. Examples in Node.js, Python, and Go. Works with any framework, any language, any webhook provider.

Notifications You must be signed in to change notification settings

volleyhq/volley-local-dev-example

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

1 Commit
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Volley Local Development Guide

Complete guide to testing webhooks locally with Volley - Works with any framework, any language, any webhook provider.

Volley License: MIT

This repository demonstrates how to test webhooks locally using Volley with various frameworks and languages. No ngrok, no tunneling, no exposing your server.

🎯 What You'll Learn

  • How to set up Volley for local webhook testing
  • How to use Volley CLI to forward webhooks
  • Examples in multiple languages and frameworks
  • Best practices for local webhook development

πŸš€ Quick Start

Prerequisites

Installation

  1. Install Volley CLI:

    # macOS
    brew tap volleyhq/volley
    brew install volley
    
    # Linux
    wget https://github.com/volleyhq/volley-cli/releases/latest/download/volley-linux-amd64.tar.gz
    tar -xzf volley-linux-amd64.tar.gz
    sudo mv volley /usr/local/bin/
  2. Login to Volley:

    volley login
  3. Create a webhook source:

    • Go to Volley Dashboard
    • Create a new source
    • Copy your ingestion ID (e.g., abc123xyz)
  4. Configure your webhook provider:

    • Add your Volley webhook URL: https://api.volleyhooks.com/hook/YOUR_INGESTION_ID
    • Configure in Stripe, GitHub, Twilio, etc.
  5. Start your local server (see examples below)

  6. Forward webhooks to localhost:

    volley listen --source YOUR_INGESTION_ID --forward-to http://localhost:3000/webhook

πŸ“š Examples

Node.js / Express

// server.js
const express = require('express');
const app = express();

app.use(express.json());

app.post('/webhook', (req, res) => {
  console.log('Webhook received:', req.body);
  // Your webhook handling logic here
  res.json({ received: true });
});

app.listen(3000, () => {
  console.log('Server running on http://localhost:3000');
});

Forward webhooks:

volley listen --source abc123xyz --forward-to http://localhost:3000/webhook

Python / Flask

# app.py
from flask import Flask, request, jsonify

app = Flask(__name__)

@app.route('/webhook', methods=['POST'])
def webhook():
    data = request.json
    print(f'Webhook received: {data}')
    # Your webhook handling logic here
    return jsonify({'received': True})

if __name__ == '__main__':
    app.run(port=3000)

Forward webhooks:

volley listen --source abc123xyz --forward-to http://localhost:3000/webhook

Python / FastAPI

# main.py
from fastapi import FastAPI
from pydantic import BaseModel

app = FastAPI()

class WebhookData(BaseModel):
    event: str
    data: dict

@app.post("/webhook")
async def webhook(data: WebhookData):
    print(f'Webhook received: {data}')
    # Your webhook handling logic here
    return {"received": True}

Run:

uvicorn main:app --port 3000
volley listen --source abc123xyz --forward-to http://localhost:3000/webhook

Go

// main.go
package main

import (
    "encoding/json"
    "fmt"
    "log"
    "net/http"
)

func webhookHandler(w http.ResponseWriter, r *http.Request) {
    var data map[string]interface{}
    json.NewDecoder(r.Body).Decode(&data)
    
    fmt.Printf("Webhook received: %+v\n", data)
    // Your webhook handling logic here
    
    w.Header().Set("Content-Type", "application/json")
    json.NewEncoder(w).Encode(map[string]bool{"received": true})
}

func main() {
    http.HandleFunc("/webhook", webhookHandler)
    log.Println("Server running on http://localhost:3000")
    log.Fatal(http.ListenAndServe(":3000", nil))
}

Run:

go run main.go
volley listen --source abc123xyz --forward-to http://localhost:3000/webhook

Ruby / Sinatra

# app.rb
require 'sinatra'
require 'json'

post '/webhook' do
  data = JSON.parse(request.body.read)
  puts "Webhook received: #{data}"
  # Your webhook handling logic here
  { received: true }.to_json
end

Run:

ruby app.rb
volley listen --source abc123xyz --forward-to http://localhost:3000/webhook

πŸ”„ Multiple Destinations

You can forward the same webhook source to multiple local endpoints:

# Terminal 1: Main API
volley listen --source abc123xyz --forward-to http://localhost:3000/webhook

# Terminal 2: Webhook processor
volley listen --source abc123xyz --forward-to http://localhost:3001/process

# Terminal 3: Logging service
volley listen --source abc123xyz --forward-to http://localhost:3002/log

πŸ†š Why Volley Instead of ngrok?

Feature Volley ngrok
Webhook URLs βœ… Permanent, never change ❌ Change on restart
Tunneling ❌ Not required βœ… Required
Local Server Privacy βœ… Completely private ⚠️ Exposed through tunnel
Built-in Retry βœ… Automatic ❌ No
Monitoring βœ… Full dashboard ❌ Limited
Production Ready βœ… Same URL for dev/prod ❌ Dev tool only
Offline Support βœ… Webhooks queued ❌ Must be online

Learn more: Volley vs ngrok

πŸ” Security Best Practices

1. Verify Webhook Signatures

Always verify webhook signatures when available:

// Example: Stripe webhook verification
const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);
const event = stripe.webhooks.constructEvent(
  req.body,
  req.headers['stripe-signature'],
  process.env.STRIPE_WEBHOOK_SECRET
);

2. Use Environment Variables

Never commit secrets:

# .env
WEBHOOK_SECRET=your_secret_here

3. Idempotency

Handle duplicate webhooks:

const eventId = req.body.id;
if (await isEventProcessed(eventId)) {
  return; // Already processed
}
await markEventAsProcessed(eventId);

πŸ§ͺ Testing

Manual Testing

  1. Trigger a webhook from your provider (Stripe, GitHub, etc.)
  2. Watch it appear in your local server logs
  3. Check Volley dashboard for delivery status

Automated Testing

// test/webhook.test.js
const request = require('supertest');
const app = require('../server');

test('handles webhook', async () => {
  const response = await request(app)
    .post('/webhook')
    .send({ event: 'test', data: {} });
  
  expect(response.status).toBe(200);
});

πŸ“š Additional Resources

🀝 Contributing

Found a bug or want to add an example? Please open an issue or submit a pull request!

πŸ“„ License

MIT License - See LICENSE file for details


Built with ❀️ using Volley

About

Complete guide to testing webhooks locally with Volley. Examples in Node.js, Python, and Go. Works with any framework, any language, any webhook provider.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published