How to Automate a DCA Strategy From TradingView Webhook Alerts
If you run a DCA strategy, TradingView webhook alerts can execute it for you so you are not logging in to place the same buy over and over. Dollar-cost averagi...
TradingView reports that your alert fired, not that your order was placed. Here are the webhook failures that break most automations - silent delivery, auth rejections, malformed JSON, symbol mismatches, duplicates - and the specific fix for each.
Your strategy triggered. The alert log shows it fired. And nothing happened on the exchange. Most common TradingView webhook errors look exactly like this: a chart event that clearly occurred, a receiving endpoint that never heard about it, and no obvious place to look. TradingView does not surface delivery failures in the interface, so a broken automation can run for days looking healthy while every single order quietly dies in transit.
This guide walks through the failures that account for the overwhelming majority of broken webhook automations, in the order you should check them. Each section covers what the failure looks like from your side, what is actually happening underneath, and the specific fix.
A TradingView webhook is a one-way message. When your alert fires, TradingView sends an HTTP POST to the URL you configured and then forgets about it. It does not retry meaningfully, it does not warn you when the response is an error, and it does not show you the response body. If your endpoint returns a 401, TradingView's alert log still says the alert triggered.
That asymmetry is the root of most debugging confusion. The alert firing and the order being placed are two separate events connected by a fragile link, and only one of them is visible in the platform you are watching. The practical consequence: never treat "the alert fired" as evidence that anything downstream worked. You need visibility on the receiving end, which is why the debugging checklist later in this guide starts by capturing the raw request rather than staring at the chart.
Before blaming the payload or the exchange, confirm a request left TradingView.
Three causes dominate. First, the Webhook URL checkbox in the alert's Notifications tab is unchecked — the URL is saved but the delivery channel is off. Second, the alert is set to Once Per Bar when you need Once Per Bar Close, or vice versa, so it is firing at a moment you are not watching. Third, the alert expired; TradingView alerts have plan-dependent expiry, and an expired alert silently stops.
There is also a plan requirement here that catches new users: webhook notifications require a paid TradingView plan. On a free plan the field may appear but never deliver.
Fix: open the alert, confirm the webhook checkbox is ticked and the URL is complete including `https://`, verify the trigger condition, and check the expiry date. Then use a request-capture endpoint to confirm bytes actually arrive. Our walkthrough on testing a TradingView webhook locally with ngrok shows how to see the raw request before it ever reaches an exchange.
The request arrives and is refused. This is the most common failure after setup changes, because TradingView cannot send custom HTTP headers. Anything your receiver needs for authentication has to travel in the URL or in the JSON body.
Typical causes: a token in the body that no longer matches after a key rotation; a secret pasted with a trailing space or a line break; an endpoint expecting an `Authorization` header that TradingView simply cannot send; or an HMAC signature computed over a different string than the one the receiver verifies.
Fix: move authentication into the payload or the URL path, and regenerate the secret cleanly rather than editing it in place. If you use signed requests, confirm both sides sign the exact same raw body bytes — whitespace and key ordering matter. The mechanics are covered in detail in our guide to securing a TradingView webhook with HMAC signing.
The receiver got the message and could not parse it. TradingView alert messages are plain text; JSON is a convention you impose, and nothing in the alert box validates it.
The usual culprits are smart quotes pasted from a document instead of straight quotes, a trailing comma after the last field, an unquoted string value, or a Pine Script placeholder that expands into something unexpected. `{{strategy.order.comment}}` inserting a comment that itself contains a quote character will break the surrounding JSON instantly.
Fix: paste the message into a JSON validator before saving the alert, type quotes directly rather than pasting them, and keep placeholders in numeric positions unquoted and text positions quoted. If a placeholder can contain free text, either sanitize it in Pine or drop it from the payload. A known-good structure is laid out in our reference on structuring a TradingView webhook JSON payload for orders.
The payload parses, authentication passes, and the exchange rejects an unknown instrument. TradingView tickers and exchange API symbols are different namespaces. A chart showing `BINANCE:BTCUSDT` is not automatically the string the API expects, and `{{ticker}}` may expand with a venue prefix, a perpetual suffix, or a delimiter the exchange does not recognize.
Spot and derivatives markets compound this. The same underlying pair often has one symbol on the spot API and a different one on the futures API, routed to a different base endpoint entirely.
Fix: hard-code the symbol in the alert message when you run one alert per instrument — it removes an entire failure class. If you need `{{ticker}}` for a multi-symbol strategy, map the value explicitly on the receiving side and reject anything not in the map rather than passing an unknown string through to the exchange.
Duplicates are more damaging than silence, because they leave your real position out of sync with what your strategy believes it holds.
They arise from repainting intrabar conditions that fire and unfire, from `Once Per Bar` on a condition true across several ticks, from a retry after an ambiguous timeout, or from a duplicated alert left running after you cloned one to edit it.
Fix: use Once Per Bar Close for anything that trades real size, and send a deterministic client order ID with every order so a repeated request is recognized rather than executed twice. Audit your active alert list regularly for forgotten clones.
Here the plumbing is fine and the trading parameters are not. Common rejections include quantity below the venue's minimum notional, price or size precision beyond the allowed decimal places, insufficient balance in the specific wallet the order routes to, leverage or margin mode not configured for the contract, and API keys lacking trade permission.
That last one is worth isolating. A key created for read access will authenticate perfectly and refuse every order, which reads like an intermittent bug. It should have trade permission and no withdrawal permission — see why trade-only API keys matter for how to set that up.
Fix: read the exchange's rejection code rather than guessing, round sizes to the venue's step size before submitting, and confirm funds sit in the wallet the order actually draws from.
Transient failures behave differently from deliberate rejections: the same request would likely succeed a moment later. Rate limiting (HTTP 429), gateway timeouts during volatile periods, and temporary maintenance on a venue all fall here.
Fix: retry with exponential backoff and jitter, cap the attempts, and always send the same client order ID on the retry so a duplicate cannot be created. Treat a timeout as unknown rather than failed — query order status before resubmitting. The distinction between transient and permanent failures is unpacked in our guide to handling failed and rejected orders in a trading bot.
Work outward from the chart, and stop at the first step that fails:
The alert firing and the order being placed are separate events. TradingView reports the trigger, not the delivery outcome, so a rejected or unparseable request looks identical to a successful one from the chart. Capture the request at your endpoint and read the response code to find where the chain broke.
No. TradingView sends the alert message as the request body without configurable headers, which is why authentication has to live in the URL or inside the JSON payload. Endpoints that require an `Authorization` header need an alternative scheme such as a token field or a signature over the body.
Test conditions are usually calm and single-symbol. Live markets add rate limits during volatility, precision and minimum-notional rules that only bite at certain sizes, and multi-symbol payloads that expose symbol-mapping gaps. Move to live in stages, with small size and full logging, rather than switching everything at once.
Attach a client order ID derived deterministically from the signal, and send that identical ID on every retry. Exchanges that support client order IDs recognize the repeat and decline to create a second order, which makes an ambiguous timeout safe to retry.
Yes. Webhook notifications are a paid-plan feature, and alert count and expiry limits also vary by plan. If the webhook field appears configured but nothing ever arrives at your endpoint, plan level is worth checking early.
Most webhook errors are not strategy problems — they are delivery problems, and they are fixable once you can see where the message stops. If you would rather not maintain that plumbing yourself, SignalToExchange is a non-custodial relay that validates each incoming signal, submits the order with a deterministic client order ID, and returns the exchange's actual response. Your funds stay on your own exchange and connect through trade-only API keys with no withdrawal access. Request access or start your free trial.
Automated trading involves risk. SignalToExchange is execution infrastructure and does not provide financial advice, trading signals, or guarantees of any kind.
Non-custodial execution. Trade-only API keys. Independent infrastructure built for reliability.
Request Early AccessTrade-only API key enforcement. No withdrawal permissions. No custody.