example · fastapi

01 / 06

FastAPI spam filter.

Updated May 12, 2026

A runnable FastAPI route that scores a contact-form message with the official Python SDK before deciding whether to deliver, queue, or drop it.

python
# pip install fastapi uvicorn siftfy
import os
from fastapi import FastAPI
from pydantic import BaseModel, EmailStr
from siftfy import AsyncSiftfy

app = FastAPI()
client = AsyncSiftfy(api_key=os.environ["SIFTFY_KEY"], timeout=2.0)

class ContactSubmission(BaseModel):
    email: EmailStr
    message: str

@app.post("/contact")
async def contact(payload: ContactSubmission) -> dict[str, bool]:
    probability = 0.0
    try:
        result = await client.predict(payload.message)
        probability = result.spam_probability
    except Exception:
        # Fail open so a provider outage does not lose a real lead.
        probability = 0.0

    if probability >= 0.85:
        return {"ok": True}
    if probability >= 0.50:
        await queue_for_review(payload.email, payload.message, probability)
    else:
        await deliver_to_inbox(payload.email, payload.message)
    return {"ok": True}

Production notes

  1. 01Use the official SDK when you want typed responses and retry behavior.
  2. 02Keep the same success response for spam and clean messages.
  3. 03Queue borderline submissions instead of dropping them until thresholds are proven.

Common questions

How do I add Siftfy spam detection to a FastAPI app?

Install the `siftfy` Python package, instantiate `AsyncSiftfy` with your API key, then call `client.predict(text)` inside an async route handler before forwarding the submission downstream. The full handler is shown in the code block above.

What spam-probability thresholds should I use in FastAPI?

Start with 0.85 for hard drops and 0.50 for review queues. These keep false positives low while still catching obvious spam. Re-tune after a week of review-queue audits — most teams settle between 0.80–0.90 for the drop threshold.

How do I handle Siftfy API timeouts in FastAPI?

Set a tight client timeout (2 seconds is typical), wrap the predict call in try/except, and fall open by treating any failure as probability 0.0. Real visitors should never lose a submission to a transient classification outage.

Can I run this on serverless FastAPI deployments?

Yes. The same handler works on AWS Lambda (Mangum), Vercel Python runtime, and self-hosted ASGI servers. Keep the AsyncSiftfy client module-scoped so it's reused across warm invocations.

Get a free API key

More patterns: all examples, contact forms, API reference.