Technical overview
How Transyt works
From the moment a webhook arrives to the moment you replay it six months later. Every step logged, every payload stored, every failure explained.
Webhook arrives
Your provider sends a webhook to your Transyt endpoint. We accept the request immediately and return 200 OK to the provider.
The webhook is written to PostgreSQL before we respond. If we accepted it, it's stored. No race conditions, no lost events.
POST https://ingest.transyt.com/stripe/acme-prod
Content-Type: application/json
Stripe-Signature: t=1704067200,v1=5257a...
{"id": "evt_1234", "type": "invoice.paid", ...} Signature verified
We validate the webhook signature using the provider's specific algorithm. Stripe uses HMAC-SHA256. Twilio uses request signing. Each provider is different.
Invalid signatures are rejected with 401 and logged. Valid webhooks proceed to delivery. You can optionally skip verification for providers that don't sign.
# Stripe: HMAC-SHA256 with timestamp
expected = HMAC-SHA256(webhook_secret, timestamp + "." + payload)
# Twilio: Request URL signing
# AWS SNS: Certificate validation
# Mailgun: HMAC-SHA256 with timestamp Event deduplicated
Before processing, we check if we've seen this event before. Providers sometimes send duplicates — during retries, infrastructure issues, or edge cases.
Deduplication is enforced at the database level with a unique constraint on (account, provider_event_id). If we've seen it, we skip delivery but still return 200 to the provider.
-- PostgreSQL unique constraint
CREATE UNIQUE INDEX idx_events_dedup
ON events (account_id, provider_event_id);
-- Duplicate insert → no-op, not error Delivered to your app
We POST the verified payload to your configured endpoint. Your app processes it and returns a response. 2xx means success. Anything else triggers retry.
We forward the original payload with additional headers: X-Transyt-Event-Id (our ID), X-Transyt-Signature (our signature), and X-Transyt-Delivery-Attempt (attempt number).
POST https://your-app.com/webhooks/stripe
Content-Type: application/json
X-Transyt-Event-Id: evt_01HQXK7Y2Z...
X-Transyt-Signature: t=1704067201,v1=8f3a2...
X-Transyt-Delivery-Attempt: 1
{"id": "evt_1234", "type": "invoice.paid", ...} Retry on failure
If delivery fails (timeout, 5xx, network error), we retry with exponential backoff. 10 attempts over roughly 4 hours before we mark it as failed.
Retry schedule: 10s, 30s, 1m, 5m, 15m, 30m, 1h, 2h, 4h, 4h. Each attempt is logged with response code, timing, and any error message.
Attempt 1: immediate → 503 Service Unavailable
Attempt 2: +10 seconds → 503 Service Unavailable
Attempt 3: +30 seconds → 503 Service Unavailable
Attempt 4: +1 minute → 200 OK ✓
Total time: 1m 40s
Delivery status: DELIVERED Alert on failure
After a configurable number of failed attempts (default: 3), we notify you via email or Slack. You'll know something is wrong before it becomes a crisis.
Alerts include the event ID, provider, error message, and a direct link to the event in your dashboard. Daily digests summarize all failures from the past 24 hours.
🚨 Webhook delivery failing
Event: evt_01HQXK7Y2Z...
Provider: Stripe
Type: invoice.paid
Attempts: 3/10
Last error: Connection timeout
View event: https://app.transyt.com/events/evt_01HQXK7Y2Z Replay when ready
Once you've fixed the issue, replay the event with one click. We'll re-deliver the exact payload that was originally received. No data loss, no guessing.
Replay uses the stored payload — headers, body, everything. It's indistinguishable from a fresh delivery except for the X-Transyt-Delivery-Attempt header.
# Original delivery failed at 2024-01-15 09:23:17
# You deployed a fix at 2024-01-15 10:45:00
# One-click replay at 2024-01-15 10:46:12
POST https://your-app.com/webhooks/stripe
X-Transyt-Event-Id: evt_01HQXK7Y2Z...
X-Transyt-Delivery-Attempt: 11 # indicates replay
→ 200 OK ✓ The result
Zero lost webhooks
Stored before forwarded. Even if your app is down for hours, every event is waiting when you come back online.
Complete audit trail
Every payload, header, and delivery attempt logged. Query by time, provider, status, or event type. Export anytime.
Clear accountability
When something fails, you'll know exactly what, when, and why. No more "the webhook never arrived" debates.
See it in action
Set up in 5 minutes. Point your provider at Transyt, we'll handle the rest.
Start free