Filter Expression

When to use it

filterExpression is a recursive boolean tree. Use it when the request needs more than the flat AND-only semantics of the convenience filterobject: for example, "calls or bullish trades", "calls with premium >= $100k or contracts expiring this week", or any composition deeper than a single conjunction.

Two node shapes live in the tree. A terminal node is a single condition: a field, an operation, and one or more values. A compound node groups two or more children under an AND or OR conjunction. The two shapes are mutually exclusive at a single level; mixing terminal and compound fields on the same node is rejected with a validation error.

Terminal filters

A terminal is a leaf in the expression tree: a single field/operation/value condition. Every compound expression eventually grounds out in terminals.

Single terminal
{
  "filterExpression": {
    "field": "TICKER",
    "operation": "EQUALS",
    "values": ["AAPL"]
  }
}
Terminal rules
  • field is required and must resolve to a filterable field for the endpoint you are calling. See Field Reference for the full inventory.
  • operation is required. Accepts canonical names (EQUALS) or shorthand (=, EQ); see Operations below.
  • values (or its alias value) is required and must be non-empty. Multiple values within a single terminal are OR-semantic.
  • The two compound fields (conjunction, filters) must be omitted on a terminal. Mixed shapes are rejected with a validation error.

Compound filters

A compound node combines multiple child filters under a single conjunction. The children list is fully recursive: a compound can contain terminals, other compounds, or any mix.

Flat AND

AND of three terminals
{
  "filterExpression": {
    "conjunction": "AND",
    "filters": [
      { "field": "TICKER", "operation": "=", "value": "AAPL" },
      { "field": "MONEY_TYPE", "operation": "=", "value": "ITM" },
      { "field": "CONTRACT_TYPE", "operation": "=", "value": "CALL" }
    ]
  }
}

Nested AND / OR

AND containing an OR
{
  "filterExpression": {
    "conjunction": "AND",
    "filters": [
      { "field": "TICKER", "operation": "=", "value": "AAPL" },
      {
        "conjunction": "OR",
        "filters": [
          { "field": "SENTIMENT", "operation": "=", "value": "BULLISH" },
          { "field": "TRADE_SIDE", "operation": "=", "value": "AA" }
        ]
      }
    ]
  }
}
Compound rules
  • conjunction is required. Values: AND, OR.
  • filters is required and must contain at least one child. Children can themselves be terminal or compound; the tree is fully recursive.
  • The three terminal fields (field, operation, values) must be omitted on a compound node.
  • Maximum recursion depth is 5. Maximum total terminal filters in the expression is 100.

Operations

Six comparison operations are supported. Each one accepts the canonical UPPER_SNAKE_CASE name plus symbolic and abbreviated aliases.

Operation aliases
  • EQUALS: =, ==, EQ, EQUAL.
  • DOES_NOT_EQUAL: !=, <>, NEQ, NOT_EQUALS, NOT_EQUAL.
  • GREATER_THAN: >, GT, GREATER.
  • GREATER_THAN_OR_EQUAL_TO: >=, GTE, GE, GREATER_OR_EQUAL.
  • LESS_THAN: <, LT, LESS.
  • LESS_THAN_OR_EQUAL_TO: <=, LTE, LE, LESS_OR_EQUAL.

Multi-value terminals

The canonical field name is values, typed as a collection. The singular value is accepted as an alias, and a scalar is coerced to a one-element collection. Multiple values on a single terminal are OR-semantic: the row matches if any of the listed values is a match.

Four shapes, one terminal
// All four are equivalent: a single value resolves to a one-element collection.
{ "field": "TICKER", "operation": "EQUALS", "value": "AAPL" }
{ "field": "TICKER", "operation": "EQUALS", "values": "AAPL" }
{ "field": "TICKER", "operation": "EQUALS", "value": ["AAPL"] }
{ "field": "TICKER", "operation": "EQUALS", "values": ["AAPL"] }

// Multi-value with OR semantics (any of the listed values is a match):
{ "field": "TICKER", "operation": "EQUALS", "values": ["AAPL", "NVDA", "TSLA"] }

Limits

Two structural limits keep the expression tree to a manageable size. Both surface as a validation error when exceeded.

Maximum recursion depth: 5
The root counts as depth 0. A compound containing a compound is depth 2. The validator rejects expressions that exceed depth 5 with a field error pointing at the offending sub-tree.
Maximum total terminals: 100
Across the entire expression, the sum of leaf terminals must be at most 100. If you need more selectivity than this, send multiple requests and combine results client-side.

Combining with filter

The convenience filter object and filterExpression can both be present on the same request. They are AND-ed: every row in the response must satisfy filter and satisfy filterExpression.

Both at once
{
  "filter": {
    "tickers": ["AAPL", "NVDA"]
  },
  "filterExpression": {
    "conjunction": "OR",
    "filters": [
      { "field": "CONTRACT_TYPE", "operation": "=", "value": "CALL" },
      { "field": "SENTIMENT", "operation": "=", "value": "BULLISH" }
    ]
  }
}

// Reads as: (ticker IN [AAPL, NVDA]) AND (calls OR bullish sentiment).

Use filterfor the simple "narrow by ticker / by expiration / by sector" cases: it is shorter to write. Reach for filterExpression when you need OR semantics, nested logic, or a comparison operator other than equality.

Worked example

Putting it together: today's session, three tickers, calls only, premium at or above $100,000, AND (bullish sentiment OR a trade above the ask).

Realistic request
{
  "sessionDate": "2026-05-13",
  "filterExpression": {
    "conjunction": "AND",
    "filters": [
      { "field": "TICKER", "operation": "=", "values": ["AAPL", "MSFT", "NVDA"] },
      { "field": "CONTRACT_TYPE", "operation": "=", "value": "CALL" },
      { "field": "PREMIUM", "operation": ">=", "value": "100000" },
      {
        "conjunction": "OR",
        "filters": [
          { "field": "SENTIMENT", "operation": "=", "value": "BULLISH" },
          { "field": "TRADE_SIDE", "operation": "=", "value": "AA" }
        ]
      }
    ]
  }
}

// Reads as: today's session, AAPL/MSFT/NVDA, calls only, premium >= $100,000,
// AND (bullish sentiment OR traded above ask).

Where to go next