Webhook Responses
What the webhook answers to every request, and what each error code means and how to fix it.
On this page
Accepted
{
"success": true,
"id": "9f1c…",
"logId": "9f1c…",
"payload": {"ticker": "AAPL", "action": "buy"}
}
200 means the signal was accepted and saved. The trade runs right after, on each subscription; open the signal to see the result. A signal with delay also gets a delayedUntil time. A batch is answered with {"success": true, "signals": [ … ]}.
Accepted is not the same as traded
A subscription can still skip the trade, for example outside a trading window or when the side isn't allowed. The reason is shown on the signal's page.
Refused
{
"success": false,
"logId": "9f1c…",
"messageCode": "invalid-action",
"message": "The action field must be one of: buy, sell, exit, reverse, breakeven, cancel, add, resize."
}
A refused signal is not traded at all: fix the alert and send it again.
When the URL matched a strategy, the refused signal is listed in that strategy's Signals (marked invalid) so you can see what was sent. The exceptions are a deactivated account, and repeated wrong-secret requests, of which only some are logged.
Message codes
| messageCode | HTTP | What it means |
|---|---|---|
post-required |
400 | The request wasn't a POST. Webhooks must be sent with the POST method. |
not-found |
404 | No strategy has this webhook URL. Copy the URL again from the strategy page. |
invalid-password |
400 | The secret at the end of the URL is wrong, or was rotated. Copy the current URL. |
account-inactive |
403 | The account that owns this strategy is deactivated, so nothing is traded. |
too-many-requests |
429 | More than 60 requests in a minute or 500 in an hour reached this webhook. |
not-trading-view |
400 | The strategy only accepts TradingView, and the request came from another IP address. |
not-trend-spider |
400 | The strategy only accepts TrendSpider, and the request came from another IP address. |
invalid-ip-address |
400 | The sender's IP address isn't in the strategy's allowed list. |
empty-json |
400 | The request body (or the batch list) was empty. |
malformed-json |
400 | The body isn't valid JSON: often a trailing comma, curly quotes, or an unfilled placeholder. Also sent for a character that can't be stored, such as \u0000. |
batch-signals-not-enabled |
400 | A JSON list (batch) was sent, but the strategy's Allow batch signals is off. |
too-many-payload-items |
400 | A batch had more than 5 signals. |
empty-ticker-name |
400 | The ticker field is missing or empty. |
invalid-payload |
400 | The ticker is longer than 32 characters. |
invalid-action |
400 | action isn't one of the allowed actions (see Alert message fields). |
invalid-options-ticker-format |
400 | The ticker looks like an option contract but isn't in a format we read. |
invalid-ticker-and-option-type |
400 | The contract in ticker is a call and optionType says put (or the other way round). |
invalid-quantity |
400 | quantity isn't a positive number (0 is allowed only for resize). |
invalid-quantity-type |
400 | quantityType isn't one of the six allowed values. It's case-sensitive. |
quantity-type-requires-quantity |
400 | quantityType was sent without a quantity. |
resize-requires-quantity |
400 | A resize signal needs a quantity of 0 or more. |
invalid-quantity-type-action |
400 | A quantityType was sent with a cancel signal. |
invalid-percent-of-position-action |
400 | percent_of_position works only with buy, sell, reverse and exit. |
invalid-risk-dollar-amount-action |
400 | risk_dollar_amount works only with buy, sell, reverse and add. |
invalid-risk-percent-action |
400 | risk_percent works only with buy, sell, reverse and add. |
invalid-sentiment |
400 | sentiment isn't bullish/long, bearish/short or flat. |
invalid-sentiment-action |
400 | sentiment can only be sent with buy, sell or resize. |
invalid-breakeven-order-type |
400 | A breakeven signal needs orderType stop or stop_limit. |
invalid-cancel-order-type |
400 | cancelOrderType isn't one of market, limit, stop, stop_limit, trailing_stop. |
invalid-message-length |
400 | message is longer than 255 characters. |
invalid-message-tags |
400 | message contains HTML tags. |
invalid-bid-ask-spread-filter-amount-and-percent |
400 | Both bidAskSpreadFilter and bidAskSpreadFilterPercent were sent. Send one. |
invalid-bid-ask-spread-filter-amount |
400 | bidAskSpreadFilter isn't a positive number. |
invalid-bid-ask-spread-filter-percent |
400 | bidAskSpreadFilterPercent isn't between 0.01 and 99.99. |
invalid-take-profit-value-required |
400 | takeProfit isn't an object, or has none of percent, amount, limitPrice or pnlAmount. |
invalid-stop-loss-value-required |
400 | stopLoss isn't an object, or has none of percent, amount, stopPrice or pnlAmount. |
invalid-stop-loss-type |
400 | stopLoss.type isn't stop, stop_limit or trailing_stop. |
invalid-stop-loss-stop-price-required |
400 | stopLoss.limitPrice was sent without stopLoss.stopPrice. |
invalid-stop-loss-pnl-trailing |
400 | stopLoss.pnlAmount can't be used with a trailing stop. |
invalid-stop-loss-trail-value |
400 | Both stopLoss.trailAmount and stopLoss.trailPercent were sent. Send one. |
invalid-stop-loss-trail-value-required |
400 | A trailing stop loss needs stopLoss.trailAmount or stopLoss.trailPercent. |
invalid-delay-format |
400 | delay isn't seconds (1–86400), a relative time like "+5 minutes", or a time with a timezone. |
invalid-delay-past |
400 | delay points to a time in the past. |
invalid-delay-exceeds-max |
400 | delay is more than 24 hours away. |
invalid-delay-missing-timezone |
400 | delay is a clock time with no timezone, e.g. "5:30 pm" instead of "5:30 pm EST". |
invalid-expires-at |
400 | expiresAt isn't a future date or a relative time like "+1 month". |
unsupported-ticker |
400 | The strategy has an allowed-tickers list and this ticker isn't on it. |
queue-unavailable |
503 | The signal was saved but couldn't be handed off for execution. Nothing traded: send it again. |
no-matching-subscriptions |
200 | Accepted, but the strategy is off or has no enabled subscription, so nothing will trade. |
Take profit and stop loss codes
All of these are HTTP 400.
| messageCode | What it means |
|---|---|
invalid-take-profit-<field> |
That takeProfit number isn't positive. <field> is one of: amount, percent, limit-price, pnl-amount. |
invalid-stop-loss-<field> |
That stopLoss number isn't positive. <field> is one of: amount, percent, limit-price, pnl-amount, stop-price, trail-amount, trail-percent, trail-price. |
invalid-take-profit-amount-and-percent / invalid-stop-loss-amount-and-percent |
Both amount and percent were sent. Send one. |
invalid-take-profit-relative-and-absolute / invalid-stop-loss-relative-and-absolute |
A relative value (amount or percent) and an absolute price were both sent. Send one. |
invalid-take-profit-pnl-incompatible / invalid-stop-loss-pnl-incompatible |
pnlAmount was combined with another value. Send pnlAmount alone. |
| ## When to send a signal again |
Only 503 queue-unavailable means "send it again": the signal was saved but nothing traded. Many alert senders retry a failed delivery on their own.
Don't resend after a 200
Don't resend a signal that got 200, even if the trade was later skipped. Sending it again can trade twice.
↑ ↓ to move · Enter to open · Esc to close