Appearance
Are you an LLM? You can read better optimized documentation at /webhooks/tradingview-setup.md for this page in Markdown format
TradingView Webhook Setup
A TradingView webhook creates a Synthetic Channel in TTMT — one that behaves like a Telegram signal channel on every surface (Signal Log, Trade Log, Stats, Config Profiles) and runs through the same execution path: each alert is validated, safety-checked, routed to your active accounts, and executed by the adaptive order engine under your risk limits.
The difference is the source. Instead of a Telegram provider posting a message, you or your Pine script fires an HTTPS alert.
Admin-enabled feature
TradingView webhooks are enabled per user by the TTMT team. If Automation › Webhooks is not visible in your sidebar, contact support to request access.
Creating a webhook
Open Automation › Webhooks in the sidebar and click New Webhook. A three-step wizard opens.
Step 1 — Configure
Give the webhook a name (this becomes the channel name in your Signal Log and Trade Log) and choose which accounts should receive its alerts. With multiple accounts, each checked account gets its own running/stopped switch — the same broadcast pattern as every other channel.
Creating the webhook sets it to Pending Verification. No alerts trade until you complete Step 3.
Step 2 — Reveal
Your webhook URL and secret are shown. This is the only time the full secret appears. Copy both before closing the dialog — a checkbox confirms you have copied the secret, and the dialog cannot be dismissed by pressing Escape or clicking outside.
- URL — paste this into TradingView's Webhook URL field. It is not secret.
- Secret — paste this into the
"secret"field in your alert Message JSON. Keep it private.
If you lose the secret, you can rotate it from the channel's Webhook tab. Rotation invalidates the previous secret immediately.
Step 3 — Verify
Before any capital moves, TTMT waits for your first real alert from TradingView. While the webhook is Pending Verification:
- Inbound alerts are logged but place no trade.
- The wizard shows a live listener: "Waiting for your first alert…"
Send a test alert from TradingView (just trigger one manually or let a condition fire). When TTMT receives it, the listener updates:
✓ Received: BUY XAUUSD @ 15
Review the parsed payload, then click Confirm & activate. From this point on, alerts trade.
If the wizard times out after around three minutes with no event, a troubleshooting panel appears showing the URL, secret, and expected JSON. You can close the wizard and finish from the channel's Webhook tab — the webhook stays Pending Verification server-side until you confirm.
The JSON payload
Paste this JSON into the Message box when creating a TradingView alert:
json
{
"secret": "ttmt_hook_REPLACE_WITH_YOUR_WEBHOOK_SECRET",
"action": "BUY",
"symbol": "{{ticker}}",
"timeframe": "{{interval}}",
"bar_time": "{{time}}",
"price": {{close}},
"strategy": "My Strategy Name",
"client_id": "{{ticker}}_{{interval}}_{{time}}"
}For a SELL alert, change "action": "BUY" to "action": "SELL".
Replace ttmt_hook_REPLACE_WITH_YOUR_WEBHOOK_SECRET with the secret you copied in Step 2.
Only secret, action, and symbol do real work
TTMT uses your alert to know which way to trade (action) and what instrument (symbol), authenticated by your secret. The bar_time, timeframe, price, strategy, and client_id fields are optional payload metadata — they help TTMT de-duplicate repeated alerts and enrich your logs, but none of them set your entry, stop, or targets. Those come from your account and profile defaults (see SL/TP defaults below).
The price field is optional metadata, not your entry
The template keeps {{close}} unquoted so price arrives as a JSON number, which is the tidiest form. A quoted numeric string (for example "2345.67") is also accepted — TTMT reads price as a number or a numeric string. Either way, price is only recorded for your logs. It is not the price TTMT enters at, and it does not influence how your prices are checked; TTMT opens a market or limit order from the live broker price and your account's SL/TP defaults.
Placeholder cheat-sheet
| Placeholder | What it becomes | Notes |
|---|---|---|
{{ticker}} | Symbol on your chart, e.g. OANDA:XAUUSD | Required (via symbol) |
{{interval}} | Chart timeframe, e.g. 60 for 1-hour | Optional; feeds the de-dupe key |
{{time}} | Bar open timestamp in milliseconds | Optional but strongly recommended — see below |
{{close}} | Bar close price — unquoted number | Optional log metadata; not the entry price |
{{strategy.order.alert_message}} | Per-order action from strategy.entry(alert_message=...) | Strategy path only |
{{strategy.order.id}} | Order ID — appended to client_id for multi-order bars | Strategy path only |
Why bar_time is strongly recommended. bar_time is not required, but you should send it. TTMT uses it to de-duplicate repeated alerts for the same bar and to judge whether an alert is fresh enough to act on (see the 15-minute freshness guard below). Without it, TTMT falls back to weaker de-duplication, so a chart that re-fires the same bar can open a second trade.
The price value is recorded as log metadata only. TTMT does not use the bar close as your trade entry price, and it does not feed the price checks that screen for bad values — it opens a market or limit order based on the live broker price and your account's SL/TP defaults.
Pine script paths
The TTMT webhook reference indicator (ttmt-webhook.pine) shows three ways to fire alerts. Choose the path that fits your setup.
Path 1 — alertcondition (shared / published indicator)
When to use: you are publishing the indicator or sharing it with others and cannot embed a secret in the script.
The JSON lives in TradingView's Message box, not in the Pine source. The {{...}} placeholders substitute at alert-fire time in the Message box and in alertcondition(message=...) — they do not substitute inside alert() string arguments.
Steps:
- Add the TTMT indicator to your chart.
- Open Create Alert (Alt+A).
- Set the Condition to the indicator's BUY or SELL condition.
- Paste the JSON template into the Message box and replace the placeholder secret with your real
ttmt_hook_secret. - Enter your webhook URL in the Webhook URL field and save.
Path 2 — alert() (private / unpublished copy)
When to use: you keep the script private and prefer the secret to live in the script's input field rather than the alert Message box.
Fork the reference indicator and keep it unpublished. Enter your real ttmt_hook_ secret in the Webhook Secret input field inside the script. The JSON is assembled from Pine built-ins at bar close using str.tostring() concatenation, and alert() fires with freq_once_per_bar_close — once per confirmed bar, no tick noise.
Keep the script unpublished
A Pine script with a real ttmt_hook_ secret in an input field must remain private/unpublished. If the script is shared or published, the secret is exposed and anyone could fire trades against your account.
Path 3 — strategy
When to use: a strategy() script where you want {{strategy.order.alert_message}} to carry the direction and {{strategy.order.id}} to disambiguate multiple orders on the same bar.
In the strategy alert's Message box (Order Fills section), use:
json
{
"secret": "ttmt_hook_REPLACE_WITH_YOUR_WEBHOOK_SECRET",
"action": "{{strategy.order.alert_message}}",
"symbol": "{{ticker}}",
"timeframe": "{{interval}}",
"bar_time": "{{time}}",
"price": {{close}},
"strategy": "My Strategy Name",
"client_id": "{{ticker}}_{{interval}}_{{time}}_{{strategy.order.id}}"
}Set alert_message="BUY" or alert_message="SELL" on your strategy.entry() calls so {{strategy.order.alert_message}} carries the right direction.
Today, strategy exits open new trades — they do not close positions
Every webhook alert is an independent new trade signal. There is currently no close or reverse alert type, and an alert never carries entry, stop, or take-profit levels into the trade — every alert opens a fresh trade using your account and profile defaults.
Do not wire strategy.exit() or strategy.close() alerts to your TTMT webhook expecting them to flatten an open position. Today they arrive as new-trade signals and will attempt to open a position in that direction. Wire BUY and SELL entry alerts only.
Close and reverse handling from a webhook alert is on the roadmap but is not committed — don't build a strategy that depends on it yet.
Symbol mapping
TradingView tickers include exchange prefixes (OANDA:XAUUSD, BINANCE:BTCUSDT) that don't match broker symbols. You must map each TV ticker to its broker symbol manually.
Open the Symbol mapping panel from the webhook hub or the channel's Webhook tab. Add a row for each ticker your strategy sends:
| TV ticker | Broker symbol |
|---|---|
OANDA:XAUUSD | XAUUSD |
BINANCE:BTCUSDT | BTCUSD |
PEPPERSTONE:EURUSD | EURUSD |
If no mapping exists for an incoming ticker, the alert is rejected. No trade is placed. The rejection appears in the delivery log with reason unmapped_symbol and shows you the exact ticker string TTMT received.
Verify step pre-fills the mapping
During the Verify step, the first incoming alert reveals the exact ticker string your chart sends. TTMT surfaces it — "We received OANDA:XAUUSD" — so you can map it before the webhook goes live. An unmapped_symbol rejection in the delivery log also links directly to the mapping modal pre-filled with that ticker.
SL/TP defaults — required
Webhook alerts carry only a direction (BUY/SELL) and a symbol — no stop-loss or take-profit levels. TTMT builds the trade's stop and targets from your configured defaults.
Because a webhook trade has no stop of its own, TTMT enforces a stop-loss safety guard: it will not let a webhook alert trade any account that isn't set up to receive a stop. For every account assigned to the webhook, that account's effective settings must have the signal SL override enabled and a non-zero default SL pip value.
Every assigned account must be armed — one unarmed account blocks the whole alert
The guard checks all of the webhook's active accounts. If even one assigned account is missing its SL override or has a zero default SL, the alert is rejected with reason webhook_zero_sl_guard and no account trades it. Arm every account before you go live.
To arm an account, configure a non-zero default stop with the SL override enabled — either directly in that account's SL/TP settings, or by binding a Config Profile that has SL override on and a non-zero default SL. See Override modes for how the SL override works.
Take-profit behavior is separate and is not enforced the same way. Your default take-profit targets (and TP behavior) are applied from your settings as a recommendation — TTMT does not block an alert for lack of a TP the way it does for a missing stop. The stop is the hard safety requirement; the targets follow your normal TP configuration.
Delivery log
Every inbound alert — whether it traded or not — is recorded in the delivery log on the channel's Webhook tab. Check here first when diagnosing issues.
| Status | What happened |
|---|---|
verification_ping | Alert received while pending verification — no trade was placed |
signal_created | Alert processed successfully — a signal and trade were created |
deduped | Duplicate alert for the same bar (same client_id / bar_time) — ignored |
rejected | Alert rejected before any trade — see the reason column |
circuit_open | Per-minute or per-day cap was hit — webhook auto-paused |
container_down | Trading instance was unreachable — TradingView may retry the alert |
failed | Processing error — contact support if this persists |
Rejection reasons
| Reason | Fix |
|---|---|
unmapped_symbol | Add the TV ticker shown in the log to your symbol map |
webhook_zero_sl_guard | Configure SL/TP defaults on this channel |
no_active_assignment | Assign at least one account to this webhook |
webhook_paused | Webhook is paused — resume it from Automation › Webhooks |
stale_alert | Alert's bar_time was more than 15 minutes old — see the freshness guard below |
Circuit breaker defaults
| Limit | Default |
|---|---|
| Alerts per minute | 60 |
| Trades per day | 50 |
Both limits apply per webhook. If either cap is breached, the webhook auto-pauses and you receive a notification. Resume from Automation › Webhooks. Contact support if your strategy legitimately needs higher limits.
The 15-minute freshness guard
TTMT will not act on a stale alert. If an alert's bar_time is more than 15 minutes old by the time it arrives, TTMT skips it and records stale_alert in the delivery log — no trade is placed.
This guard protects you from acting on late deliveries: a queued retry, a delayed alert, or a burst of backlogged alerts that arrive long after the bar they describe. Trading a signal that's a quarter-hour stale usually means chasing a move that has already happened.
Send bar_time and use bar-close alerts
The freshness check reads bar_time, so include {{time}} in your payload (the templates above already do). Firing alerts on bar close — as the alert() path does with freq_once_per_bar_close — keeps the timestamp accurate and well inside the window. If you see stale_alert rejections on alerts that fired on time, check for a large clock skew or a retry backlog in TradingView's alert history.
Troubleshooting checklist
No entries in the delivery log at all Check that your TradingView alert is enabled (not expired), the Webhook URL is pasted correctly without trailing spaces, and the alert condition is actually firing.
400 in TradingView's alert history Your JSON is malformed. Validate it with a JSON linter. Common causes are a stray trailing comma, an unescaped quote in your strategy name, or a missing brace. (A quoted numeric price is not a cause — TTMT accepts price as a number or a numeric string.)
401 Unauthorized in the delivery log The "secret" value in your alert Message doesn't match your webhook secret, or the secret has been rotated. Check the value on the Webhook tab and rotate if it has been lost.
unmapped_symbol rejections Open the Symbol mapping panel and add the exact ticker string shown in the delivery log.
webhook_zero_sl_guard rejections At least one account assigned to this webhook has no stop-loss safety configured. Arm every assigned account — enable the signal SL override and set a non-zero default SL — either on the channel's SL/TP tab or via a bound Config Profile. One unarmed account blocks the alert for all of them.
stale_alert rejections The alert's bar_time was more than 15 minutes old when it reached TTMT. Fire alerts on bar close, include {{time}} in the payload, and check TradingView's alert history for a retry backlog. See the freshness guard.
Webhook stuck at Pending Verification If you see verification_ping entries in the delivery log but the webhook hasn't activated, click Confirm & activate in the Verify step of the wizard — or from the channel's Webhook tab if you closed the wizard.
Webhook auto-paused (circuit_open) Resume from the hub. If your strategy fires more than 60 alerts per minute or more than 50 trades per day legitimately, contact support to adjust the caps.

