Skip to main content

finance_query/adapters/polygon/stocks/
filings.rs

1//! SEC filing endpoints: 10-K sections, 8-K text, EDGAR index, risk factors.
2
3use serde::{Deserialize, Serialize};
4
5use crate::adapters::common::encode_path_segment;
6use crate::error::{FinanceError, Result};
7
8use super::super::build_client;
9use super::super::models::PaginatedResponse;
10
11/// SEC filing metadata.
12#[derive(Debug, Clone, Serialize, Deserialize)]
13#[non_exhaustive]
14pub struct FilingEntry {
15    /// Accession number.
16    pub accession_number: Option<String>,
17    /// Filing date.
18    pub filing_date: Option<String>,
19    /// Filing type (e.g., `"10-K"`, `"8-K"`).
20    pub filing_type: Option<String>,
21    /// Filing URL.
22    pub filing_url: Option<String>,
23    /// Company name.
24    pub company_name: Option<String>,
25    /// CIK.
26    pub cik: Option<String>,
27    /// Tickers.
28    pub tickers: Option<Vec<String>>,
29}
30
31/// SEC filing section content.
32#[derive(Debug, Clone, Serialize, Deserialize)]
33#[non_exhaustive]
34pub struct FilingSection {
35    /// Section key/name.
36    pub section: Option<String>,
37    /// Section text content.
38    pub content: Option<String>,
39}
40
41/// Risk factor entry.
42#[derive(Debug, Clone, Serialize, Deserialize)]
43#[non_exhaustive]
44pub struct RiskFactor {
45    /// Risk factor title.
46    pub title: Option<String>,
47    /// Risk factor text.
48    pub text: Option<String>,
49    /// Risk category.
50    pub category: Option<String>,
51    /// Filing date.
52    pub filing_date: Option<String>,
53}
54
55/// Risk category.
56#[derive(Debug, Clone, Serialize, Deserialize)]
57#[non_exhaustive]
58pub struct RiskCategory {
59    /// Category name.
60    pub name: Option<String>,
61    /// Description.
62    pub description: Option<String>,
63}
64
65/// Filing sections response.
66#[derive(Debug, Clone, Serialize, Deserialize)]
67#[non_exhaustive]
68pub struct FilingSectionsResponse {
69    /// Request ID.
70    pub request_id: Option<String>,
71    /// Status.
72    pub status: Option<String>,
73    /// Sections.
74    pub results: Option<Vec<FilingSection>>,
75}
76
77/// Fetch SEC EDGAR index (filing metadata).
78pub async fn sec_edgar_index(params: &[(&str, &str)]) -> Result<PaginatedResponse<FilingEntry>> {
79    let client = build_client()?;
80    client.get("/v1/reference/sec/filings", params).await
81}
82
83/// Fetch 10-K filing section content.
84pub async fn filing_10k_sections(
85    accession_number: &str,
86    params: &[(&str, &str)],
87) -> Result<FilingSectionsResponse> {
88    let client = build_client()?;
89    let path = format!(
90        "/v1/reference/sec/filings/{}/sections",
91        encode_path_segment(accession_number)
92    );
93    let json = client.get_raw(&path, params).await?;
94    serde_json::from_value(json).map_err(|e| FinanceError::ResponseStructureError {
95        field: "10k_sections".to_string(),
96        context: format!("Failed to parse 10-K sections: {e}"),
97    })
98}
99
100/// Fetch 8-K filing text.
101pub async fn filing_8k_text(
102    accession_number: &str,
103    params: &[(&str, &str)],
104) -> Result<FilingSectionsResponse> {
105    let client = build_client()?;
106    let path = format!(
107        "/v1/reference/sec/filings/{}/8k",
108        encode_path_segment(accession_number)
109    );
110    let json = client.get_raw(&path, params).await?;
111    serde_json::from_value(json).map_err(|e| FinanceError::ResponseStructureError {
112        field: "8k_text".to_string(),
113        context: format!("Failed to parse 8-K text: {e}"),
114    })
115}
116
117/// Fetch risk factors from SEC filings.
118pub async fn risk_factors(params: &[(&str, &str)]) -> Result<PaginatedResponse<RiskFactor>> {
119    let client = build_client()?;
120    client.get("/v1/reference/sec/risk-factors", params).await
121}
122
123/// Fetch risk factor categories.
124pub async fn risk_categories() -> Result<PaginatedResponse<RiskCategory>> {
125    let client = build_client()?;
126    client.get("/v1/reference/sec/risk-categories", &[]).await
127}