Metadata-Version: 2.4
Name: nyfin
Version: 0.1.0
Summary: Python SDK for the hosted nyfin NYSE finance data API.
Project-URL: Homepage, https://api.nyfin.bluedoor.sh/v1/health
Project-URL: API, https://api.nyfin.bluedoor.sh/v1/openapi.json
Project-URL: Documentation, https://github.com/bluedoor-ai/nyfin#readme
Project-URL: Source, https://github.com/bluedoor-ai/nyfin
Project-URL: Rate Limits, https://github.com/bluedoor-ai/nyfin/blob/main/nyfin/RATE_LIMIT_RESULTS.md
Author-email: BlueDoor <sam@bluedoor.sh>
License: MIT
Keywords: finance,market-data,nyfin,nyse,stocks
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Financial and Insurance Industry
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Office/Business :: Financial
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.10
Requires-Dist: certifi>=2024.2.2
Description-Content-Type: text/markdown

# nyfin

Python SDK for the hosted [nyfin](https://api.nyfin.bluedoor.sh) NYSE financial data API.

The hosted API exposes 12 anonymous-readable NYSE endpoints (quote, screener, corporate actions, dividends, ETF data, regulatory compliance, search) behind a cached, typed REST surface. Not affiliated with, endorsed by, or sponsored by NYSE, Inc. or ETF Central.

## Install

```bash
pip install nyfin
```

## Quick start

```python
from nyfin import Client

client = Client()

# Quote snapshot — full quote, history, board, totals, options, trends
ibm = client.quote("IBM")

# Symbol → canonical row resolver
canonical = client.quote_resolve("IBM", mic_code="XNYS")

# Paginated screener by instrument type
equities = client.quote_screener("EQUITY", page=1, page_size=25)

# Corporate actions feed (date-ranged, paginated)
actions = client.corporate_actions("2026-04-01", "2026-12-31", page=1, page_size=50)

# Dividend ex-dates from NYSE Listing Manager
divs = client.dividends_ex_dates()

# ETF Central
spy_quote = client.etf_quote("SPY")
spy_price = client.etf_price("SPY")
popular = client.etf_most_popular()
state = client.etf_market_state()

# Regulatory
noncompliant = client.noncompliant_directory(market="NYSE", page_size=25)
status = client.noncompliant_lookup("ALUR")

# Site search
results = client.search("IBM", collection="nyse_quotes")
```

Every response is a `{data, meta}` envelope:

```python
{
    "data": {...},  # endpoint payload
    "meta": {
        "endpoint_id": "nyse.quote.snapshot",
        "served_from": "origin",  # or "cache" / "stale"
        "cached_at": "2026-05-05T20:00:00.000Z",
        "ttl_seconds": 15,
        "stale_seconds": 30,
        "version": "0.1.0"
    }
}
```

## Module-level convenience

```python
import nyfin

quote = nyfin.quote("IBM")
divs = nyfin.dividends_ex_dates()
results = nyfin.search("IBM")
```

## Methods

| Method | Endpoint | Purpose |
|---|---|---|
| `Client.quote(symbol)` | `/v1/quote` | Full quote snapshot for a NYSE symbol |
| `Client.quote_resolve(symbol, mic_code)` | `POST /v1/quote/resolve` | Resolve normalized ticker → canonical row |
| `Client.quote_screener(instrument_type, ...)` | `POST /v1/quote/screener` | Paginated directory by instrument type |
| `Client.corporate_actions(from_date, to_date, ...)` | `/v1/corporate-actions` | Corporate actions feed |
| `Client.dividends_ex_dates()` | `/v1/dividends/ex-dates` | Upcoming dividend ex-dates |
| `Client.etf_quote(symbol)` | `/v1/etf/quote` | ETF quote (ETF Central) |
| `Client.etf_price(symbol)` | `/v1/etf/price` | ETF price (ETF Central) |
| `Client.etf_most_popular()` | `/v1/etf/most-popular` | Curated most-popular ETFs |
| `Client.etf_market_state()` | `/v1/etf/market-state` | State-of-the-market commentary |
| `Client.noncompliant_directory(...)` | `/v1/regulatory/noncompliant` | Noncompliant-issuer directory |
| `Client.noncompliant_lookup(symbol)` | `/v1/regulatory/noncompliant/{symbol}` | Per-symbol compliance lookup |
| `Client.search(q, collection, page)` | `/v1/search` | Site search across NYSE.com |
| `Client.endpoints()` | `/v1/endpoints` | List of public endpoints |
| `Client.openapi()` | `/v1/openapi.json` | OpenAPI 3.1 specification |
| `Client.health()` | `/v1/health` | Service health |

Required `instrument_type` values for `quote_screener`: `EQUITY`, `INDEX`, `WARRANT`, `RIGHT`, `CLOSED_END_FUND`, `REIT`, `UNIT`, `TRUST`. Other values are rejected with a 400.

Required `collection` values for `search`: `nyse_quotes`, `nyse_pages_cms2`, `nyse_uploadedfiles`, `nyse_appurls`.

## Configuration

| Env var | Effect |
|---|---|
| `NYFIN_BASE_URL` | Override the API base URL (default `https://api.nyfin.bluedoor.sh`) |
| `NYFIN_CONTACT` | Sent as `X-Nyfin-Contact` for higher rate-limit tiers (v0.2.0+) |
| `NYFIN_API_KEY` | Sent as `Authorization: Bearer` for the API-key tier (v0.2.0+) |

```python
client = Client(base_url="...", contact="you@example.com", timeout=20.0)
```

## Errors

```python
from nyfin import NyfinError, NyfinRateLimitError, NyfinValidationError

try:
    client.quote_screener("BANANA")  # not in enum
except NyfinValidationError as e:
    print(e)  # HTTP 400: 'instrument_type' must be one of [...]

try:
    # ... heavy concurrent calls ...
except NyfinRateLimitError as e:
    print(e)  # HTTP 429: rate limited
```

## What's NOT in v0.1.0

- **No raw passthrough.** The hosted API only exposes the friendly typed routes above.
- **No identity-tier rate limiting.** `X-Nyfin-Contact` and `Authorization` are accepted as forward-compat headers but not enforced server-side in v0.1.0.
- **5 ETF Central WAF-gated endpoints** (`data-api/funds/{symbol}`, `data-api/nyse/mapping/{symbol}`, segment search) — planned for v0.2.0 with the necessary WAF warmup infrastructure.
- **TOP API + Market Event Feed** — credentialed-only NYSE programs; out of v0.1.0 anonymous scope.

## Disclaimer

This is an unofficial wrapper around publicly-readable NYSE.com and ETF Central JSON endpoints. NYSE, Inc., Intercontinental Exchange, and ETF Central LLC are not affiliated with this project. Use at your own risk and within those services' Terms of Service. The hosted API is provided as a courtesy without uptime guarantees.
