---
title: "Send a Webhook to Discord | WebhookRelay"
meta:
  "og:description": "Send any webhook to Discord. Step-by-step guide to forward an incoming webhook to a Discord channel, transforming the raw payload into Discord's { content } format in flight."
  "og:title": "Send a Webhook to Discord"
  description: "Send any webhook to Discord. Step-by-step guide to forward an incoming webhook to a Discord channel, transforming the raw payload into Discord's { content } format in flight."
---

![Stripes](https://webhookrelay.com/blog/webhook-to-discord/images/stripes.svg)

# **Send a Webhook to Discord**

Send any webhook to Discord. Step-by-step guide to forward an incoming webhook to a Discord channel, transforming the raw payload into Discord's { content } format in flight.

![Send a Webhook to Discord: Transform &amp; Forward Any Payload](https://webhookrelay.com/blog/webhook-to-discord/images/blog/heroes/route.jpg)

You have a service that fires webhooks — a CI pipeline, a contact form, an uptime monitor, a payment provider, an alerting tool — and you want each event to show up in a **Discord channel**. The problem: Discord doesn't accept arbitrary payloads. It expects a specific JSON body, and the webhook your source sends almost never matches that shape.

[Webhook Relay](https://webhookrelay.com) sits in the middle. It receives the incoming webhook at a stable public URL, **transforms** the payload into the format Discord expects, and delivers it — no glue server, no Lambda, no maintenance.

> **Build it visually first:** the free [webhook → Slack/Discord/Teams formatter](https://webhookrelay.com/blog/webhook-to-discord/webhook-message-formatter/) lets you paste a sample payload, template the Discord embed, preview it live, and copy the exact transform function used below — a faster, automatable [Discohook alternative](https://webhookrelay.com/blog/webhook-to-discord/webhook-message-formatter/) for incoming webhooks.

## [How it works](#how-it-works)

The flow is a single hop with a transform in the middle:

```
Your service  ──▶  Webhook Relay  ──▶  transform to { content }  ──▶  Discord channel
 (raw webhook)      (public URL)        (serverless function)         (message appears)
```

Discord expects a JSON body like this POSTed to a Discord webhook URL:

```
{ "content": "your message" }
```

A generic incoming webhook isn't shaped like that, so we add a small [transformation function](https://webhookrelay.com/blog/webhook-to-discord/features/transform-webhooks/) that wraps the raw body into Discord's format before delivery. That one feature is what turns Webhook Relay into a universal "anything → Discord" bridge.

## [Step 1: Create the Discord webhook URL](#step-1-create-the-discord-webhook-url)

In Discord, open **Server Settings → Integrations → Webhooks → New Webhook**. Pick the channel you want messages to land in, give it a name, and click **Copy Webhook URL**. It looks like:

```
https://discord.com/api/webhooks/123456789/AbCdEf...
```

Keep this URL handy — it's the destination Webhook Relay will deliver to.

## [Step 2: Create a Webhook Relay public endpoint](#step-2-create-a-webhook-relay-public-endpoint)

Open [the new public destination page](https://my.webhookrelay.com/new-public-destination) and paste the Discord webhook URL as the **destination**. Webhook Relay gives you back an **input URL** — a public endpoint that you'll point your source service at.

That input URL is now a stable address you can hand to any service. Everything sent to it gets forwarded toward Discord.

## [Step 3: Add a transformation function](#step-3-add-a-transformation-function)

Right now, anything you send to the input URL would be forwarded to Discord _as-is_ — and Discord would reject it, because it isn't in `{ "content": "..." }` shape. Add a [transformation](https://webhookrelay.com/blog/webhook-to-discord/features/transform-webhooks/) to fix that.

Click **Transform** on the input, open the [Functions](https://my.webhookrelay.com/functions) page, create a function "from scratch", and paste this Lua:

```
local json = require("json")

local payload = {
    content = r.RequestBody,
}

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

r:SetRequestHeader("content-type", "application/json")
r:SetRequestMethod("POST")
r:SetRequestBody(body)
```

This takes the raw incoming body, wraps it as `{ "content": "..." }`, sets the right headers and method, and lets Webhook Relay deliver it. Discord now accepts the message and posts it to your channel.

## [Step 4: Point your source at the URL and test](#step-4-point-your-source-at-the-url-and-test)

Configure your source service (the CI tool, form, monitor, payment provider — whatever you're integrating) to send its webhook to the Webhook Relay **input URL**.

To confirm everything works before wiring up the real service, fire a quick test with `curl`:

```
curl -X POST https://my.webhookrelay.com/v1/webhooks/your-input-id \
  -d 'Deployment finished: build #482 passed on main'
```

Within a second or two, **Deployment finished: build #482 passed on main** appears in your Discord channel. If nothing shows up, open the request log in your dashboard to see exactly what was received and delivered.

## [Going further](#going-further)

Once the basic bridge works, the transform function is where the real power is.

**Build a richer message with embeds.** If your source sends JSON, parse it and construct a Discord `embeds` object instead of a flat string — title, description, a colored sidebar, and labelled fields:

```
local json = require("json")

local event = json.decode(r.RequestBody)

local payload = {
    embeds = {
        {
            title = "Deployment " .. event.status,
            description = event.message,
            color = 5814783,
        },
    },
}

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

r:SetRequestHeader("content-type", "application/json")
r:SetRequestMethod("POST")
r:SetRequestBody(body)
```

**Filter out noise.** Not every event deserves a ping. Use [forwarding rules](https://webhookrelay.com/blog/webhook-to-discord/features/forwarding-rules/) to only deliver events that match a condition, or drop them in the function with an early `return`.

**Fan out to multiple channels.** Add more destinations so one incoming webhook lands in several Discord channels — or in Discord _and_ Slack — at the same time. See [forwarding to multiple destinations](https://webhookrelay.com/blog/webhook-to-discord/features/webhook-multiple-destinations/).

For a complete real-world walkthrough using this exact pattern, see [TradingView alerts to Discord](https://webhookrelay.com/blog/webhook-to-discord/blog/trading-view/), where a plain alert message is transformed into a Discord notification.

## [FAQ](#faq)

**What does Discord need to receive?** A `POST` with a JSON body of `{ "content": "your message" }` (or an `embeds` array for rich cards) to a Discord channel webhook URL. The transform function produces exactly that.

**Do I need to run a server?** No. Webhook Relay receives, transforms, and delivers everything in the cloud. There's nothing to host or keep online.

**How do I see the raw payload my source sends?** Send it to a free [Webhook Bin](https://webhookrelay.com/blog/webhook-to-discord/webhook-bin/) first to inspect the exact body and headers, then write your transform around that structure.

## [Get started](#get-started)

[Create a free Webhook Relay account](https://my.webhookrelay.com/register) and set up your first "anything → Discord" bridge in a few minutes. Not sure what your source sends? [Inspect the payload in a Webhook Bin](https://webhookrelay.com/blog/webhook-to-discord/webhook-bin/) first, then write the transform to match.