Metadata-Version: 2.4
Name: verifence
Version: 0.1.0
Summary: Official Python SDK for Verifence — the pre-send firewall for SMS verification.
License: MIT
License-File: LICENSE
Keywords: fraud,otp,sms,sms-pumping,verifence,verification
Requires-Python: >=3.8
Description-Content-Type: text/markdown

# Verifence Python SDK

Official Python client for [Verifence](../../README.md) — the pre-send firewall for
SMS verification. Zero dependencies (standard library only, Python ≥ 3.8).

```bash
pip install verifence
```

> **Your API key is a secret.** Every call is server-to-server. Read it from an
> environment variable; never ship it in client code.

## Usage

```python
import os
from verifence import Verifence, QuotaExceededError

vf = Verifence(os.environ["VERIFENCE_KEY"])

# Before you hand a message to Twilio/Vonage/etc:
verdict = vf.check(
    phone="+14155552671",
    client_ip=request.remote_addr,   # the END USER's IP, from your inbound request
    user_id="u_123",
)

if not verdict["allow"]:
    # Do not send — you just saved the message fee.
    return "too_many_verification_requests", 429

# ... send the SMS with your provider ...

# After the user enters the correct code:
vf.confirm(client_ip=request.remote_addr)
```

Handle a spent quota:

```python
try:
    verdict = vf.check("+14155552671", ip)
except QuotaExceededError as e:
    print("quota resets at", e.resets_at)
```

## API

| Method | Returns |
|---|---|
| `check(phone, client_ip, user_id=None, require_mobile=False)` | `{"allow": bool, "reason": str \| None, "detail": str, "degraded": bool, ...}` |
| `confirm(client_ip)` | `{"recorded": bool}` |
| `stats()` | account totals |

A block is a **200** with `allow=False` — not an exception. Only bad input, auth,
and quota (429) raise. Self-hosting? `Verifence(key, base_url="https://verifence.internal")`.
