Getting Started

Dead Letter Webhook Recovery Proxy

Dead Letter is a high-availability webhook ingestion gateway. It sits between external webhook providers (like Stripe, Shopify, GitHub) and your application server. If your application server goes down, database operations lock up, or rate limits are exceeded, Dead Letter intercepts the failing payloads, stores them securely in a Dead Letter Queue (DLQ), and handles automatic or manual retries.

Why use Dead Letter? Webhook delivery is notoriously fragile. Most providers try to deliver only a few times before permanently deleting event payloads. Dead Letter guarantees at-least-once webhook delivery by routing traffic through an isolation proxy with configurable backoff policies.

General Integration Steps

1. Create Endpoint

Go to your Dead Letter console, navigate to Endpoints, and click 'Create Endpoint'. Provide your target URL (e.g., https://my-app.com/api/webhooks).

2. Obtain Ingestion Slug & HMAC Secret

Copy your new endpoint's Ingestion URL (containing the slug) and the generated HMAC Secret Key. The Ingestion URL will serve as the webhook target.

3. Update Third-Party Provider Settings

Paste the Dead Letter Ingestion URL into your webhook provider settings page (Stripe, Shopify, or GitHub) as the destination endpoint.

Configure Webhook Providers

Configure your service providers to direct events to your Dead Letter ingestion proxy.

STRIPE

Stripe Webhook Configuration

  • Navigate to your Stripe Webhook Dashboard .
  • Click the Add endpoint button in the top right.
  • In the Endpoint URL field, paste your Dead Letter Ingestion URL: https://api.deadletterhub.io/ingest/<your-slug>.
  • Select the event types you want to forward (e.g., charge.succeeded, customer.subscription.deleted).
  • Save the configuration. You are ready to intercept events.
View full Stripe integration guide
SHOPIFY

Shopify App Webhooks

  • Log in to your Shopify Admin page and navigate to Settings > Notifications.
  • Scroll down to the Webhooks section and click Create webhook.
  • Select the Event type (e.g., Order creation).
  • Ensure the format is set to JSON.
  • In the URL input, paste your Dead Letter Ingestion URL.
  • Select the latest webhook API version and click Save.
View full Shopify integration guide
GITHUB

GitHub Webhooks

  • Open your Repository on GitHub, click Settings, and choose Webhooks.
  • Click Add webhook in the top right.
  • Paste your Ingestion URL into the Payload URL field.
  • Set the Content type dropdown to application/json.
  • Choose the events you want to trigger the webhook (e.g., push, pull_request).
  • Ensure the webhook checkbox is marked Active and click Add webhook.
View full GitHub integration guide
Security

Signature Verification

To secure your destination endpoints from unauthorized requests, Dead Letter signs all forwarded webhook payloads using your endpoint's unique secret key. This signature is computed using a HMAC SHA-256 hashing algorithm over the raw request payload body and is sent in the headers as:

Header name:x-dead-letter-signature

Timing Attacks Protection

When verifying the signature, avoid using standard string equality operators (like == or ===). Standard comparisons exit early when a mismatch is found, leaking execution time variations that allow attackers to guess the signature byte-by-byte. Always use constant-time comparison functions.

SDK Recipes

Verification Code Snippets

Copy and integrate these secure verification functions directly into your webhook route handlers.

verify.js
const crypto = require('crypto');

/**
 * Verifies the signature of a webhook payload sent by Dead Letter.
 * 
 * @param {string|object} payload - The raw request body string or parsed JSON object.
 * @param {string} signature - The signature from the 'x-dead-letter-signature' header.
 * @param {string} secretKey - The endpoint's HMAC Secret Key.
 * @returns {boolean} - True if signature is valid, false otherwise.
 */
function verifySignature(payload, signature, secretKey) {
  const payloadString = typeof payload === 'string' 
    ? payload 
    : JSON.stringify(payload);
    
  const computedSignature = crypto
    .createHmac('sha256', secretKey)
    .update(payloadString)
    .digest('hex');

  // Prevent timing attacks using timingSafeEqual
  const signatureBuffer = Buffer.from(signature, 'hex');
  const computedBuffer = Buffer.from(computedSignature, 'hex');

  if (signatureBuffer.length !== computedBuffer.length) {
    return false;
  }

  return crypto.timingSafeEqual(signatureBuffer, computedBuffer);
}
API Reference

API Key Management

Dead Letter supports programmatic API access via workspace-level API keys. You can create, rotate, and revoke keys from the API Keys page in the dashboard.

Key Prefixes and Permissions

PrefixRolePermissions
dl_live_Read-WriteCreate, update, delete endpoints; view and retry events; manage alerts
dl_read_Read-OnlyView endpoints, event logs, and analytics; no mutations allowed

Authentication

Include the API key in the Authorization header of your requests:

Authorization: Bearer dl_live_abc123def456...

Key Rotation and Revocation

To rotate a key, create a new key in the dashboard, update your applications to use the new key, then revoke the old key. Revoked keys are immediately invalidated and cannot be restored. We recommend rotating keys every 90 days as a security best practice.

Limits

Rate Limiting

Dead Letter applies rate limits at multiple levels to protect the ingestion pipeline from abuse and ensure fair resource allocation across tenants.

Per-Second Limits (Ingestion)

TierLimit
Free10 req/s
Pro100 req/s
Enterprise500 req/s

Monthly Volume Caps

TierLimit
Free100,000 events/mo
Pro1,000,000 events/mo
EnterpriseUnlimited

IP-Level Rate Limiting

A global IP-based rate limit of 100 requests per second is applied to the ingestion endpoint before any workspace-level checks. This protects against attacks targeting invalid slugs.

Response Headers

Every ingestion response includes rate limit headers so you can monitor and manage your usage programmatically:

HeaderDescription
X-RateLimit-LimitWorkspace per-second rate limit
X-RateLimit-RemainingRequests remaining in the current second window
X-Monthly-Events-LimitMonthly event cap
X-Monthly-Events-CountEvents used this month
X-IP-RateLimit-LimitIP-level per-second rate limit
X-IP-RateLimit-RemainingIP requests remaining in the current window

Handling 429 Responses

When you receive a 429 Too Many Requests response, back off and retry after a short delay. Check the X-RateLimit-Remaining header to gauge when the window resets. For monthly cap violations, a 402 Payment Required is returned with a link to upgrade your tier.

Delivery

Webhook Event Lifecycle

Every webhook payload that reaches Dead Letter follows a defined lifecycle through the ingestion, queue, and delivery pipeline.

Delivery Flow

POST /ingest202 AcceptedPENDING

First attemptSUCCESS(delivered)

Failure (5xx / timeout)Retry queue

Retry 1 (1 min)SUCCESSorschedule next

Retry N (8h + backoff)FAILED (DLQ)

Manual retryPENDINGSUCCESSorFAILED

Retry Schedule

Failed deliveries are retried at the following intervals, with a maximum of 8 attempts:

1m5m15m30m1h2h4h8h

Event Statuses

PENDING — Queued for delivery or retry

SUCCESS — Successfully delivered (2xx response)

FAILED — All retries exhausted, moved to DLQ

Delivery Guarantees

Dead Letter provides at-least-once delivery. Each webhook is delivered at least once; under error conditions (network failures, worker crashes), duplicate delivery is possible. Use the x-dead-letter-event-id header to deduplicate on your destination server.

Troubleshooting

API Error Codes

The Dead Letter ingestion API uses standard HTTP response codes to indicate success or failure. All error responses include a JSON body with an error field describing the issue.

CodeMeaningAction
202AcceptedWebhook received and queued for delivery. No further action needed.
400Bad RequestInvalid payload format or missing required fields. Check the error message for details and fix the request.
401UnauthorizedAPI key or authentication token is missing, invalid, or expired. Check your Authorization header.
402Payment RequiredMonthly ingestion volume cap exceeded. Visit your billing page to upgrade your workspace tier.
404Not FoundNo endpoint matches the provided ingestion slug. Verify the slug in your Dead Letter dashboard.
413Payload Too LargePayload exceeds the maximum allowed body size. Reduce payload size and retry.
429Too Many RequestsPer-second rate limit exceeded for this workspace or IP. Wait for the window to reset.
500Internal ErrorAn unexpected server error occurred. Dead Letter will attempt to retry automatically.