Webhooks
Everything that flows in and out over HTTP. TradingView pushes alerts in; our bot engine pushes actionable signals out to Discord.
Incoming webhooks
TradingView alerts
Pro / PremiumRoute a TradingView alert straight into TradingWizard. The URL is static; the sender is identified by the api_token field inside the JSON body, so the token is the shared secret. Pro/Premium accounts immediately kick off AI analysis on the symbol and any matching price alerts fire in-app and via email.
Payload shape
{
"symbol": "{{ticker}}",
"exchange": "{{exchange}}",
"interval": "{{interval}}",
"action": "{{strategy.market_position}}",
"price": "{{strategy.order.price}}",
"strategy": "{{strategy.order.id}}",
"api_token": "YOUR_TRADINGWIZARD_API_TOKEN"
}Paste this template into the Message field of a TradingView alert. Only symbol, action, price, and api_token are strictly required — strategy is optional and used for dedup and logs. Missing or wrong api_token returns 401 / 403. Starter accounts get an automated upgrade email instead of analysis.
Outgoing webhooks
Discord — bot signals
CommunityEach market (crypto / stock / forex) has a dedicated Discord webhook URL for OPEN and CLOSE signals, plus a separate URL for UPDATE events when a bot moves its stop or target. Configuration lives in Vercel env as DISCORD_WEBHOOK_<MARKET>_SIGNALS and DISCORD_WEBHOOK_<MARKET>_UPDATES.
Filtering (from lib/discordWebhooks.ts)
// Only actionable, high-conviction signals leave the server
// 1. Verdict must be BUY or SELL — WAIT / HOLD / NEUTRAL are dropped
// 2. Bot confidence must be >= 60% for OPEN signals
// 3. CLOSE events with |PnL %| < 1.5 are treated as "scratch" and skipped
MATERIALITY = {
DISCORD_THRESHOLD: 1.5, // |PnL %| below this is NOT posted
SCRATCH_BAND: 0.5, // within this band = scratch trade
}Payload shape (OPEN)
{
"symbol": "BTCUSDT",
"side": "BUY",
"entry": 67840.0,
"stopLoss": 66200.0,
"takeProfit": 71500.0,
"confidence": 74,
"timeframe": "4h",
"botName": "BTC Momentum",
"reason": "Breakout of 4h consolidation with volume confirmation"
}Every outbound payload passes through a PII scrubber that strips email-like strings and known sensitive keys (email, userId, stripeCustomerId, tokens) before the request is serialised. Per-URL cooldowns honour Discord's 429 retry_after inside the same warm lambda instance.
Pulse and Market Track events
DigestThe hourly Market Pulse cron and the Market Track engine fan out notable moves — fear & greed shifts, regime changes, breakouts, earnings reactions — to the same Discord channels. Scratch-band moves and low-significance events never get posted. Bot backtest results and end-of-run summaries go to DISCORD_WEBHOOK_BOT_RESULTS.
Payload shape (Market Track)
{
"symbol": "ETHUSDT",
"sentiment": "bullish",
"explanation": "ETH reclaimed the 200-day after a 3-day accumulation candle.",
"triggerSource": "momentum",
"detectedAt": "2026-04-20T14:30:00Z"
}Retries & idempotency
TradingView
TradingView does not retry. We key dedup off the strategy / alert id from the payload combined with symbol + timestamp. If you need guaranteed delivery, trigger the alert Once per bar close rather than Every tick.
Discord (outbound)
Best-effort. On 429 we back off for the duration Discord returns (per-URL cooldown). No automatic replay — a dropped signal is dropped, by design, to prevent stale setups from posting late.
Pulse / Market Track
Events are written to MongoDB first and only then fanned out, so the system-of-record never depends on Discord delivery. Reposting the same event is a no-op.
Security
- TradingView: authenticated via the
api_tokenfield inside the JSON body (a per-user secret). Rotate the token from Settings → API Keys the moment you suspect a leak. - Replay protection: TradingView alerts are deduped by the payload's
strategy/ alert id. Replays are rejected before any side effects. - IP allowlists: recommended but optional. TradingView uses a documented fixed set of IPs — whitelist them at the edge if your threat model needs it. Vercel serves our origin from its global edge, so we do not operate a static outbound IP range.
- Outbound: every payload passes through a PII scrubber that strips email-like strings and known sensitive keys (
email,userId, tokens) before the request leaves us.
Testing
TradingView — test webhook
In the TradingView strategy editor, open the alert dialog and click Test webhook. Paste our URL, drop the payload template shown above into the Message field, and fire. A successful request returns 200 with { "success": true, "action_received": "..." }.
Next: REST API
The same API key used for TradingView webhooks also unlocks the programmatic API.