Metadata-Version: 2.4
Name: turingverify
Version: 0.2.0
Summary: Official Python SDK for the Turing Verify API
Project-URL: Homepage, https://verify.turingcerts.com/developers
Project-URL: Documentation, https://api.verify.turingcerts.com/v1/docs/reference
Project-URL: Repository, https://github.com/turing-space/turing-verifier
Project-URL: Issues, https://github.com/turing-space/turing-verifier/issues
Author-email: "Turing Space Inc." <support@turingcerts.com>
License: MIT
License-File: LICENSE
Keywords: api,documents,forensics,turingverify,verification
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
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
Requires-Python: >=3.10
Requires-Dist: httpx>=0.27
Requires-Dist: pydantic>=2
Provides-Extra: dev
Requires-Dist: pytest-asyncio>=1; extra == 'dev'
Requires-Dist: pytest>=8; extra == 'dev'
Requires-Dist: respx>=0.21; extra == 'dev'
Description-Content-Type: text/markdown

# turingverify

Official Python SDK for the [Turing Verify](https://verify.turingcerts.com) document verification API.

## Install

```bash
pip install turingverify
```

Requires Python 3.9+. Depends only on `httpx` and `pydantic`.

## Quickstart

```python
from turingverify import TuringVerify

client = TuringVerify(api_key="tv_live_sk_...")

with open("diploma.pdf", "rb") as f:
    ver = client.verifications.create(file=f, filename="diploma.pdf")

print(ver.verdict, ver.confidence)
# → 'ACCEPT' 0.94
```

## Async

```python
import asyncio
from turingverify import AsyncTuringVerify

async def main():
    async with AsyncTuringVerify(api_key="tv_live_sk_...") as client:
        ver = await client.verifications.retrieve("ver_abc...")
        print(ver.verdict)

asyncio.run(main())
```

## Verifying webhook signatures

```python
from turingverify import verify_signature, SignatureVerificationError

@app.post("/hooks/turing-verify")
async def receive(request):
    body = await request.body()
    sig = request.headers["X-TuringVerify-Signature"]
    try:
        verify_signature(body, sig, SECRET, tolerance=300)
    except SignatureVerificationError:
        return 400, "bad signature"
    # ...process event
```

## Errors

Every error inherits `TuringVerifyError`:

```python
from turingverify import (
    TuringVerifyError,       # base class
    APIError,                # generic non-2xx
    AuthenticationError,     # 401
    InvalidRequestError,     # 400 / 422
    RateLimitError,          # 429 — exposes .retry_after
    IdempotencyConflictError,# 409
    SignatureVerificationError,  # webhook HMAC failed
)
```

## Retry behavior

- 5xx, 429, and network errors retry with exponential backoff (+ jitter).
- `Retry-After` is honored when the server sends it.
- `max_retries=3` by default — pass `max_retries=0` to disable.

## Idempotency

Every `POST /v1/verifications` call gets an automatic UUID4 `Idempotency-Key`
header. Pass `idempotency_key="..."` to use your own. Replays within 24h
return the cached response.

## CLI

```bash
# Environment variables:
export TURING_VERIFY_API_KEY=tv_live_sk_...

turingverify verify path/to/diploma.pdf
turingverify tokens create --name ci-pipeline --env live
turingverify webhooks list
turingverify webhooks send-test whk_abc...
turingverify --json tokens list
```

## License

MIT — see [LICENSE](./LICENSE).
