The four mistakes that turn JSON into text/plain
TradingView reads the message after it fills in the placeholders. If that text is valid JSON, the webhook goes out as application/json; one wrong character and the same message goes as text/plain, which a receiver that only takes JSON turns away.
- A text placeholder outside quotes.
"action": {{strategy.order.action}}arrives as"action": buy, and a bare word is not JSON. Write"action": "{{strategy.order.action}}". Numbers such as{{close}}and{{strategy.order.contracts}}can go bare.{{interval}}is text: it can read 5 on one chart and 1D on another. - Curly quotes. Phones, notes apps and word processors turn
"into “ and ”. JSON only takes the straight one. - A comma after the last field.
{"ticker": "{{ticker}}",}is not JSON; delete the last comma. - Single quotes and comments.
{'ticker': '{{ticker}}'}and// noteare fine in JavaScript and wrong in JSON.
The builder marks each of these on its line and column as you type, and shows the body your receiver gets with sample values in place of the placeholders.
Keep JSON out of JSON: alert_message
A strategy can write the whole message itself. Each order call, strategy.entry(), strategy.exit(), strategy.order(), strategy.close() or strategy.close_all(), takes an alert_message, and TradingView puts it wherever the alert's Message box says {{strategy.order.alert_message}}. Leave nothing else in the box: a JSON message from the script, dropped inside another JSON string, brings its own quotes and breaks the outer one.
Whether other placeholders work inside alert_message is not settled by TradingView's own docs: the Alerts guide says they cannot be used there, and the Alerts FAQ's example uses them. The Pine code this page writes builds every value in Pine (syminfo.ticker, str.tostring(close), the order's own buy or sell), so it does not depend on either. An indicator's alert() fills in no placeholders at all, so there the message is always built in Pine.
A strategy's sell is not always a short
{{strategy.order.action}} is buy or sell for the order that filled, and a sell can be the exit of a long. PineConnector warns that sending every fill as an entry can open a position you did not mean; TradersPost reads "sentiment": "{{strategy.market_position}}" (long, short or flat) as the position the signal should leave you in. Send the position along with the action, or build exits as their own messages with alert_message.
Test before you trade on it
A valid message is half of it: the receiver's settings, your symbol names and TradingView's delivery are the other half, and this page sees none of them. Send a test alert to a request inspector or your own server, read the Content-Type it arrives with, then run the bridge on a demo account. The TradingView webhook guide has a small server that logs what arrives, and the Pine Script checker reads the strategy for repaint risks before its alerts go live.