Sarathi developer docs: webhook contract

Use the webhook to turn a TradingView alert into a Sarathi order card. The card still needs a Confirm or Skip decision. The webhook receiver is hosted at https://server-production-d3f7.up.railway.app.

Webhook URL

Send an HTTP POST to your personal URL:

POST https://server-production-d3f7.up.railway.app/hook/<token>

Treat the token and the full URL as secrets. The request body limit is 16 KiB.

JSON body

The canonical alert fields are:

FieldAccepted typeMeaning
symstringRequired instrument symbol. symbol and ticker are aliases.
sidestringRequired. BUY, SELL, LONG, and SHORT are accepted case-insensitively. action is an alias.
typestringOptional strategy label. strategy is an alias.
pricenumber or numeric stringOptional entry reference. close and entry are aliases.
slnumber or numeric stringOptional stop. stop and stoploss are aliases.
tpnumber or numeric stringOptional target. target and takeprofit are aliases.
qtynumber or numeric stringOptional quantity. quantity and size are aliases.
timestring recommendedOptional TradingView time. When present, it participates in deduplication.
idstring recommendedOptional explicit deduplication key. It takes precedence over time.

Unknown JSON fields are ignored. Numeric values are parsed with parseFloat; non-finite or absent values become null. The current parser does not runtime-validate a non-null type, time, or id, so send strings for a stable contract.

Example:

{
  "sym": "{{ticker}}",
  "side": "BUY",
  "type": "ORB",
  "price": "{{close}}",
  "sl": 57400,
  "tp": 57790,
  "qty": 30,
  "time": "{{timenow}}"
}

In a TradingView strategy alert, set the alert dialog message to {{strategy.order.alert_message}} so the order call's alert_message is posted.

Plain-text body

The parser also accepts this shape:

BUY BANKNIFTY 30 sl=57400 tp=57790

The first word can be BUY, SELL, LONG, or SHORT; the second is the symbol; the optional third value is an integer quantity. sl= and tp= may appear later in the text. Plain text does not carry strategy, price, time, or an explicit dedupe id.

Symbol normalisation and universe gate

Symbols are trimmed and uppercased. A leading NSE:, BSE:, or MCX: prefix and a trailing continuous-contract suffix 1! or 2! are removed. NIFTY50 becomes NIFTY, GOLD becomes GOLDM, and SILVER becomes SILVERM.

After normalisation, the symbol must resolve to an active member of Sarathi's universe. Tier 1 is NIFTY, BANKNIFTY, MIDCPNIFTY, SENSEX, GOLDM, SILVERM, RELIANCE, and TCS. Tier 2 contains supported NIFTY 50 F&O names. A miss returns HTTP 400:

{
  "error": "symbol not in universe",
  "hint": "Tier-1: NIFTY, BANKNIFTY, MIDCPNIFTY, SENSEX, GOLDM, SILVERM, RELIANCE, TCS; tier-2: NIFTY 50 F&O names",
  "symbol": "NORMALISED_SYMBOL"
}

Deduplication and expiry

If id is present, it is the dedupe key. Otherwise, a truthy time produces symbol|side|type|time. The uniqueness check is per Sarathi user. A duplicate returns HTTP 200 with {"duplicate":true,"ok":true}. Without id or time, the alert has no dedupe key.

Accepted signals expire from the pending state after SIGNAL_EXPIRY_MIN. The server default is 15 minutes. An expired card cannot be confirmed later and remains in the journal.

Webhook responses

StatusMeaning
200Accepted as pending or held, ignored because the body was empty or an unexpanded placeholder, or recognised as a duplicate.
400The body is malformed, required fields are missing, the side is unknown, or the symbol is outside the universe.
404The webhook token is unknown. Body: {"error":"unknown token"}.
413The request body is larger than 16 KiB.
429A rate limiter in front of the hook rejected the request. The current hook route itself does not emit 429.

Pine v6 alert pattern

Build one message and reuse it for both the order's alert_message and the bar-close alert() call. Keep TradingView placeholders outside str.format(). Use {0,number,#.##} or str.tostring(value, "#.##") so grouped thousands do not make the JSON invalid.

alertMsg = '{"sym":"{{ticker}}",' +
     str.format('"side":"{0}","type":"{1}",', side, stratType) +
     '"price":{{close}},' +
     str.format('"sl":{0,number,#.##},"tp":{1,number,#.##},"qty":{2,number,#}', slLvl, tpLvl, qty) +
     ',"time":"{{timenow}}"}'

if barstate.isconfirmed and entryCondition
    strategy.entry("Long", strategy.long, qty = qty, alert_message = alertMsg)
    alert(alertMsg, alert.freq_once_per_bar_close)

API

Sarathi has no public API. The web app talks to the server over an authenticated RPC channel that is not a supported integration surface. The only inbound integration is the per-user webhook described above. Outbound webhooks are planned; see webhook connectors.

Sarathiसारथी

Sarathi means charioteer. The charioteer drives; the warrior decides when to shoot. Here the software drives, and you confirm every order.

Status

Pre-launch · pre-revenue
Bridge verified live 24 Aug 2026

Get started →

Sarathi is an execution bridge, not an investment adviser, and is not registered with SEBI as a Research Analyst. Nothing on this page is advice or a recommendation to trade. Sarathi never holds your funds or securities; every order is placed by you, on your own broker account. Derivatives trading carries substantial risk of loss.

Chart illustrations use TradingView Lightweight Charts™. Every price on this page is made up.

TradingView and Telegram are trademarks of their respective owners. Sarathi is not affiliated with or endorsed by them.