Connect TradingView Alerts to Nyria
End-to-end TradingView setup: the webhook URL, the Pine Script alert message, Once Per Bar Close timing, and the four mistakes that trip most users up.
By the end you will have a TradingView Pine Script alert that fires on bar close, posts a JSON payload to your Nyria strategy webhook, and routes a real order to your connected broker.
You need a paid TradingView plan before you start. Sending a webhook is a paid TradingView feature: on the free plan the Webhook URL box in the alert dialog is greyed out and nothing on this page can work around it. TradingView also requires two-factor authentication on your account before it will send webhooks at all. Which paid tiers include webhooks is TradingView's to change, so check TradingView's pricing before you buy. Nyria charges nothing for setting up alerts.
Paper trade first. TradingView webhooks are a best-effort, third-party delivery channel; delays of 2–45 seconds are normal and outside Nyria's control. Validate the full chain on a paper account before pointing this at a live broker.
Prerequisites
- A Nyria strategy with TradingView selected as the alert source. If you don't have one yet, follow the Quick Start first.
- A connected broker. See the per-broker setup pages: Schwab, Tradier, tastytrade, Alpaca.
- A paid TradingView plan with two-factor authentication enabled, per the note above. The free plan cannot send webhooks.
The webhook URL
Every Nyria strategy exposes one webhook endpoint:
POST https://trades.nyria.io/webhooks/<tokenHash><tokenHash> is the unique token shown on your strategy's Integration tab. It is a 64-character hexadecimal string like 4f9c2a91b7d34e0f.... Copy it exactly. The token is a secret; anyone who has it can send orders to the strategy, so treat it like an API key.
If you ever need to rotate it (suspected leak, employee turnover, etc.), regenerate from the same Integration tab. The old URL stops accepting traffic immediately.
The endpoint accepts any text or JSON. There is no required template. Nyria's parser reads what you send and pairs it with the strategy config. This tutorial uses JSON because it is the most predictable shape; see Webhook Payload Reference for every field Nyria recognizes and for plain-text examples.
Step 1: Copy the webhook URL from Nyria
Open your strategy in the Nyria app and click the Integration tab.
In the Webhook URL card, click the copy icon. The URL has the shape
https://trades.nyria.io/webhooks/<tokenHash>. On a TradingView strategy
this card only appears once the alert wizard has validated a message, so
do that first if you do not see it.
Paste it somewhere temporary. You will need it in Step 4. Do not share this URL in screenshots, public Discords, or commit it to a repo.
Step 2: Write the Pine Script alert message
In TradingView's Pine editor, add an alert() call inside your strategy or indicator. The alert message is what TradingView posts to the webhook URL.
Use a string template literal so TradingView substitutes your runtime values at fire time:
//@version=5
strategy("Nyria SPY Long", overlay=true)
// Replace with your real entry/exit logic.
longCondition = ta.crossover(ta.sma(close, 9), ta.sma(close, 21))
shortCondition = ta.crossunder(ta.sma(close, 9), ta.sma(close, 21))
if longCondition
strategy.entry("Long", strategy.long)
if shortCondition
strategy.close("Long")
// Fire one alert per bar close, with a structured JSON payload.
alertMessage = '{"ticker":"{{ticker}}","action":"{{strategy.order.action}}","marketPosition":"{{strategy.market_position}}","prevMarketPosition":"{{strategy.prev_market_position}}","price":{{close}}}'
if barstate.isconfirmed and (longCondition or shortCondition)
alert(alertMessage, alert.freq_once_per_bar_close)Starting from an indicator() script? You'd otherwise wire a separate
alert per signal, per ticker. Convert it to a strategy first with
Convert an Indicator to a Strategy
so this single Order-fills alert covers every side.
What each field does once TradingView substitutes the placeholders:
| Field | TradingView variable | Why Nyria needs it |
|---|---|---|
ticker | {{ticker}} | Underlying symbol the order routes against. |
action | {{strategy.order.action}} | Resolves to buy or sell. Nyria maps to entry/exit using your strategy config. |
marketPosition | {{strategy.market_position}} | long, short, or flat after this fill. |
prevMarketPosition | {{strategy.prev_market_position}} | The same value before this fill. Nyria reads the two together to decide entry vs exit, so send both. |
price | {{close}} | Used for limit pricing if your strategy is configured for limit orders. |
A fired alert turns the above template into a concrete payload like:
{
"ticker": "SPY",
"action": "buy",
"marketPosition": "long",
"prevMarketPosition": "flat",
"price": 542.18
}Step 3: Add the script to a chart
Open the symbol you want to trade in TradingView (e.g. SPY on the 5-minute chart).
In the Pine editor, click Add to chart. Confirm the strategy arrows render where you expect.
If anything looks off (late arrows, signals that disappear, arrows on bars that never existed in real time), your script is likely repainting. Fix the script before continuing. See Alert Sources → TradingView Repainting Warning for the common causes.
Step 4: Create the TradingView alert
With the chart focused, press Alt+A (Windows) or Option+A (Mac), or
click the alarm-clock icon in the right toolbar.
In the Condition dropdown, pick your strategy. Leave the second dropdown on Order fills only so the alert fires when the strategy actually generates a trade, not on every bar.
Set Trigger to Once Per Bar Close. This is the single most important setting in this tutorial. See the next section for why.
Set Expiration to Open-ended so the alert does not silently expire mid-trade. Not every TradingView plan offers open-ended alerts; if yours does not, pick the furthest-out date and put a reminder in your calendar to renew it. An expired alert stops firing without telling you, and the first sign is usually a position that never closed.
Open the Notifications tab. Tick Webhook URL and paste the Nyria URL from Step 1.
Open the Message field. Either leave the default
{{strategy.order.alert_message}} (which uses the alertMessage
string from your Pine code) or paste the JSON template directly. Both
work; the Pine-side string is easier to version-control.
Click Create.
Step 5: Fire a test alert
You have two options to confirm the wiring without waiting for a real signal:
Option A: Check it inside Nyria. On the strategy's Integration tab, paste the message your alert sends into the check box. Nyria fills in the TradingView placeholders with example values, reads the result the way a live alert is read, and shows the trade each side would produce. No order is placed.
Two things this check does not do, both worth knowing before you rely on it:
- It is not a JSON validator. Nyria reads plain text as readily as JSON, so a payload with a missing brace or a stray comma still passes — it is simply read as text. A green result means Nyria understood the message, not that the message is well-formed JSON.
- It does not prove TradingView is sending anything. It runs entirely inside Nyria against the text you pasted. Only a real alert arriving proves the webhook is wired, and the walkthrough tells you when one does.
Option B: Send a manual cURL. Replace <tokenHash> with your actual token and run:
curl -X POST https://trades.nyria.io/webhooks/<tokenHash> \
-H "Content-Type: application/json" \
-d '{
"ticker": "SPY",
"action": "buy",
"marketPosition": "long",
"prevMarketPosition": "flat",
"price": 542.18
}'The response should be 200 OK with "status": "processed" in the JSON body. The same trade then appears in the strategy's Logs tab within ~1 second.
If both options succeed and the broker shows a paper order, the chain is wired correctly. Wait for a live signal (or scroll back on the chart and click Recalculate) to confirm the end-to-end loop one more time before moving the strategy off paper.
About Once Per Bar Close
TradingView gives you four trigger frequencies for alerts. Only one of them is safe for automated trading:
| Frequency | What it does | Use for trading? |
|---|---|---|
| Only Once | Fires exactly one alert across the lifetime of the alert. | No. The alert dies after the first signal. |
| Once Per Bar | Fires the first time the condition becomes true on a forming bar. | No. Can fire and then "unfire" if the bar reverses before close. You get a phantom order. |
| Once Per Bar Close | Fires once, after the bar closes and the condition is confirmed true. | Yes. This is the only setting Nyria recommends. |
| Once Per Minute | Fires at most once per minute regardless of bar timing. | No. Decouples the alert from your strategy's actual fills. |
Once Per Bar Close is the only setting that guarantees the value of {{close}} is the real bar close, not an intra-bar tick, and the only setting that prevents the same bar from triggering multiple times.
If you use Once Per Bar, you will see orders fire on the open of a bar, then a second alert fire when the same bar's condition flips back, leaving your bot with conflicting fills. There is no Nyria-side filter that can recover from this. Fix it at the TradingView trigger setting.
Common pitfalls
1. Duplicate alerts
Symptoms: two webhook hits within a second of each other; the broker shows two opens instead of one.
Causes, in order of frequency:
- The TradingView alert is set to Once Per Bar instead of Once Per Bar Close.
- Two alerts are configured on the same chart for the same strategy (e.g. you cloned an alert and forgot to delete the original). Open Alerts → Manage and confirm exactly one alert per signal exists.
- Your Pine code calls
alert()inside a block that runs on every tick. Wrap the call inif barstate.isconfirmedas shown in Step 2.
Nyria deduplicates identical alert bodies for about five minutes. If you legitimately need a second order on the same bar (e.g. scaling in), make the body different each time. The cleanest way is a unique metadata.message_id:
{
"ticker": "SPY",
"action": "buy",
"metadata": { "message_id": "{{timenow}}" }
}2. Wrong tokenHash
Symptoms: 404 Not Found in TradingView's alert log, or 400 Bad Request if the token was copied with a stray space.
Causes:
- The token was copied with a leading/trailing space. Copy the URL using Nyria's copy button rather than a manual highlight.
- The strategy's token was rotated. Open Integration, copy the new URL, and update every TradingView alert that points at this strategy.
- You pasted the strategy's public share URL (which starts with
https://app.nyria.io/share/...) instead of the webhook URL. Only thetrades.nyria.io/webhooks/...URL accepts POSTs.
3. Market order when you wanted limit, or vice versa
Symptoms: orders fill at a worse price than expected, or orders never fill and time out.
Causes:
- Your strategy is configured for Market orders but the Pine payload sets
"order_type": "limit"(the per-alert field overrides the strategy default). Either removeorder_typefrom the payload or change the strategy. - Your strategy is configured for Limit but the payload omits a
price. If the strategy's Limit Target is Alert Price, the alert is rejected. Otherwise Nyria uses the configured target (bid, ask, mid or custom), which may not match your intent. Always sendpricewhen you mean a specific one. - You sent
"price": {{close}}on a low-liquidity symbol and the bar close is far from the current quote. Add a slippage buffer in your Pine code, or switch to market for low-liquidity instruments.
4. A placeholder arrives instead of the symbol
Symptoms: the strategy's Logs tab shows an entry refused for a symbol that reads {{syminfo.ticker}}, {{tickerid}} or similar, with the braces still in it.
TradingView substitutes only the placeholders it publishes and passes every other one through as literal text. A Pine variable name is not an alert placeholder: inside alert() you concatenate the value ('{"instrument":"' + syminfo.ticker + '"}'), while in the alert dialog's Message box you use {{ticker}}. Mixing the two sends the braces themselves to Nyria, and there is no symbol to trade.
Fix it in the alert message. Adding the placeholder to your instrument list will not help — see TradingView alert messages for every placeholder Nyria's check fills in.
5. Repainting strategies
Symptoms: backtest shows 90% win rate; live trading loses money.
The script generated signals that didn't exist in real time. Nyria cannot detect this. It has no view of your Pine code. Read Alert Sources → TradingView Repainting Warning, then verify your script uses barstate.isconfirmed, avoids lookahead=barmerge.lookahead_on, and references close[1] rather than close when pulling higher-timeframe data.
Going from paper to live
Run the strategy on paper for at least 1–2 weeks. Compare every fill in the strategy's Logs tab against TradingView's alert log to catch dropped or duplicated signals early.
In Nyria, disable the bot connected to the paper account.
Create a new bot on the same strategy pointed at your live broker
account. The webhook URL does not change: same <tokenHash>, new
bot.
Re-enable. The next TradingView alert routes to the live broker.
Switching from paper to live does not require updating the TradingView alert. The webhook URL is per-strategy, not per-broker. Make sure you actually want live before flipping the bot. There is no intermediate "are you sure" between a fired alert and a live fill.
What's next
- Convert an Indicator to a Strategy: using an
indicator()script? Turn it into astrategy()so one alert covers every side. - Webhook Payload Reference: every field Nyria accepts in the JSON payload.
- Alert Sources: Discord, Telegram, and other non-TradingView sources.
- Strategies: how Nyria turns a payload into an order using your strategy config.
- Troubleshooting: error codes mapped to fixes if the webhook returns non-2xx.
Choose an Alert Source
Compare TradingView, Discord, TrendSpider and custom webhooks: what each one can send Nyria, and the rules every alert source has to follow.
Convert a TradingView Indicator to a Strategy
Turn an indicator() Pine script into a strategy() so one Order Fills Only alert covers every entry and exit, instead of an alert per signal per ticker.