1. What a Webhook Is (Plain English)
A webhook is an automated HTTP message — like a text message sent between pieces of software over the internet. When TradingView fires an alert (e.g. "RSI crossed below 30"), it can send that alert as a webhook: a small package of data delivered to a URL you specify.
The Webhook Portal is the address that receives those messages. When a signal arrives, it does not blindly pass it to Gunbot. Instead, it acts like a bouncer:
| Step | What happens |
|---|---|
| 1. Arrives | Signal knocks on the door (POST to http://localhost:8081/webhook) |
| 2. Authenticated | Signature checked if a secret is configured. If signature fails REJECTED |
| 3. Gate rules checked | Time window, rate limit, symbol filter, etc. If any rule fails GATED |
| 4. Indicators checked | Live RSI, MACD, Bollinger, etc. fetched from Gunbot. If any filter fails GATED |
| 5. Executed | Order sent to Gunbot EXECUTED. Gunbot places the trade on your exchange. |
You can send webhooks from TradingView alerts, custom Python or Node.js scripts, the Twitter Monitor, or any tool that can make an HTTP POST request (including Postman or curl for testing).
2. The Log Tab
The Log tab is your live feed of every signal that has arrived, with its outcome. The feed updates automatically via a live server connection (SSE) — you do not need to reload the page.
Status Badges
Every log entry has a colour-coded badge:
| Badge | Meaning | What caused it |
|---|---|---|
| EXECUTED | Passed all gates. Order sent to Gunbot. | All rules and indicators passed; Gunbot accepted the order |
| GATED | Blocked by a gate rule or indicator filter. No order sent. | One of your configured rules returned false |
| REJECTED | Bad format, failed authentication, or unrecognisable payload. | Invalid JSON, missing required field, or wrong HMAC signature |
| PENDING | Waiting for consensus (consensus mode only). | Multiple sources must agree before executing |
| TEST | Injected manually using the test tool. | You sent it via the Test panel — not a real incoming signal |
Viewing Details
Click any log entry to expand it and see: the full JSON payload, which gate rule blocked it (for GATED), the rejection reason (for REJECTED), the Gunbot response (for EXECUTED), and a millisecond-precise timestamp.
Filter Buttons
Use the filter row above the log to show only signals with a specific status: All, Executed, Gated, Rejected, Pending. If you filter to "Gated" and the log is empty, the "No gated webhooks" state shows a button to clear the filter and show all signals.
3. Config Tab
| Field | What it does | Default | Notes |
|---|---|---|---|
| Gunbot URL | Where Gunbot's API lives | http://localhost:3001 | Only change if Gunbot runs on a non-standard port |
| Gunbot Token | Your Gunbot API key, used to authenticate trade orders | (empty) | Find it in Gunbot Settings API |
| Webhook Secret | HMAC signing key — signals must be signed with this to pass | (empty) | Leave empty for TradingView — TV cannot send custom headers |
| Gate Enabled | Master switch for all gate rules and indicator filters | On | Off = all valid signals execute immediately, no filtering |
| Indicator Pair | Which pair's candle data is used for indicator calculations | USDT-BTC | Must be a pair that exists in Gunbot on the indicator exchange |
| Indicator Exchange | Which exchange to pull candle data from | binance | Must be a configured exchange in Gunbot |
Settings are saved to a config file automatically when you click Save — they persist across server restarts.
4. Gate Rules
Gate rules are the filters that decide whether a signal is allowed through. They run in order — if any rule fails, the signal is GATED immediately and subsequent rules are not checked. You can enable, disable, or reorder rules in the Gate tab.
| Rule Type | What it does | Key settings |
|---|---|---|
| Gunbot Auth | Checks that Gunbot is online and authenticated before executing. Prevents orders being sent to an offline Gunbot. | None — automatic check |
| Indicator Gate | Runs all your enabled indicator filters. If any filter fails, the signal is gated. | Configured separately in the Indicators tab |
| Time Window | Only allows signals during specified hours and days of the week. | Start hour, end hour, days of week (0=Sun, 1=Mon … 6=Sat) |
| Symbol Filter | Allows or blocks signals for specific trading pairs. | symbols[] list; mode: allowlist or blocklist |
| Rate Limit | Maximum number of signals allowed within a rolling time window. | windowMinutes (default 60), maxCount (default 10) |
| Cooldown | Minimum time that must pass between any two signals executing. | seconds (default 60) |
| Action Filter | Only allows specific trade actions. Use to make the portal buy-only or sell-only. | allowed: ["buy"], ["sell"], or ["buy","sell"] |
| Source Filter | Allows or blocks signals based on their source field. | sources[] list; mode: allowlist or blocklist |
| Price Deviation | Blocks if the signal price is too far from the current market price. Catches stale or erroneous signals. | maxPercent (e.g. 5 = block if signal price is >5% from market price) |
| Balance Check | Verifies sufficient balance exists before executing. Prevents failed orders due to insufficient funds. | None — automatic check against Gunbot balances |
To add a new rule: click + Add Rule in the Gate tab, select the type, configure its settings, and save. To reorder rules, drag them — rules are checked top to bottom.
5. Indicators Tab
The Indicators tab shows all 31 available technical indicator filters. Enable any indicator and set a condition — the Indicator Gate rule will then check this condition live for every incoming signal.
The candle data used comes from the Indicator Pair and Indicator Exchange set in the Config tab (e.g. USDT-BTC on Binance). Indicators update every 10 seconds. At least 14 candles of data must be available before indicators can be calculated.
Condition Types
| Condition | Meaning | Example |
|---|---|---|
| range | Value must be between low and high (inclusive) | RSI range [30, 50] pass if RSI is between 30 and 50 |
| min | Value must be at or above this number | ADX min 25 pass if ADX ≥ 25 (trend is strong) |
| max | Value must be at or below this number | RSI max 40 pass if RSI ≤ 40 (oversold zone) |
All 31 Indicators
| Field Name | Indicator | What it measures | Typical range |
|---|---|---|---|
rsi | RSI (14) | Momentum oscillator | 0–100 · Buy zone: <40 |
macd | MACD Line | Trend momentum | Varies · Positive = bullish |
macdSignal | MACD Signal | MACD trigger line | Varies · Cross above = buy |
macdHist | MACD Histogram | MACD minus Signal | Varies · Positive = rising momentum |
bbUpper | Bollinger Upper Band | Mean + 2σ price level | Price-relative · Above = overbought |
bbLower | Bollinger Lower Band | Mean − 2σ price level | Price-relative · Below = oversold |
bbMiddle | Bollinger Middle | 20-period SMA | Price-relative |
bbPct | Bollinger %B | Where price sits within the bands | 0–1 · Below 0 = outside lower band |
bbWidth | Bollinger Width | Band spread (volatility proxy) | Varies · High = high volatility |
ema8 | EMA 8 % | % price is above/below 8-period EMA | Negative = price below EMA |
ema21 | EMA 21 % | % price is above/below 21-period EMA | Negative = short-term bearish |
ema50 | EMA 50 % | % price is above/below 50-period EMA | Negative = medium-term bearish |
ema200 | EMA 200 % | % price is above/below 200-period EMA | Negative = long-term bear trend |
sma20 | SMA 20 % | % price is above/below 20-period SMA | Varies |
vwap | VWAP % | % price is above/below VWAP | Negative = below fair value |
atr | ATR | Average True Range — absolute volatility | Price-relative |
atrPct | ATR % | ATR as a percentage of price | >2% = high volatility |
stochK | Stochastic %K | Fast stochastic oscillator | 0–100 · Below 20 = oversold |
stochD | Stochastic %D | Slow stochastic (signal line) | 0–100 · Below 20 = oversold |
williams | Williams %R | Momentum indicator | −100 to 0 · Below −80 = oversold |
cci | CCI | Commodity Channel Index | Varies · Below −100 = oversold |
mfi | MFI | Money Flow Index (volume-weighted RSI) | 0–100 · Below 20 = oversold |
roc | ROC | Rate of Change % | Varies · Negative = price declining |
adx | ADX | Trend strength (directionless) | 0–100 · Above 25 = strong trend |
obv | OBV | On-Balance Volume | Varies · Rising = accumulation |
vwma20 | VWMA 20 % | % price above/below volume-weighted MA | Varies |
donchianUpper | Donchian Upper | Highest high over 20 periods | Price-relative · Breakout = bullish |
donchianLower | Donchian Lower | Lowest low over 20 periods | Price-relative · Breakdown = bearish |
donchianMidPct | Donchian Mid % | % price above/below Donchian midline | Varies |
chaikin | Chaikin MF | Chaikin Money Flow | −1 to 1 · Above 0 = buying pressure |
aroon | Aroon Oscillator | Trend direction strength | −100 to 100 · Above 0 = uptrend |
6. Sending a Test Signal
Use the Test panel in the Webhook Portal UI to inject a signal without sending it from an external source. This lets you verify your gate rules and indicators are working before connecting TradingView.
Signal JSON Format
| Field | Required | Accepted values |
|---|---|---|
action | Yes | "buy" or "sell" |
exchange | Yes | Gunbot exchange name (e.g. "binance", "bybit") |
symbol | Yes | Gunbot pair format: "USDT-BTC", "USDT-ETH" |
amount | Yes | Number — trade size in base currency units |
price | No | Number — reference price. 0 or omit = use live market price |
source | No | String — label shown in log (e.g. "tradingview", "script") |
type | No | "MARKET" (default) |
refPrice | No | Number — only used by the Price Deviation gate rule |
7. TradingView Setup
TradingView alerts can be sent as webhooks to the Portal. Because TradingView is on the internet and the Portal runs on your local machine, you need ngrok to create a public tunnel to your local port 8081.
Setup Steps
| Step | What to do |
|---|---|
| 1 | Download ngrok from ngrok.com, create a free account, and authenticate it |
| 2 | Run: ngrok http 8081 — copy the https://xxxx.ngrok.io URL it shows |
| 3 | In TradingView, create an alert. Under "Notifications", enable "Webhook URL" |
| 4 | Enter: https://xxxx.ngrok.io/webhook as the webhook URL |
| 5 | In the alert message box, enter JSON using TradingView's dynamic variables |
Example Alert Message
X-WEN-Signature). If you set a webhook secret, every TradingView alert will be rejected with a 401 error. Leave the Webhook Secret field blank when using TradingView as your signal source.8. Gate Performance Stats
The Gate tab shows aggregate statistics since the server started:
| Stat | What it shows |
|---|---|
| Total received | All signals that arrived at the webhook endpoint |
| Executed | Signals that passed all gates and were sent to Gunbot |
| Gated | Signals blocked by a gate rule or indicator filter |
| Rejected | Signals that failed authentication or had bad format |
| Pass rate | Executed Total as a percentage |
A high gated count with strict indicator filters is expected — that's the gate working. A high rejected count suggests a misconfigured source (bad JSON format, wrong HMAC key).
9. Testing Checklist
- Send a test signal with valid JSON via the Test panel should appear as EXECUTED in the log
- Send a test signal with
"action": "hold"(invalid) should appear as REJECTED - Enable the Time Window rule set to hours in the past send a signal should be GATED
- Enable Rate Limit with maxCount=1 send two signals quickly second should be GATED
- Enable Symbol Filter as blocklist containing USDT-BTC send USDT-BTC signal should be GATED
- Enable RSI filter set to range [0, 5] (always false) next signal should be GATED by indicator gate
- Turn off the Gate (Config Gate Enabled: Off) all valid signals should execute immediately
- Set a Webhook Secret send a signal without a signature should be REJECTED with 401
- Clear the Webhook Secret same signal should now pass
- Check the Indicators tab shows live values (not all "—") for your configured pair
- Verify indicator values update every ~10 seconds without page reload
- Check Gate Stats panel after sending several signals — counts should be accurate
- Health check returns valid JSON: http://localhost:8081/health
- Log auto-updates when a signal arrives (SSE is working) — no page reload needed
10. Known Limitations
| Limitation | Detail |
|---|---|
| TradingView HMAC | Cannot use webhook secrets with TradingView — TV does not support custom request headers |
| ngrok URL changes | Free tier ngrok gives a new URL every restart; must update TradingView alerts each time |
| Indicator warmup | Requires at least 14 candles of data before RSI and other indicators can be calculated (~14 minutes on 1m timeframe) |
| Log limit | Only the last 500 log entries are kept — older entries are dropped automatically |
| Payload size | Maximum 64 KB per webhook payload — more than enough for any signal, but extremely large payloads will be rejected |
| Single exchange for indicators | All indicator filters use data from one pair/exchange combination — there is no per-signal indicator source |
11. Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
| All signals REJECTED | Invalid JSON format, or a webhook secret is set but the source isn't signing | Test with the built-in test panel first. If TradingView: clear the webhook secret |
| Signals always GATED by indicator gate | Indicator data not loaded, or filter condition is too strict | Check the Indicators tab — if values show "—", wait for candle warmup (~14 minutes). Loosen the filter range |
| Gunbot Auth gate always failing | Gunbot is offline, or the Gunbot token is wrong | Verify Gunbot is running. Re-enter the token in Config |
| Log stops auto-updating | SSE connection dropped (network interruption or long idle) | Reload the page — SSE reconnects automatically on load |
| "Gate: indicator data unavailable" | Gunbot cannot fetch candle data for the indicator pair | Check the Indicator Pair and Exchange in Config — ensure that pair exists and is active in Gunbot |
| TradingView alert gives 401 | Webhook secret is set | Clear the webhook secret in Config |
12. Bug Report Checklist
Include all of the following when reporting a Webhook Portal bug:
- Tool: Webhook Portal (:8081)
- Step-by-step description of what you were doing
- What you expected to happen vs what actually happened
- The exact JSON of the signal you sent (paste it in full)
- The log entry — click it and paste the full expanded detail
- Which gate rules were enabled, and their settings
- Which indicator filters were enabled, and the live values shown at the time
- Health check JSON: http://localhost:8081/health
- Screenshot of the full Log tab and the expanded signal detail
- Browser and OS version
- Approximate time it happened