Skip to content

Webhook

Webhooks let you send journey data to external services such as analytics, CRM systems, and marketing tools. You can:

  • Notify external systems when a customer takes an action in the journey
  • Send customer data to analytics tools
  • Trigger third-party emails, SMS, or WhatsApp on specific journey events

How to set up the Webhook element

Anchor link to

Add the Webhook element

Anchor link to

Drag-and-drop the Webhook element to the canvas. Place Webhook anywhere you’d like, keeping in mind what journey info you’re going to send to a third-party service.

Webhook element on canvas with name and request settings

Name the Webhook step and specify the request URL and type

Anchor link to

In the STEP NAME field, enter a name for the webhook. It might be handy to name webhooks according to the services they send data to or the use case.

Next, in the URL field, specify the request URL to which the data should be sent. Next to the URL field, select the request type from the REQUEST TYPE dropdown: GET or POST.

Webhook configuration interface showing URL field and REQUEST TYPE dropdown for selecting GET or POST method

Configure headers

Anchor link to

In the HEADERS section, set the content type.

By default, the content type is application/json. If the service you’re sending the webhook to requires another content type, enter the appropriate one in the Content-Type header value.

Examples of content types are:

  • x-www-form-urlencoded
  • text/plain
  • text/xml

Add additional headers if needed by clicking + ADD HEADER. You can remove any header by clicking the ‘x’ icon next to it.

Add whatever authentication header your endpoint requires, for example:

  • Authorization: Bearer <token>
  • X-Api-Key: <key>
  • Authorization: Basic <base64(user:pass)>

Only a static secret in a header is supported. OAuth2 token-exchange flows, mTLS, and request signing on the Pushwoosh side aren’t supported. You can also restrict the endpoint to Pushwoosh’s IP addresses instead of, or in addition to, a header secret. See Pushwoosh IP addresses.

For HTTP Basic authentication specifically, do the following:

  1. Open a plain text editor and type your username and password with no spaces, separated by a colon. For example: <username>:<password>
  2. Encode this string into Base64.
  3. Copy the resulting Base64 string (for example, <base64-encoded-string>).
  4. In the webhook settings, add an Authorization header with the value: Basic <base64-encoded-string>. Make sure there is a space after the word “Basic”.
Authorization header example for Basic authentication in webhook settings showing Content-Type and Authorization headers

Mark a header value as secret

Anchor link to

Click the eye icon next to a header’s value to mask it. Pushwoosh hides that value everywhere it would otherwise leave the service: in the UI, in API responses, and in the journey’s version history.

Webhook headers list with a masked Authorization value and disabled eye icon next to an unmasked Content-Type value with an active eye icon
  • Automatic masking. Headers whose names look like credentials are masked automatically, even if you never click the eye icon. This includes Authorization, Proxy-Authorization, Cookie, Set-Cookie, and any name containing token, secret, password, credential, auth, or api-key/api_key/apikey (with a hyphen, an underscore, or no separator).
  • Change a masked value. Click into the field showing •••••••• and type the new value. There’s no button to reveal the stored value. The eye icon stays locked while the mask is shown. To remove the secret flag from a header, type a new value first, then click the icon.
  • Rename a masked header. Renaming a header whose value is currently shown as the mask clears that value. Enter it again under the new name. Renaming a header that currently holds a value you just typed keeps that value.

Add the JSON request body

Anchor link to

In the DATA section, enter your JSON request body. Make sure the request body is in correct JSON format.

Example:

{
"hwid": "{{device:hwid}}"
}

Use dynamic data and macros

Anchor link to

The DATA BUILDER panel allows you to insert dynamic information (such as user, device, tag, or event data) directly into your JSON request body. With Dynamic Data, you can include values specific to the individual user progressing through the journey.

For this:

  1. Select a category. You can pull data from three categories:
  • Device: Use Device data when you need technical information tied to the user’s device.

  • Tag: Use Tag data when you want to send information stored in the user profile.

  • Event: Use Event data when the webhook should send values from the triggering event of the journey.

  1. Select a parameter (for example, HWID, favourite category, etc.).
  2. Pushwoosh generates a macro that looks like this:
{{tag:Language}}
  1. Copy the macro and paste it into your JSON body in the DATA section.

When the webhook runs in a live journey, Pushwoosh automatically replaces the macro with the actual value for that user.

Insert Dynamic Data placeholders into the webhook request body

Map webhook response data to variables

Anchor link to

Besides sending data out, the Webhook element can also capture data from the response it receives and turn it into variables. These variables can then be used later in the journey. For example, set a tag with Update user profile, or schedule a Time Delay based on a value returned by the external service. For a full journey example, see Using webhook response data in your journey.

In the RESPONSE MAPPING section, click + ADD MAPPING and fill in two fields for each value you want to capture:

  • Path: the location of the value inside the response JSON body
  • Attribute: the name you use to reference this value later in the journey
Response mapping section with Path and Attribute fields and Add mapping button in webhook settings

For example, if your CRM responds with:

{
"data": {
"user": {
"id": "789xyz"
}
}
}

Set Path to data.user.id and Attribute to crm_user_id to capture that ID.

Map every element of an array

Anchor link to

Put * where the response has an array to capture a value from every element instead of just one, for example items.*.item_name. What you put in Attribute decides the shape of the result:

  • Include {n} in Attribute (for example item_{n}) to get one attribute per element, counted from 1: item_1, item_2, item_3, and so on. {n} can sit anywhere in the name, for example item_{n}_sku.
  • Leave {n} out (for example item_names) to join every element into a single attribute, separated by commas: Sofa, Lamp, Rug.

For example, if your CRM responds with:

{
"items": [
{ "item_name": "Sofa" },
{ "item_name": "Lamp" },
{ "item_name": "Rug" }
]
}

Set Path to items.*.item_name and Attribute to item_{n} to get item_1 = Sofa, item_2 = Lamp, item_3 = Rug. Set Attribute to item_names instead to get a single item_names = Sofa, Lamp, Rug.

A numbered attribute like item_3 can be referenced anywhere a regular webhook response attribute can: in Update user profile, in a Time Delay, or in Dynamic Content.

Timeout, retries, and failed requests

Anchor link to

Pushwoosh waits up to 10 seconds for a response. The whole Webhook step, including sending the request and processing the response, is capped at 30 seconds.

On a 500, 502, 503, or 504 response, or a network error, Pushwoosh retries the request once before giving up. Any other non-2xx response is not retried.

Rate limits

Anchor link to

Pushwoosh limits how many webhook requests an account can send per second. The limit is sized well above real traffic peaks, so normal journeys aren’t affected. A burst that exceeds it waits briefly for room before failing.

Endpoint cooldown

Anchor link to

If an endpoint fails several times in a row, Pushwoosh stops sending it requests for a while instead of retrying a broken endpoint on every traveler, starting at 30 seconds and doubling on further failures up to 5 minutes. A single successful request clears this and resumes normal delivery.

What happens when a request fails

Anchor link to

The Webhook element has no separate branch for failed requests. Any of the following drops the traveler from the journey at this step:

CauseWhat triggers it
Blocked endpoint addressThe URL is private, internal, loopback, or link-local, including cloud metadata endpoints
Rate limitThe account’s per-second webhook request limit is exceeded and no room opens up during the brief wait
Endpoint cooldownThe endpoint failed several times in a row and Pushwoosh is temporarily skipping it
TimeoutNo response within 10 seconds, or the step exceeds its 30-second cap
Network errorThe request couldn’t reach the endpoint at all
Non-2xx responseThe endpoint returned an error status that isn’t retried, or was retried once and failed again

See Request error.

If you can’t afford to lose travelers here, have your endpoint always return a 2xx response and put any failure state in the response body instead, for example as a value your Response mapping can pick up.

This applies to every Webhook step, including ones set up before this change. An endpoint address that now matches the blocked-address rule above will start failing the same way.

Unlike a failed request, a response that arrives but doesn’t map cleanly, such as invalid JSON, an unresolved Path, or a body over 64 KB, does not drop the traveler. See the note under Response mapping above.

Test the Webhook

Anchor link to

Click Test webhook to verify that your webhook configuration is correct and the request is sent successfully.

If a header still shows the stored mask, Pushwoosh fills in the real, saved value for the test request. The value never appears in your browser.

This substitution only works for a header already saved on this exact step. A step you haven’t saved yet, or one you just copied, has no saved value behind the mask, so Pushwoosh sends the test request without that header.

Save your configuration

Anchor link to

Click Apply to save your webhook configuration.

Open the Calls log tab in the point’s drawer to see what Pushwoosh actually sent for this step: time, user, result, and duration, going back 30 days.

Filter by result (Success, HTTP error, No response) or search by the exact User ID or HWID. Click a row to expand it and see the request (method, URL, and body) and, depending on the outcome, either the response (status and body) or the error text. Duration covers the whole step, including time spent on an automatic retry.