Skip to content

Production Readiness

Before launching your webhook pipeline to production, ensure your configuration follows security best practices and reliability standards. This guide provides a comprehensive checklist and detailed recommendations for running Hookbase securely and reliably.

Pre-Launch Checklist

Use this checklist to verify your production configuration:

CategoryItemStatusNotes
SecuritySignature verification enabled for all sourcesSee Signature Verification
API key scopes limited to minimum requiredUse read:events instead of admin where possible
HTTPS-only destinations configuredNever send webhooks to http:// endpoints
IP filtering configured for sensitive sourcesAllowlist provider IPs where available
Field encryption enabled for PII fieldsEncrypt sensitive data like emails, SSNs
rejectInvalidSignatures enabled on sourcesPrevents processing of unverified webhooks
ReliabilityRetry policies configured with backoffRecommended: 3-5 retries with exponential backoff
Failover destinations set for critical routesSecondary destination for automatic failover
Circuit breakers enabled on destinationsPrevents cascading failures
Deduplication enabled to prevent duplicatesUse idempotencyKey or content-based dedup
Notification channels linked to routesGet alerted on delivery failures
Cron monitoring active for scheduled jobsMonitor cron execution success rates
MonitoringAlert channels configured for critical routesEmail, Slack, or webhook notifications
Audit logs reviewed periodicallyCheck for unauthorized access attempts
Analytics dashboard checked for anomaliesMonitor event volume and failure rates
Health endpoint monitored externallyUse uptime monitoring service
Access ControlOrganization roles assigned appropriatelyAdmin, Developer, Viewer roles
API key rotation scheduled (quarterly)Rotate keys every 90 days minimum
Unused API keys revokedRemove keys for deactivated services
Least privilege principle appliedGrant minimum scopes needed

Signature Verification

Signature verification is the most critical security control for webhooks. It ensures that incoming webhooks are authentic and haven't been tampered with.

Why It Matters

Without signature verification:

  • Attackers can send fake webhooks to trigger unauthorized actions
  • Replay attacks can resubmit legitimate webhooks
  • Man-in-the-middle attacks can modify webhook payloads

Enabling Verification

When creating a source, always enable signature verification:

bash
curl -X POST https://api.hookbase.app/api/organizations/{orgId}/sources \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Stripe Payments",
    "provider": "stripe",
    "verifySignatures": true,
    "rejectInvalidSignatures": true,
    "signingSecret": "whsec_abc123..."
  }'

Provider-Specific Configuration

Each provider has different signature verification mechanisms:

ProviderHeaderAlgorithmConfiguration
StripeStripe-SignatureHMAC-SHA256Signing secret from webhook settings
GitHubX-Hub-Signature-256HMAC-SHA256Secret token from webhook config
SlackX-Slack-SignatureHMAC-SHA256Signing secret from app credentials
ShopifyX-Shopify-Hmac-SHA256HMAC-SHA256Shared secret from admin panel
TwilioX-Twilio-SignatureHMAC-SHA1Auth token from console

Reject vs. Accept Invalid Signatures

The rejectInvalidSignatures setting controls behavior when verification fails:

rejectInvalidSignatures: true (Recommended for Production)

  • Invalid webhooks return 401 Unauthorized
  • Event is NOT stored in Hookbase
  • No deliveries are attempted
  • Audit log records the rejection

rejectInvalidSignatures: false (Development/Testing Only)

  • Invalid webhooks return 200 OK
  • Event is stored with verificationStatus: "failed"
  • Deliveries are still attempted (not recommended)
  • Useful for debugging signature issues

Production Requirement

Always set rejectInvalidSignatures: true in production. Accepting unverified webhooks defeats the purpose of signature verification and exposes your system to attacks.

Secret & Key Rotation

Regular rotation of secrets and API keys is essential for security hygiene.

API Key Rotation

Rotate API keys on a regular schedule (recommended: every 90 days):

Step 1: Create new API key

bash
curl -X POST https://api.hookbase.app/api/organizations/{orgId}/api-keys \
  -H "Authorization: Bearer CURRENT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Production API Key (2026-Q2)",
    "scopes": ["read:sources", "read:events", "write:routes"],
    "expiresAt": "2026-06-01T00:00:00Z"
  }'

Step 2: Update services to use new key

  • Deploy new key to all services that consume your webhooks
  • Verify services are working with new key
  • Monitor for authentication errors

Step 3: Revoke old key

bash
curl -X DELETE https://api.hookbase.app/api/organizations/{orgId}/api-keys/{keyId} \
  -H "Authorization: Bearer NEW_API_KEY"

Zero-Downtime Rotation

Set expiresAt on the old key to 7 days in the future instead of immediately revoking it. This allows a grace period for services to migrate.

Source Signing Secret Rotation

For webhook sources, rotate signing secrets using the built-in rotation mechanism:

bash
# Via CLI
hookbase sources rotate-secret src_abc123 --org myorg

# Via API
curl -X POST https://api.hookbase.app/api/organizations/{orgId}/sources/{sourceId}/rotate-secret \
  -H "Authorization: Bearer YOUR_API_KEY"

This returns a new signingSecret. Update it in your webhook provider:

json
{
  "id": "src_abc123",
  "name": "Stripe Payments",
  "signingSecret": "whsec_NEW_SECRET",
  "previousSecret": "whsec_OLD_SECRET",
  "secretRotatedAt": "2026-02-11T10:30:00Z"
}

Graceful Migration

Hookbase keeps the previous secret active for 24 hours, allowing webhooks signed with either the old or new secret to pass verification. This prevents dropped webhooks during rotation.

Zero-Downtime Rotation Strategy

For critical production systems:

  1. Pre-rotate: Create new secret but don't activate yet
  2. Update provider: Configure webhook provider with new secret (but don't delete old config yet)
  3. Activate: Rotate secret in Hookbase (both secrets now valid for 24h)
  4. Monitor: Watch delivery success rates for any verification failures
  5. Clean up: After 24h, remove old secret from provider configuration

Replay Prevention

Replay attacks involve resubmitting valid webhooks to trigger duplicate actions (e.g., double-charging a customer).

Deduplication

Enable deduplication to automatically reject duplicate webhooks:

bash
curl -X POST https://api.hookbase.app/api/organizations/{orgId}/sources \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Stripe Payments",
    "provider": "stripe",
    "deduplication": {
      "enabled": true,
      "strategy": "idempotency_key",
      "keyPath": "id",
      "windowMinutes": 1440
    }
  }'

Deduplication Strategies:

  • idempotency_key: Uses provider's unique event ID (e.g., Stripe's id field)
  • content_hash: SHA-256 hash of entire payload (catches exact duplicates)
  • custom_field: Extract custom field via JSONPath (e.g., $.transaction.id)

Timestamp Checking

Many providers include a timestamp in their signature. Hookbase automatically rejects webhooks with timestamps outside a tolerance window:

json
{
  "provider": "stripe",
  "timestampTolerance": 300
}

This rejects webhooks older than 5 minutes (300 seconds), preventing replay of captured webhook requests.

Idempotency Keys in Destinations

For critical operations, ensure your destination endpoints support idempotency keys:

bash
curl -X POST https://api.hookbase.app/api/organizations/{orgId}/transforms \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Add Idempotency Header",
    "type": "jsonata",
    "expression": "{\"headers\": {\"Idempotency-Key\": $.event.id}}"
  }'

Attach this transform to routes delivering to payment processors or other systems where duplicate requests could cause problems.

Network Security

Control which traffic can reach your webhook sources and where deliveries can be sent.

IP Filtering

Restrict webhook sources to accept only traffic from known provider IPs:

bash
curl -X PATCH https://api.hookbase.app/api/organizations/{orgId}/sources/{sourceId} \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "ipFiltering": {
      "enabled": true,
      "mode": "allowlist",
      "rules": [
        {
          "cidr": "3.18.12.0/22",
          "description": "Stripe webhooks (us-east-1)"
        },
        {
          "cidr": "3.130.192.0/22",
          "description": "Stripe webhooks (us-east-2)"
        }
      ]
    }
  }'

Provider IP Ranges:

ProviderIP RangesDocumentation
StripeMultiple /22 blockshttps://stripe.com/docs/ips
GitHubhttps://api.github.com/metahttps://docs.github.com/webhooks/webhook-events-and-payloads#ip-addresses
SlackMultiple /24 blockshttps://api.slack.com/changelog/2018-05-01-webhook-ip-ranges
ShopifyMultiple /22 blockshttps://shopify.dev/docs/apps/webhooks

Dynamic IP Ranges

Some providers change their IP ranges. Subscribe to their change notifications and update your allowlist accordingly. Consider using denylist mode if allowlisting is not feasible.

HTTPS-Only Enforcement

Never send webhooks to unencrypted HTTP endpoints:

bash
curl -X POST https://api.hookbase.app/api/organizations/{orgId}/destinations \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Payment Processor",
    "url": "https://api.example.com/webhooks",
    "requireHttps": true
  }'

With requireHttps: true, any attempt to use an http:// URL will fail validation.

Custom Domains with SSL

For inbound webhooks, use custom domains with SSL certificates:

bash
curl -X POST https://api.hookbase.app/api/organizations/{orgId}/custom-domains \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "domain": "webhooks.example.com",
    "sslMode": "full_strict"
  }'

This allows webhooks at https://webhooks.example.com/receive/{sourceSlug} with your own SSL certificate, improving trust and branding.

Data Protection

Protect sensitive data in webhook payloads both at rest and in transit.

Field Encryption

Encrypt PII fields before storing or forwarding webhooks:

bash
curl -X POST https://api.hookbase.app/api/organizations/{orgId}/sources/{sourceId}/field-encryption \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "fields": [
      {
        "path": "$.customer.email",
        "algorithm": "AES-256-GCM"
      },
      {
        "path": "$.customer.ssn",
        "algorithm": "AES-256-GCM"
      },
      {
        "path": "$.payment.cardNumber",
        "algorithm": "AES-256-GCM"
      }
    ]
  }'

Encrypted fields are stored as:

json
{
  "customer": {
    "email": "enc_AES256GCM_abc123...",
    "name": "John Doe"
  }
}

Encryption Key Management

Hookbase uses your organization's encryption key (AES-256-GCM). This key is stored in Cloudflare KV and rotated annually. For compliance requirements (HIPAA, PCI-DSS), contact support for custom key management options.

Field Masking

For non-encrypted fields that shouldn't appear in logs:

bash
curl -X POST https://api.hookbase.app/api/organizations/{orgId}/sources \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Payment Events",
    "maskedFields": [
      "$.customer.email",
      "$.payment.last4",
      "$.customer.phone"
    ]
  }'

Masked fields appear as *** in audit logs and the dashboard but are delivered normally to destinations.

Payload Retention Policies

Configure how long webhook payloads are stored:

bash
curl -X PATCH https://api.hookbase.app/api/organizations/{orgId}/settings \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "dataRetention": {
      "events": {
        "retentionDays": 90,
        "deletePayloadAfterDays": 30
      },
      "deliveries": {
        "retentionDays": 90
      },
      "auditLogs": {
        "retentionDays": 365
      }
    }
  }'

This configuration:

  • Keeps event metadata for 90 days
  • Deletes full payloads after 30 days (headers/status remain)
  • Retains delivery attempts for 90 days
  • Keeps audit logs for 1 year

Compliance

For GDPR, CCPA, or other privacy regulations, configure retention policies to automatically delete customer data. Use deletePayloadAfterDays to purge PII while keeping delivery status for debugging.

Reliability Configuration

Configure retry policies, circuit breakers, and failover for production-grade reliability.

Retry Policies

Configure retries with exponential backoff:

For Transient Failures (Network Issues, 5xx Errors):

bash
curl -X POST https://api.hookbase.app/api/organizations/{orgId}/destinations \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "External API",
    "url": "https://api.example.com/webhooks",
    "retryPolicy": {
      "maxAttempts": 5,
      "initialDelaySeconds": 2,
      "maxDelaySeconds": 300,
      "backoffMultiplier": 2,
      "retryableStatusCodes": [408, 429, 500, 502, 503, 504]
    }
  }'

This produces delays: 2s, 4s, 8s, 16s, 32s (capped at 300s).

For Rate-Limited APIs:

json
{
  "retryPolicy": {
    "maxAttempts": 10,
    "initialDelaySeconds": 60,
    "maxDelaySeconds": 3600,
    "backoffMultiplier": 1.5,
    "retryableStatusCodes": [429],
    "respectRetryAfterHeader": true
  }
}

For Critical Webhooks (No Tolerance for Loss):

json
{
  "retryPolicy": {
    "maxAttempts": 20,
    "initialDelaySeconds": 1,
    "maxDelaySeconds": 86400,
    "backoffMultiplier": 2,
    "retryableStatusCodes": [0, 408, 429, 500, 502, 503, 504]
  }
}

Status Code 0

Status code 0 represents network failures (DNS resolution, connection timeout, etc.). Include it for maximum reliability.

Circuit Breaker Tuning

Prevent cascading failures by opening circuits on repeated errors:

bash
curl -X PATCH https://api.hookbase.app/api/organizations/{orgId}/destinations/{dstId}/circuit-breaker \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "enabled": true,
    "failureThreshold": 10,
    "successThreshold": 3,
    "timeoutSeconds": 10,
    "halfOpenAttempts": 2,
    "resetTimeoutSeconds": 60
  }'

Configuration Explained:

  • failureThreshold: 10 - Open circuit after 10 consecutive failures
  • successThreshold: 3 - Close circuit after 3 consecutive successes
  • timeoutSeconds: 10 - Treat requests taking >10s as failures
  • halfOpenAttempts: 2 - Try 2 requests in half-open state before reopening
  • resetTimeoutSeconds: 60 - Wait 60s before transitioning to half-open

For High-Traffic Destinations:

json
{
  "failureThreshold": 50,
  "successThreshold": 10,
  "resetTimeoutSeconds": 300
}

For Critical Low-Traffic Destinations:

json
{
  "failureThreshold": 3,
  "successThreshold": 1,
  "resetTimeoutSeconds": 30
}

Failover Setup

Configure automatic failover to secondary destinations:

bash
curl -X POST https://api.hookbase.app/api/organizations/{orgId}/routes \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Payment Processing with Failover",
    "sourceId": "src_abc123",
    "destinationId": "dst_primary",
    "failover": {
      "enabled": true,
      "destinationId": "dst_secondary",
      "triggerConditions": [
        "circuit_open",
        "all_retries_exhausted",
        "timeout"
      ]
    }
  }'

Failover Triggers:

  • circuit_open - Primary destination's circuit breaker is open
  • all_retries_exhausted - All retry attempts failed
  • timeout - Request exceeded timeout threshold
  • status_5xx - Any 5xx response (even if retries remain)

Failover Delivery Guarantee

Failover does NOT guarantee exactly-once delivery. A webhook may be delivered to both primary and secondary if the primary succeeds after a long delay. Ensure your secondary destination is idempotent.

Monitoring & Alerting

Set up proactive monitoring to catch issues before they impact customers.

Notification Channels

Configure notification channels for alerts:

Slack:

bash
curl -X POST https://api.hookbase.app/api/organizations/{orgId}/notification-channels \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Engineering Alerts",
    "type": "slack",
    "config": {
      "webhookUrl": "https://hooks.slack.com/services/T00/B00/xxx"
    },
    "events": [
      "route.circuit_opened",
      "route.high_failure_rate",
      "source.quota_exceeded",
      "destination.all_retries_failed"
    ]
  }'

Email:

bash
curl -X POST https://api.hookbase.app/api/organizations/{orgId}/notification-channels \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "On-Call Email",
    "type": "email",
    "config": {
      "recipients": ["[email protected]", "[email protected]"]
    },
    "events": [
      "route.circuit_opened",
      "cron.execution_failed"
    ]
  }'

Webhook (for PagerDuty, Datadog, etc.):

bash
curl -X POST https://api.hookbase.app/api/organizations/{orgId}/notification-channels \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "PagerDuty",
    "type": "webhook",
    "config": {
      "url": "https://events.pagerduty.com/v2/enqueue",
      "headers": {
        "Authorization": "Token token=YOUR_INTEGRATION_KEY"
      }
    },
    "events": [
      "route.circuit_opened",
      "source.signature_verification_failed"
    ]
  }'

What to Alert On

Recommended alerts for production systems:

EventSeverityDescription
route.circuit_openedCriticalCircuit breaker opened, deliveries paused
route.high_failure_rateWarning>10% failure rate over 5 minutes
source.quota_exceededWarningMonthly event quota reached
destination.all_retries_failedErrorWebhook delivery failed after all retries
cron.execution_failedErrorScheduled cron job failed
source.signature_verification_failedWarningInvalid signature (potential attack)
organization.quota_approachingInfo80% of plan quota used

CLI Monitoring Commands

Use the CLI for real-time monitoring:

bash
# Watch live events
hookbase events tail --source src_abc123

# Monitor delivery success rate
hookbase analytics deliveries --source src_abc123 --last 1h

# Check circuit breaker status
hookbase destinations status dst_abc123

# View recent failures
hookbase deliveries list --status failed --limit 50

# Monitor cron executions
hookbase cron status cron_abc123 --last 24h

Health Endpoint Monitoring

Monitor Hookbase's health endpoint with external uptime services:

bash
curl https://api.hookbase.app/health

Response:

json
{
  "status": "healthy",
  "timestamp": "2026-02-11T10:30:00Z",
  "services": {
    "database": "healthy",
    "queue": "healthy",
    "storage": "healthy"
  }
}

Use services like Pingdom, UptimeRobot, or Better Uptime to monitor this endpoint and alert on outages.

Access Control

Implement role-based access control and least privilege principles.

RBAC Overview

Hookbase supports three organization roles:

RolePermissionsUse Case
AdminFull access: manage members, billing, API keys, all resourcesCTO, DevOps lead
DeveloperCreate/update sources, destinations, routes, transforms, filtersEngineering team
ViewerRead-only access to events, deliveries, analyticsSupport, monitoring

Assign roles when inviting members:

bash
curl -X POST https://api.hookbase.app/api/organizations/{orgId}/members \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "[email protected]",
    "role": "developer"
  }'

API Key Scopes

API keys support fine-grained scopes for least privilege access:

ScopePermissionsUse Case
read:eventsList and retrieve eventsAnalytics, monitoring
read:deliveriesList and retrieve deliveriesDebugging, monitoring
read:sourcesList and retrieve sourcesConfiguration audits
write:sourcesCreate/update sourcesAutomation scripts
write:routesCreate/update routesDynamic routing
adminFull API accessService accounts, automation

Example: Read-Only Monitoring Key

bash
curl -X POST https://api.hookbase.app/api/organizations/{orgId}/api-keys \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Datadog Monitoring",
    "scopes": ["read:events", "read:deliveries"],
    "expiresAt": "2027-02-11T00:00:00Z"
  }'

Example: Route Management Key

bash
curl -X POST https://api.hookbase.app/api/organizations/{orgId}/api-keys \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Dynamic Routing Service",
    "scopes": ["read:sources", "write:routes", "read:destinations"],
    "expiresAt": "2027-02-11T00:00:00Z"
  }'

Principle of Least Privilege

Grant the minimum scopes required:

Anti-Pattern

json
{
  "name": "Frontend Dashboard",
  "scopes": ["admin"]
}

This grants full access to a client-side application, which could leak credentials.

Best Practice

json
{
  "name": "Frontend Dashboard",
  "scopes": ["read:events", "read:deliveries", "read:sources"]
}

Read-only access prevents malicious users from modifying configuration.

Audit Logging

All API key usage is logged in audit logs:

bash
curl https://api.hookbase.app/api/organizations/{orgId}/audit-logs \
  -H "Authorization: Bearer YOUR_API_KEY"

Review audit logs for:

  • Unauthorized access attempts (action: "api.unauthorized")
  • API key creation/deletion (action: "api_key.created")
  • Source configuration changes (action: "source.updated")
  • Member role changes (action: "member.role_updated")

Set up alerts for suspicious patterns:

bash
curl -X POST https://api.hookbase.app/api/organizations/{orgId}/notification-channels \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Security Alerts",
    "type": "email",
    "config": {
      "recipients": ["[email protected]"]
    },
    "events": [
      "audit.unauthorized_access",
      "audit.api_key_created",
      "audit.member_added"
    ]
  }'

Next Steps

Released under the MIT License.