Validate the rendered message
Do not validate only the template. Trigger a test alert and inspect the message received after placeholders or dynamic values are resolved.
Pine Script alert guide
A stock trading signals JSON format should be predictable for the system that receives it. Start with a small schema, keep text in double quotes, send numbers as numbers, and validate the exact payload before connecting it to any automated workflow.
This is an illustrative schema, not a universal broker contract. Add keys only when the endpoint has a documented use for them. A JSON alert is a message contract, not an order by itself. The placeholder template must be rendered by TradingView before JSON parsing; {{close}} is not valid raw JSON.
{
"symbol": "{{exchange}}:{{ticker}}",
"bar_time": "{{time}}",
"action": "buy",
"price": {{close}},
"timeframe": "{{interval}}",
"signal_id": "ema_cross_up_v1"
}The alert() function accepts a dynamic series string. This sample waits for a confirmed bar, converts the price to text for string assembly, and leaves the resulting JSON price unquoted so the receiver gets a number. Use a standard time-based chart for this example. Select this indicator and “Any alert() function call” when creating the alert. Validate the received symbol mapping and JSON; arbitrary user text would need JSON escaping.
//@version=6
indicator("EMA signal JSON", overlay = true)
fastEma = ta.ema(close, 9)
slowEma = ta.ema(close, 21)
longSignal = ta.crossover(fastEma, slowEma)
plot(fastEma, color = color.blue)
plot(slowEma, color = color.orange)
if longSignal and barstate.isconfirmed
payload = '{"symbol":"' + syminfo.tickerid +
'","action":"buy","price":' +
str.tostring(close, format.mintick) +
',"timeframe":"' + timeframe.period +
'","bar_time_ms":' + str.tostring(time) +
',"signal_id":"ema_cross_up_v1"}'
alert(payload, alert.freq_once_per_bar_close)Do not validate only the template. Trigger a test alert and inspect the message received after placeholders or dynamic values are resolved.
TradingView warns against putting passwords or login credentials in the webhook body. Authenticate and authorize at the receiver.
For this one-event-per-rule-per-bar example, deduplicate by rule version, instrument, timeframe and bar timestamp. A fixed signal_id alone would suppress later valid signals. Multiple events per bar need a richer event key; reconcile delivery and execution separately.
Treat Pine Script as the signal source. The receiver remains responsible for schema checks, limits, logging, and any execution decision.
Sources checked October 21, 2026.