An unauthenticated webhook is an open door. Anyone who guesses or scrapes the URL can send fake signals to your trading server — and with automated execution wired up, that means fake trades hitting your broker in real time. If you're sending TradingView alerts to any execution layer, webhook security is not optional.

TradingView's alert system gives you two practical ways to authenticate: a shared secret in the URL, or an HMAC signature in the request body. This guide explains when each makes sense, how to implement them, and the mistakes that quietly break both.

The core constraint: no custom headers

Before anything else, understand the limitation. TradingView's alert configuration lets you set a URL and a Message body, and nothing else. You cannot add an Authorization header, a X-API-Key header, or any other custom HTTP header.

That eliminates the authentication pattern most web APIs use. What's left:

Those are your two real options. Everything else — IP allowlisting, mutual TLS, geoblocking — is defense in depth layered on top, not a substitute.

Option 1: URL token authentication

The simplest approach. Generate a long random string, embed it in the webhook URL, and have your server reject requests that don't match.

https://your-server.com/webhook?token=a7f3c2e8b9d4f1a6c0e5b2d9f4a1c7e3b0d6f2a8c5e1b7d4f0a3c9e6b2d8f5a1

On the server side:

@app.route("/webhook", methods=["POST"])
def webhook():
    token = request.args.get("token", "")
    expected = os.getenv("WEBHOOK_TOKEN", "")
    if not token or not hmac.compare_digest(token, expected):
        return jsonify({"error": "unauthorized"}), 401
    # ... process signal

What to get right:

What URL tokens don't protect against:

URL tokens are good enough for most retail use cases if the token is long, rotated occasionally, and kept out of logs. They're not good enough for high-value accounts or multi-tenant systems.

Option 2: HMAC-SHA256 signatures

HMAC moves the secret out of the URL and into a cryptographic signature computed over the request body. The webhook URL is public; only someone who knows the shared secret can forge a valid signature.

The alert body looks like this:

{
  "timestamp": 1713456000,
  "action": "buy",
  "symbol": "EURUSD",
  "price": 1.0842,
  "signature": "9f3c2e8b9d4f1a6c0e5b2d9f4a1c7e3b0d6f2a8c5e1b7d4f0a3c9e6b2d8f5a1b"
}

The server recomputes the signature over the body (minus the signature field) and compares:

import hmac, hashlib, time, json

def verify_signature(body: bytes, secret: str) -> bool:
    try:
        data = json.loads(body)
    except ValueError:
        return False
    provided = data.pop("signature", "")
    timestamp = int(data.get("timestamp", 0))

    # Reject stale signatures (replay protection)
    if abs(time.time() - timestamp) > 60:
        return False

    # Recompute HMAC over the canonical body
    canonical = json.dumps(data, sort_keys=True, separators=(",", ":"))
    expected = hmac.new(
        secret.encode(), canonical.encode(), hashlib.sha256
    ).hexdigest()
    return hmac.compare_digest(provided, expected)

What HMAC gives you that tokens don't:

What HMAC requires:

Which should you use?

Use URL tokens when: - You're on a free or basic TradingView plan (no HMAC templating) - Your trading capital is modest and the token is rotated occasionally - You control the full network path and can keep URLs out of logs

Use HMAC when: - You're on TradingView Premium or higher - You're running a multi-tenant service where leaked credentials from one user shouldn't affect others - You need an audit trail proving signals weren't tampered with en route - Your broker account is large enough that a single rogue trade could do real damage

For many retail setups, URL tokens with good hygiene are fine. For production trading infrastructure serving paying customers, HMAC is the correct default. If you're building a TradingView webhook to MT5 pipeline — see our pillar guide on how this architecture works — you should support both, because your users will span both tiers.

Common mistakes that break either scheme

Even with the right primitive, these mistakes sink webhook security:

How iNakaTrader handles this

iNakaTrader supports all three authentication modes — HMAC-SHA256 with timestamp, URL token, and header token — selectable per license. New licenses default to per-user 64-character URL tokens so users on any TradingView plan can get started immediately. Upgrade to HMAC later without re-pasting every alert URL. The admin panel can rotate credentials in one click, and the old URL stops working instantly.


Ready to wire up authenticated webhook trading? Start with iNakaTrader →