OpenAI Webhooks Implementation Guide: Setup & Best Practices

Updated September 25, 202510 min read

OpenAI webhooks enable efficient handling of long-running API tasks like the Deep Research API. Instead of polling for completion, webhooks push real-time notifications when operations finish. This guide covers implementation, security, and best practices.

When to Use OpenAI Webhooks

OpenAI webhooks are ideal for operations that don't require immediate responses or take significant time to complete. Key use cases include:

  • Deep Research API requests that process large datasets
  • Batch processing operations
  • Long-running AI model inference tasks
  • File processing and analysis workflows
  • Any task where polling would be inefficient

OpenAI Webhook Setup Process

Step 1: Project Configuration

Webhooks are configured per-project in OpenAI:

  1. Navigate to your OpenAI project dashboard
  2. Select the project where you want to configure webhooks
  3. Go to the Webhooks section in project settings
  4. Click "Create" to add a new webhook endpoint
  5. Enter your webhook URL (must be HTTPS for production)
  6. Select the events you want to receive
  7. Save the configuration and copy the signing secret

Important: Save Your Signing Secret

The signing secret is shown only once when you create the webhook. Store it securely in your environment variables - you'll need it for signature verification.

Step 2: Webhook Endpoint Implementation

Your webhook endpoint must:

  • Accept POST requests with JSON payloads
  • Return 2xx status code within a few seconds
  • Verify webhook signatures for security
  • Handle requests idempotently
// Python Flask example with OpenAI client
from flask import Flask, request, jsonify from openai import OpenAI import os app = Flask(__name__) client = OpenAI() webhook_secret = os.environ.get('OPENAI_WEBHOOK_SECRET') @app.route('/openai/webhook', methods=['POST']) def handle_openai_webhook(): try: # Verify and unwrap the webhook event = client.webhooks.unwrap( request.data, request.headers, secret=webhook_secret ) # Process the event process_openai_event(event) return jsonify({"status": "success"}), 200 except Exception as e: print(f"Webhook error: {e}") return jsonify({"error": str(e)}), 400 def process_openai_event(event): if event.type == "research.completed": handle_research_completion(event.data) elif event.type == "batch.completed": handle_batch_completion(event.data) else: print(f"Unhandled event type: {event.type}")

Webhook Signature Verification

Understanding OpenAI Signatures

OpenAI includes verification headers with each webhook:

user-agent: OpenAI/1.0 content-type: application/json webhook-id: msg_1234567890abcdef webhook-timestamp: 1672531200 webhook-signature: v1,signature_here

The signature follows the standard-webhooks specification and must be verified to ensure authenticity.

Implementation Examples

// Python with OpenAI client (recommended)
import openai def verify_webhook(request_data, headers, secret): try: event = client.webhooks.unwrap( request_data, headers, secret=secret ) return event except Exception as e: print(f"Signature verification failed: {e}") raise
// Node.js example
const OpenAI = require('openai'); const openai = new OpenAI(); app.post('/webhook', (req, res) => { try { const event = openai.webhooks.unwrap( req.body, req.headers, process.env.OPENAI_WEBHOOK_SECRET ); // Process the verified event processEvent(event); res.status(200).json({ received: true }); } catch (error) { console.error('Webhook verification failed:', error); res.status(400).json({ error: 'Invalid signature' }); } });

Local Development and Testing

Using ngrok for Local Testing

OpenAI recommends using ngrok to create a secure tunnel for local development:

# Install ngrok
npm install -g ngrok
# Start your local server
python app.py # Running on localhost:5000
# Create public tunnel
ngrok http 5000
# Use the HTTPS URL for webhook configuration
https://abc123.ngrok.io/openai/webhook

Configure this ngrok URL in your OpenAI project webhook settings for local testing.

Testing Webhook Events

Test your webhook implementation by:

  • Triggering actual OpenAI API operations that generate webhooks
  • Using OpenAI's test event functionality (when available)
  • Creating mock webhook payloads for unit testing
  • Validating signature verification with test secrets

Webhook Event Types

Deep Research Events

  • research.started - Research task initiated
  • research.completed - Research finished successfully
  • research.failed - Research task failed
  • research.cancelled - Task was cancelled

Batch Processing Events

  • batch.created - Batch processing started
  • batch.completed - All items processed
  • batch.failed - Batch processing failed
  • batch.progress - Progress update

Webhook Payload Structure

{ "id": "evt_1234567890", "type": "research.completed", "created_at": "2025-01-25T10:30:00Z", "data": { "id": "research_abc123", "object": "research", "status": "completed", "results": { "summary": "Research findings...", "sources": [...], "confidence_score": 0.95 }, "created_at": "2025-01-25T10:00:00Z", "completed_at": "2025-01-25T10:30:00Z" }, "api_version": "2025-01-15" }

Production Best Practices

⚡ Handle Retries Properly

OpenAI retries failed webhooks with exponential backoff for up to 72 hours:

app.post('/webhook', (req, res) => { // Always return 2xx for successful processing // Return 4xx for permanent failures (don't retry) // Return 5xx for temporary failures (will retry) try { const event = verifyAndUnwrap(req); processEvent(event); res.status(200).json({ processed: true }); } catch (error) { if (error.type === 'signature_invalid') { // Don't retry signature failures return res.status(400).json({ error: 'Invalid signature' }); } // Temporary error - OpenAI will retry res.status(500).json({ error: 'Processing failed' }); } });

🔄 Implement Idempotency

Handle duplicate webhooks gracefully using event IDs:

processed_events = set() def process_webhook(event): event_id = event.get('id') if event_id in processed_events: print(f"Duplicate event ignored: {event_id}") return {"status": "already_processed"} # Process the event result = handle_event(event) # Mark as processed processed_events.add(event_id) return result

📊 Monitoring and Logging

  • • Log all webhook receipts with timestamps
  • • Track processing success/failure rates
  • • Monitor signature verification failures
  • • Set up alerts for webhook downtime
  • • Dashboard for webhook health metrics

Common Troubleshooting Issues

Common Issues and Solutions:

  • ⚠️
    Signature Verification Fails: Ensure you're using the correct signing secret and passing the raw request body to verification.
  • ⚠️
    Webhooks Not Received: Check that your endpoint is publicly accessible via HTTPS and returns 2xx status codes.
  • ⚠️
    Timeout Issues: Respond within a few seconds. Use async processing for long-running tasks.
  • ⚠️
    Duplicate Events: Implement idempotency checks using the event ID to handle retries gracefully.

Debug OpenAI Webhooks with Hooklistener

Hooklistener provides comprehensive webhook debugging for OpenAI integrations. Capture, inspect, and replay webhook events with signature verification, retry tracking, and team collaboration features.

Real-time OpenAI webhook capture
Signature verification testing
Event replay and debugging tools
Retry and failure monitoring
Start Debugging OpenAI Webhooks →

Related OpenAI Resources