Pine Script tool
TradingView Alert Webhook Builder
Compose the JSON body TradingView will POST to your webhook, check it parses once the placeholders resolve, and catch a misspelled placeholder before it reaches your server as literal text.
What your server would receive
{
"secret": "replace-with-your-own-shared-secret",
"action": "buy",
"ticker": "AAPL",
"exchange": "NASDAQ",
"quantity": 39,
"price": 187.42,
"position": "long",
"position_size": 39,
"order_id": "Long",
"time": "2026-09-04T14:39:58Z"
}Sample values, not live data. The point of the preview is the shape of the payload and whether the quoting is right, not the numbers.
Placeholder reference
These are the placeholders TradingView substitutes when an alert fires. Click one to append it to your template. Two constraints are worth knowing before you build the payload: the strategy placeholders only resolve on alerts created from a strategy, and the plot placeholders only on alerts created from an indicator. Mixing them produces literal text rather than an error, which is exactly the failure that is hardest to notice.
Symbol and chart
- The symbol’s ticker, such as AAPL or BTCUSDT.
- The exchange the symbol trades on.
- The chart timeframe the alert was created on.
Price and time
- Closing price of the bar that triggered the alert.
- Opening price of the triggering bar.
- High of the triggering bar.
- Low of the triggering bar.
- Volume of the triggering bar.
- Opening time of the triggering bar, in UTC.
- The moment the alert fired, in UTC.
Strategy orders (strategies only)
- Whether the order was a buy or a sell.
- Number of contracts or units in the order.
- Price the order was filled at.
- The order id you passed to the entry or exit call.
- The comment argument on the order call, if set.
- The alert_message argument on the order call. This is how you send per-order text.
- Position size after the order was filled.
- Position direction after the order: long, short, or flat.
- Absolute size of the position after the order.
- Position direction before the order was filled.
Indicator plots (indicators only)
- Value of the first plot in the script, counting from zero.
- Value of a plot referenced by its title, which survives reordering.
Where placeholders work, and where they do not
This is the distinction that causes the most wasted time. Placeholders are substituted by TradingView in the Message field of the alert dialog. They are not substituted inside a string you build in Pine Script and pass to the alert() function, because by the time that string exists your code has already assembled it. Putting {{close}} inside an alert() call sends the literal characters.
When you need dynamic text from inside Pine Script, build it there with str.tostring() and string concatenation, which is what the code example below does. When you need per-order text on a strategy, the alert_message argument on the order call is the bridge: you build the string in Pine, and it arrives in the webhook through the {{strategy.order.alert_message}} placeholder in the dialog. That combination is how most non-trivial webhook setups actually work.
Quoting deserves one deliberate decision rather than a guess. A placeholder inside quotes arrives as a JSON string, and the same placeholder without quotes arrives as a bare number. Both are valid and they are not interchangeable: a receiver expecting a number and given "39" will often fail in a way that looks like a connection problem. The preview above exists mainly to make this visible, since a payload that parses as JSON can still have every numeric field typed as a string.
Security, and one honest warning
A webhook endpoint that acts on incoming messages is an endpoint that anyone who learns the URL can send messages to. TradingView posts from its own servers over HTTPS, but the URL itself is the only thing standing between the internet and whatever your receiver does. That is why the templates here include a shared secret field: your server should reject any payload whose secret does not match, and it should treat every other field as untrusted input rather than as instructions.
Beyond the secret, the standard measures apply. Validate that the ticker and action are values you expect rather than passing them through, put a sane limit on quantity, log what arrives, and make the handler idempotent so a duplicate delivery does not double an order. Alerts can fire more than once for the same condition depending on the frequency setting, and a receiver that assumes exactly-once delivery will eventually be wrong.
The larger point is worth stating plainly, because it sits outside what any builder can help with: connecting a script to anything that places real orders is a decision with consequences that no amount of correct JSON addresses. Nothing here is a recommendation to do it, and the choice, along with everything that follows from it, is entirely yours.
The Pine Script side of an alert
The script is where the alert originates, and the two mechanisms in the code above cover almost every case. On a strategy, alert_message on the order call gives each order its own text. On an indicator, or wherever you need an alert that is not tied to an order, alert() fires one with a message you assemble yourself.
Note the frequency argument on the alert() call. alert.freq_once_per_bar_close fires only on a confirmed bar, which is the setting that avoids alerts firing on a value that later changes as the bar develops. If you have ever received an alert and found the condition no longer true when you looked, that is repainting rather than a delivery problem, and our guide to repainting covers why. The alerts guide goes through the rest of the alert mechanics.
//@version=6
strategy("Alert message per order", overlay = true)
// Placeholders like {{strategy.order.action}} are substituted by
// TradingView in the alert dialog's message field. They are NOT
// substituted inside a string you build here, because this string is
// already assembled by your code. For dynamic text from Pine, build it
// with str.tostring() and send it via alert() or alert_message.
longSignal = ta.crossover(ta.sma(close, 10), ta.sma(close, 30))
shortSignal = ta.crossunder(ta.sma(close, 10), ta.sma(close, 30))
// alert_message gives each order its own text, which then arrives in the
// webhook through the {{strategy.order.alert_message}} placeholder.
if longSignal
strategy.entry("Long", strategy.long,
alert_message = "open long " + syminfo.ticker + " at " + str.tostring(close, format.mintick))
if shortSignal
strategy.close("Long",
alert_message = "close long " + syminfo.ticker + " at " + str.tostring(close, format.mintick))
// An indicator, or a strategy that needs an alert independent of an order,
// uses alert() instead. Build the whole payload as a string.
payload = '{"ticker":"' + syminfo.ticker + '","close":' + str.tostring(close) + '}'
if longSignal
alert(payload, alert.freq_once_per_bar_close)PineScripter is an AI built specifically for Pine Script. You describe what you want in plain English and it writes TradingView-ready v6 code. Because it is specialized on the Pine Script language and its exact function signatures, it tends to produce code that compiles far more reliably than general-purpose models like ChatGPT, which often invent functions that do not exist in Pine Script.
Related free calculators
From the blog
PineScripter is an AI developer tool that helps you write Pine Script code. It is not a financial advisor and will never offer financial, investment, or trading advice. Everything on this page, including the calculator and the explanations, is provided purely for educational and informational purposes. Any decision about how to interpret an indicator or trade a market is entirely your own. See our full disclaimer for more.