example · fastapi

01 / 06

FastAPI spam filter.

Updated May 12, 2026

This FastAPI example wires the Siftfy spam-detection API into a Python contact endpoint. The handler scores incoming message text with the official AsyncSiftfy client, drops submissions scored above the response's own `max_confidence`, queues everything from 0.50 up to that ceiling for review, and delivers the rest. It fails open on provider timeouts so a brief outage never silently loses a real lead.

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, ceiling = 0.0, None
    try:
        result = await client.predict(payload.message)
        probability, ceiling = result.spam_probability, result.max_confidence
    except Exception:
        # Fail open so a provider outage does not lose a real lead.
        probability = 0.0

    # Drop only ABOVE the ceiling the response reports. At the ceiling the score
    # is censored, so a fixed constant never fires on the model's own opinion.
    if ceiling is not None and probability > ceiling:
        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. 01`max_confidence` is the highest score the model is allowed to return on its own word; only a score above it is more than the model's opinion.
  2. 02Use the official SDK when you want typed responses and retry behavior.
  3. 03Keep the same success response for spam and clean messages.
  4. 04Queue 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?

Take the drop threshold from the response, not from a constant. `max_confidence` is the highest score the model is allowed to return on its own, so a score above it carries evidence beyond the model — that is the only safe place to drop. A hard-coded 0.85 sits above that ceiling and never fires. Start the review queue at 0.50 and re-tune that floor after a week of queue audits.

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.