> ## Documentation index
> Fetch the complete documentation index at: https://api-docs.scanr.ai/llms.txt
> Use it to discover every page before exploring further.

# Building Scan Payloads

This page builds scan payloads one filter category at a time. Every example is a complete request body for `POST /api/v2/scan` and runs as-is. Read [How Scanning Works](https://api-docs.scanr.ai/scanning.md) first for the model: universe, groups, filters and timeframes.

> **You rarely start here:** Most payloads begin as a sentence sent to [`/scan/natural`](https://api-docs.scanr.ai/natural-language-scans.md), or as **Export filters** from the [scanr.ai scanner](https://scanr.ai/scan) (see [Get a payload](https://api-docs.scanr.ai/scanning.md#get-a-payload)). Use this page to read what those produce, check it, and make small edits by hand. An exported or generated payload is the object inside `instructions` in the examples below.

All examples use the same universe (common stocks, ordinary shares and ADRs on the major U.S. exchanges) and sort largest-first, so only the filters change between them.

## The skeleton

```json
{
  "instructions": {
    "Universe": {
      "Exchange": ["nasdaq", "nyse", "amex", "arca", "bats", "bx"],
      "Type": ["cs", "os", "adrc"]
    },
    "All": [
      {
        "Stock": {
          "PrevDayClose": [
            { "State": { "Value": { "Lower": { "Operator": "gte", "Value": 5 } } } }
          ]
        }
      }
    ],
    "Sort": { "field": "market_cap", "direction": "desc" }
  }
}
```

Three rules hold everywhere:

- A category (`Stock`, `Technical`, …) maps a **filter name** to a **list of rows**. Two rows under one name are two separate conditions, and both must hold in an `All` group.
- Send numbers as plain JSON numbers.
- The catalog (`GET /api/v2/scan/instructions`) echoes descriptive fields such as `DisplayName`, `Description`, `Type` and `InstructionType`. Leave them out of your payload; the one exception is `DisplayName` on chart patterns ([below](#chart-patterns)).

## Stock filters

`Stock` filters screen on quote and profile data: `PrevDayClose`, `PrevDayVolume`, `TodaysVolume`, `Last`, `Change`, `ChangePercent`, `Gap`, `MarketCap`, `SharesFloat`, `SharesOutstanding`, `Week52High`, `Week52Low`, `Sector`, `Industry`, `Earnings` and more.

**Numeric ranges** take a `Lower` bound (`gt` or `gte`), an `Upper` bound (`lt` or `lte`), or both. Market cap is in dollars:

```json
{
  "instructions": {
    "Universe": {
      "Exchange": ["nasdaq", "nyse", "amex", "arca", "bats", "bx"],
      "Type": ["cs", "os", "adrc"]
    },
    "All": [
      {
        "Stock": {
          "MarketCap": [
            {
              "State": {
                "Value": {
                  "Lower": { "Operator": "gte", "Value": 300000000 },
                  "Upper": { "Operator": "lt", "Value": 2000000000 }
                }
              }
            }
          ],
          "PrevDayVolume": [
            { "State": { "Value": { "Lower": { "Operator": "gte", "Value": 500000 } } } }
          ]
        }
      }
    ],
    "Sort": { "field": "market_cap", "direction": "desc" }
  }
}
```

**Price comparisons** compare a level with the current price. `Week52High` with `EqualTo` and a `WithinPercent` tolerance finds stocks trading within 15% of their 52-week high:

```json
{
  "instructions": {
    "Universe": {
      "Exchange": ["nasdaq", "nyse", "amex", "arca", "bats", "bx"],
      "Type": ["cs", "os", "adrc"]
    },
    "All": [
      {
        "Stock": {
          "Week52High": [
            { "State": { "Price": { "Comparison": { "EqualTo": true }, "WithinPercent": 15 } } }
          ]
        }
      }
    ],
    "Sort": { "field": "market_cap", "direction": "desc" }
  }
}
```

**Sector and industry** take a list of names. The allowed names are in the catalog (`Stock.Sector[0].State.Options`) and at `GET /api/v2/stocks/sectors` and `GET /api/v2/stocks/industries`:

```json
{
  "instructions": {
    "Universe": {
      "Exchange": ["nasdaq", "nyse", "amex", "arca", "bats", "bx"],
      "Type": ["cs", "os", "adrc"]
    },
    "All": [
      {
        "Stock": {
          "Sector": [{ "State": { "Value": ["Healthcare"] } }],
          "MarketCap": [
            { "State": { "Value": { "Lower": { "Operator": "gte", "Value": 1000000000 } } } }
          ]
        }
      }
    ],
    "Sort": { "field": "market_cap", "direction": "desc" }
  }
}
```

## Technical studies

`Technical` holds 100+ studies: moving averages (`SMA`, `EMA`, `WMA`, `KAMA`, …), momentum (`RSI`, `MACD`, `STOCH`, `ADX`, `CCI`, `MFI`, …), volatility (`ATR`, `NATR`, `BBANDS`), volume (`OBV`, `AD`, `RELVOL_STDDEV`) and statistics (`LINEARREG_SLOPE`, `CORREL`, `STDDEV`). Each row has:

| Field | Meaning |
| --- | --- |
| `Timeframe` | **Required.** `1d`, `1wk`, `15m`, … (see [Timeframes](https://api-docs.scanr.ai/scanning.md#timeframes)). |
| `Inputs` | The series the study runs on, such as `["bar_close"]` or `["bar_high", "bar_low", "bar_close"]`. Use the study's default from the catalog unless you mean otherwise. |
| `Params` | The study's parameters, each as `{ "Value": n }`: `{ "Period": { "Value": 50 } }`. Omitted parameters use their defaults. |
| `Returns.Want` | The condition. Its key is the study's **output plot name**, and its value says what to compare the output with. |
| `Within` | Optional. The condition may hold on any of the last *N* bars instead of only the latest. |
| `BarsAgo` | Optional. Evaluate the condition *N* bars back instead of on the latest bar. |

### Plot names

The key inside `Want` is an output name from the catalog's `Returns.Plot`. For most studies it is the study's own name, but not always:

| Study | Plot names |
| --- | --- |
| `SMA`, `EMA`, `RSI`, `ATR`, `ADX` | Same as the study: `SMA`, `EMA`, `RSI`, `ATR`, `ADX` |
| `MACD` | `MACD`, `Signal`, `MACDHist` |
| `BBANDS` | `Upper`, `Middle`, `Lower` |
| `STOCH` | `SlowK`, `SlowD` |
| `RELVOL_STDDEV` | `VALUE` |

### Compare with a number

RSI(14) below 30 on the daily chart:

```json
{
  "instructions": {
    "Universe": {
      "Exchange": ["nasdaq", "nyse", "amex", "arca", "bats", "bx"],
      "Type": ["cs", "os", "adrc"]
    },
    "All": [
      {
        "Technical": {
          "RSI": [
            {
              "Timeframe": "1d",
              "Inputs": ["bar_close"],
              "Params": { "Period": { "Value": 14 } },
              "Returns": { "Want": { "RSI": { "Value": { "LessThan": 30 } } } }
            }
          ]
        }
      }
    ],
    "Sort": { "field": "market_cap", "direction": "desc" }
  }
}
```

The comparators are `GreaterThan`, `GreaterThanOrEqual`, `LessThan`, `LessThanOrEqual`, `EqualTo` and `NotEqualTo`.

### Compare with the price

`Price` compares the study with the current price, and reads *study* `<comparator>` *price*. "Price above its 200-day SMA" is therefore `SMA` `LessThan` price:

```json
{
  "instructions": {
    "Universe": {
      "Exchange": ["nasdaq", "nyse", "amex", "arca", "bats", "bx"],
      "Type": ["cs", "os", "adrc"]
    },
    "All": [
      {
        "Technical": {
          "SMA": [
            {
              "Timeframe": "1d",
              "Inputs": ["bar_close"],
              "Params": { "Period": { "Value": 200 } },
              "Returns": { "Want": { "SMA": { "Price": { "Comparison": { "LessThan": true } } } } }
            }
          ]
        }
      }
    ],
    "Sort": { "field": "market_cap", "direction": "desc" }
  }
}
```

### Compare with another study

`Study` compares one study's output with another's. The inner study marks the output it contributes with `"PlotChild": true`. Add `CrossesAbove` or `CrossesUnder` to ask for a cross rather than a state, and `Within` to say how recent.

A golden cross, the 50-day SMA crossing above the 200-day SMA in the last 5 sessions:

```json
{
  "instructions": {
    "Universe": {
      "Exchange": ["nasdaq", "nyse", "amex", "arca", "bats", "bx"],
      "Type": ["cs", "os", "adrc"]
    },
    "All": [
      {
        "Technical": {
          "SMA": [
            {
              "Timeframe": "1d",
              "Inputs": ["bar_close"],
              "Params": { "Period": { "Value": 50 } },
              "Within": 5,
              "Returns": {
                "Want": {
                  "SMA": {
                    "Study": {
                      "CrossesAbove": {
                        "SMA": [
                          {
                            "Timeframe": "1d",
                            "Inputs": ["bar_close"],
                            "Params": { "Period": { "Value": 200 } },
                            "Returns": { "Want": { "SMA": { "PlotChild": true } } }
                          }
                        ]
                      }
                    }
                  }
                }
              }
            }
          ]
        }
      }
    ],
    "Sort": { "field": "market_cap", "direction": "desc" }
  }
}
```

For "the 50-day is above the 200-day" (a state, not a cross), use `GreaterThan` and drop `Within`.

### Volume and liquidity

`RELVOL_STDDEV` measures today's volume in standard deviations from its recent average; its plot name is `VALUE`. Pair it with an `SMA` of `bar_dollar_volume` to skip illiquid names. This is scanr.ai's Unusual Volume screen:

```json
{
  "instructions": {
    "Universe": {
      "Exchange": ["nasdaq", "nyse", "amex", "arca", "bats", "bx"],
      "Type": ["cs", "os", "adrc"]
    },
    "All": [
      {
        "Technical": {
          "RELVOL_STDDEV": [
            {
              "Timeframe": "1d",
              "Inputs": ["bar_volume"],
              "Params": { "Length": { "Value": 60 } },
              "Returns": { "Want": { "VALUE": { "Value": { "GreaterThan": 3 } } } }
            }
          ],
          "SMA": [
            {
              "Timeframe": "1d",
              "Inputs": ["bar_dollar_volume"],
              "Params": { "Period": { "Value": 50 } },
              "Returns": { "Want": { "SMA": { "Value": { "GreaterThan": 10000000 } } } }
            }
          ]
        }
      }
    ],
    "Sort": { "field": "market_cap", "direction": "desc" }
  }
}
```

The input series a study can read (`bar_close`, `bar_volume`, `bar_dollar_volume`, and more) are listed under `Reference.ValidStudyInputs` in the catalog.

## Indicator filters

`Indicator` filters read scanr.ai's pre-computed scores for each stock:

| Filter | Range | Meaning |
| --- | --- | --- |
| `RelativeStrengthMkt` | 1–99 | Percentile of trailing performance against the whole market. 99 is the strongest. |
| `RelativeStrengthSector` | 1–99 | The same, against the stock's sector. |
| `RelativeStrengthIndustry` | 1–99 | The same, against the stock's industry. |
| `TrendEfficiency` | 0–100 | How cleanly the stock is trending rather than chopping. |
| `RegimeExtension` | −100–100 | How far price is stretched from its adaptive mean, in ATR units ×10. |
| `RegimeDivergence`, `RegimeDivergencePct` | −200–200, 1–99 | Extension relative to the stock's peer group, raw and ranked. |
| `GroupStrength` | −100–100 | The extension of the stock's sector or thematic ETF. Positive means the group itself is strong. |
| `MarketStrength`, `MarketEfficiency` | −100–100, 0–100 | The same readings for the broad market; identical for every stock. |
| `PETTM` | 0 and up | Trailing P/E. Loss-making companies have none and never match. |

Each row compares the score's `Value`. Leaders in strong groups (RS 80+ and a positive group):

```json
{
  "instructions": {
    "Universe": {
      "Exchange": ["nasdaq", "nyse", "amex", "arca", "bats", "bx"],
      "Type": ["cs", "os", "adrc"]
    },
    "All": [
      {
        "Indicator": {
          "RelativeStrengthMkt": [
            { "Returns": { "Want": { "Value": { "GreaterThanOrEqual": 80 } } } }
          ],
          "GroupStrength": [
            { "Returns": { "Want": { "Value": { "GreaterThanOrEqual": 10 } } } }
          ]
        }
      }
    ],
    "Sort": { "field": "market_cap", "direction": "desc" }
  }
}
```

## Fundamental filters

`Fundamental` filters read 300+ metrics from company filings: growth rates (`Epsgrowth`, `Revenuegrowth`, `Revenueqoqgrowth`), per-share figures (`Dilutedeps`), income, balance-sheet and cash-flow lines, and valuation ratios. Each row's `State` says which filing to read and what to compare:

| Field | Meaning |
| --- | --- |
| `FilingType` | `10q` (quarterly) or `10k` (annual). |
| `Within` | How many recent filings to consider. |
| `Lag` | How many filings back to start: `0` is the latest, `4` is the same quarter a year earlier. |
| `WantsValue` | Compare with a number: `SingleValue` with one comparator set to `true` and a `Value`, or `RangeValue` with `Lower` and `Upper`. |
| `WantsOtherFundamental` | Compare with another fundamental row, under `Comp`. |

Growth rates are fractions: `0.25` means 25%. Annual EPS growth of at least 25%, with the latest quarter's diluted EPS above the same quarter last year:

```json
{
  "instructions": {
    "Universe": {
      "Exchange": ["nasdaq", "nyse", "amex", "arca", "bats", "bx"],
      "Type": ["cs", "os", "adrc"]
    },
    "All": [
      {
        "Fundamental": {
          "Epsgrowth": [
            {
              "State": {
                "FilingType": "10k",
                "WantsValue": { "SingleValue": { "GreaterThanOrEqual": true, "Value": 0.25 } }
              }
            }
          ],
          "Dilutedeps": [
            {
              "State": {
                "FilingType": "10q",
                "Within": 1,
                "Lag": 0,
                "WantsOtherFundamental": {
                  "GreaterThan": true,
                  "Comp": {
                    "Dilutedeps": [
                      { "State": { "FilingType": "10q", "Within": 1, "Lag": 4 } }
                    ]
                  }
                }
              }
            }
          ]
        }
      }
    ],
    "Sort": { "field": "market_cap", "direction": "desc" }
  }
}
```

The metric names are the keys of the catalog's `Fundamental` section.

## Candlestick patterns

`CandlestickPattern` holds 60+ patterns named after their TA-Lib functions (`CDLHAMMER`, `CDLMORNINGSTAR`, `CDLENGULFING`, `CDL3WHITESOLDIERS`, …). Each row sets a `Timeframe`, the `Inputs` the pattern reads, and `Within` for how many recent bars may contain it. A hammer in the last 3 sessions, with RSI still below 40:

```json
{
  "instructions": {
    "Universe": {
      "Exchange": ["nasdaq", "nyse", "amex", "arca", "bats", "bx"],
      "Type": ["cs", "os", "adrc"]
    },
    "All": [
      {
        "CandlestickPattern": {
          "CDLHAMMER": [
            {
              "Timeframe": "1d",
              "Inputs": ["bar_open", "bar_high", "bar_low", "bar_close"],
              "Within": 3
            }
          ]
        },
        "Technical": {
          "RSI": [
            {
              "Timeframe": "1d",
              "Inputs": ["bar_close"],
              "Params": { "Period": { "Value": 14 } },
              "Returns": { "Want": { "RSI": { "Value": { "LessThan": 40 } } } }
            }
          ]
        }
      }
    ],
    "Sort": { "field": "market_cap", "direction": "desc" }
  }
}
```

> **Two-sided patterns:** Some patterns (`CDLENGULFING`, `CDLHARAMI`) fire in both directions. Set `Direction` on the row to keep one side: `"bullish"`, `"bearish"`, or `"any"` (the default). A bullish engulfing in the last 5 sessions is `"CDLENGULFING": [{ "Timeframe": "1d", "Inputs": ["bar_open", "bar_high", "bar_low", "bar_close"], "Within": 5, "Direction": "bullish" }]`.
>
> `SupportedDirections` on each pattern in `GET /api/v2/scan/instructions` lists the sides it can fire. A side a pattern never fires, such as `"bearish"` on `CDLHAMMER`, is rejected. `Sentiment` is a descriptive label and does not filter.

## Chart patterns

`ChartPattern` finds 17 detected formations: `CupAndHandle`, `BullFlag`, `BearFlag`, `AscendingTriangle`, `DescendingTriangle`, `SymmetricalTriangle`, `DoubleBottom`, `DoubleTop`, `HeadAndShoulders`, `InverseHeadAndShoulders`, `RisingWedge`, `FallingWedge`, `ChannelUp`, `ChannelDown`, `HorizontalChannel`, `MultipleTop` and `MultipleBottom`. Each row carries the pattern's `DisplayName` from the catalog (it identifies the pattern and must be kept), its direction, a `Timeframe` (`5m`, `1hr` or `1d`) and how far back to look:

```json
{
  "instructions": {
    "Universe": {
      "Exchange": ["nasdaq", "nyse", "amex", "arca", "bats", "bx"],
      "Type": ["cs", "os", "adrc"]
    },
    "All": [
      {
        "ChartPattern": {
          "CupAndHandle": [
            {
              "DisplayName": "Cup and Handle",
              "BullishBearish": "BULLISH",
              "Timeframe": "1d",
              "LookbackBars": 100
            }
          ]
        }
      }
    ],
    "Sort": { "field": "market_cap", "direction": "desc" }
  }
}
```

Copy each pattern's row from the catalog's `ChartPattern` section and change only `Timeframe` and `LookbackBars`.

## Excluding stocks

An `Exclude` group removes its matches from the result. Large caps above their 50-day average, except financials:

```json
{
  "instructions": {
    "Universe": {
      "Exchange": ["nasdaq", "nyse", "amex", "arca", "bats", "bx"],
      "Type": ["cs", "os", "adrc"]
    },
    "All": [
      {
        "Stock": {
          "MarketCap": [
            { "State": { "Value": { "Lower": { "Operator": "gte", "Value": 10000000000 } } } }
          ]
        },
        "Technical": {
          "SMA": [
            {
              "Timeframe": "1d",
              "Inputs": ["bar_close"],
              "Params": { "Period": { "Value": 50 } },
              "Returns": { "Want": { "SMA": { "Price": { "Comparison": { "LessThan": true } } } } }
            }
          ]
        }
      }
    ],
    "Exclude": [
      {
        "Stock": {
          "Sector": [{ "State": { "Value": ["Financial", "Finance, Insurance, And Real Estate"] } }]
        }
      }
    ],
    "Sort": { "field": "market_cap", "direction": "desc" }
  }
}
```

## Universe restrictions

Countries and themes narrow the universe before any filter runs. U.S. and Canadian companies in the `silver-miners` theme with RS above 70 (get real theme keys from `GET /api/v2/scan/universe-themes`):

```json
{
  "instructions": {
    "Universe": {
      "Exchange": ["nasdaq", "nyse", "amex", "arca", "bats", "bx"],
      "Type": ["cs", "os", "adrc"],
      "Country": ["us", "ca"],
      "Theme": ["silver-miners"],
      "ThemeMaxTier": 2
    },
    "All": [
      {
        "Indicator": {
          "RelativeStrengthMkt": [
            { "Returns": { "Want": { "Value": { "GreaterThanOrEqual": 70 } } } }
          ]
        }
      }
    ],
    "Sort": { "field": "market_cap", "direction": "desc" }
  }
}
```

An unknown theme key matches nothing rather than failing, so check keys against the theme list.

## Sorting

`Sort.field` is one of `market_cap`, `shares_out`, `shares_float` or `ticker`; `Sort.direction` is `asc` or `desc`. Without a `Sort`, the order is unspecified.

## Common mistakes

| Symptom | Cause |
| --- | --- |
| `400 … Timeframe is required for technical study` | Every `Technical` row needs a `Timeframe`. |
| `400 … Invalid option` on `Timeframe` | Use the exact values: `1wk`, not `1w`; `1hr`, not `1h`. |
| `400` on `Country` | Country codes are lower-case: `us`, not `US`. |
| A study filter matches nothing | The `Want` key isn't the study's plot name (`VALUE` for `RELVOL_STDDEV`, `SlowK` for `STOCH`). |
| ETFs or OTC names in the result | `Universe.Type` or `Universe.Exchange` was left empty. |
| Fewer matches than expected with `All` + `Any` | They don't intersect; results are unioned. Put everything in one `All` group. |

## Next

- [Natural-Language Scans](https://api-docs.scanr.ai/natural-language-scans.md): Have the API write the payload from a sentence.
- [Run an End-of-Day Screen](https://api-docs.scanr.ai/guides/end-of-day-screen.md): Run a payload every day and export the matches.
- [Find Relative-Strength Leaders](https://api-docs.scanr.ai/guides/relative-strength-leaders.md): RS-driven screens, step by step.
- [API Reference](https://api-docs.scanr.ai/api): The full `ScannerPayload` schema.
