API reference
Current setups
/tickers/{symbol}/patternsKey requiredCurrent setups on a tracked ticker
Returns the setups the last nightly run sees on one tracked ticker: family and direction, the two lines as dated endpoints, the trigger rule and price, stop and target, and the family and ticker track records. An empty setups list means nothing is forming; available false means the nightly has no current book for the symbol. The ticker must be tracked (403 ticker_not_tracked otherwise). Setups and their ids change nightly, so do not cache them across sessions.
Authentication
Needs a key: send Authorization: Bearer tp_live_… (see Authentication). Counted against the key's limits of 60 requests a minute and 10,000 a day.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
symbol | path | string | yes | Exchange symbol, upper case (BRK.B, not BRK-B). Lower case is accepted and upper-cased. |
X-TradingPal-Client | header | string | no | Optional name of the agent or script making the call. It is recorded in the account's usage log so the user can see which client made which calls; the User-Agent is recorded when it is absent. |
Request
curl "https://api.tradingpal.io/api/v1/tickers/NVDA/patterns" \
-H "Authorization: Bearer $TRADINGPAL_API_KEY"Response
JSON. The fields this route adds are below; every response also carries the envelope fields (api_version, as_of_session, data_version, source, disclaimer).
| Field | Type | Description |
|---|---|---|
symbol | string | The symbol asked for, upper-cased. |
available | boolean | True when the nightly has a current candidate book for the symbol. False when the symbol is excluded from pattern analysis or no current book exists; setups is then empty. |
reason | string · nullable | Why available is false, when the reason is known: not_covered means the symbol is excluded from pattern analysis. Absent when available is true, and when the nightly simply has no current book for the symbol. |
setups | array of Setup | The current setups, one per eligible candidate. Empty when nothing is forming. |
demo | boolean | True on the demo routes. Absent on the keyed route. |
next | string · nullable | On the demo routes, a sentence saying where to get a key for other tickers. Absent on the keyed route. |
Example response
{
"api_version": "v1",
"as_of_session": "2026-09-25",
"symbol": "NVDA",
"available": true,
"setups": [
{
"setup_id": "NVDA:D:falling_wedge:1",
"lineage_id": "lineage-1",
"symbol": "NVDA",
"interval": "D",
"family": "falling_wedge",
"family_label": "Falling wedge",
"pattern_type": "falling_wedge",
"direction": "bullish",
"status": "forming",
"pattern_start": "2026-08-08",
"pattern_end": "2026-09-07",
"as_of_session": "2026-09-25",
"last_close": 101.5,
"price_scale": "log",
"lines": {
"upper": {
"start": {
"date": "2026-08-08",
"price": 110
},
"end": {
"date": "2026-09-07",
"price": 104
},
"touch_count": 3,
"touches": [
{
"date": "2026-08-08",
"price": 111.2
}
]
},
"lower": {
"start": {
"date": "2026-08-08",
"price": 90
},
"end": {
"date": "2026-09-07",
"price": 98
},
"touch_count": 2,
"touches": []
}
},
"trigger_rule": "A daily close above the upper line; the trigger price moves with the line.",
"plans": [
{
"direction": "bullish",
"trigger_price": 105.25,
"stop_price": 96,
"target_price": 120
}
],
"track_record": {
"family": {
"scope": "family",
"family": "falling_wedge",
"symbol": null,
"win_rate_pct": 54,
"sample_size": 1287,
"wins": 695,
"losses": 592,
"avg_win_pct": 8.1,
"avg_loss_pct": -4.2,
"median_win_pct": 6.3,
"avg_trade_pct": 2.4,
"avg_r": 0.41,
"expected_r": 0.41,
"profit_factor": 1.61,
"avg_hold_bars": 11.2,
"backtest_range": [
"2006-09-25",
"2026-09-25"
],
"measured": "Every detector-confirmed breakout … open trades are excluded.",
"summary": "Falling wedge: 1,287 resolved trades from 2006-09-25 to 2026-09-25; 54% reached the target, average win +8.1%, average loss -4.2%, median win +6.3%."
},
"ticker": null
}
}
]
}Errors
Errors are JSON with the Error shape; the fix field says what to do.
| Status | Code | Meaning | Fix |
|---|---|---|---|
| 401 | missing_api_key | The request had no Authorization: Bearer tp_live_… header and the route needs one. | Send the header on every keyed call. Only the demo, families and universe routes answer without it. |
| 401 | invalid_api_key | The key is not one we know, or it has been revoked. | Create a new key on the Keys page and replace it wherever the old one was stored. |
| 403 | forbidden | The account behind the key is not on a plan with API access. | During the beta, keys work on Premium accounts. Upgrade the account, then retry with the same key. |
| 403 | ticker_not_tracked | The ticker is not on the account’s tracked list, and pattern, history and chart calls work only on tracked tickers. | Add it with PUT /tickers (or the set_tracked_tickers MCP tool), then retry. The fix field says how many slots are free. |
| 429 | rate_limited | The key passed 60 requests in a minute or 10,000 in a day, or a keyless caller passed 30 a minute from one IP. | Wait details.retry_after_seconds, then retry. Cache the nightly answers; they do not change until the next session. |