Stripe webhook to any URL with JSONata
Fire a signed, JSONata-templated HTTPS request to any endpoint when a Stripe event happens. The escape hatch for every integration we don't ship as a named action.
Free trial · From $19/mo · No credit card required
The problem
There is always one more service. An internal admin API, a chat tool with no Slack equivalent, a staging webhook, a side project a teammate runs. You need a way to fire a templated HTTPS request to any URL when a Stripe event happens, with proper retries and signing, without standing up a relay server or paying Zapier per task. The HTTP action is that escape hatch.
Configure a URL, method, headers, and a JSONata-templated JSON body referencing the Stripe event. Enable HMAC signing so the receiver can verify the request is really from your workflow. Outbound retries on 5xx, surfaces 4xx errors immediately, respects retry-after on 429, and dedupes on the Stripe invocation id so a retry doesn't fire the request twice. JSONata covers most ad-hoc transformations (currency conversion, conditional fields, derived booleans) inside the action config, so the receiver does not need to know it is talking to Stripe.
How the HTTP action works
- 1
Set URL, method, and headers
Pick the HTTPS endpoint, the method (POST, PUT, PATCH), and any static headers (Authorization, Content-Type). Header values support JSONata if you need them dynamic — useful for per-customer auth tokens. - 2
Template the body with JSONata
Write a JSON body that references the Stripe event. JSONata supports conditionals ($contains, $boolean), arithmetic, date formatting, and array reshaping, so the payload can be shaped to whatever the receiver expects without a separate transform step. - 3
Enable HMAC signing (recommended)
Outbound can sign every request with an HMAC over the body using a shared secret. Receivers can verify the signature, dedupe on the X-Outbound-Invocation-Id header, and trust the source — same pattern as Stripe's own webhooks. - 4
Tune retries and timeouts
By default, the action retries 5xx with exponential backoff up to 24 hours, respects 429 retry-after, and fails fast on 4xx. Override the policy per action if your receiver needs different semantics — for example, one-shot fire-and-forget for non-critical sends.
trigger:
event: customer.subscription.updated
steps:
- action: outbound.http
config:
method: POST
url: https://admin.acme.com/internal/subscription-changed
headers:
Authorization: "Bearer {{ secrets.ADMIN_TOKEN }}"
Content-Type: application/json
sign_with: hmac-sha256
body:
customer_id: "{{customer.id}}"
new_plan: "{{items.data[0].price.nickname}}"
seats: "{{items.data[0].quantity}}"
renews_at: "{{$fromMillis(current_period_end * 1000)}}"
is_upgrade: "{{items.data[0].price.unit_amount > previous_attributes.items.data[0].price.unit_amount}}"Example workflow configuration
Screenshot of the HTTP action config in the Stripe Workflow builder. Shows a URL input, a method dropdown set to POST, a headers grid with one static header and one JSONata-templated header, a JSON body editor with templated values highlighted, an HMAC sign toggle enabled with a secret name reference, and a retries section with a max-retries field.
Outbound vs custom webhook handler
| Outbound | custom webhook handler | |
|---|---|---|
| Hosted relay to maintain | — | |
| Signature verification + retries built-in | you build it | |
| Idempotent on Stripe invocation id | you build it | |
| Setup time | ≈4 minutes | Half a day to a week |
| JSONata body templating | — | |
| Pricing model | From $19/mo flat | Hosting + dev time |
| Lives inside the Stripe Dashboard | — |
Frequently asked questions
How is this different from Stripe's native webhook endpoints?+
Can I call non-HTTPS endpoints?+
What's in the HMAC signature?+
How are 4xx errors handled?+
Is there a payload size limit?+
Related integrations
Write Stripe events to Postgres
When the target is your database, the Postgres action skips the HTTP layer entirely.
Send Stripe events to Discord
If the destination is Discord, the branded action handles rate limits and rich embeds for you.
Trigger Stripe from any HTTPS POST
The mirror image, coming with Inbound: external services POST in, a workflow fires.