External signals (TradingView & data APIs)

Let your strategy read signals from outside: TradingView alerts, on-chain or sentiment APIs, your own service. Two ways in, one way to read them.

1) Webhook — they push to us

Issue a URL in Settings → External signals and paste it into the Webhook URL field of a TradingView alert.

  • Issue one URL per service. You name it at issue time ('TradingView', 'my script'), and that name is how you pick which URL to delete later
  • If one URL leaks, delete just that one — every other integration keeps working. With a single shared URL, deleting it kills them all at once
  • One URL = one slot. You pick the slot name at issue time (tv, btc4h …) and everything sent to that URL always lands in that slot — nothing to append
  • So whoever holds the URL cannot switch the slot name and overwrite another signal — it is structurally impossible. Sending to a different slot is rejected, not silently redirected — a misconfiguration should tell you it is one
  • Any issued URL can be viewed again with Show webhook URL in the list — losing it is not a reason to reissue
  • The list shows when each URL last received something — that is how you check a URL is still live
  • The body is stored as-is: JSON stays JSON, plain text becomes { text: "..." }
  • One quota, counted in slots (Free 3 → Elite 30). URLs and polling jobs share the same slots, so 2 URLs + 1 polling job fills the free plan. The 'slots n/max' badge at the top of the card is that number

2) Polling — we ask them on a schedule

Register a URL (and an API key if needed) and your own agent calls it every interval, storing the result as a signal.

  • Your server makes the call, not ours — it goes out with your IP and your key, so you use the provider's limits normally
  • API keys go in headers: stored encrypted, handed only to your agent (after saving you see names only)
  • Minimum interval depends on your plan — Free 1h · Basic 30m · Pro 15m · Elite 1 second
  • Even at a short interval, reports to forexsori servers are batched to 10s — your strategy reads your own agent's archive, so there is no added delay
  • For APIs that need a body (GraphQL etc.), pick POST under Advanced and enter the body. Choose a Content-Type from the list or type your own (default application/json)

Backfilling history in one call

If the response is a list, history fills in at once. Fill both Advanced fields:

  • Array location (itemsPath) — where the list sits. e.g. if the top level has an array named data, enter data
  • Time field (timeField) — the timestamp field inside each item. e.g. timestamp

Both are required. Leave them empty and the whole response is stored as one row.

Example (Fear & Greed): URL https://api.alternative.me/fng/?limit=90 · array data · time field timestamp → 90 days arrive at once.

Reading it in a strategy

Both ways are read with the same function.

  • Returns { payload, at, age }payload exactly as sent, at the signal time, age seconds ago
  • No signal → null (never faked as 0 or an empty object)
  • To ignore stale signals, gate on age yourself (e.g. only within the last hour)
  • We never interpret the content. Field names and shapes are up to the sender, so your strategy parses it (ask the AI and it will)

It works in backtests too

Stored signals are replayed bar by bar, as of that moment (no look-ahead).

Honest limitation: backtests only cover the period since you started collecting. History before the webhook existed does not exist, and we do not reconstruct TradingView's logic (that would be fabrication). So the earlier you connect, the longer the testable window. Polling fills history immediately if the response contains it.

Where it is stored

  • The full archive lives on your agent (your server) — your disk is the limit
  • forexsori servers keep only a short buffer: signals not yet handed to your agent (up to 2000) and summaries of delivered ones (100). 'Recent signals' in settings shows this buffer
  • If your agent is off, signals wait in the buffer and are handed over when it reconnects

Slot names

A slot is the name that separates signals (tv, fng, onchain …). Lowercase letters, digits, - and _, 1–20 chars — you choose them. Webhooks and polling share one namespace, so a name cannot be used by both, and URLs and polling jobs are counted together against your plan's slot count (Free 3 → Elite 30).