Metadata-Version: 2.4
Name: secapi-py
Version: 0.1.1
Summary: Official Python SDK for the SEC API (secapi.dev) - SEC filings, financials, insider and institutional data.
Project-URL: Homepage, https://secapi.dev
Project-URL: Documentation, https://secapi.dev/docs
Project-URL: Repository, https://github.com/secapi-dev/secapi-python
Project-URL: Issues, https://github.com/secapi-dev/secapi-python/issues
Project-URL: API Reference, https://api.secapi.dev/api/core/v3/api-docs
Author-email: SEC API <support@secapi.dev>
License: MIT License
        
        Copyright (c) 2026 secapi.dev
        
        Permission is hereby granted, free of charge, to any person obtaining a copy
        of this software and associated documentation files (the "Software"), to deal
        in the Software without restriction, including without limitation the rights
        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        copies of the Software, and to permit persons to whom the Software is
        furnished to do so, subject to the following conditions:
        
        The above copyright notice and this permission notice shall be included in all
        copies or substantial portions of the Software.
        
        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
        SOFTWARE.
License-File: LICENSE
Keywords: 13f,api,edgar,filings,finance,financials,insider,sdk,sec,xbrl
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Financial and Insurance Industry
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Office/Business :: Financial :: Investment
Classifier: Typing :: Typed
Requires-Python: >=3.8
Requires-Dist: httpx[http2]>=0.27
Requires-Dist: pydantic<3,>=2
Provides-Extra: dev
Requires-Dist: mypy>=1.8; extra == 'dev'
Requires-Dist: pytest>=7; extra == 'dev'
Requires-Dist: ruff>=0.5; extra == 'dev'
Description-Content-Type: text/markdown

# secapi - Python SDK for the SEC API

The official Python client for [**secapi.dev**](https://secapi.dev) - SEC filings,
financial statements, standardized metrics & ratios, insider transactions, and
13F institutional holdings, all from one clean, typed client.

```python
from secapi import SECClient

client = SECClient(api_key="YOUR_API_KEY")

results = client.filings.search(ticker="AAPL", form="10-K")
print(results)
```

- **Pleasant, resource-oriented API** - `client.filings.search(...)`, `client.financials.income_statement(...)`. No URLs to build.
- **Typed responses** - real objects with autocomplete (`filing.accession_number`, `filing.filing_date`), powered by Pydantic v2. No dictionary spelunking.
- **Helpful errors** - `AuthenticationError`, `RateLimitError`, `NotFoundError`, `ValidationError`, `ServerError` instead of raw HTTP codes.
- **Fast & robust** - built on [httpx](https://www.python-httpx.org/) with HTTP/2, connection pooling, timeouts, and automatic retries with backoff.
- **Stays in sync with the API** - models are generated from the API's OpenAPI spec.

---

## Installation

```bash
pip install secapi-py
```

The PyPI package is **`secapi-py`** (the plain `secapi` name is taken by another project). Import it as:

```python
from secapi import SECClient
```

Requires Python 3.8+.

## Authentication

Get an API key from [secapi.dev](https://secapi.dev). Provide it explicitly:

```python
client = SECClient(api_key="YOUR_API_KEY")
```

...or set an environment variable and omit the argument:

```bash
export SECAPI_API_KEY="YOUR_API_KEY"
```

```python
client = SECClient()  # reads SECAPI_API_KEY
```

## Quickstart

```python
from secapi import SECClient

client = SECClient(api_key="YOUR_API_KEY")

# Find Apple's annual reports
filings = client.filings.search(ticker="AAPL", form="10-K", limit=5)
for filing in filings.data:
    print(filing.filing_date, filing.form_type, filing.accession_number)

# Pull the latest income statement for Microsoft
income = client.financials.income_statement(ticker="MSFT")
for row in income.rows or []:
    print(row.plabel)
```

## Resources

Every top-level API category is its own namespace on the client.

### `client.filings`

```python
client.filings.search(ticker="AAPL", form=["10-K", "8-K"], start_date="2025-01-01")
client.filings.get("0000320193-26-000006")               # every filing for an accession no.
client.filings.retrieve("0000320193", "0000320193-26-000006")
client.filings.documents("0000320193", "0000320193-26-000006")
client.filings.form_types()
```

### `client.financials`

```python
# As-reported statements - by accession number, or by ticker/CIK (latest filing)
client.financials.income_statement(ticker="MSFT")
client.financials.balance_sheet("0000320193-26-000006")
client.financials.cash_flow(ticker="AAPL", form="10-K")

# Standardized statements, raw XBRL, company & concept search
client.financials.income_statement_standardized(ticker="AAPL")
client.financials.xbrl("0000320193-26-000006")
client.financials.companies(ticker="AAPL")
client.financials.concepts("revenue")

# Cross-period metrics, ratios and rankings
client.financials.metrics(["revenue", "net_income"], ticker="AAPL")
client.financials.ratios(ticker="AAPL", group="profitability")
client.financials.top_metrics("revenue", limit=10)
client.financials.top_ratios("gross_margin")

# Revenue segments
client.financials.segments_geography("AAPL")
client.financials.segments_product_service("AAPL", period="2024")
```

### `client.entities`

```python
client.entities.get("AAPL")              # by ticker or CIK
client.entities.list(q="Apple", limit=20)
client.entities.filings("AAPL", form="10-K")
client.entities.sic_codes()
```

### `client.insiders`

```python
client.insiders.latest(limit=50)                       # newest insider trades
client.insiders.search(ticker="AAPL", acquired_disposed="A")
client.insiders.transactions(person_cik="0001214123")  # one insider
client.insiders.buying(limit=25)
client.insiders.top_buyers()
client.insiders.owners("AAPL")
client.insiders.buy_sell_ratio("AAPL")
client.insiders.person("0001214123")
```

### `client.institutions`

```python
client.institutions.list(q="Berkshire")
client.institutions.holdings("0001067983", sort="value")
client.institutions.buys("0001067983", quarter="2024Q3")
client.institutions.sectors("0001067983")
client.institutions.activity()                          # market-wide smart money
```

## Typed responses

Responses are Pydantic models, so you get attribute access and editor
autocomplete instead of raw dictionaries:

```python
filings = client.filings.search(ticker="AAPL", form="10-K")

first = filings.data[0]
first.company_name      # -> entity_name on the model
first.accession_number  # "0000320193-26-000006"
first.filing_date       # datetime.date(2026, 1, 15)
filings.pagination.has_more_data  # True / False
```

Need a plain dict? Every model has `.to_dict()` (snake_case) and
`.to_dict(by_alias=True)` (the original API keys). Unknown fields the API adds in
the future are preserved automatically, so your code keeps working.

## Error handling

```python
from secapi import SECClient
from secapi.exceptions import (
    AuthenticationError,
    RateLimitError,
    NotFoundError,
    ValidationError,
    ServerError,
    SecApiError,
)

client = SECClient(api_key="...")
try:
    client.entities.get("AAPL")
except RateLimitError as exc:
    print("Slow down:", exc.message)
except AuthenticationError:
    print("Check your API key")
except NotFoundError:
    print("No such entity")
except SecApiError as exc:        # base class for everything this SDK raises
    print("Request failed:", exc)
```

Every `APIStatusError` exposes `.status_code`, `.code`, `.message`, `.details`,
and `.request_id` (handy when contacting support).

## Configuration

```python
import httpx
from secapi import SECClient

client = SECClient(
    api_key="...",
    timeout=httpx.Timeout(30.0, connect=10.0),  # or a float
    max_retries=2,         # retries 429/5xx with exponential backoff
    http2=True,            # enabled by default
    base_url="https://api.secapi.dev",
)

# Reuse the client across requests; close it (or use a context manager) when done.
with SECClient(api_key="...") as client:
    client.filings.search(ticker="AAPL")
```

Internals you can reach for if you need them: `client.session` (the underlying
`httpx.Client`), `client.base_url`, and `client.api_key`.

## Development

The response models are generated from the API's OpenAPI document
(`https://api.secapi.dev/api/core/v3/api-docs`), vendored at
`scripts/openapi.json`.

```bash
pip install -e ".[dev]"

# Regenerate models from the spec
python scripts/generate_models.py

# Fail if the committed models drift from the spec (run this in CI)
python scripts/generate_models.py --check

# Unit tests (offline, mocked transport)
pytest

# Integration tests against the live API
export SECAPI_API_KEY="YOUR_API_KEY"
pytest -m integration
```

## License

MIT - see [LICENSE](LICENSE).
