Self-hosted spam scoring · v0.1

Spam scoring that runs on your own servers

Spamkit is an HTTP API that returns a score and a verdict for user-submitted text. It never deletes or blocks anything. Your app makes the call.Python and TypeScript clients · pinned model revision

incomingspam

WINNER!! You have been selected to receive a $1000 prize. Call 09061701461 now

incomingreview

I can improve your Shopify SEO. Reply for a free audit.

incomingclean

Your verification code is 015215. It expires in two hours.

incomingclean

Hi Jamie, could you review PR 412 when you get a moment?

Built on

spamton 7aa94d0 Python 3.12 tested Node 22 tested CPU inference Dockerfile included

Product

Screen every submission without sending it away

0.988 · spam
01

Score

One request returns a raw score, a verdict and the pinned model version. Text stays in process memory while it is scored.

scoreverdictmodel_version
itemscorecall
threshold 0.50 TP 0 FP 0 FN 0 TN 0
02

Evaluate

Point the CLI at your own labeled file. See the confusion matrix, a threshold sweep and every miss by row number. The file never leaves your machine.

Illustrative data, not a benchmark.

spamkit evaluatecsv · jsonlno upload
  • Dockerfile pins model 7aa94d0
  • no model download at runtime
  • compose: read-only filesystem, non-root
03

Deploy

The Dockerfile fetches the model at a pinned revision at build time, so the service downloads nothing at runtime. The image has not been built yet.

docker compose/readyz/metrics

How it works

Four steps from first call to tuned thresholds

Step 1

Send the text

Post the submission and an optional ID to /v1/score. Only the text is scored.

Step 2

Read the verdict

You get a raw score, one of clean, review or spam, and the model version.

Step 3

Decide in your app

Publish, hold or reject as your product requires. Review is the default until you set thresholds.

Step 4

Measure and tune

Run spamkit evaluate on labeled examples. Re-run it on the same file after each change to compare.

Quick start

From clone to first score

# from the repo root
pip install "spamkit-api[server]"
spamkit fetch-model --dest models/spamton   # pinned revision, needs network once
spamkit serve                                # 127.0.0.1:8080

# in another terminal
curl -s -X POST 127.0.0.1:8080/v1/score \
  -H "content-type: application/json" \
  -d '{"text":"Win a prize now"}'

Verified on macOS with Python 3.12. The Docker path is not verified yet.

Live demo

Move the thresholds and watch the verdicts

Every score is a real spamton output on the pinned revision. The verdict depends only on the score and your two thresholds.

Prize scam0.000

Between the thresholds the verdict is review. Scores are not calibrated probabilities.

SDKs

Typed clients, one contract

One contract, two clients

Both SDKs are tested against the same fixtures for score responses and error codes. Retries are off by default. When you turn them on, they retry only transport errors, timeouts, 429 and 5xx, which is safe because scoring is read-only. The Python package is on PyPI as spamkit-api. The npm package is not published yet.

Limits

What it does not do yet

Working today

  • Scores English text with a pinned spamton revision
  • Three-way verdicts with thresholds you set
  • Offline evaluation with a confusion matrix and sweep
  • Optional bearer auth, size limits, overload protection and health checks

Not yet

  • No accuracy claims. Measure on your own data first
  • Scores are not calibrated probabilities
  • English only. Text only, with no images, links or sender signals
  • Not a replacement for a WAF, bot protection or an email provider's filters
  • The Docker image has not been built or tested yet
  • The Python package is on PyPI as spamkit-api. The npm package is not published yet
  • Latency was measured once, on Apple Silicon. x86 numbers are not measured
  • One worker per process. Each worker loads its own copy of the model

FAQ

Your questions, answered

Still asking? Read the SDK notes or the limits.

How long does setup take?

The local path is tested: install the package, fetch the model, then serve. The Dockerfile is written but not yet built. We have not timed setup with outside users.

Can it learn from our own data?

Not in this version. You can measure it on your labeled examples and pick thresholds. Fine-tuning is out of scope for v0.1.

Does it replace our existing spam filter?

No. It scores text only. Keep your WAF, bot protection and email provider filters, and use Spamkit as one signal in your own decision.

Which languages are supported?

English only. The training data is English, so other languages are not measured.

Where does the text go?

It stays in the process memory of the service you run. Logs and metrics never include text or caller IDs. Local deployment reduces exposure, but your own logging and access controls still apply.

Is the score a probability?

No. It is a raw model output. Calibration has not been measured, so use thresholds chosen from your own evaluation.

Score your first submission today

Install the package, fetch the model, send one request. Then measure it on the messages your users actually send.

color