Metadata-Version: 2.4
Name: avetrust
Version: 0.1.0
Summary: SDK Python officiel d'AveTrust — vérification d'identité (eKYC) : sessions, résultats, webhooks signés, sandbox.
Project-URL: Repository, https://gitlab.avepay.net/avetrust/avetrust-python
License: MIT
License-File: LICENSE
Keywords: avetrust,ekyc,identity,kyc,regula,verification
Requires-Python: >=3.9
Requires-Dist: httpx>=0.27
Provides-Extra: dev
Requires-Dist: mypy>=1.10; extra == 'dev'
Requires-Dist: pytest>=8; extra == 'dev'
Description-Content-Type: text/markdown

# avetrust (Python)

SDK Python officiel d'**AveTrust** — vérification d'identité de niveau forensique (eKYC).
Sessions de vérification, résultats, **webhooks signés**, streaming temps réel et **sandbox**.

## Installation

Distribué via le registry public d'AveTrust :

```bash
pip install avetrust --index-url https://gitlab.avepay.net/api/v4/projects/42/packages/pypi/simple
```

Python ≥ 3.9. Une seule dépendance : `httpx`.

## Démarrage rapide

```python
from avetrust import AveTrust

av = AveTrust("sk_test_…")  # clé test → sandbox (gratuit, déterministe)

v = av.verifications.create(
    checks=["DOCUMENT", "LIVENESS", "FACE_MATCH"],
    callback_url="https://mon-app/kyc/webhook",
    simulate="approved",  # ignoré hors sandbox
)

av.verifications.send_link(
    v.id, channel="EMAIL", to="client@exemple.com",
    link=f"https://verify-test.avetrust.net/s/{v.token}",
)
```

## Recevoir le résultat (webhook)

Vérifiez **toujours** la signature (corps brut requis) :

```python
# Exemple Flask
@app.post("/kyc/webhook")
def webhook():
    try:
        event = av.webhooks.construct_event(
            request.get_data(),  # bytes bruts
            request.headers.get("X-AveTrust-Signature"),
            os.environ["AVETRUST_WEBHOOK_SECRET"],
        )
    except Exception:
        return "", 400

    if not event["livemode"]:
        return "", 200  # événement sandbox

    if event["data"]["decision"]["outcome"] == "APPROVED":
        activate_account(event["data"].get("externalUserId"))
    return "", 200
```

## Suivi en temps réel (SSE, sans polling)

```python
result = av.verifications.stream(
    v.token,
    on_progress=lambda e: print("étape :", e["step"]),
    on_status=lambda e: print("statut :", e["status"]),
)
print("verdict :", result["status"])  # APPROVED | REVIEW | REJECTED
```

## Sandbox

Une clé `sk_test_…` : **aucun appel réel, gratuit, non facturé**, verdict **déterministe** via `simulate`. Webhooks avec `livemode=False`.

```python
av = AveTrust("sk_test_…")
assert av.is_test_mode
v = av.verifications.create(checks=["DOCUMENT"], simulate="rejected")
```

## Erreurs typées

```python
from avetrust import AuthenticationError, RateLimitError, AveTrustError

try:
    av.verifications.create()
except AuthenticationError:
    ...  # clé invalide
except RateLimitError:
    ...  # quota
except AveTrustError as e:
    print(e.code, e.status, e.request_id)
```

## API

| Méthode | Description |
|---|---|
| `verifications.create(...)` | Crée une session (renvoie `id` + `token`) |
| `verifications.retrieve(id)` | Résumé |
| `verifications.result(id)` | Résultat complet |
| `verifications.list(...)` | Liste paginée (`status`, `test`) |
| `verifications.stream(token, ...)` | Suivi temps réel (SSE) |
| `verifications.send_link(id, ...)` | Envoie le lien hébergé |
| `verifications.decide(id, outcome)` | Décision manuelle |
| `api_keys.list() / create(name, env) / revoke(id)` | Clés |
| `webhooks.construct_event(payload, sig, secret)` | Vérifie + parse |

## Licence

© AveTrust — usage réservé.
