Skip to main content
Nectr uses GitHub webhooks to receive real-time notifications when pull requests are opened or updated. This guide explains how webhooks are configured, verified, and processed.

Overview

When you connect a repository in Nectr, the system automatically:
  1. Creates a webhook on the GitHub repository
  2. Generates a unique secret for signature verification
  3. Configures the webhook to listen for PR events
  4. Stores the webhook secret in the database
Webhook Flow:

Automatic Webhook Installation

Webhooks are automatically installed when you connect a repository through the Nectr UI.

Installation Process

1

User Connects Repository

User clicks “Connect” on a repository in the Nectr dashboard.Frontend calls: POST /api/v1/repos/{owner}/{repo}/install
2

Generate Webhook Secret

Backend generates a cryptographically secure random secret:
3

Install Webhook via GitHub API

Backend calls GitHub API to create the webhook:
Events subscribed:
  • pull_request - PR opened, updated, closed, etc.
  • issues - Issue opened, updated, closed, etc.
4

Store Webhook in Database

Backend saves the webhook ID and secret:
Source: app/integrations/github/webhook_manager.py:10-48

Webhook Configuration

Webhook Properties

Per-Repo vs Global Secrets

Nectr uses per-repository webhook secrets for security:
  • ✅ Each repository has a unique webhook secret
  • ✅ Secrets are generated automatically on connection
  • ✅ Stored in the database installations table
  • ✅ Falls back to GITHUB_WEBHOOK_SECRET env var if not found

Signature Verification

Nectr verifies that webhook requests actually came from GitHub using HMAC-SHA256 signature verification.

How It Works

GitHub calculates an HMAC-SHA256 signature of the webhook payload using the secret you provided:
This signature is sent in the X-Hub-Signature-256 header.
Why hmac.compare_digest()? Prevents timing attacks by comparing strings in constant time.
  • Development: Signature verification is skipped
  • Production: Invalid signatures are rejected with 403
In production, webhooks with invalid signatures are rejected to prevent:
  • Spoofed webhook requests
  • Replay attacks
  • Unauthorized access to the webhook endpoint

Event Processing

1. Webhook Receiver

The webhook endpoint receives events and returns 200 OK immediately to avoid GitHub’s 10-second timeout.
Key points:
  • Returns 200 OK within milliseconds
  • Actual PR review happens in background task
  • GitHub’s 10-second timeout is avoided

2. GitHub App Event Filtering

Nectr uses per-repo webhooks, not GitHub App webhooks. GitHub App events are rejected:

3. Deduplication

Nectr prevents duplicate reviews by checking for recent pending/processing events:
Deduplication scope:
  • Same PR number
  • Same repository
  • Within 1 hour
  • Status: pending or processing

4. Background Processing

PR reviews happen in background tasks that can take 30-60 seconds:
Source: app/api/v1/webhooks.py:41-93

Event Types

Nectr processes specific pull request events: Trigger condition:
Only opened and synchronize events trigger AI reviews.

Webhook Management

Viewing Webhooks

Check installed webhooks for a repository:

Disconnecting a Repository

When you disconnect a repository, Nectr automatically removes the webhook:
Webhook removal:

Testing Webhooks

Local Development with ngrok

GitHub webhooks require a public URL. Use ngrok to expose your local server:
1

Install ngrok

2

Start your local backend

3

Create ngrok tunnel

ngrok will output a public URL like:
4

Update BACKEND_URL

Set your BACKEND_URL to the ngrok URL:
Restart your backend for the change to take effect.
5

Connect a test repository

Connect a repository through the Nectr UI. The webhook will be created with your ngrok URL.
ngrok free tier URLs expire when you restart ngrok. You’ll need to update BACKEND_URL and reconnect repositories each time.

Manual Webhook Testing

Test the webhook endpoint directly:
Expected response:

Troubleshooting

Possible causes:
  1. Webhook not installed
    • Check: https://github.com/{owner}/{repo}/settings/hooks
    • Solution: Reconnect the repository in Nectr
  2. Wrong webhook URL
    • Check: Webhook payload URL should be {BACKEND_URL}/api/v1/webhooks/github
    • Solution: Update BACKEND_URL and reconnect repository
  3. Event type not supported
    • Only pull_request events with actions opened or synchronize trigger reviews
    • Check GitHub webhook delivery logs for event details
  4. Signature verification failing
    • Check logs for: Invalid webhook signature for {repo}
    • Solution: Reconnect repository to regenerate secret
Cause: Webhook signature verification failed in production.Solutions:
  1. Reconnect the repository to generate a new webhook secret
  2. Check that APP_ENV=production is set correctly
  3. Verify the secret in database matches the webhook configuration in GitHub
  4. Check that you’re not modifying the request body before verification
Cause: GitHub couldn’t reach your webhook endpoint.Solutions:
  1. Check that BACKEND_URL is publicly accessible
  2. Verify SSL certificate is valid (required for production)
  3. Check firewall/network rules
  4. View delivery details in GitHub webhook settings: Recent Deliveries tab
Cause: Deduplication logic not working or multiple webhooks installed.Solutions:
  1. Check for duplicate webhook configurations in GitHub settings
  2. Verify only one active Installation record exists for the repo
  3. Check logs for “duplicate_skipped” messages
  4. Ensure database is accessible (deduplication queries database)
Cause: Background task crashed or timed out.Solutions:
  1. Check backend logs for errors in process_pr_in_background
  2. Verify AI service (Anthropic) is accessible
  3. Check GitHub API rate limits
  4. Look for database connection issues
  5. Manually update event status in database if needed

Security Best Practices

Without signature verification, anyone who knows your webhook URL can trigger reviews.
GitHub requires valid SSL certificates for webhooks in production.
Platforms like Railway, Heroku, and Fly.io provide SSL certificates automatically.
  • Secrets are stored in plaintext in the database (they’re not sensitive like OAuth tokens)
  • Each repository has a unique secret
  • Secrets are generated with secrets.token_hex(32) (cryptographically secure)
  • Never log or expose webhook secrets in error messages
Regularly check GitHub’s webhook delivery logs:https://github.com/{owner}/{repo}/settings/hooks/{webhook_id}Look for:
  • Failed deliveries (red X)
  • Response codes other than 200
  • Timeout errors

Next Steps

Environment Variables

Configure webhook secrets and other settings

Feature Flags

Enable parallel review agents and other features