# Nexure Python SDK

Decision visibility for the AI era. Record, analyze, and audit AI-influenced decisions with a single API call.

## Installation

```bash
pip install nexure
```

## Quick Start

```python
from nexure import Nexure

nx = Nexure(api_key="nx_live_...")

# Record a decision in 3 lines
record = nx.decisions.record(
    decision_type="credit_underwriting",
    evidence={"fico_score": 711, "dti_ratio": 0.38, "loan_amount": 45000},
    action="approve",
    decided_by="reviewer_schen",
)
print(record.id)  # dec_a1b2c3d4e5f6
```

## What You Can Do

```python
# Generate an AI-synthesized decision brief
brief = nx.briefs.generate(
    decision_type="credit_underwriting",
    evidence={
        "fico_score": 711,
        "dti_ratio": 0.38,
        "loan_amount": 45000,
        "loan_purpose": "home_improvement",
        "employment_status": "employed",
    },
)
print(f"Quality: {brief.quality_score}/100")
for flag in brief.flags:
    print(f"  [{flag['severity']}] {flag['name']}")

# View analytics
overview = nx.analytics.overview(days=30)
print(f"Override rate: {overview.override_rate:.1%}")

# Detect reviewer anomalies
overrides = nx.analytics.override_rates()
for r in overrides.reviewers:
    if r.is_anomaly:
        print(f"Anomaly: {r.reviewer} — {r.override_rate:.0%} override rate")

# Verify the immutable ledger
result = nx.ledger.verify()
print(f"Chain valid: {result.valid} ({result.records_checked} records)")
```

## Async Support

```python
from nexure import AsyncNexure
import asyncio

async def main():
    async with AsyncNexure(api_key="nx_live_...") as nx:
        decisions = await nx.decisions.list(limit=10)
        for d in decisions.decisions:
            print(f"{d.id}: {d.action} (trust={d.trust_score})")

        overview = await nx.analytics.overview()
        print(f"Total: {overview.total_decisions}")

asyncio.run(main())
```

## Resource Namespaces

All resources follow the same pattern:

```python
items = nx.decisions.list(limit=50, offset=0)  # List
item = nx.decisions.get("dec_...")               # Get single
item = nx.decisions.record(**params)             # Create
```

| Namespace | Methods | Description |
|-----------|---------|-------------|
| `nx.decisions` | `record()`, `get()`, `list()`, `forensics()`, `export()` | Record and query decisions |
| `nx.packages` | `create()`, `get()` | Create evidence packages |
| `nx.briefs` | `generate()`, `get()` | AI-synthesized decision briefs |
| `nx.analytics` | `overview()`, `override_rates()`, `drift()`, `comparisons()`, `visibility_score()` | Dashboard analytics |
| `nx.templates` | `list()`, `get()`, `register()`, `update()` | Decision templates |
| `nx.ledger` | `verify()` | Hash chain verification |
| `nx.anomalies` | `list()`, `get()`, `acknowledge()`, `resolve()`, `dismiss()`, `detect()` | Anomaly alerts |
| `nx.outcomes` | `record()`, `batch()`, `for_decision()`, `stats()`, `by_reviewer()`, `by_override()` | Outcome tracking |
| `nx.explanations` | `generate()`, `list()`, `portal_link()`, templates CRUD | Customer explanations |
| `nx.api_keys` | `create()`, `list()`, `revoke()` | API key management |

## Error Handling

```python
from nexure import NexureError, AuthenticationError, RateLimitError, NotFoundError

try:
    record = nx.decisions.get("dec_nonexistent")
except NotFoundError:
    print("Decision not found")
except AuthenticationError:
    print("Invalid API key")
except RateLimitError as e:
    print(f"Rate limited. Retry after {e.retry_after}s")
except NexureError as e:
    print(f"API error ({e.status_code}): {e.message}")
```

## Configuration

| Parameter | Env Var | Default |
|-----------|---------|---------|
| `api_key` | `NEXURE_API_KEY` | required |
| `base_url` | `NEXURE_API_BASE_URL` | `https://api.nexuredata.com/v1` |
| `timeout` | — | `30.0` seconds |

```python
# From env vars
nx = Nexure()  # reads NEXURE_API_KEY and NEXURE_API_BASE_URL

# Explicit
nx = Nexure(api_key="nx_live_...", base_url="https://api.nexuredata.com/v1", timeout=60.0)

# Context manager
with Nexure(api_key="nx_live_...") as nx:
    record = nx.decisions.record(...)
```

## Requirements

- Python 3.9+
- httpx
- pydantic 2

## License

MIT
