> ## Documentation Index
> Fetch the complete documentation index at: https://developer.keverd.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Python

# Python SDK

```bash theme={null}
pip install keverd
```

Python 3.9+. Zero runtime dependencies.

## Initialize + verify

```python theme={null}
import os
from keverd import Keverd

keverd = Keverd(secret_key=os.environ["KEVERD_SECRET_KEY"])  # kv_sk_…
result = keverd.verify(event_id)

if result.get("action") == "block":
    ...
elif result.get("action") == "allow":
    ...
```

## FastAPI

```python theme={null}
import os
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from keverd import Keverd

app = FastAPI()
keverd = Keverd(secret_key=os.environ["KEVERD_SECRET_KEY"])


class LoginBody(BaseModel):
    event_id: str
    email: str
    password: str


@app.post("/login")
def login(body: LoginBody):
    risk = keverd.verify(body.event_id)
    if risk.get("action") == "block":
        raise HTTPException(
            status_code=403,
            detail={"error": "Blocked", "reasons": risk.get("reasons")},
        )
    return {"ok": True, "visitor_id": risk.get("visitor_id")}
```

## Webhooks

```python theme={null}
import os
from fastapi import Request, Response

@app.post("/webhooks/keverd")
async def keverd_webhook(request: Request):
    raw = await request.body()  # raw bytes — do not parse first
    event = keverd.webhooks.construct_event(
        raw,
        request.headers.get("x-keverd-signature", ""),
        os.environ["KEVERD_WEBHOOK_SECRET"],
    )
    if event["type"] == "verification.completed":
        verification = event["data"]["object"]
    return Response(status_code=200)
```

## Errors

`KeverdError`, `KeverdAPIError`, `KeverdSignatureError`
