DFin API Reference - Stock Screener and SEC Filing Search API

DFin API v1

Search filings and run the DFin equity screener through stable JSON endpoints. Runtime endpoint paths, request constraints, rate limits, and key choices are rendered from the same code that serves the API.

1.0 Overview

Base URLhttps://www.dfin.pro
API versionv1
Runtime base path/api/v1/
Docs alternateMarkdown / LLM version
Postman collectionDownload collection

2.0 Global Rules

2.1 Authentication

Send the API key in the HTTP authorization header.

$env:DFIN_API_KEY = "paste-your-api-key-here"

2.2 Request Format

POST endpoints accept JSON request bodies with Content-Type: application/json. GET endpoints do not require a JSON body.

2.3 Rate Limits

WindowStarter tier limitNotes
Per minute30 requests per minuteAuthenticated requests that later fail validation can still count.
Rolling 24 hours1,000 requests per rolling 24 hoursMissing or invalid API keys fail before throttling.

2.4 Screener Controls

Screener POST endpoints share pagination, sorting, field selection, and result_format behavior. Pagination defaults to {"limit":100,"offset":0}, page.limit must be between 1 and 1000, and result_format can be rows, tickers.

2.5 Common Errors

StatusMeaningTypical fix
400Request validation failed.Check parameter names, types, allowed values, and screener mode.
401Missing, malformed, inactive, or invalid API key.Set DFIN_API_KEY and use the generated Authorization header shown in the examples.
429Rate limit exceeded.Back off and retry after the throttle window resets.
502Filing search backend did not return a usable result.Retry later or narrow the search request.

3.0 Endpoint Summary

AreaMethodPathPurpose
Filing Search POST /api/v1/filings/search/ Search structured company filings.
Screener GET /api/v1/screener/options/ Return compact request-building metadata for the current screener API contract.
Screener POST /api/v1/screener/basic/ Run the simple screener filter set.
Screener POST /api/v1/screener/advanced/ Run the advanced screener contract.

5.0 Screener

The screener endpoints expose the DFin equity screener through a contract-driven API. Use the options endpoint as the source of truth for current public filter, sort, field, shared-default, and accepted option metadata.

For step-by-step walkthroughs, start with the API v1 examples library, including the starter-screen screener API examples and the advanced growth filter examples.

5.1 Get screener options

Return compact request-building metadata for the current screener API contract.

The options response is compact for API and AI clients: modes.basic and modes.advanced list allowed filter keys directly, sort.fields lists sortable field names for the existing sort.field request property, and filter_type_defaults carries shared operators and rule limits. Growth-rule currency bases are derived from each metric's value_fields[value_type] keys.

curl -X GET "https://www.dfin.pro/api/v1/screener/options/" \
  -H "Authorization: Bearer ${DFIN_API_KEY}"

Example response

{
  "result_formats": [
    "rows",
    "tickers"
  ],
  "page": {
    "default_limit": 100,
    "default_offset": 0,
    "max_limit": 1000
  },
  "sort": {
    "fields": [
      "marketCap_usd",
      "return_1y"
    ]
  },
  "modes": {
    "basic": [
      "country",
      "sector",
      "marketCap_usd",
      "..."
    ],
    "advanced": [
      "country",
      "incomeStatementGrowth",
      "marketCap_usd",
      "..."
    ]
  },
  "filter_type_defaults": {
    "range": {
      "operators": [
        "min",
        "max"
      ]
    },
    "growth_rule_group": {
      "horizons": [
        1,
        2,
        3,
        5,
        7,
        8,
        10
      ],
      "value_types": [
        "cagr",
        "multiple"
      ],
      "value_type_formats": {
        "cagr": "percent",
        "multiple": "number"
      },
      "missing_data_policy": "exclude",
      "max_rules": 5
    }
  },
  "filters": {
    "country": {
      "label": "Country",
      "input_type": "multi_select",
      "operators": [
        "include",
        "exclude"
      ],
      "default_operator": "include",
      "options_source": "countries"
    }
  },
  "option_values": {
    "countries": [
      "Canada",
      "United States"
    ]
  },
  "fields": [
    "companyName",
    "full_ticker",
    "marketCap_usd"
  ]
}

5.2 Request envelope

Both screener POST endpoints accept the same top-level envelope. The difference is which filter keys are allowed.

5.2.1 Fields

ParameterTypeRequiredDefaultNotes
filters object No {} Filter payload keyed by screener filter name.
sort object No {} Supports the screener sort object, including field and descending direction.
page object No {} Supports limit and offset. The public maximum limit is code-defined. Maximum limit is 1000.
fields array of string No - item max length 120 Requested output fields for rows responses.
result_format string No "rows" choices: rows, tickers Rows returns row objects. Tickers returns a flat ticker list and ignores custom fields.

5.2.2 Building screener requests

The options endpoint is the contract an agent should inspect before composing a screen. It tells you which filters exist, which endpoint can accept each filter, which values can be submitted, which output fields can be requested, and which sort keys are valid.

StepWhat to do
Fetch options Call GET /api/v1/screener/options/ first. Treat that response as the current source of valid filters, modes, option values, sort fields, output fields, and shared defaults.
Choose endpoint Use POST /api/v1/screener/basic/ only when every selected filter is listed in options.modes.basic. Use POST /api/v1/screener/advanced/ when any selected filter is advanced-only.
Build filters For each selected filter, inspect options.filters[filterName].input_type and use the matching payload grammar. When a definition omits common operators or limits, inherit them from options.filter_type_defaults[input_type].
Select output For rows responses, choose field names from options.fields. For compact ticker-only output, set result_format to tickers and omit custom fields.
Sort and page Choose sort.field from options.sort.fields, submit sort as an object with field and desc, and keep page.limit between 1 and the documented maximum.

5.2.3 Filter payload grammar

Each entry in filters is keyed by a filter name from options.filters. Use that filter's input_type to choose the payload shape. When a filter definition omits common operators or limits, inherit them from options.filter_type_defaults[input_type]; values shown directly on the filter definition are more specific and take precedence.

Input typePayload shapeNotesExample
range {"filterName":{"min":number,"max":number}} Use min, max, or both to set numeric thresholds. The available range keys come from filter_type_defaults.range. {"marketCap_usd":{"min":10000000000}}
multi_select {"filterName":{"operator":"include","values":["accepted option"]}} Use values from option_values or from an inline options list. If the user does not ask to exclude values, use the filter default_operator. {"country":{"operator":"include","values":["United States"]}}
text {"description_keywords":{"fts":"search terms"}} Use this for full-text searches against company business descriptions. {"description_keywords":{"fts":"cloud software"}}
metric_rule_group {"filterName":{"missing_policy":"strict","rules":[...]}} Use range rules for thresholds and compare rules when the screen needs TTM, a fiscal year, or a trailing fiscal-year average. {"returnOnInvestedCapital":{"rules":[{"kind":"range","operand":{"kind":"average","years":3,"anchor":{"scope":"fy","offset":0}},"min":0.15}]}}
growth_rule_group {"filterName":{"rules":[{"metric":"revenue","horizon_years":5,"value_type":"cagr","currency_basis":"reported","min":0.10}]}} Choose the metric, horizon, value type, currency basis, and threshold. Valid currency bases come from metric.value_fields[value_type]. {"incomeStatementGrowth":{"rules":[{"metric":"revenue","horizon_years":5,"value_type":"cagr","currency_basis":"reported","min":0.10}]}}
volatility_rule_group {"volatility":{"rules":[{"kind":"range","field":"daily_return_vol_1y_annualized","max":0.40}]}} Use member fields from filters.volatility.members. Range rules test one member; compare rules compare two members. {"volatility":{"rules":[{"kind":"compare","left_field":"daily_return_vol_1y_annualized","operator":"lt","right_field":"daily_return_vol_5y_annualized"}]}}
field_compare {"volatility_compare":{"left_field":"field","operator":"lt","right_field":"field"}} Legacy/simple field comparison form for volatility fields. The canonical volatility rule group is preferred for new advanced requests. {"volatility_compare":{"left_field":"daily_return_vol_1y_annualized","operator":"lt","right_field":"daily_return_vol_5y_annualized"}}

5.2.4 Using option values

For filters with options_source, submit values from the matching list in options.option_values. These are accepted request values, not browser display labels. For filters with inline options, submit one of those listed values. For growth metrics, derive valid currency_basis values from the keys under metric.value_fields[value_type]; for example, if a metric has value_fields.cagr.reported and value_fields.cagr.usd, both reported and usd are valid for CAGR.

5.2.5 Units and thresholds

TopicRule
Percentages and ratios Use decimal values: 0.10 means 10%, 0.5 means 50%, and 1.0 means 100%.
USD amounts Fields ending in _usd, such as marketCap_usd, use raw U.S. dollars, not millions or billions.
CAGR Growth value_type cagr uses decimal annualized rates, so min 0.10 means at least 10% annualized growth.
Growth multiple Growth value_type multiple uses numeric multiples, so min 2.0 means the metric at least doubled over the horizon.
TTM TTM means trailing twelve months and is used by simple shorthand fields such as dividendYieldTTM.
FY offsets In metric-rule operands, FY offset 0 means the latest eligible fiscal year. Larger offsets move backward one fiscal year at a time.

5.2.6 Request snippets

These snippets show only the relevant part of the request body. Put filter examples under the top-level filters object when sending a screener POST request.

CaseWhen to use itJSON
Multi-select filter Country, sector, industry, currency, and database coverage filters use an operator plus accepted values.
{
  "country": {
    "operator": "include",
    "values": [
      "United States"
    ]
  }
}
Range filter Range filters accept min, max, or both.
{
  "marketCap_usd": {
    "min": 10000000000
  }
}
Text filter Business-description search uses the fts key.
{
  "description_keywords": {
    "fts": "cloud software"
  }
}
Metric rule group Historical metric rules can target TTM, one fiscal year, or a trailing fiscal-year average.
{
  "returnOnInvestedCapital": {
    "missing_policy": "strict",
    "rules": [
      {
        "kind": "range",
        "operand": {
          "kind": "average",
          "years": 3,
          "anchor": {
            "scope": "fy",
            "offset": 0
          }
        },
        "min": 0.15
      }
    ]
  }
}
Growth rule group Growth filters combine metric, horizon, value type, currency basis, and min/max thresholds.
{
  "incomeStatementGrowth": {
    "rules": [
      {
        "metric": "revenue",
        "horizon_years": 5,
        "value_type": "cagr",
        "currency_basis": "reported",
        "min": 0.1
      }
    ]
  }
}
Volatility rule group Volatility rules can filter one member field or compare two member fields.
{
  "volatility": {
    "rules": [
      {
        "kind": "range",
        "field": "daily_return_vol_1y_annualized",
        "max": 0.4
      }
    ]
  }
}
Sort and fields Sort with a supported field and request row fields from options.fields.
{
  "sort": {
    "field": "marketCap_usd",
    "desc": true
  },
  "fields": [
    "full_ticker",
    "companyName",
    "marketCap_usd"
  ]
}

5.3 Run a basic screener

The basic endpoint accepts business profile filters, database coverage, market and valuation ranges, returns, volatility ranges, common TTM shorthand ranges, and net income.

curl -X POST "https://www.dfin.pro/api/v1/screener/basic/" \
  -H "Authorization: Bearer ${DFIN_API_KEY}" \
  -H "Content-Type: application/json" \
  -d '{"filters":{"country":{"operator":"include","values":["United States"]},"sector":{"operator":"include","values":["Information Technology"]},"marketCap_usd":{"min":1000000000},"return_1y":{"min":0.1}},"sort":{"field":"marketCap_usd","desc":true},"page":{"limit":100,"offset":0},"fields":["full_ticker","companyName","marketCap_usd"],"result_format":"rows"}'

Example response

{
  "total": 1,
  "limit": 100,
  "offset": 0,
  "loaded_fields": [
    "full_ticker",
    "companyName",
    "marketCap_usd"
  ],
  "temporary_columns": [],
  "rows": [
    {
      "full_ticker": "AAPL.US",
      "companyName": "Apple",
      "marketCap_usd": 3000000000000
    }
  ]
}

5.4 Run an advanced screener

The advanced endpoint accepts every basic filter plus the canonical advanced screener contract, including metric rule groups, growth/CAGR/multiple filters, composite metric member filters, and canonical volatility rule groups.

curl -X POST "https://www.dfin.pro/api/v1/screener/advanced/" \
  -H "Authorization: Bearer ${DFIN_API_KEY}" \
  -H "Content-Type: application/json" \
  -d '{"filters":{"country":{"operator":"include","values":["United States"]},"incomeStatementGrowth":{"rules":[{"metric":"revenue","horizon_years":5,"value_type":"cagr","currency_basis":"reported","min":0.1}]}},"result_format":"tickers","page":{"limit":100,"offset":0}}'

Example response

{
  "total": 2,
  "limit": 100,
  "offset": 0,
  "tickers": [
    "AAPL.US",
    "MSFT.US"
  ]
}

6.0 Confusing Cases

  • Basic vs advanced: basic rejects advanced-only filter keys. Use /api/v1/screener/options/ to inspect modes.basic and modes.advanced.
  • Rows vs tickers: result_format="tickers" returns a flat tickers array and forces the backend to request only full_ticker.
  • Pagination: page.limit defaults to 100 and must be between 1 and 1000.
  • Filter metadata: the current public screener filter, sort, field, and option metadata comes from /api/v1/screener/options/, not from a static docs table.

For a browser reference to the same screener concepts, see the DFin stock screener.

Pic
dbot