---
title: "Execute scripts on webhook | WebhookRelay"
meta:
  "og:description": "Execute commands such as bash, python or ruby when webhooks are received"
  "og:title": "Execute scripts on webhook"
  description: "Execute commands such as bash, python or ruby when webhooks are received"
---

![Stripes](https://webhookrelay.com/docs/tutorials/cicd/webhook-exec/images/stripes.svg)

Documentation

**Fundamentals**

# **Execute scripts on webhook**

Execute commands such as bash, python or ruby when webhooks are received

## [Executing commands on a host machine](#executing-commands-on-a-host-machine)

Relay agent lets executing any commands or scripts on a host machine when webhooks are received. To use this functionality, use `--relayer exec` option together with `--command python` (or any other command such as `node`) followed by optional arguments. For example to execute python script in a file called `my-script.py`:

```
relay forward --bucket my-bucket-name --relayer exec --command python my-script.py
```

Here:

- **--bucket** specifies which bucket to subscribe to
- **--relayer** specifies `exec` relayer (by default it would forward to an HTTP endpoint)
- **--command** is the main command to execute, for bash scripts you would use `bash` command
- **my-script.py** is the optional script/application file

This script will receive webhook data through standard input ([stdin](https://en.wikipedia.org/wiki/Standard_streams)). You can read this data and optionally return a response. Response will be visible in the webhook log through the Webhook Relay web interface.

> Executed script will always be marked with status code 200 even though it will not be forwarded to a destination by the relay agent. When running in a `--relayer exec` mode, agent will only execute commands without forwarding webhooks. To also forward webhooks, launch a second agent.

### [Python example](#python-example)

Here is a simple Python script that will read from standard input and save the webhook payload into a file with a timestamp.

```
import sys
from time import gmtime, strftime
import datetime

payload = sys.stdin.read()

now = datetime.datetime.now()
timestamp = str(now.strftime("%Y%m%d_%H:%M:%S"))

filename = "webhook-" + timestamp + ".json"

file = open(filename,"w") 
file.write(payload)
file.close()

print("received")
```

### [Default input mode](#default-input-mode)

By default **relay** agent only sends request body through the stdin into the script:

```
relay forward --bucket forward-a --relayer exec --command python my-script.py
Executing command on webhooks: 
https://my.webhookrelay.com/v1/webhooks/1eff80d0-b258-4175-983c-b03f8961608d -> python my-script.py
[i] Please ensure that your buckets have at least one internal output destination, otherwise this agent will not receive webhooks.
```

Now, send a webhook:

```
curl --request POST \
  --url https://my.webhookrelay.com/v1/webhooks/1eff80d0-b258-4175-983c-b03f8961608d \
  --data '{
    "msg": "webhook msg"
}'
```

File contents will be:

```
{
    "msg": "webhook msg"
}
```

### [JSON input mode](#json-input-mode)

Launching **relay** agent you should see that it's now executing commands instead of forwarding webhooks:

```
relay forward --bucket forward-a --relayer exec --input-mode json --command python my-script.py
Executing command on webhooks: 
https://my.webhookrelay.com/v1/webhooks/1eff80d0-b258-4175-983c-b03f8961608d -> python my-script.py
[i] Please ensure that your buckets have at least one internal output destination, otherwise this agent will not receive webhooks.
```

Let's send another webhook:

```
curl --request POST \
  --url https://my.webhookrelay.com/v1/webhooks/1eff80d0-b258-4175-983c-b03f8961608d \
  --data '{
    "msg": "webhook msg"
}'
```

You should now see a file created with contents:

```
{
  "type": "webhook",
  "meta": {
    "bucked_id": "e1ea4726-89e1-4983-84ac-fc92cb153647",
    "bucket_name": "forward-a",
    "input_id": "1eff80d0-b258-4175-983c-b03f8961608d",
    "input_name": "Default public endpoint",
    "output_name": "https://bin.webhookrelay.com/#/bins/f8235d2a-2156-4b3e-a110-0cfd9ab3a3fa",
    "output_destination": "https://bin.webhookrelay.com/v1/webhooks/84575fa2-4d9d-4aa4-942f-4e5ffea52dae"
  },
  "headers": {
    "Accept": [
      "*/*"
    ],
    "Content-Length": [
      "25"
    ],
    "User-Agent": [
      "insomnia/6.6.2"
    ],
  },
  "query": "",
  "body": "{\n\t\"msg\": \"webhook msg\"\n}",
  "method": "POST",
  "status": "",
  "message": ""
}
```

## [Background service configuration](#background-service-configuration)

To execute commands when running in a [background service mode](https://docs.webhookrelay.com/installation-options/installation-options/background-service) add additional 'relayer' section:

```
version: "v1"
key: your-secret-key # will be encrypted on startup
secret: your-secret  # will be encrypted on startup
buckets:
  - bucket-1-name
  - bucket-2-name
relayer:
  type: exec
  # inputMode: json # uncomment to receive full JSON payload with headers, query and other metadata
  timeout: 2 # timeout in seconds
  command: python
  commandArgs: [ 'my-script.py' ]
```

## [Debugging scripts and commands](#debugging-scripts-and-commands)

To debug your commands you can use standard shell pipes. For example to try the previous Python example without Webhook Relay:

```
echo my-data-here | python my-script.py
```

Or, if your test data is in a file:

```
cat test_data.json | python my-script.py
```

Did this page help you?