When developing webhook integrations, you need to test how your application handles Helicone events before deploying to production. Webhooks local testing uses tunneling tools like ngrok to expose your local development server to the internet, allowing Helicone to send real webhook events to your local machine for debugging and integration testing.

Why use Webhooks Local Testing

  • Debug integration issues: Test webhook handlers with real events before deploying to production
  • Iterate quickly: Make changes to your webhook handler and test immediately without deployment cycles
  • Validate event handling: Ensure your application correctly processes different webhook event types and payloads

Quick Start

1

Create webhook handler

Set up a local server to receive webhook events:
from fastapi import FastAPI, Request
import json

app = FastAPI()

@app.post("/webhook")
async def webhook_handler(request: Request):
    # Parse the webhook payload
    payload = await request.json()
    
    # Log the event for debugging
    print(f"Received event: {payload['event_type']}")
    print(f"Request ID: {payload['request_id']}")
    
    # Your webhook logic here
    # e.g., store in database, trigger notifications, etc.
    
    return {"status": "success"}

# Run with: uvicorn main:app --reload --port 8000
2

Set up ngrok tunnel

Install and configure ngrok to expose your local server:
# Install ngrok (macOS)
brew install ngrok

# Or download from https://ngrok.com/download

# Start tunnel to your local server
ngrok http 8000
You’ll see output like:
Forwarding  https://abc123.ngrok-free.app -> http://localhost:8000
Copy the HTTPS URL for the next step.
3

Configure webhook in Helicone

Add your ngrok URL to Helicone’s webhook settings:
  1. Go to your Helicone dashboard → Settings → Webhooks
  2. Click “Add Webhook”
  3. Enter your ngrok URL with the webhook path: https://abc123.ngrok-free.app/webhook
  4. Select the events you want to receive
  5. Save the webhook configuration

Use Cases

Test webhook integration during local development:
from fastapi import FastAPI, Request, HTTPException
import json
import logging

app = FastAPI()
logger = logging.getLogger(__name__)

@app.post("/webhook/helicone")
async def helicone_webhook(request: Request):
    try:
        payload = await request.json()
        
        # Log full payload for debugging
        logger.info(f"Webhook payload: {json.dumps(payload, indent=2)}")
        
        # Process the webhook payload
        request_id = payload["request_id"]
        model = payload.get("model")
        cost = payload.get("cost", 0)
        user_id = payload.get("user_id")
        
        logger.info(f"Webhook for request {request_id}")
        logger.info(f"Model: {model}, Cost: {cost}")
        
        if user_id:
            logger.info(f"User: {user_id}")
            
        # Check if this is a high-cost request
        if cost > 1.0:
            logger.warning(f"High cost request detected: {cost}")
        
        return {"status": "processed"}
        
    except Exception as e:
        logger.error(f"Webhook error: {str(e)}")
        raise HTTPException(status_code=500, detail=str(e))

# Test with property filter
# Add header: Helicone-Property-Environment: development