> For clean Markdown content of this page, append .md to this URL. For the complete documentation index, see https://learning.postman.com/llms.txt. For full content including API reference and SDK examples, see https://learning.postman.com/llms-full.txt.

# Webhooks in Postman

<Info class="plan">
  This feature is available on Postman Solo, Team, and Enterprise plans. For more information, see the [pricing page](https://www.postman.com/pricing/).
</Info>

Webhook listeners let you capture, inspect, route, and replay incoming webhook events without leaving Postman. They give you a public URL to register with any provider and a workspace-shared event log to debug what's coming in.

Webhook listener toggles are located in the **Services** panel and enable you to do the following:

* Capture and inspect of every incoming event, with raw headers, raw body, timestamps, and response status.
* Route events to any target URL or respond to the producer with a custom status, headers, and body.
* Replay any captured event, useful for re-running events through your routing rule while you debug.

## Create a listener

To create a listener, do the following:

1. In the sidebar, click <img alt="Add icon" src="https://assets.postman.com/postman-docs/aether-icons/v12/icon-action-add-stroke.svg#icon" width="20px" /> and select **Webhook**.
2. In the upper-right of the workbench, click <img alt="Copy icon" src="https://assets.postman.com/postman-docs/aether-icons/v12/icon-action-copy-stroke.svg#icon" width="20px" /> **Webhook URL** and share it with your provider.

The listener begins capturing events as soon as it's created. You can stop and restart it at any time using the **Start/Pause** toggle.

A listener URL has the following format:

```
https://<webhook-id>.webhook.pstmn.io
```

Each listener has its own stable URL that survives across sessions and doesn't change when you toggle the listener off and on. A single workspace can have multiple listeners, so you can keep separate listeners for different providers, environments, or experiments.

## Inspect captured events

Every event captured by the listener is stored in the **Events** tab. For each event you can view:

* The raw headers as received.
* The raw body. Postman never reformats the event's body.
* The timestamp at which the event arrived.
* The response status sent back to the producer.

Payload bodies are displayed with syntax highlighting. The event log is shared with every member of the workspace.

## Routing events

The **Routing** tab controls what Postman does with each incoming event. You can either forward the event to another URL, or respond to the producer directly, but not both at the same time.

### Forwarding

Forwarding sends each incoming event to a target URL of your choice. The target can be a public URL, a staging or beta environment, or a `localhost` address on your machine, so you can connect to a local server during development without standing up a tunneling tool.

To configure forwarding, do the following:

1. On your listener, open the **Routing** tab.
2. Select **Forward**.
3. Enter the target URL, for example `http://localhost:3000/webhook` or `https://staging.myapp.com/webhook`.

The listener URL is stable, so it's registered only once with the provider. You can change the forward target as you move between environments.

### Responding

Some providers expect the webhook endpoint to return a specific response, which you can manage directly from the listener without standing up a server.

To configure a response, do the following:

1. On your listener, open the **Routing** tab.
2. Select **Respond**.
3. Set the status code to return an HTTP response (for example, `200`).
4. Add any response headers in the key-value editor.
5. Provide a response body. The body can be static, or it can reference values from the incoming request using template syntax.

### Reference values from the incoming request

Both the response body and response headers support template syntax for pulling values out of the incoming request. The syntax follows [object-path](https://www.npmjs.com/package/object-path) conventions, wrapped in double curly braces (`{{ }}`).

<ParamField path="$body">
  The incoming request body. Example: `{{$body 'challenge'}}`
</ParamField>

<ParamField path="$headers" type="number" default="50">
  The incoming request headers. Example: `{{$headers 'x-event-id'}}`
</ParamField>

<ParamField path="$query" type="number" default="50">
  The incoming query string parameters. Example: `{{$query 'token'}}`
</ParamField>

Postman substitutes the value from the incoming request when it sends the response. Object-path syntax also handles nested fields, for example `{{$body 'event.user.id'}}`.

## Replay events

Any captured event can be replayed. Postman re-sends the exact raw headers and raw body as they arrived. The replayed event flows through the routing rule the listener currently has configured. If the rule is set to forward, the replayed event is forwarded. If the rule is set to respond, Postman returns the configured response.

Replays are useful for:

* Re-running an event against your local server while debugging without asking the provider to send it again.
* Verifying that a fix works against a captured event you couldn't reproduce.
* Sanity-checking idempotency, so you can replay the same event twice and confirm your handler behaves correctly.

To replay an event, do the following:

1. In the **Events** tab, select the event you want to replay.
2. Click <img alt="Play icon" src="https://assets.postman.com/postman-docs/aether-icons/v12/icon-action-play-stroke.svg#icon" width="20px" /> **Replay**.

Each event is replayed individually.