Filings API Reference#
abstract · Cargo Docs
The Filings domain handle fetches SEC filings for a given symbol. It is backed by EDGAR (keyless — no API key required) with an optional Polygon fallback, and is always available with no feature gate.
Getting a Handle#
Create a Filings handle from a Providers instance and call .get() to fetch the filing data:
use finance_query::{Providers, edgar};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// EDGAR is keyless but SEC requires a contact email in the User-Agent.
// Initialise it once per process (or set the EDGAR_EMAIL env var).
edgar::init("you@example.com")?;
let providers = Providers::builder().build().await?;
let filings = providers.filings("AAPL");
let result = filings.get().await?;
for f in result.filings.iter().take(5) {
println!(
"{} {}: {}",
f.filing_date.as_deref().unwrap_or("?"),
f.filing_type.as_deref().unwrap_or("?"),
f.filing_url.as_deref().unwrap_or("-")
);
}
Ok(())
}
- Parsing a company's full submissions index (
edgar::submissions→EdgarSubmissions, roughly a thousand filings) takes **around a millisecond** or less.
note · EDGAR requires a contact email
EDGAR needs no API key, but SEC's fair-access policy requires a contact email
in the request User-Agent. Call edgar::init("you@example.com") once before
fetching, or set the EDGAR_EMAIL environment variable.
The returned ProviderFilings value contains the ticker symbol (symbol) and a list of individual filing entries (filings).
Each entry is a ProviderFiling:
| Field | Type | Description |
|---|---|---|
accession_number | Option<String> | SEC accession number (unique filing ID) |
filing_date | Option<String> | Filing date as YYYY-MM-DD |
filing_type | Option<String> | Filing type (e.g., "10-K", "10-Q", "8-K") |
filing_url | Option<String> | URL to the filing document |
company_name | Option<String> | Company name at time of filing |
cik | Option<String> | SEC CIK number |
Congressional Trades#
Call .congressional_trades() to fetch legislator stock-trade disclosures naming this symbol, filed under the STOCK Act as Periodic Transaction Reports (PTRs):
use finance_query::{Capability, Provider, Providers};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let providers = Providers::builder()
.route(Capability::FILINGS, [Provider::CongressTrades, Provider::Edgar])
.build()
.await?;
let filings = providers.filings("AAPL");
for trade in filings.congressional_trades().await? {
println!(
"{} {}: {} {} on {}",
trade.office.as_deref().unwrap_or("?"),
trade.last_name.as_deref().unwrap_or("?"),
trade.trade_type.as_deref().unwrap_or("?"),
trade.amount.as_deref().unwrap_or("?"),
trade.transaction_date.as_deref().unwrap_or("?")
);
}
Ok(())
}
Two keyless sources feed this: the House Clerk (housetrades feature) and the Senate eFD system (senatetrades feature), merged by Provider::CongressTrades when both are compiled in. Each result row's office field says which chamber it came from, "House" or "Senate". If the Senate source fails (a network error, or Akamai bot protection blocking the request; see the Senate PTR page for why that happens), the merge drops just those rows and returns House-only results rather than failing the whole call. Only both sources failing (or the single compiled source failing, when just one is enabled) surfaces an error.
| Field | Type | Description |
|---|---|---|
symbol | Option<String> | Ticker symbol traded |
first_name | Option<String> | Legislator's first name |
last_name | Option<String> | Legislator's last name |
office | Option<String> | "House" or "Senate", depending on which source the row came from |
district | Option<String> | District, for House members; always None for Senate rows |
trade_type | Option<String> | Transaction type (e.g. "Purchase", "Sale") |
amount | Option<String> | Reported transaction amount range (e.g. "$1,001 - $15,000") |
asset_description | Option<String> | Description of the asset traded |
transaction_date | Option<String> | Date the transaction occurred (YYYY-MM-DD) |
disclosure_date | Option<String> | Date the transaction was publicly disclosed (YYYY-MM-DD) |
link | Option<String> | Link to the source disclosure filing |
Filing Sections#
Call .sections(accession_number, form) to fetch the sectioned text of one filing (10-K or 8-K), split into FilingSections by item heading:
use finance_query::{FilingSectionForm, Providers};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let providers = Providers::builder().build().await?;
let filings = providers.filings("AAPL");
let submissions = filings.get().await?;
let latest_10k = submissions
.filings
.iter()
.find(|f| f.filing_type.as_deref() == Some("10-K"))
.and_then(|f| f.accession_number.as_deref())
.unwrap_or_default();
for section in filings.sections(latest_10k, FilingSectionForm::TenK).await? {
println!(
"{}: {} chars",
section.section.as_deref().unwrap_or("?"),
section.content.as_deref().unwrap_or("").len()
);
}
Ok(())
}
This is served by keyless EDGAR (best-effort heading detection over the filing's own HTML — see the module's recall caveat below) or Polygon, whichever the FILINGS route resolves to first; the default route already puts EDGAR ahead of nothing else, so no explicit .route() call is required.
| Field | Type | Description |
|---|---|---|
section | Option<String> | Section key/name (e.g. "risk_factors", "mdna") |
content | Option<String> | Section text content |
Risk Factors#
Call .risk_factors() for this symbol's risk factors, extracted from its most recent 10-K:
use finance_query::Providers;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let providers = Providers::builder().build().await?;
let filings = providers.filings("AAPL");
for factor in filings.risk_factors().await?.iter().take(5) {
println!("{}", factor.title.as_deref().unwrap_or("?"));
}
Ok(())
}
| Field | Type | Description |
|---|---|---|
title | Option<String> | Risk factor title |
text | Option<String> | Risk factor text |
category | Option<String> | Risk category |
filing_date | Option<String> | Date of the filing the factor was extracted from (YYYY-MM-DD) |
note · Recall caveat
EDGAR's section and risk-factor extraction is heuristic: it detects Item N headings in the filing's raw HTML rather than using a structured index, so malformed or unusually formatted filings can yield partial or empty results. It returns best-effort output rather than erroring on those filings.
Fails to Deliver#
Call .fails_to_deliver() for this symbol's SEC fails-to-deliver history, the settlement-date record of shares that a broker-dealer failed to deliver on time:
use finance_query::{Providers, edgar};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
edgar::init("you@example.com")?;
let providers = Providers::builder().build().await?;
let filings = providers.filings("AAPL");
for row in filings.fails_to_deliver().await? {
println!(
"{}: {:?} shares of {:?}",
row.date.as_deref().unwrap_or("?"),
row.quantity,
row.name
);
}
Ok(())
}
This is served by keyless EDGAR (secftd feature), which the default FILINGS route already puts ahead of Yahoo, so no explicit .route() call is required once secftd is compiled in. FMP also serves this operation for callers who route Capability::FILINGS to it instead.
| Field | Type | Description |
|---|---|---|
symbol | Option<String> | Ticker symbol |
date | Option<String> | Settlement date (YYYY-MM-DD) |
quantity | Option<f64> | Number of shares that failed to deliver |
price | Option<f64> | Closing price on the settlement date |
name | Option<String> | Security name |
description | Option<String> | Additional description, when reported |
See Also#
- EDGAR Provider Reference: low-level EDGAR API (CIK resolution, submissions, XBRL company facts, full-text search)
- House PTR: House-side congressional trades source
- Senate PTR: Senate-side congressional trades source
- Getting Started: building a
Providersinstance
