API reference

Pattern history

GET/tickers/{symbol}/historyKey required

The last occurrences on a ticker, newest first

Returns the last occurrences of patterns on one ticker with what happened next, newest entry first: entry, stop, target, exit, realized move, R multiple and hold time. This is the receipt behind the ticker track record, not the full ledger: at most 5 rows. outcome narrows the rows to resolved (win or loss) or open trades; total says how many matched before the limit. Per-ticker samples are small, so quote the count beside any rate. The ticker does not need to be tracked.

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

NameInTypeRequiredDescription
symbolpathstringyesExchange symbol, upper case (BRK.B, not BRK-B). Lower case is accepted and upper-cased.
limitqueryintegernoMaximum number of rows to return, 1 to 5 (default 5). History on a ticker is its last occurrences, not the full ledger. Values outside the range are clamped; a non-integer answers 400 bad_request. total says how many rows matched before the limit.
outcomequerystring (enum)noWhich rows to include: all, resolved (win or loss only) or open (still running). Case-insensitive; any other value answers 400 bad_request. One of all, resolved, open.
X-TradingPal-ClientheaderstringnoOptional 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/history?limit=5&outcome=resolved" \
  -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).

FieldTypeDescription
symbolstringThe symbol asked for, upper-cased.
availablebooleanTrue when a current-schema pattern history is stored for the symbol. False when none is; occurrences is then empty and total is 0.
occurrencesarray of History rowThe rows, newest entry first, after the outcome filter and the limit.
countintegerNumber of rows in occurrences.
totalintegerNumber of rows matching the outcome filter before the limit was applied.

Example response

Response
{
  "api_version": "v1",
  "symbol": "NVDA",
  "available": true,
  "occurrences": [
    {
      "setup_id": "NVDA:D:falling_wedge:500",
      "lineage_id": "l500",
      "family": "falling_wedge",
      "family_label": "Falling wedge",
      "pattern_type": "falling_wedge",
      "direction": "bullish",
      "outcome": "win",
      "entry_date": "2026-05-04",
      "entry_price": 100,
      "stop_price": 95,
      "target_price": 108,
      "exit_date": "2026-05-20",
      "exit_price": 108,
      "realized_move_pct": 8,
      "target_move_pct": 8,
      "r_multiple": 1.6,
      "unrealized_r": null,
      "hold_bars": 12,
      "attempt": {
        "number": 1,
        "count": 1
      }
    }
  ],
  "count": 1,
  "total": 1
}

Errors

Errors are JSON with the Error shape; the fix field says what to do.

StatusCodeMeaningFix
401missing_api_keyThe 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.
401invalid_api_keyThe key is not one we know, or it has been revoked.Create a new key on the API Keys page and replace it wherever the old one was stored.
403forbiddenThe account behind the key is not on Premium+. API and MCP access requires Premium+ subscription at $30/month; Premium alone does not unlock the API.Get Premium+ ($30/month, all of the benefits in Premium plus API and MCP access) from the Quickstart, where a first subscription starts with 14 days free, or switch an existing Premium subscription to it there, then retry with the same key.
429rate_limitedThe 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.
400bad_requestA query parameter is malformed: limit or offset is not an integer, outcome is not all, resolved or open, a scan filter (family, direction, status, max_distance_pct) is not one of its allowed values, or filters is not a valid predicate list (the message names the predicate).The message names the parameter. Correct it and retry.