""" Pydantic schemas for SEC filing endpoints. """ from datetime import datetime from typing import Any, Dict, List, Optional from pydantic import BaseModel, ConfigDict, Field class FilingDocumentInfo(BaseModel): model_config = ConfigDict(json_schema_extra={ "example": { "type": "EX-99.1", "description": "Press Release", "filename": "ex991pressrelease.htm", "url": "https://www.sec.gov/Archives/edgar/data/320193/000032019324000006/ex991pressrelease.htm", "size": "42 KB", } }) type: Optional[str] = None description: Optional[str] = None filename: Optional[str] = None url: Optional[str] = None size: Optional[str] = None class FilingSummary(BaseModel): model_config = ConfigDict(json_schema_extra={ "example": { "accession_number": "0000320193-24-000006", "form_type": "8-K", "filing_date": "2024-02-01", "accepted_at": "2024-02-01T21:00:05+00:00", "primary_document": "a8-k20240201.htm", "filing_description": "Results of Operations and Financial Condition", "documents_count": 4, "parsed_status": "succeeded", "items": ["2.02", "9.01"], } }) accession_number: str form_type: str filing_date: str accepted_at: Optional[str] = None primary_document: Optional[str] = None filing_description: Optional[str] = None documents_count: Optional[int] = None parsed_status: Optional[str] = None items: Optional[List[str]] = None class FilingSearchResponse(BaseModel): model_config = ConfigDict(json_schema_extra={ "example": { "ticker": "AAPL", "filings": [ { "accession_number": "0000320193-24-000006", "form_type": "8-K", "filing_date": "2024-02-01", "accepted_at": "2024-02-01T21:00:05+00:00", "primary_document": "a8-k20240201.htm", "filing_description": "Results of Operations and Financial Condition", "documents_count": 4, } ], "total_count": 42, "metadata": {"limit": 20, "offset": 0, "form_types": ["8-K"]}, } }) ticker: str filings: List[FilingSummary] total_count: int metadata: dict = Field(default_factory=dict) class FilingDocumentListResponse(BaseModel): model_config = ConfigDict(json_schema_extra={ "example": { "accession_number": "0000320193-24-000006", "documents": [ { "type": "8-K", "description": "8-K", "filename": "a8-k20240201.htm", "url": "https://www.sec.gov/Archives/edgar/data/320193/000032019324000006/a8-k20240201.htm", "size": "8 KB", }, { "type": "EX-99.1", "description": "Press Release", "filename": "ex991pressrelease.htm", "url": "https://www.sec.gov/Archives/edgar/data/320193/000032019324000006/ex991pressrelease.htm", "size": "42 KB", }, ], "metadata": {"total_documents": 4}, } }) accession_number: str documents: List[FilingDocumentInfo] metadata: dict = Field(default_factory=dict) class ExhibitContentResponse(BaseModel): model_config = ConfigDict(json_schema_extra={ "example": { "accession_number": "0000320193-24-000006", "exhibit_type": "EX-99.1", "content": "Apple Reports First Quarter Results...\nCUPERTINO, California — February 1, 2024 — Apple Inc. today announced financial results for its fiscal 2024 first quarter...", "content_type": "text/html", "filename": "ex991pressrelease.htm", "url": "https://www.sec.gov/Archives/edgar/data/320193/000032019324000006/ex991pressrelease.htm", } }) accession_number: str exhibit_type: str content: str content_type: Optional[str] = None filename: Optional[str] = None url: Optional[str] = None # ── Bulk filing search ────────────────────────────────────────────────────── class BulkFilingSearchRequest(BaseModel): model_config = ConfigDict(json_schema_extra={ "example": { "tickers": ["AAPL", "MSFT", "NVDA"], "form_type": "8-K", "start_date": "2024-01-01", "end_date": "2024-12-31", "limit_per_ticker": 5, } }) tickers: List[str] = Field(..., min_length=1, max_length=200) form_type: Optional[str] = None start_date: Optional[str] = None end_date: Optional[str] = None limit_per_ticker: int = Field(default=20, ge=1, le=100) class BulkFilingSearchItem(BaseModel): ticker: str success: bool filings: List[FilingSummary] = [] total_count: int = 0 error: Optional[str] = None class BulkFilingSearchResponse(BaseModel): results: List[BulkFilingSearchItem] total_tickers: int successful_count: int failed_count: int query_time_seconds: float metadata: Dict[str, Any] = Field(default_factory=dict) # ── Bulk exhibit ──────────────────────────────────────────────────────────── class BulkExhibitRequest(BaseModel): model_config = ConfigDict(json_schema_extra={ "example": { "items": [ {"accession_number": "0000320193-24-000006", "exhibit_type": "EX-99.1"}, {"accession_number": "0001045810-24-000010", "exhibit_type": "EX-99.1"}, ] } }) items: List[Dict[str, str]] = Field(..., min_length=1, max_length=50) # Each item: {"accession_number": "...", "exhibit_type": "EX-99.1"} class BulkExhibitItem(BaseModel): accession_number: str exhibit_type: str success: bool content: Optional[str] = None content_type: Optional[str] = None filename: Optional[str] = None url: Optional[str] = None error: Optional[str] = None class BulkExhibitResponse(BaseModel): results: List[BulkExhibitItem] total_items: int successful_count: int failed_count: int query_time_seconds: float # ── Filing Events ──────────────────────────────────────────────────────────── class FilingEventResponse(BaseModel): model_config = ConfigDict(json_schema_extra={ "example": { "id": "550e8400-e29b-41d4-a716-446655440000", "ticker": "AVGO", "accession_number": "0001193125-26-144028", "form_type": "8-K", "filing_date": "2026-04-06", "item_number": "8.01", "event_type": "other_material_event", "title": "Other Events", "summary": "Broadcom Inc. and Google LLC have entered into a Long Term Agreement...", "content_source": "primary_doc", } }) id: str ticker: str accession_number: str form_type: str filing_date: str item_number: str event_type: str title: Optional[str] = None summary: Optional[str] = None content_source: Optional[str] = None class FilingEventsSearchResponse(BaseModel): ticker: str events: List[FilingEventResponse] total_count: int metadata: Dict[str, Any] = Field(default_factory=dict) class BulkParseRequest(BaseModel): model_config = ConfigDict(json_schema_extra={ "example": {"tickers": ["AVGO", "AAPL"], "limit": 50} }) tickers: Optional[List[str]] = None # None = all pending limit: int = Field(default=100, ge=1, le=1000) class BulkParseResponse(BaseModel): succeeded: int failed: int skipped: int total: int query_time_seconds: float