Skip to main content

Webhook Endpoints — Execute Trade Signal

A TVH webhook endpoint accepts a TradeCommand JSON payload and turns it into a trade on an exchange. This page is the wire reference for the two variants — queued and classic. For the URLs to paste into a TradingView alert and the IP whitelist, see Webhook URLs & IP Whitelist.

TL;DR
  • Queued (POST /) is the default. It deduplicates, retries on transient failures, and absorbs exchange rate-limit bursts, at the cost of a small queue-hop delay. Use this unless you have a specific reason not to.
  • Classic (POST /api/ExecuteTradeSignalClassic) skips the queue and executes inline — faster, but no retry and no dedup. Use only for scalping when you have confirmed you need the lower latency.
  • Both variants exist on both base URLs: alerts.tv-hub.org for everything except Binance, binance.tv-hub.org for all Binance markets.
  • The body schema is the full TradeCommand. Most setups use 6–10 fields.

Endpoint variants

URLBaseQueueWhen to use
https://alerts.tv-hub.org/alertsDefault. All exchanges except Binance.
https://alerts.tv-hub.org/api/ExecuteTradeSignalClassicalertsLow latency, scalping. Accept no-retry, no-dedup.
https://binance.tv-hub.org/binanceAll Binance markets (Spot, USD-M & Coin-M Futures).
https://binance.tv-hub.org/api/ExecuteTradeSignalClassicbinanceBinance, low latency.

Use the Binance host for Binance, the default host for everything else. The copy-paste URLs and IP whitelist are in Webhook URLs & IP Whitelist.

Request — single trade

MethodPOST
Content-Typeapplication/json or text/plain
BodyA single TradeCommand object

The minimum useful payload requires five fields:

FieldPurpose
tokenYour TVH User Token (from Account → Settings). Treat it like a password.
exchangeExchange identifier (e.g. binance, bybit-futures, kucoin).
pairSymbol on that exchange (e.g. BTCUSDT).
isBuy / isSell / isCloseDirection flag for normal webhook/API commands. Use orderType only for TradingView strategy-alert templates.
apiKeyThe ApiKeyName you set when you added the exchange key in TVH.

Plus sizing (one of unitsType + value, units, or positionSize). The full 84-field schema is in Trade Command → Parameter Reference.

Quick close

A close needs no sizing — just point it at the open position and set isClose:

{"pair":"ETHUSD","exchange":"Bitmex-Testnet","apiKey":"Key1","token":"YOUR_TOKEN","isClose":true}

This market-closes the current position on that pair and cancels its pending orders (SL, TPs, DCA limits). See Close & Cancel for partial closes and hedge-mode variants.

Request — batch (square-bracket syntax)

Send multiple commands in a single webhook by wrapping them in an array:

[
{"token":"...","exchange":"binance","pair":"BTCUSDT","isBuy":true,"apiKey":"K1","unitsType":"percent","unitsPercent":1},
{"token":"...","exchange":"bybit","pair":"ETHUSDT","isBuy":true,"apiKey":"K2","unitsType":"percent","unitsPercent":1}
]

The queued endpoint enqueues each entry independently. The classic endpoint executes them in parallel. Cross-ref: Features → Batch & Timing.

Code examples — single trade (queued)

curl -X POST https://alerts.tv-hub.org/ \
-H "Content-Type: application/json" \
-d '{
  "token": "YOUR_TOKEN",
  "exchange": "binance",
  "pair": "BTCUSDT",
  "isBuy": true,
  "isMarket": true,
  "unitsType": "percent",
  "unitsPercent": 1,
  "apiKey": "BinanceKey1",
  "alertTimestamp": "BTCUSDT-1716364800"
}'

Test with Postman

Any HTTP client works. In Postman: set the method to POST, the URL to a webhook endpoint, the body to raw, and paste your TradeCommand. A 200 OK means the signal was accepted (on the queued endpoint, check the Activity Log for the execution result; the Classic endpoint returns the result directly — see below).

Postman POST to the TVH webhook with a raw TradeCommand body, returning 200 OK

The example above is a minimal close command — {"pair":"ETHUSD","exchange":"Bitmex-Testnet","apiKey":"Key1","token":"your-token","isClose":true}.

Code examples — classic (low latency)

The body is identical. Only the URL changes.

Classic returns the execution result

The Classic endpoint runs synchronously, so its response body carries the actual outcome — a human-readable success string, or the exchange's error message if the trade was rejected. The queued endpoint instead returns immediately with an empty body, and its result only appears in the Activity Log.

curl -X POST https://alerts.tv-hub.org/api/ExecuteTradeSignalClassic \
-H "Content-Type: application/json" \
-d '{
  "token": "YOUR_TOKEN",
  "exchange": "bybit",
  "pair": "BTCUSDT",
  "isBuy": true,
  "isMarket": true,
  "unitsType": "percent",
  "unitsPercent": 1,
  "apiKey": "BybitKey1"
}'

Code examples — batch

curl -X POST https://alerts.tv-hub.org/ \
-H "Content-Type: application/json" \
-d '[
  {"token":"YOUR_TOKEN","exchange":"binance","pair":"BTCUSDT","isBuy":true,"isMarket":true,"unitsType":"percent","unitsPercent":1,"apiKey":"BinanceKey1"},
  {"token":"YOUR_TOKEN","exchange":"bybit","pair":"ETHUSDT","isBuy":true,"isMarket":true,"unitsType":"percent","unitsPercent":1,"apiKey":"BybitKey1"}
]'

Response

A successful webhook returns 200 OK. The body is typically empty for the queued endpoint (the trade is now in the queue, no result yet) and contains a human-readable status message for the classic endpoint (executed inline so the result is known).

HTTP/1.1 200 OK
Content-Length: 0
200 does not mean "trade executed"

For the queued endpoint, 200 OK means "signal accepted into the queue". The actual exchange call happens asynchronously inside the queue worker. Check the Activity Log in the TVH dashboard for the execution outcome. For the classic endpoint, 200 OK does mean "exchange responded successfully" — but the body carries the human-readable result.

Error responses

StatusMeaningNotes
400 Bad RequestMalformed body, unknown user, parsing failure, sizing inconsistentThe body is a plaintext error message. Inspect it.
401 UnauthorizedNot used for webhooks (token is in body).
403 ForbiddenSubscription expired and ApiKey is past its trial window.Renew or extend.
422 Unprocessable EntityCurrently surfaces as 400 with a descriptive message. Reserved.
500 Internal Server ErrorServer-side issue. Auto-retried by the queued endpoint.Inspect Activity Log.

For the full mapping of error bodies to causes, see Error Codes.

Queued vs Classic — when to use which

PropertyQueued (/)Classic (/api/ExecuteTradeSignalClassic)
Retry on 5xx exchange errors✅ (retries field, default 1)
Deduplication via alertTimestamp
Rate-limit backpressure✅ (queue throttles)
Order preserved within a chain⚠️ Best-effort
End-to-end latencyHigher (queue hop)Lower (inline)
Failure visibilityActivity Log onlyResponse body + Activity Log

Default recommendation: queued. Switch to classic only when you have measured the latency and confirmed the trade-offs are acceptable.

Idempotency

Set alertTimestamp on every webhook to opt into deduplication. The lock is keyed on (token, apiKey-or-exchange, alertTimestamp) and the lock row is written on first processing.

alertTimestamp lock is permanent

The lock is not a 5-minute sliding window. Once written it lives forever. A duplicate payload, same token, same apiKey/exchange, same alertTimestamp, produces the same lock key. TVH recognises it as a duplicate and silently drops it.

Recommended Pine pattern: alertTimestamp="{{ticker}}-{{timenow}}" — unique per bar per symbol. See Trade Command → Timing & Idempotency.

Unsubstituted Pine placeholder is silently replaced

If alertTimestamp arrives as the literal string {{ticker}}-{{time}}, meaning TradingView did not substitute the placeholder, the server replaces it with a fresh GUID before the signal lands in the queue. The same happens when alertTimestamp is empty.

This guarantees a 200 OK but defeats deduplication: every call gets a unique GUID, so a duplicate alert from a misconfigured Pine template will re-trade instead of getting dropped by the lock. The receiver does not warn you when this fallback fires.

Always send a real, substituted value in production. Pine pattern: alertTimestamp="{{ticker}}-{{timenow}}".

Activity Log

Every webhook call appears in the TVH dashboard Activity Log within a few seconds, including:

  • The full request body
  • The user token resolved to a username
  • The trade result (success / failure / skipped due to duplicate)
  • Any error message from the exchange
  • Latency from receipt to exchange response

Filter by exchange, pair, status, or date range. Activity Log is the source of truth for diagnosing webhook problems — the HTTP response alone is rarely enough because trade execution is asynchronous for the queued path.

Webhook signing / HMAC

Not supported. The token field in the body is the only credential. If you need to prove that a webhook payload originated from a trusted source, that constraint lives on your side — TVH does not generate or verify HMAC signatures. TLS is mandatory (all endpoints reject plaintext HTTP).

Cross-references