Metadata-Version: 2.4
Name: kepler-insights
Version: 1.1.0
Summary: Official Python SDK for the Kepler Insights API — curated company-scoring intelligence over a 67-signal engine.
Project-URL: Homepage, https://api.keplerinsights.us
Project-URL: Documentation, https://docs.keplerinsights.us
Project-URL: Support, https://console.keplerinsights.us
Author-email: Kepler Insights <noah@keplerinsights.us>
License-Expression: MIT
License-File: LICENSE
Keywords: api-client,company-intelligence,kepler,scoring,vc
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Financial and Insurance Industry
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
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 :: Software Development :: Libraries :: Python Modules
Classifier: Typing :: Typed
Requires-Python: >=3.10
Requires-Dist: httpx<1.0,>=0.27
Requires-Dist: pydantic<3.0,>=2.0
Provides-Extra: dev
Requires-Dist: build>=1.0; extra == 'dev'
Requires-Dist: pytest>=8.0; extra == 'dev'
Requires-Dist: respx>=0.21; extra == 'dev'
Requires-Dist: ruff>=0.5; extra == 'dev'
Description-Content-Type: text/markdown

# Kepler Insights — Python SDK

Official Python SDK for the [Kepler Insights API](https://api.keplerinsights.us) — curated company-scoring intelligence over a 67-signal engine.

## Install

```bash
pip install kepler-insights
```

Requires Python 3.10+. Depends on [httpx](https://www.python-httpx.org/) and [pydantic v2](https://docs.pydantic.dev/latest/).

## Quickstart

```python
from kepler_insights import Kepler

with Kepler(api_key="ki_live_...") as client:
    score = client.score("stripe.com")
    print(f"{score.domain}: {score.ki_rating} ({score.composite_score:.1f})")
    print(f"  team: {score.buckets.team_structure:.1f}")
    print(f"  market: {score.buckets.market_position:.1f}")
```

Sandbox keys (`ki_test_...`) accept only the 4 canned domains — `acme.test`, `unicorn.test`, `struggling.test`, `cohort.test`. See the [Sandbox guide](https://docs.keplerinsights.us/sandbox).

## API surface

| Method | Endpoint | Returns |
|---|---|---|
| `client.score(domain)` | POST `/v1/score` | `Score` |
| `client.get_score(domain)` | GET `/v1/score/{domain}` | `Score` |
| `client.start_score(domain)` | POST `/v1/score?wait=false` | `Job` (Growth+) |
| `client.get_job(job_id)` | GET `/v1/jobs/{job_id}` | `JobResponse` |
| `client.history(domain, limit=, cursor=)` | GET `/v1/score/{domain}/history` | `HistoryPage` |
| `client.iter_history(domain, max_records=)` | (auto-paginates) | iterator of `HistoryRecord` |
| `client.cohort(domain)` | GET `/v1/company/{domain}/cohort` | `Cohort` |
| `client.confidence(domain)` | GET `/v1/company/{domain}/confidence` | `Confidence` |
| `client.distribution()` | GET `/v1/distribution` | `Distribution` |
| `client.movers(window)` | GET `/v1/movers` | `Movers` |
| `client.signals()` | GET `/v1/signals` | `SignalsManifest` |
| `client.usage()` | GET `/v1/usage` | `Usage` |

## Async cold scoring

Cold scoring takes 30–60 seconds. On Growth and above, you can start a job and poll without holding an HTTP connection open:

```python
job = client.start_score("stripe.com")    # returns immediately
score = job.wait(timeout=180)             # blocks until complete; raises on timeout
```

If the API short-circuits to a cached-fresh response (no cold work needed), `start_score` returns a `Job` already in the `complete` state — `wait()` returns instantly. This mirrors Stripe's `payment_intent` "no action needed" pattern.

## Error handling

Every error inherits from `KeplerError`. Branch on the specific subclass or the stable `error.code` string:

```python
from kepler_insights import (
    Kepler,
    AuthError,
    ColdBudgetExhausted,
    FreeTierSandboxOnly,
    NotFound,
    RateLimitError,
    ScoringTimeout,
)

try:
    score = client.score("stripe.com")
except FreeTierSandboxOnly:
    print("Upgrade to Starter for live scoring.")
except ColdBudgetExhausted as e:
    print(f"Monthly cap hit. Resets in {e.retry_after}s. Upgrade for more.")
except RateLimitError as e:
    print(f"Rate limited. Retry in {e.retry_after}s.")
except ScoringTimeout:
    print("Cold scoring exceeded sync budget — use start_score() for async.")
except NotFound:
    print("Never scored. Trigger one with score(domain).")
except AuthError:
    print("Invalid or revoked API key.")
```

The SDK auto-retries on 5xx and network errors with exponential backoff (3 attempts by default). It never retries 4xx — those are caller errors.

## Configuration

```python
client = Kepler(
    api_key="ki_live_...",
    base_url="https://api.keplerinsights.us",   # override only for testing
    timeout=70.0,                                # per-request timeout (s)
    retries=3,                                   # 5xx retry attempts
)
```

For custom transports (proxies, mTLS, etc.) inject your own `httpx.Client`:

```python
import httpx
custom = httpx.Client(timeout=120, transport=httpx.HTTPTransport(retries=0))
client = Kepler(api_key="ki_live_...", http_client=custom)
```

## Development

```bash
git clone <repo>
cd Ki_dev/sdk-python
python3 -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
pytest
```

## License

MIT. The API itself is proprietary; the SDK wrapper is MIT-licensed so you can vendor it freely.
