TradingView Webhooks: Send Alerts to Discord, Slack or an API

Set up TradingView webhook alerts for Discord, Slack or any API. Includes JSON payloads, JavaScript transforms, fan-out and troubleshooting.

TradingView can POST an alert to any HTTPS webhook URL. To send that alert to Discord, Slack or an API, put a Webhook Relay input between TradingView and the destination, then reshape the payload for each output.

The important constraints are easy to miss: TradingView only accepts destination ports 80 and 443, cancels requests that take longer than three seconds, requires two-factor authentication for webhook alerts, and chooses application/json only when the alert message is valid JSON. These requirements are documented in TradingView's webhook alert guide.

What you will build

TradingView alert
       |
       v
Webhook Relay input
       |
       +--> transform to Discord --> Discord channel
       +--> transform to Slack   --> Slack channel
       +--> preserve JSON        --> your API

One stable input URL receives the alert. Each output can use its own JavaScript transformation, so Discord and Slack do not need to agree on a payload format.

1. Create the Webhook Relay input

Open the new public destination page, add your first destination URL, and copy the generated input URL.

For Discord, create an incoming webhook under Server Settings > Integrations > Webhooks and use its URL as the destination. Discord's webhook API accepts a content string or an embeds array.

For Slack, create an incoming webhook for the target channel and use that URL. Slack's incoming webhook guide accepts JSON with text or Block Kit blocks. Treat both Discord and Slack webhook URLs as secrets.

2. Send structured JSON from TradingView

In TradingView, create an alert, enable Webhook URL, and paste the Webhook Relay input URL. Use valid JSON in the Message field:

{
  "ticker": "{{ticker}}",
  "exchange": "{{exchange}}",
  "price": {{close}},
  "action": "{{strategy.order.action}}",
  "time": "{{time}}"
}

TradingView replaces the placeholders when the alert fires. Its placeholder reference lists the values available for indicators and strategies.

Keep numeric placeholders such as {{close}} unquoted only when they always resolve to a number. If a value can be blank or textual, quote it so the result remains valid JSON.

3. Transform the alert for Discord

Attach this function to the Discord output:

let alert

try {
  alert = JSON.parse(r.body)
} catch (error) {
  alert = { ticker: "TradingView", action: "alert", price: r.body }
}

const message = {
  embeds: [{
    title: `${alert.ticker} ${alert.action || "alert"}`,
    description: `Price: ${alert.price}`,
    fields: [
      { name: "Exchange", value: String(alert.exchange || "unknown"), inline: true },
      { name: "Time", value: String(alert.time || "unknown"), inline: true }
    ]
  }]
}

r.setMethod("POST")
r.setHeader("Content-Type", "application/json")
r.setBody(JSON.stringify(message))

The try block also handles an older plain-text alert without dropping it.

4. Transform the same alert for Slack

Add a second output with the Slack incoming webhook URL and attach a Slack-specific function:

const alert = JSON.parse(r.body)

const message = {
  text: `${alert.ticker} ${alert.action || "alert"} at ${alert.price}`,
  blocks: [
    {
      type: "section",
      text: {
        type: "mrkdwn",
        text: `*${alert.ticker}* ${alert.action || "alert"}\nPrice: *${alert.price}*`
      }
    },
    {
      type: "context",
      elements: [{
        type: "mrkdwn",
        text: `${alert.exchange || "Unknown exchange"} | ${alert.time || "No timestamp"}`
      }]
    }
  ]
}

r.setHeader("Content-Type", "application/json")
r.setBody(JSON.stringify(message))

If you prefer plain messages, use { "text": "..." }. The blocks example is useful when you want the ticker and price to remain scannable in a busy channel.

Forward TradingView alerts to your own API

Your API may already accept the JSON from TradingView. In that case, add it as another output without a body transform. You can still add authentication without placing secrets in the TradingView alert:

r.setHeader("Authorization", "Bearer " + cfg.get("DESTINATION_API_TOKEN"))
r.setHeader("Content-Type", "application/json")

Store DESTINATION_API_TOKEN in the function's configuration variables. TradingView explicitly warns against putting credentials in the webhook body.

For private APIs on localhost, a private VM, or a cluster service, follow the localhost webhook forwarding guide and run the relay agent inside the network.

Safety for broker and trading APIs

A webhook can technically call a broker or exchange endpoint, but a chat notification and a trade execution are not the same risk class. Before enabling live orders:

  1. Use a paper-trading account.
  2. Allowlist symbols, actions and maximum position size.
  3. Reject malformed or duplicate alerts.
  4. Keep API credentials in configuration variables.
  5. Put work that may exceed three seconds behind a queue.
  6. Alert on rejected and failed deliveries.

Do not rely on a human-readable alert string as an order instruction. Send explicit JSON fields and validate every one.

Troubleshooting TradingView webhooks

TradingView sends text/plain

The alert message is not valid JSON. Paste the final message into a JSON validator and check quoting around placeholders. TradingView sets application/json only when the rendered message parses as JSON.

The request times out

TradingView cancels requests after three seconds. Check the Webhook Relay delivery duration and destination response. A slow downstream API should accept the event quickly and process it asynchronously.

Discord returns 400

Discord expects at least one supported field such as content or embeds. Confirm the function is attached to the Discord output and that it sets Content-Type: application/json.

Slack returns an invalid-payload error

Slack expects JSON with a text string or valid Block Kit. Inspect the transformed request body in the delivery log, not only the original TradingView message.

The webhook option is unavailable

Confirm that two-factor authentication is enabled and that your TradingView plan supports webhook alerts. Use an HTTPS URL on port 443.

Next steps

Use the webhook transformation cookbook to add routing and validation, or start with the free Webhook Bin to inspect the exact TradingView request before connecting a real destination.

Frequently asked questions

How do I send a TradingView alert to Discord?

Send the TradingView alert to a Webhook Relay input, attach a JavaScript function that creates Discord's content or embeds payload, and forward the result to the Discord incoming webhook URL.

Why does TradingView say my webhook timed out?

TradingView cancels webhook requests that take more than three seconds. Acknowledge quickly and move slow broker, database or enrichment work behind an asynchronous queue.

Does TradingView send JSON webhooks?

TradingView uses application/json when the alert message is valid JSON. Otherwise it sends text/plain. Put valid JSON in the alert message when your destination needs structured fields.

Can one TradingView alert go to several destinations?

Yes. A Webhook Relay bucket can fan one input out to multiple outputs, with a different transform on each output for Discord, Slack, an internal service or another API.