All docs
4 min read

Spam classification

A submission lands in spam when one (or more) of three layers flagged it. Knowing which layer is what makes triage fast.

The three layers

Submissions pass through three independent filters before being saved. Any one of them can route the submission to the spam folder. The first one that flags wins, and the field spam_reason records which layer fired.

Layer Triggers when spam_reason value
1. Captcha hCaptcha or reCAPTCHA token is missing or invalid (returns 422 — never lands as spam)
2. Honeypot A hidden honeypot field was filled in honeypot
3. Akismet Akismet's classifier returns is_spam: true akismet
4. Heuristics Internal rules — repeated identical payloads, blocked-domain lists, suspicious link density heuristics:<rule>
5. AI moderation AI moderation score crosses the threshold (default 80/100) ai_moderation:<score>
6. Custom rules A custom rule on the form matched rule:<rule_id>
Manual You marked it as spam from the dashboard or via the MCP mark_as_spam tool manual:<source>

Captcha failures don't actually create a spam record — they're rejected at the wall with a 422. Everything below the captcha layer accepts the submission and routes it.

Where to see the reason

In the dashboard:

  1. Open the form's submissions tab
  2. Switch to the Spam folder (top-right tab)
  3. Click any submission

The detail panel shows spam_reason near the top. Hover for the human-readable description.

Via the API:

GET /api/v1/forms/{public_id}/submissions/{id}

The response includes spam_reason and (when the layer was AI moderation) ai_moderation_score.

Via MCP:

get_submission { id: "01HFXX..." }

Same field surfaces.

Marking something not-spam

Three ways:

  1. Dashboard. Open the submission → click Not spam. It moves to received and the reason is cleared.
  2. API. PATCH /api/v1/forms/{public_id}/submissions/{id} with { "status": "received" }.
  3. MCP. update_submission { id, status: "received" } or bulk_submissions { ids: [...], action: "mark_not_spam" } for batches up to 500.

Marking not-spam moves the record but doesn't suppress future flags. The next submission from the same source might re-flag for the same reason.

We don't retrain on your corrections

Be honest, useful answer: marking not-spam doesn't feed back into our spam classifiers. The external spam classifier is a black box that doesn't accept per-customer feedback signals. Our heuristics are static rules. AI moderation runs on a frozen prompt + score threshold.

If a specific kind of legitimate submission keeps getting flagged, the right move is:

  • For Akismet false positives: mark the sending domain or email as a custom rule allow-list (Form → Spam → Custom rules → "always allow if email matches…").
  • For honeypot false positives: check that your form isn't auto-filling honeypot fields via password manager. Rename the honeypot field if it does.
  • For AI moderation false positives: raise the threshold per-form (Form → AI moderation → score threshold). Default 80; raising to 90 dramatically reduces false positives at the cost of letting some borderline content through.

These are knobs you control. Marking individual submissions, while useful for cleaning your inbox, does not adjust those thresholds for future submissions.

Marking as spam manually

If something legitimate-looking gets through and you want it in spam:

  • Dashboard. Submission → Mark as spam.
  • MCP. mark_as_spam { id } — sets status: spam, spam_reason: manual:mcp.

Manual spam is identical to auto-flagged spam in the database. It just has manual:<source> as the reason for audit clarity.

Disabling a layer

You can turn off any of the auto-classification layers per form, under Form → Spam protection:

  • Captcha: required for hosted forms; optional for legacy forms (we recommend keeping it on)
  • Honeypot: on by default
  • Akismet: on by default; opt-out is a single toggle. See sub-processors for the regional and DPA implications
  • AI moderation: Pro+ only; on by default
  • Heuristics: on for all forms; not configurable individually, but the underlying rules are documented at Spam → How it works

Disabling layers means more spam in your inbox. We don't recommend disabling more than one at a time.

What's next