Stripe sends webhook events for everything: charges, subscriptions, invoices, disputes, payouts. Most of that payload is noise for your application. With Hookpipe, you can transform Stripe webhooks to extract only the fields you need, filter by event type, and forward clean payloads to your endpoints. No middleware to deploy, no code to maintain.
A typical Stripe webhook event carries 50+ fields across deeply nested objects. The invoice.payment_succeeded event alone includes the full invoice object, line items, customer details, subscription metadata, and billing timestamps. Your application probably needs three or four of those fields.
Without a webhook relay sitting between Stripe and your app, you end up writing boilerplate parsing code in every handler. Worse, if you need to route different Stripe webhook events to different services — charges to your billing service, disputes to your support tool, payouts to your finance dashboard — you're building a routing layer from scratch.
Pull just the customer email, amount, and status from a charge event. Drop the 40 other fields your app ignores.
Send charge.succeeded events to your billing service and customer.subscription.deleted to your churn tracker. Use separate hooks with filters.
Rename Stripe's nested field paths into the flat structure your API expects. No more data.object.customer chains in your handler.
Here's a real-world invoice.payment_succeeded event payload from Stripe. This is what arrives at your webhook endpoint:
{
"id": "evt_1RBx2kJf8aLzKp4qXdV",
"object": "event",
"type": "invoice.payment_succeeded",
"data": {
"object": {
"id": "in_1RBx2kJf8aLzKp4qN7m",
"object": "invoice",
"customer": "cus_PqR8xYkL3mN",
"customer_email": "jamie@example.com",
"customer_name": "Jamie Chen",
"amount_paid": 2900,
"currency": "usd",
"status": "paid",
"subscription": "sub_1RBx2kJf8aLz",
"period_start": 1708300800,
"period_end": 1710979200,
"hosted_invoice_url": "https://invoice.stripe.com/i/acct_1R.../inv_...",
"lines": {
"data": [
{
"description": "Pro Plan (Feb 18 - Mar 18, 2026)",
"amount": 2900,
"price": {
"id": "price_1RBxKp4q",
"product": "prod_PqR8",
"unit_amount": 2900,
"recurring": { "interval": "month" }
}
}
]
},
"payment_intent": "pi_3RBx2kJf8aLz",
"charge": "ch_3RBx2kJf8aLz",
"billing_reason": "subscription_cycle",
"metadata": {}
}
},
"created": 1708300860,
"livemode": true,
"pending_webhooks": 2,
"request": { "id": "req_Kp4qXdV", "idempotency_key": null }
}
That's a lot of data. Your billing dashboard probably only needs the customer email, amount, currency, and subscription ID. Your Slack notification might only need the customer name and what they paid. Hookpipe lets you define exactly what to extract.
Here's how to set up a Hookpipe hook that transforms Stripe webhook events into clean, flat payloads and forwards them to your app.
curl -X POST https://hookpipe.app/api/auth/keys \
-H "Content-Type: application/json" \
-d '{"name": "stripe-integration"}'
Save the API key from the response — it's shown only once.
This hook extracts the essential payment fields from any Stripe invoice event and forwards a clean payload to your app:
curl -X POST https://hookpipe.app/api/hooks \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "stripe-invoices",
"destinationUrl": "https://your-app.com/api/billing/webhook",
"transformConfig": {
"fieldMapping": {
"event_type": "type",
"customer_id": "data.object.customer",
"customer_email": "data.object.customer_email",
"amount_cents": "data.object.amount_paid",
"currency": "data.object.currency",
"invoice_status": "data.object.status",
"subscription_id": "data.object.subscription",
"billing_reason": "data.object.billing_reason",
"source": "stripe",
"processed_by": "hookpipe"
},
"filters": [
{"field": "type", "operator": "contains", "value": "invoice."}
]
}
}'
In your Stripe Dashboard → Webhooks, add a new endpoint:
https://hookpipe.app/hooks/YOUR_HOOK_ID
Select the events you want — invoice.payment_succeeded, invoice.payment_failed, etc. Stripe will now send those events to Hookpipe, which transforms and forwards them.
Instead of the full Stripe event object, your endpoint gets this:
{
"event_type": "invoice.payment_succeeded",
"customer_id": "cus_PqR8xYkL3mN",
"customer_email": "jamie@example.com",
"amount_cents": 2900,
"currency": "usd",
"invoice_status": "paid",
"subscription_id": "sub_1RBx2kJf8aLz",
"billing_reason": "subscription_cycle",
"source": "stripe",
"processed_by": "hookpipe"
}
Clean. Flat. Exactly what your billing service needs. No nested object traversal in your handler code.
Track successful and failed charges with just the fields that matter:
curl -X POST https://hookpipe.app/api/hooks \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "stripe-charges",
"destinationUrl": "https://your-app.com/api/payments",
"transformConfig": {
"fieldMapping": {
"event": "type",
"charge_id": "data.object.id",
"amount": "data.object.amount",
"currency": "data.object.currency",
"customer": "data.object.customer",
"status": "data.object.status",
"failure_reason": "data.object.failure_message",
"receipt_url": "data.object.receipt_url",
"source": "stripe"
},
"filters": [
{"field": "type", "operator": "contains", "value": "charge."}
]
}
}'
Route subscription cancellations and updates to your analytics pipeline:
curl -X POST https://hookpipe.app/api/hooks \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "stripe-subscriptions",
"destinationUrl": "https://your-app.com/api/churn-tracker",
"transformConfig": {
"fieldMapping": {
"event": "type",
"subscription_id": "data.object.id",
"customer_id": "data.object.customer",
"plan_status": "data.object.status",
"cancel_at": "data.object.cancel_at",
"canceled_at": "data.object.canceled_at",
"current_period_end": "data.object.current_period_end"
},
"filters": [
{"field": "type", "operator": "contains", "value": "customer.subscription."}
]
}
}'
You don't need to trigger real Stripe events to test. Send a simulated payload directly to your hook:
curl -X POST https://hookpipe.app/hooks/YOUR_HOOK_ID \
-H "Content-Type: application/json" \
-d '{
"type": "invoice.payment_succeeded",
"data": {
"object": {
"customer": "cus_test123",
"customer_email": "test@example.com",
"amount_paid": 4900,
"currency": "usd",
"status": "paid",
"subscription": "sub_test456",
"billing_reason": "subscription_create"
}
}
}'
Check what was received and forwarded using the payloads API:
curl https://hookpipe.app/api/hooks/YOUR_HOOK_ID/payloads \
-H "Authorization: Bearer YOUR_API_KEY"
Each stored payload shows both the original rawBody and the transformedBody so you can verify your field mappings are correct. If the forward failed (maybe your destination was down), use the replay endpoint to retry:
curl -X POST https://hookpipe.app/api/hooks/YOUR_HOOK_ID/payloads/PAYLOAD_ID/replay \
-H "Authorization: Bearer YOUR_API_KEY"
contains operator on the type field lets you scope each hook to a specific category (charges, invoices, subscriptions)."source": "stripe" makes it trivial to identify where a payload came from when your app receives webhooks from multiple providers.GET /api/hooks/:id/logs periodically to check for forwarding failures. Hookpipe retries up to 3 times with exponential backoff, but persistent failures (wrong URL, auth errors) will show up in logs.Create your first hook in three API calls. No account required for the free tier.