DocumentationFundamentals

Functions

Use functions to transform webhooks, modify payloads, filter requests, integrate systems, and more.

Functions let you run custom code on every webhook that passes through Webhook Relay. Use them to transform payloads, modify headers, filter unwanted requests, make HTTP calls to external APIs, and integrate different systems together.

Functions can be written in JavaScript or Lua. Both languages have access to the same request object (r) and built-in modules for HTTP requests, JSON, cryptography, and more.

What can you do with functions?

  • Transform payloads — reshape webhook data from one format to another, for example converting a GitHub push event into a Slack message.
  • Filter requests — inspect incoming webhooks and reject ones that don't match your criteria.
  • Modify headers and method — add authentication headers, change the HTTP method, or set a custom path before forwarding.
  • Make HTTP requests — call external APIs to enrich data, fetch tokens, or send notifications to multiple services.
  • Validate webhooks — verify HMAC signatures, check shared secrets, and ensure webhook authenticity.
  • Customize responses — return custom status codes and response bodies to the webhook sender.

Quick example: transform a payload

This function takes an incoming JSON webhook and reshapes it into a Slack message format:

const payload = JSON.parse(r.body)

const slackMessage = {
    text: `New event from ${payload.source}: ${payload.message}`
}

r.setBody(JSON.stringify(slackMessage))
r.setHeader("Content-Type", "application/json")
local json = require("json")

local payload, err = json.decode(r.RequestBody)
if err then error(err) end

local slack_message = {
    text = "New event from " .. payload.source .. ": " .. payload.message
}

local encoded, err = json.encode(slack_message)
if err then error(err) end

r:SetRequestBody(encoded)
r:SetRequestHeader("Content-Type", "application/json")

Quick example: filter requests

This function only forwards webhooks that have an action field set to "completed":

const payload = JSON.parse(r.body)

if (payload.action !== "completed") {
    r.stopForwarding()
    return
}
local json = require("json")

local payload, err = json.decode(r.RequestBody)
if err then error(err) end

if payload.action ~= "completed" then
    r:StopForwarding()
    return
end

Quick example: call an external API

Functions can make HTTP requests to enrich webhook data or notify other services:

const payload = JSON.parse(r.body)

// look up additional data from an external API
const resp = http.request("GET", "https://api.example.com/users/" + payload.user_id, {
    headers: {
        Authorization: "Bearer " + cfg.get("API_TOKEN")
    }
})

const user = JSON.parse(resp.body)

// enrich the original payload with user data
payload.user_name = user.name
payload.user_email = user.email

r.setBody(JSON.stringify(payload))
local json = require("json")
local http = require("http")

local payload, err = json.decode(r.RequestBody)
if err then error(err) end

-- look up additional data from an external API
local resp, err = http.request("GET", "https://api.example.com/users/" .. payload.user_id, {
    headers = {
        Authorization = "Bearer " .. cfg:GetValue("API_TOKEN")
    }
})
if err then error(err) end

local user, err = json.decode(resp.body)
if err then error(err) end

-- enrich the original payload with user data
payload.user_name = user.name
payload.user_email = user.email

local encoded, err = json.encode(payload)
if err then error(err) end

r:SetRequestBody(encoded)

Next steps

Explore the guides in this section for detailed examples:

Did this page help you?