Metadata-Version: 2.4
Name: altfiscore
Version: 0.1.0
Summary: Official Python SDK for the AltFiScore alternative credit scoring and decisioning API
Project-URL: Homepage, https://altfiscore.com
Project-URL: Documentation, https://altfiscore.com/developers
Project-URL: Source, https://github.com/Altfiscore/altfiscore-python
Author-email: AltFiScore <developers@altfiscore.com>
License: MIT
License-File: LICENSE
Keywords: altfiscore,bnpl,credit scoring,fintech,lending,underwriting
Classifier: Development Status :: 4 - Beta
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.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.9
Requires-Dist: httpx<1.0,>=0.24
Provides-Extra: dev
Requires-Dist: mypy>=1.0; extra == 'dev'
Requires-Dist: pytest-httpx>=0.30; extra == 'dev'
Requires-Dist: pytest>=7.0; extra == 'dev'
Requires-Dist: ruff>=0.1; extra == 'dev'
Description-Content-Type: text/markdown

# AltFiScore Python SDK

Official Python client for the [AltFiScore](https://altfiscore.com) alternative
credit scoring and loan decisioning API.

Alternative credit scoring and decisioning infrastructure for banks, credit
unions, fintechs, BNPL providers, and embedded lenders.

## Installation

```bash
pip install altfiscore
```

Requires Python 3.9+.

## Quickstart

```python
from altfiscore import AltFiScore

client = AltFiScore(api_key="altfi_test_...")

decision = client.decisions.bnpl(
    consumer={
        "first_name": "Ada",
        "last_name": "Okoro",
        "email": "ada@example.com",
        "dob": "1990-01-15",
        "ssn_last4": "1234",
    },
    order={
        "amount": "450.00",
        "currency": "USD",
        "installment_count": 4,
    },
)

if decision.is_approved:
    print(f"Approved {decision.approved_amount} at {decision.apr}% APR")
    for installment in decision.payment_schedule:
        print(installment["due_date"], installment["amount"])
elif decision.is_referred:
    print("Counter-offer:", decision.counter_offer)
elif decision.is_declined:
    for reason in decision.decline_reasons:
        print(reason["code"], reason["reason"])
```

## Products

Every product is a method on `client.decisions`:

```python
client.decisions.bnpl(consumer=..., order=...)
client.decisions.auto_loan(consumer=..., loan=..., vehicle=..., dealer=...)
client.decisions.mortgage(consumer=..., loan=..., property=...)
client.decisions.personal_loan(consumer=..., loan=...)
client.decisions.credit_card(consumer=..., product=...)
```

## Returning consumers

Pass a `consumer_id` instead of full PII to score a consumer you have already
onboarded:

```python
decision = client.decisions.personal_loan(
    consumer={"consumer_id": "b0c9ed84-f66c-4598-b50a-a0d8b2ddcd04"},
    loan={"amount": "12000.00", "currency": "USD", "term_months": 36},
)
```

## Pending decisions (consumer verification)

Larger amounts trigger enhanced or hard KYC. When that happens the decision is
returned in a pending state:

```python
decision = client.decisions.mortgage(consumer=..., loan=..., property=...)

if decision.is_pending:
    # Redirect the consumer to complete verification
    print(decision.consumer_complete_url)

    # Then poll until the decision is final
    final = client.decisions.poll("mortgage", decision.decision_id, timeout=180)
    print(final.outcome)
```

## Idempotency

Pass an `idempotency_key` to make create calls safe to retry. Reusing a key
returns the original decision instead of creating a new one:

```python
decision = client.decisions.bnpl(
    consumer=...,
    order=...,
    idempotency_key="order-98a7f3",
)
```

## Error handling

```python
from altfiscore import (
    AuthenticationError,
    InvalidRequestError,
    RateLimitError,
    APIError,
)

try:
    decision = client.decisions.bnpl(consumer=..., order=...)
except AuthenticationError:
    ...  # bad or revoked API key
except InvalidRequestError as e:
    ...  # 400/422 - inspect e.body for details
except RateLimitError:
    ...  # 429 - back off and retry
except APIError as e:
    ...  # 5xx or unexpected - e.status_code available
```

A **declined** applicant is **not** an error - it is a successful decision with
`decision.is_declined == True`. Exceptions are only raised for transport and
API-level failures.

## Configuration

```python
client = AltFiScore(
    api_key="altfi_live_...",
    base_url="https://api.altfiscore.com",  # override for sandbox/self-host
    timeout=30.0,                            # per-request seconds
    max_retries=2,                           # idempotent requests only
)
```

The client is also a context manager:

```python
with AltFiScore(api_key="...") as client:
    decision = client.decisions.bnpl(consumer=..., order=...)
```

## Documentation

Full API reference: <https://altfiscore.com/developers>

## License

MIT
