TradingView alerts are a great starting point. You write a Pine Script, click "Add Alert", and TradingView emails you or POSTs to a URL when conditions fire. For discretionary traders and hobby bots, this is perfect.
For production automated trading, TradingView alerts hit limits fast: plan-based alert caps, 1-minute minimum polling, no HMAC signing, no built-in retries, and Pine Script's strict sandbox. This guide shows how to migrate common TradingView alert setups to APIndicators' webhook-based API, with side-by-side examples in Pine Script, Python, and Node.
When TradingView Hits Its Limits
You need to migrate when any of these happen:
- You need more than 400 alerts (Premium plan cap)
- Your alert fires faster than TradingView's minimum 1-minute resolution
- You want signed webhooks with HMAC for tamper-proof payloads
- You need multi-indicator fusion (e.g. your ML model + 3 classical indicators)
- You are paying for TradingView and an exchange data feed and want to consolidate
APIndicators replaces the signal generation layer: you get RESTful indicator endpoints, scheduled strategy runs, and HMAC-signed webhook delivery on a single API.
Example 1: RSI Oversold Alert
Pine Script on TradingView:
//@version=5
indicator("RSI Oversold Alert", overlay=false)
rsi = ta.rsi(close, 14)
plot(rsi)
alertcondition(ta.crossover(rsi, 30), title="RSI Oversold", message="RSI crossed above 30 on {{ticker}}")
You click "Add Alert", paste a webhook URL, done.
Equivalent APIndicators approach — a Python script runs every minute, or you subscribe to a strategy that auto-fires webhooks:
import requests
import os
API_KEY = os.environ["APINDICATORS_API_KEY"]
def check_rsi_oversold(symbol):
url = f"https://api.apindicators.com/v1/pairs/{symbol}/indicators"
headers = {"Authorization": f"Bearer {API_KEY}"}
r = requests.get(url, headers=headers, params={"interval": "5m"})
data = r.json()
return data["rsi_14"] > 30 and data["rsi_14_prev"] <= 30
if check_rsi_oversold("BTCUSDT"):
print("RSI crossed above 30")
Or — and this is the cleaner pattern — register a persistent strategy with APIndicators that fires a webhook to your server when the condition hits:
curl -X POST https://api.apindicators.com/v1/strategies \
-H "Authorization: Bearer $APINDICATORS_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "rsi-oversold-btc",
"symbol": "BTCUSDT",
"interval": "5m",
"condition": "rsi_14_prev <= 30 AND rsi_14 > 30",
"webhook_url": "https://my-bot.example.com/webhook"
}'
No polling. No cron. The APIndicators scheduler evaluates the condition every candle close and fires a signed webhook only when it hits.
Example 2: Multi-Indicator Fusion
Here is where TradingView starts to strain. Say you want to enter long when all three fire: RSI crosses above 40, MACD above zero, ADX above 22. Pine Script handles it, but hitting webhook URLs reliably at scale gets fragile.
With APIndicators:
payload = {
"name": "btc-momentum-entry",
"symbol": "BTCUSDT",
"interval": "1h",
"condition": "rsi_14 > 40 AND macd > 0 AND adx_14 > 22",
"webhook_url": "https://my-bot.example.com/webhook",
"cooldown_minutes": 60
}
requests.post(
"https://api.apindicators.com/v1/strategies",
headers={"Authorization": f"Bearer {os.environ['APINDICATORS_API_KEY']}"},
json=payload
)
The cooldown_minutes field prevents the same alert from firing 60 times when conditions hover at the threshold. TradingView requires you to code this logic into Pine; APIndicators handles it at the infrastructure level.
Receiving the Webhook (Python + Node)
All APIndicators webhooks are HMAC-SHA256 signed. Verify on receipt:
Python (Flask)
from flask import Flask, request, abort
import hmac
import hashlib
import os
app = Flask(__name__)
SECRET = os.environ["APINDICATORS_WEBHOOK_SECRET"].encode()
@app.post("/webhook")
def webhook():
signature = request.headers.get("X-Signature", "")
body = request.get_data()
expected = hmac.new(SECRET, body, hashlib.sha256).hexdigest()
if not hmac.compare_digest(signature, expected):
abort(401)
payload = request.json
print(f"Signal fired: {payload['strategy_name']} on {payload['symbol']}")
return {"ok": True}
Node.js (Express)
import express from "express";
import crypto from "crypto";
const app = express();
const SECRET = process.env.APINDICATORS_WEBHOOK_SECRET;
app.post("/webhook", express.raw({type: "application/json"}), (req, res) => {
const signature = req.headers["x-signature"];
const expected = crypto.createHmac("sha256", SECRET).update(req.body).digest("hex");
if (signature !== expected) {
return res.status(401).end();
}
const payload = JSON.parse(req.body.toString());
console.log(`Signal fired: ${payload.strategy_name} on ${payload.symbol}`);
res.json({ok: true});
});
app.listen(3000);
Neither example polls. Neither example has to implement indicator math. Signals show up when they fire.
Why Programmatic Beats Alerts for Production Bots
Four specific reasons:
- Deterministic delivery. APIndicators retries failed webhook deliveries with exponential backoff. TradingView gives you one shot.
- Cryptographic integrity. HMAC signing means you can run your webhook handler on a public URL without worrying about spoofed signals.
- No Pine Script sandbox. Any condition expressible via Python or SQL can be a strategy.
- Predictable pricing. APIndicators' free tier already allows more webhook traffic than most production bots generate.
Practical Takeaways
- Use TradingView alerts for discretionary trading. Use programmatic webhooks for automated execution.
- Always verify HMAC signatures. Never accept unsigned webhook POSTs as trading signals.
- Add cooldowns at the source, not in your bot, to avoid duplicate fires.
- Log every webhook you receive with the full payload and your response.
- Start by mirroring your TradingView alerts 1:1, then add cross-indicator conditions that Pine Script cannot express cleanly.
Ready to migrate? Start at apindicators.com/docs for the full webhook schema or apindicators.com/pricing to pick a plan.