The webhook endpoint is the Bring Your Own signal source. Point any external tool — TradingView alerts, your own scripts, a Discord bot, anything that can make an HTTP request — at your personal endpoint and the trade is treated exactly like one of our native alerts: it runs through your strategy's rules, capital allocation, kill switches, and exit logic.

Endpoint
POST https://api.staxinvesting.com/webhook/trade-signal
This URL is unique to your account. Don't share it — anyone with the URL can fire trades into your strategy.
Request payload
{
"timestamp": "2025-01-13T11:00:00-05:00",
"unmodifiedTicker": "SPY250630P616.0"
}
Field reference
| Field | Type | Required | Description |
|---|---|---|---|
timestamp |
string | Yes | ISO 8601 with timezone (e.g., 2025-01-13T11:00:00-05:00) |
unmodifiedTicker |
string | Yes | Encoded option contract — see format below |
close |
number | No | Entry price for the contract. If omitted, the current market price is fetched automatically. |
Extra fields are accepted but ignored, so older integrations keep working.
unmodifiedTicker format
The ticker encodes the whole option contract in one string: SYMBOL + YYMMDD + P/C + STRIKE.
| Ticker | Symbol | Expiration | Type | Strike |
|---|---|---|---|---|
SPY250630P616.0 |
SPY | Jun 30, 2025 | Put | $616.00 |
QQQ250113C627 |
QQQ | Jan 13, 2025 | Call | $627.00 |
IWM250215P200.5 |
IWM | Feb 15, 2025 | Put | $200.50 |
Example cURL
curl -X POST https://api.staxinvesting.com/webhook/trade-signal \
-H "Content-Type: application/json" \
-d '{
"timestamp": "2025-01-13T11:00:00-05:00",
"unmodifiedTicker": "SPY250630P616.0"
}'
Reverse action
If the strategy has Reverse enabled, the webhook can also flip an open position instead of opening a new one. Send your normal payload with "action": "reverse": the bot market-closes the held option on that ticker and opens the opposite side (call ↔ put).
{
"timestamp": "2025-01-13T11:00:00-05:00",
"unmodifiedTicker": "SPY250630C760.0",
"action": "reverse",
"strike": 758.0,
"limit": 1.85
}
| Field | Type | Required | Description |
|---|---|---|---|
action |
string | No | "reverse" to flip the position. Omit (or "entry") for a normal entry. |
unmodifiedTicker |
string | Yes | Identifies the held contract to reverse (same root + side you're holding). |
strike |
number | No | Explicit new strike for the opposite side. If omitted, the strategy's Reverse Strike Offset decides it (0 = same strike). |
limit |
number | No | Limit price for the opposite entry. If omitted, it's a market entry. |
A reverse bypasses the trading-hours window and daily trade limit (it's a deliberate flip of an already-open position) but still respects the kill switch and your buying power. The response tells you whether the flip succeeded, was refused before anything closed (refusedPreClose — position intact), or closed but couldn't re-open (flat — you're now flat). See Reverse for the full behavior.
curl -X POST https://api.staxinvesting.com/webhook/trade-signal \
-H "Content-Type: application/json" \
-d '{
"timestamp": "2025-01-13T11:00:00-05:00",
"unmodifiedTicker": "SPY250630C760.0",
"action": "reverse"
}'
Validation rules
timestampandunmodifiedTickerare requiredcloseis optional (market price fetched if omitted)unmodifiedTickermust matchXXXYYMMDD[PC]STRIKE- Timestamp must fall within your configured trading hours
- Daily trade limit must not be exceeded
Success response (200)
{
"success": true,
"message": "Trade executed successfully",
"timestamp": "2025-01-11T15:30:00.123Z",
"requestId": "WHK-...",
"data": {
"tradeResult": { "success": true, "orderId": "12345", "symbol": "SPY..." },
"tradeCounter": { "current": 3, "limit": 10, "remaining": 7 }
}
}
Error response (400)
{
"success": false,
"error": "Missing required field: timestamp",
"timestamp": "2025-01-11T15:30:00.123Z",
"requestId": "WHK-..."
}
TradingView PineScript example
Use this as a starting point for a TradingView alert that builds the unmodifiedTicker dynamically from the chart's symbol and price action.
// Build the unmodifiedTicker: SYMBOL + YYMMDD + P/C + STRIKE
// Example: SPY250630P616.0 = SPY Put, Jun 30 2025, $616 strike
int strikesOut = input.int(2, "Alert Strikes OTM", group = "Alerting")
// Build Strike selection
string longStrike = str.tostring(math.ceil(close)+strikesOut)
string shortStrike = str.tostring(math.floor(close)-strikesOut)
expYear = str.substring(str.tostring(year), 2, 4)
expMonth = month < 10 ? "0" + str.tostring(month) : str.tostring(month)
expDay = dayofmonth < 10 ? "0" + str.tostring(dayofmonth) : str.tostring(dayofmonth)
longTicker = syminfo.root + expYear + expMonth + expDay + "C" + longStrike + ".0"
shortTicker = syminfo.root + expYear + expMonth + expDay + "P" + shortStrike + ".0"
if (longCondition)
webhookObj = '{"timestamp": "' + str.format_time(timenow, "yyyy-MM-dd'T'HH:mm:ssZ", syminfo.timezone) + '", "unmodifiedTicker": "' + longTicker + '"}'
alert(webhookObj, alert.freq_once_per_bar_close)
if (shortCondition)
webhookObj = '{"timestamp": "' + str.format_time(timenow, "yyyy-MM-dd'T'HH:mm:ssZ", syminfo.timezone) + '", "unmodifiedTicker": "' + shortTicker + '"}'
alert(webhookObj, alert.freq_once_per_bar_close)
Tips for dynamic tickers
- Symbol —
syminfo.rootgives the underlying (SPY, QQQ, etc.) - Expiration — build YYMMDD from
year,month,dayofmonth - Option type —
"P"or"C"based on your strategy conditions - Strike —
math.round(close), then adjust for OTM distance - Entry price — use
closeor compute from your indicator
Tip
Point a strategy at Bring Your Own (Webhook) and leave it disabled while you wire up the sender. Watch the alerts feed for a few test fires before flipping the strategy on.