Content Filter

Stop form spam, fraud, and cold outreach at the edge. POST a submission to FormShield's /v1/check and get an allow, review, or block decision in about 40ms.

Contact and signup forms are a magnet for spam, fake leads, and templated cold pitches, and regex blocklists or honeypots only catch the laziest bots. You end up hand-tuning rules and still triaging junk in your inbox instead of shipping.

Content Filter is an edge-served content model that scores contact, lead, signup, and comment submissions for spam, fraud, and cold outreach. POST a submission and get back an allow, review, or block decision — plus per-category probabilities — in about 40ms, fast enough to run inline in your submit handler.

When to use it

Reach for Content Filter when you have text a user typed and want a decision before you store it, send it, or notify on it.

Full submission

POST /v1/check takes the form fields plus any IP, email, or user agent you have, and fuses content, IP, and email signals into one calibrated score.

Text only

POST /v1/content scores a single block of text on its own — a comment, a message body — when that is all you have. No other metadata required.

Both return the same 0.01.0 score and the same per-category probabilities, so you branch on one field instead of a pile of heuristics.

How it works

  1. POST the submission

    Send the form fields (and any IP, email, or user agent you have) to POST /v1/check with a Bearer key. For text you already have in hand, POST /v1/content scores the message body alone — no other metadata required.

  2. Score at the edge

    A content model running in the Cloudflare edge classifies the text for spam, fraud, and cold outreach, fused with IP and email signals into one calibrated 0.01.0 score. The full check returns in about 40ms, so it fits inline in your submit handler.

  3. Act on the decision

    You get back a decision of allow, review, or block plus per-category probabilities. allow saves it, review queues it for a human, block drops it — your form handler branches on one field.

Quickstart

Send the submission to /v1/check from your form handler with your secret key as a Bearer token. Here a templated backlink pitch scores high and resolves to block.

bash
curl -X POST https://api.formshield.dev/v1/check \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "form_id": "contact-form",
    "form_data": {
      "name": "John Smith",
      "email": "john@example.com",
      "message": "Boost your SEO rankings fast! Limited time backlink package, act now."
    },
    "metadata": { "ip": "203.0.113.42" }
  }'

The response is wrapped in the standard envelope. The score is a calibrated probability in [0,1], decision is the enum your handler branches on, and categories breaks the risk down by type.

json
{
  "version": "1",
  "data": {
    "score": 0.92,
    "confidence": 0.81,
    "decision": "block",
    "categories": { "spam": 0.92, "fraud": 0.06, "cold_email": 0.41 },
    "signals": {
      "content": { "risk": 0.92, "spam_probability": 0.94, "language": "en", "flags": ["promotional_language", "urgency_markers"] }
    },
    "rule_matches": [],
    "fusion": { "method": "weighted_sum", "model_version": "v2" }
  },
  "error": null,
  "metadata": { "request_id": "req_abc123def456", "processing_time_ms": 38 }
}

When all you have is a block of text — a comment body, say — score it alone with /v1/content. It returns the same score and category probabilities without any IP or email metadata.

bash
curl -X POST https://api.formshield.dev/v1/content \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "text": "Boost your SEO rankings fast! Limited time backlink package, act now."
  }'

The signals it scores

The content model returns one fused score and breaks the risk down into named categories, each a 0.01.0 probability. The content signal also carries human-readable flags.

Spam and promotional content

Catches pharma, SEO and backlink pitches, gambling, crypto schemes, and templated bot copy. Surfaces human-readable flags like promotional_language, urgency_markers, and suspicious_links alongside a spam probability.

Cold outreach detection

A dedicated cold_email category scores unsolicited sales and partnership pitches separately from outright spam, so you can block junk while routing real-but-unwanted outreach to review instead of silently dropping it.

Fraud and scam signals

Flags phishing attempts, fake job and work-from-home offers, and requests for personal or financial information through a distinct fraud category, kept separate from generic spam scoring.

Server-side behavioral checks

When you pass form metadata, honeypot trips and submission timing fold into the same score, so obvious bot fills get caught without relying on client-side JavaScript.

Response fields

score float

Calibrated risk from 0.0 (clean) to 1.0 (almost certainly spam, fraud, or junk). The fusion of every signal sent.

decision string

allow, review, or block, derived from score against your project thresholds. Branch your form handler on this field.

categories object

Per-category probabilities: spam, fraud, and cold_email, each 0.01.0. Lets you act differently on each kind of junk.

signals.content object

The content model’s breakdown: risk, spam_probability, detected language, and a flags array of human-readable tells (promotional_language, urgency_markers, suspicious_links).

Common questions

How do I stop form spam without adding a CAPTCHA?

POST each submission to /v1/check from your form handler and branch on the returned decision: allow saves it, block drops it, review queues it. The content model scores the text server-side, so there is no CAPTCHA challenge or client-side widget for legitimate users to clear.

What is the difference between POST /v1/check and POST /v1/content?

/v1/check takes the full submission — form fields plus optional IP, email, and user agent — and fuses content, IP, and email signals into one decision. /v1/content scores a single block of text on its own when that is all you have. Both return the same 0.01.0 score and category probabilities.

How many credits does a check cost?

Each check costs 2 credits. The decision and per-category probabilities (spam, fraud, cold_email) come back in the same response, so a single 2-credit call covers all three classifications.

Next steps

Type to search…

↑↓ navigate open esc close