You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
257 lines
8.3 KiB
Python
257 lines
8.3 KiB
Python
"""
|
|
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, "force_reparse": False}
|
|
})
|
|
|
|
tickers: Optional[List[str]] = None # None = all pending
|
|
limit: int = Field(default=100, ge=1, le=1000)
|
|
force_reparse: bool = Field(
|
|
default=False,
|
|
description="If True, also reparse filings with status succeeded or failed (resets to pending first)",
|
|
)
|
|
|
|
|
|
class BulkParseResponse(BaseModel):
|
|
succeeded: int
|
|
failed: int
|
|
skipped: int
|
|
total: int
|
|
query_time_seconds: float
|