Skip to main content

Alert Message — Where the JSON Lives

The Message field is the body TradingView posts to TVH on every trigger. TVH parses it as JSON, runs its auto-mapping, then dispatches to the exchange. This page covers what to put in that field and how to escape quotes when you build the JSON from Pine.

TL;DR
  • The Webhook URL and the Message field are the only two fields TVH cares about.
  • The body is JSON — no HTML, no multipart, no extra prefix. TradingView posts it as application/x-www-form-urlencoded; TVH URL-decodes and strips = automatically.
  • In Pine, wrap your JSON in single quotes so the embedded " characters survive. The string then contains pure JSON, no escape gymnastics.
  • Always validate the payload against the Parameter Reference before saving the alert.

The two fields that matter

A TradingView alert has many fields. TVH only reads two:

FieldWhere to find it in TVWhat it carries
Webhook URLNotifications tab → Webhook URLThe TVH endpoint, e.g. https://alerts.tv-hub.org. See Webhook URLs & IPs.
MessageSettings tab → MessageThe JSON trade command. The whole body.

Everything else (alert name, expiration, sound, popup) is local to TradingView and never leaves your browser.

Where to get your JSON

Four common sources, in increasing order of effort and flexibility:

Open the exchange-specific Trade Command Builder, configure the trade, and click Copy JSON. Paste the result into TradingView's Message field. The builder always produces a valid payload, so you skip the JSON-validation step.

Use this for: static configurations, fixed-size trades, anything you would build once and reuse.

2. Generate it with an LLM

Describe the trade in plain language to ChatGPT, Claude, or any LLM — for example "long BTCUSDT on Binance Futures, 2% of balance, 5x leverage, 1% stop, two take-profits at +1% and +2%" — and have it produce the JSON. Give the model the canonical references so the output is valid:

Use this for: drafting a payload from a description, or generating dynamic templates you then tweak. There is no payload-validation feature in TVH, so check the output yourself — validate it against /schemas/trade-command.schema.json in an editor and run it on a demo account before going live.

3. Manual JSON

Write the JSON by hand. Use this when the builder is missing a niche field, you want a payload smaller than the builder's verbose default, or you are scripting from outside TVH.

Validate against the full schema at Parameter Reference, which always matches what the live webhook accepts.

4. From Pine via alert() or alert_message=

Your Pine script builds the JSON at runtime and emits it. This is how you get dynamic prices, dynamic sizing, dynamic pairs, and per-order dispatch.

Indicator pattern with alert():

if long_signal
alert('{"exchange":"binance","pair":"BTCUSDT","isBuy":true,"unitsType":"percent","unitsPercent":2,"isMarket":true,"token":"YOUR_TOKEN"}', alert.freq_once_per_bar_close)

Strategy pattern with alert_message=:

strategy.entry("Long", strategy.long, alert_message=buy_command)

The full mechanics are on Indicator Alerts and Strategy Alerts.

Quote escaping inside Pine strings

JSON requires double quotes around every key and every string value. Pine strings accept either ' or " as the wrapper. Use single quotes so the JSON's double quotes never collide:

// CORRECT — single quotes wrap a JSON body full of double quotes.
buy_command = '{"exchange":"binance","pair":"BTCUSDT","isBuy":true,"token":"abc"}'

// WRONG — Pine sees the first inner " as the end of the string.
// Compile error: "Syntax error at input ':'"
buy_command = "{"exchange":"binance",...}"

If you must use double-quoted Pine strings (e.g. you copy-paste from a template), escape every inner quote with \":

buy_command = "{\"exchange\":\"binance\",\"pair\":\"BTCUSDT\"}"

The single-quoted form is shorter and the convention used in every TVH example.

Building JSON dynamically

str.format() and string concatenation are useful when you need to inject a Pine value into the payload:

buy_command = str.format('{{"exchange":"binance","pair":"{0}","price":{1},"isBuy":true,"token":"YOUR_TOKEN"}}', syminfo.ticker, close)

Pine's str.format uses {0} / {1} for placeholders, so the JSON braces have to be doubled ({{ and }}). The resulting string is a single line of valid JSON.

In most cases you do not need this — use TradingView placeholders like {{ticker}} and {{close}} inside a static JSON template, and TradingView substitutes the live values before posting.

Multi-line vs compact JSON

TradingView strips newlines from the Message field on save. The post body is always one line, even if you pasted formatted JSON.

Practical implication:

  • In the Message field: paste either form. TradingView normalises it.
  • In your Pine code: keep the JSON compact (one line per command) so it fits the file and stays readable.
  • In your notes / docs: keep it pretty-printed. Just remember it gets flattened on the way out.

Sending multiple commands from one alert

Each TradingView alert posts one request. TVH treats that request as a single trade command. There is no comma-separated multi-command syntax — if you need two trades, use two alerts (or two Pine alert() calls firing on the same condition).

For the "open a position with SL and TP in one go" use case, you do not need multiple commands — a single TradeCommand already carries stopLoss, targets[], and DCA legs. See Take Profit and DCA & Scaling.

Email backup as alternative

When you cannot reach a webhook endpoint (firewall, expired plan, network outage), TradingView can email the alert instead. TVH parses the email body with the same JSON parser. Setup walkthrough: Email Backup.

The behaviour you should know about:

  • Default email-trigger delay is around 60 seconds (TradingView's own queue).
  • Set delay: -1 in the payload to opt out of the delay for that specific alert. On the email path, this bypasses the normal email-delay handler.
  • The dedup lock is permanent: sending the same alertTimestamp twice is recognised as a duplicate and dropped, a no-op forever. See Timing & Idempotency.

Pre-flight sanity checklist

Before clicking Create on the alert:

  1. Webhook URL is set and matches the exchange family — binance.tv-hub.org for Binance, default for everything else.
  2. Send plain text is ticked only if you use Email Backup (it does not affect the webhook).
  3. JSON validates — paste into JSONLint or python -m json.tool.
  4. token is set and matches the value on your API Keys page.
  5. exchange and pair use the exchange-native format — see the symbol format table.
  6. apiKey name matches an active API key on TVH.
  7. postOnly is explicitly false if you want a marketable limit order — the default is true. See Gotchas #1.

If all seven pass, the alert is ready. Trigger the condition and watch the Activity Log.

Next