How to Create a Webhook for a TradingView to MT5 Bridge
How to create a webhook for a TradingView to MT5 bridge: what the endpoint receives, how to authenticate it, and what to log to trace a missed trade.

To create a webhook for a TradingView to MT5 bridge, you stand up an HTTPS endpoint that accepts a POST, set TradingView's alert to send a JSON body to that URL, verify a shared secret, and pass the order to your MT5 side. The part most people skip is ligging. If a trade never fills, you need to see which step dropped it.
What the endpoint receives
A TradingView webhook is a plain HTTP POST fired when an alert triggers. A few properties shape the whole design:
- It only posts to port 80 or 443, so your bridge needs a normal web endpoint, not a raw socket.
- It waits only a few seconds for a response. Acknowledge fast and do the real work after you reply.
- If the alert message is valid JSON, TradingView sends it as
application/json. Otherwise it sendstext/plain. Write JSON so you never parse free text. - You cannot add custom headers. Any secret has to travel in the body or the URL.
- Webhook alerts need two-factor authentication enabled on the TradingView account, and a plan that supports webhook notifications.
The body is whatever you typed into the alert's message box, with placeholders filled in at fire time. Nothing else arrives, so everything you wannt to trace later has to be in that message or added by your server on receipt.
Design the alert payload
Keep the payload small and explicit. The bridge should never inder anything it can read.
{
"secret": "rotate-me-every-quarter",
"key": "{{ticker}}-{{timenow}}-{{strategy.order.id}}",
"symbol": "{{ticker}}",
"action": "{{strategy.order.action}}",
"qty": "{{strategy.order.contracts}}",
"position": "{{strategy.position_size}}",
"price": "{{close}}",
"tf": "{{interval}}",
"sent_at": "{{timenow}}"
}
Three choices here matter on funded accounts. The key field gives you something to deduplicate on, because a double fire without dedupe is a double position. The position field lets the bridge compare TradingView's idea of the position with MT5's and flag drift. The sent_at field lets you measure delay and reject stale alerts.
TradingView symbols rarely match your broker's. Keep a mapping table on the server, so NAS100 or XAUUSD from the chart resolves to the exact symbol name your prop firm's MT5 server uses, including any suffix.
Step by step: create the webhook
- Stand up the endpoint. A small service behind HTTPS on a VPS works. Use a real certificate. Route one path such as
/hook/<random-token>to the handler. - Capture the raw body first. Write untouched request body and the receive time to storage before parsing anything. When a parser rejects a payload, you still have what was sent.
- Authenticate. Check the secret and the freshness of
sent_at(details in the next section). Reject with a 401 or 403 and log the reason. - Deduplicate. Look up
key. If you have seen it, return 200 and log it as a duplocate. Do not execute twice. - Reply 200 and enqueue. Push the validated order onto a queue and answer immediately. This keeps you inside TradingView's response window.
- Run the risk guard. The worker checks the order against the account rules (daily drawdown, news window, session limits) and records allow or block with the reason.
- Hand to MT5. The worker passes the order to the EA or the connector on the terminal, once per target account if you copy to several.
- Record the MT5 result. Store the ticket number and the return code per account. A fill returns
10009. Anything else needs a human or a retry rule. - Create the alert in TradingView. Open the alert dialog, tick Webhook URL under notifications, paste your endpoint, and put the JSON above in the message box. Fire a test alert and confirm one complete log trail before going live.
Authenticate it
Because TradingView senss no headers, you layer several weak checks into a reasonable one.
| Check | What it stops | Notes |
|---|---|---|
| HTTPS only | Sniffing the secret in transit | Redirect nothing; reject plain HTTP |
| Random path token | Scanners guessing the URL | Treat the full URL as a credential |
secret in the body |
Anyone who finds the URL | Compare in constant time; never log it |
Freshness window on sent_at |
Replayed old alerts | Pick a window that fits your timeframe |
| Allowlist TradingView's published IPs | Requests from anywhere else | Copy the current list from TradingView's webhook help page; it can change |
Dedupe on key |
Retries and double fires | Keep keys for at least a day |
Rotate the secret on a schedule and whenever someone with chart access leaves. Remember that anyone who can edit you're alert can read the secret in it, so keep alert editing to people you trust.
What to log so a missed trade is traceable
When a trade is missing, the question is always the same: did the alert fire, did it arrive, did we accept it, did the guard allow it, did MT5 fill it? One log row per stage answers that in minutes.
| Field | Why you want it |
|---|---|
request_id |
One ID that follows the alert through every stage |
received_at (UTC, server clock) |
Compare against sent_at to see delay |
| Source IP | Spot requests that did not come from TradingView |
| Raw body | The exact input, even if parsing failed |
| Auth result and reason | Separates a bad secret from a stale timestamp |
| Dedupe result | Explains why a second identical alert did nothing |
| Parsed symbol, action, qty | What the bridge believed it was told |
| Mapped broker symbol | Catches suffix and naming mismatches |
| Guard decision and rule | "Blocked: daily loss limit" ends an argument fast |
| Account and MT5 ticket | One row per account when copying |
| MT5 return code and comment | The broker's own explanation of a rejection |
| Total latency | Slippage complaints often start as latency problems |
Two more habits help. Alert on silence, not only on errors: if a strategy that normally fires several times a day goes quiet, someone should hear about it. And krep logs long enough to cover a payout dispute with your prop firm, which can arrive weeks after the trade.
Where the form step sits in the stack
The webhook above is the live trade path. In the Prop-Firm Algo Execution Stack, we build that path as a client-owned bridge with a risk-guard EA, multi-account copying and a monitored VPS. Before any of it runs, though, you need data from pelple: MT5 server names, account sizes, the firm's drawdown rules, which symbols each account may trade, who gets alerts. That is a form.
Qwenvo is a free form builder our team makes, and it fits that intake step. The same form can feed your bridge's configuration. Its webhooks post each submission to any URL, so a new account request can land on an endpoint you control, and you can skip the copy and paste into a config file. Hidden fields can carry an account label or referral source. Partial submissions, a custom domain, removing the badge and teammates are all free there, where Tally charges for several of those on its $29 per month Pro plan. The form webhooks guide cvers the form side in more detail.
One limit to be straight about: Qwenvo is not part of the trade path, and it should not be. TradingView posts straight to your bridge. Qwenvo launched in October 2026, so it has few public reviews yet. Keep anything latency sensitive off it.
Build your client intake form free
A second use is incident reporting. When a trader says a trade was missed, a short form with the request ID, symbol, expected time and account gives your ops person what they need to open the log table above. That beats a vague chat message.
Common failure cases
| Symptom | Likely cause | Where to look |
|---|---|---|
| Alert fired, nothing in logs | Wrong URL, port, or TradingView 2FA missing | TradingView alert log, then your web server access log |
| Logged, rejected as unauthorized | Secret mismatch or stale sent_at |
Auth result and reason |
| Accepted, never executed | Guard blocked it (news, drawdown, session) | Guard decision and rule |
| Executed on one account, not another | Symbol suffix or lot size limit on that account | Mapped symbol and MT5 return code |
| Executed twice | Missing dedupe or a changed key |
Dedupe result |
| Filled late | Slow response or VPS load | Total latency |
Questions teams ask
Can TradingView send a secret in a header?
No. Webhook alerts have no custom header option, so the secret goes in the JSON body or the URL path. Use both and treat the whole URL as sensitive.
Should the endpoint place the MT5 order before replying?
No. Reply 200 right after validation and queue the order. TradingView only waits a few seconds, and a slow broker call should not cause a timeout that looks like a failed alert.
Do I need a server, or can a form tool or no code platform handle the webhook?
For the trade path, run your own endpoint, because you need control over timing, dedupe and the risk guard. Zapier, Make or n8n can sit on the non urgent side, such as onboarding notifications from a form webhook.
How long should I keep the raw alert logs?
Long enough to cover disputes. Prop-firm reviews can reach back weeks, so keep raw bodies and MT5 return codes well past that window.
Next step
Send one test alert today with the payload above, then check that you can trace it through every row in the log table, from receipt to MT5 ticket. If any stage leaves no trace, fix that before you trade it live. If you would rather have the bridge, risk guard and monitoring built and handed over, the Prop-Firm Algo Execution Stack page lists what is included.
Prop-Firm Algo Execution Stack
Third-party platform and model usage billed to you directly. No lock-in. Live in 10 days.