How to Secure a TradingView Webhook with HMAC Signing

An HMAC-signed TradingView webhook lets your receiver prove each request is authentic and unaltered. Learn how HMAC-SHA256 signing works, how to apply it to alerts, and the honest TradingView trade-off to plan around.

A webhook URL is a door into your trading automation. Anyone who learns that URL can send a request to it, and if your receiver acts on whatever arrives, a stranger can place orders in your name. An HMAC-signed TradingView webhook closes that door: it lets your receiver prove that each request really came from you and was not altered in transit. This guide explains how HMAC signing works, how to apply it to alerts, and where TradingView's design forces an honest trade-off you need to plan around.

Signals are easy. Secure execution is hard. If you are wiring alerts to real orders on a live exchange, request authentication is not optional — it is the difference between an automation you can trust and one that anyone can hijack.

Why an unsigned webhook is a risk

A plain webhook trusts the network. Your receiver listens at a public URL, and by default it will process any well-formed request that hits it. That creates three concrete problems.

First, a leaked URL is a leaked key. Webhook URLs end up in browser history, screenshots, alert configuration exports, and support chats. Once the URL is known, an unsigned endpoint has no way to tell a real alert from a forged one.

Second, there is no integrity check. Even if you trust the sender, a tampered request — a quantity changed from `0.01` to `1.0`, a symbol swapped — will be accepted as legitimate because nothing binds the contents to a secret only you hold.

Third, replay is trivial. An attacker who captures one valid request can send it again and again, firing the same order repeatedly. Idempotency controls help here, but authentication is the first line of defense.

HMAC signing addresses the first two directly and, combined with a timestamp, blunts the third.

What HMAC signing actually does

HMAC stands for hash-based message authentication code. In plain terms, it is a fingerprint of a message that can only be produced — and only be verified — by someone who holds a shared secret. It uses a one-way hash function, most commonly SHA-256, so the fingerprint reveals nothing about the secret itself.

The shared secret

You generate one random secret and store it in two places: the system that sends the alert and the receiver that acts on it. The secret never travels over the network. It is not the same as your exchange API key, and it should never be reused across services.

The signature

To sign a request, the sender feeds two things into HMAC-SHA256: the exact bytes of the request body and the shared secret. The output is a signature — a fixed-length hexadecimal string such as `9f86d081884c7d659a2feaa0c55ad015`. The sender attaches that signature to the request, usually in an HTTP header like `X-Signature`.

On the other end, your receiver repeats the same computation using its copy of the secret and the body it received. If the two signatures match, the request is authentic and unmodified. If a single byte of the body changed, or the sender did not hold the correct secret, the signatures will not match and the receiver rejects the request.

How to build a signed webhook, step by step

The pattern is the same whether your signals originate in TradingView, a custom Python bot, or an automation platform like n8n, Make, or Zapier.

Step 1 — Generate a strong shared secret

Create a long, random secret — at least 32 bytes of entropy. Do not type a memorable phrase; use a cryptographically secure generator. Store it in an environment variable or secrets manager on the receiver, never hardcoded in a repository.

Step 2 — Construct a canonical payload

Decide on the exact string that will be signed and stick to it byte for byte. Most teams sign the raw JSON body of the request. Include an `id` for idempotency and a `timestamp` so the receiver can reject stale requests. A canonical body might read: `{"action":"buy","symbol":"BTCUSDT","qty":"0.01","id":"a1b2c3d4","ts":1752200000}`.

Step 3 — Compute the HMAC-SHA256 signature

Run HMAC-SHA256 over that exact body using the shared secret. In Python this is a two-line operation with the standard `hmac` and `hashlib` modules: `hmac.new(secret, body, hashlib.sha256).hexdigest()`. The result is the signature you send.

Step 4 — Send the signature alongside the request

Attach the signature in a header, for example `X-Signature: `, and send the same body you signed. If you sign one string and send a different one — even with reordered keys or extra whitespace — verification will fail.

Step 5 — Verify on the receiving side

The receiver recomputes the signature from the raw body it received and compares it to the header using a constant-time comparison (`hmac.compare_digest` in Python) to avoid timing side channels. Only if they match — and the timestamp is recent — does it proceed to place an order.

The honest TradingView trade-off

Here is the limitation nobody should hide from you. A TradingView alert sends static text. The message you type into the alert box is fixed at the moment you create the alert; TradingView cannot run code to compute a fresh HMAC signature for each firing. That means you cannot generate a true per-message HMAC signature inside TradingView itself.

You have three realistic options. The weakest is embedding a static shared token in the alert message and checking it on arrival — better than nothing, but the token is the same every time, so a captured request can be replayed and the "signature" never changes.

A stronger option is to place a lightweight signing relay between TradingView and your exchange. TradingView posts its static alert to the relay over HTTPS; the relay adds a real, per-request HMAC signature and a timestamp before forwarding to the exchange-facing endpoint. This is exactly the role a dedicated relay layer plays.

The third option applies when your signals come from a system you control — a custom backend, or an automation flow in n8n, Make, or Zapier. Those can compute a genuine HMAC per request, so you get full signing end to end.

Best practices for signed webhooks

Whatever path you choose, these practices keep a signed webhook trustworthy:

  • Use HMAC-SHA256 or stronger; avoid MD5 and SHA-1.
  • Sign the raw request body, not a reconstructed or reserialized version of it.
  • Always compare signatures with a constant-time function to prevent timing attacks.
  • Include a timestamp and reject requests older than a short window (for example, five minutes) to limit replay.
  • Pair signing with an idempotency `id` so a duplicated request cannot place a second order.
  • Rotate the shared secret on a schedule and immediately if it may have leaked.
  • Keep the signing secret separate from your exchange API keys, and use trade-only API keys with no withdrawal permission so a compromise cannot move funds off the exchange.
  • Serve every endpoint over HTTPS so the body and signature are encrypted in transit.

For more on scoping the keys that actually touch your exchange, see our guide to trade-only API keys and how to set them up, and for how secrets are protected at rest, how we encrypt your exchange API keys.

Where SignalToExchange fits

SignalToExchange is a non-custodial relay: it receives your signal, validates it, and submits a single order to your exchange using trade-only API keys that cannot withdraw funds. Because it sits between the signal and the exchange, it is the natural place to enforce request authentication — verifying HMAC signatures on inbound webhooks and adding signed, timestamped, idempotent requests on the way to the exchange, so one signal produces exactly one order. You control the logic; the relay handles secure execution, and your funds never leave your exchange. If you are still mapping out the wiring itself, our TradingView webhook to exchange setup guide walks through the full path.

Frequently Asked Questions

Is HMAC signing the same as HTTPS?

No. HTTPS encrypts data in transit so an eavesdropper cannot read it, but it does not tell your receiver who sent a request or whether the body was changed by someone who also knows the URL. HMAC signing authenticates the sender and verifies integrity. Use both together.

Can I compute a real HMAC signature inside a TradingView alert?

Not for each message. TradingView alerts send fixed text, so they cannot run per-request cryptographic code. Use a static token as a weak check, or route the alert through a signing relay or a backend you control to add a genuine per-request signature.

What happens if the signatures do not match?

The receiver rejects the request and places no order. A mismatch usually means the body was altered, the wrong secret was used, or the signed string differed from the sent string by whitespace or key ordering. Log the failure and investigate rather than loosening the check.

How often should I rotate the shared secret?

Rotate on a regular schedule and immediately if the secret might have been exposed. Support an overlap window where both the old and new secret are accepted briefly, so in-flight requests are not dropped during the switch.

Does signing stop replay attacks on its own?

Not by itself. A valid signed request can be resent. Add a timestamp with a short acceptance window and an idempotency `id` the receiver remembers, so a repeated request is recognized and ignored.

Get started

Securing a webhook is straightforward once you separate the two jobs: prove who sent the request, and prove it was not changed. HMAC-SHA256 with a shared secret, a timestamp, and an idempotency key covers both, and a relay layer fills the gap TradingView's static alerts leave behind. Ready to route your signals through infrastructure that verifies and executes them safely? Request access / 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.

Secure Signal Routing Infrastructure

Non-custodial execution. Trade-only API keys. Independent infrastructure built for reliability.

Request Early Access

Trade-only API key enforcement. No withdrawal permissions. No custody.