riffraff

Docs

get started
with riffraff.

riffraff is a spam scoring API for contact-form submissions. you send in the content; we return a verdict, a score, and the reasons. one endpoint, one token, no SDK required.

Quickstart

five steps to your first evaluation

  1. 1

    Create your account

    Sign up with your work email. You’ll land on a dashboard with a brand-new team on the free plan (1,000 evaluations / month).

  2. 2

    Create an API token

    Go to Settings → API tokens, name it something like “Production site” and copy the token once — it’s only shown the first time.

  3. 3

    Make a test call

    From your terminal:

    curl -X POST https://api.riff-raff.dev/api/evaluate \
      -H "Authorization: Bearer YOUR_TOKEN" \
      -H "Content-Type: application/json" \
      -d '{
        "email":   "[email protected]",
        "subject": "quick question",
        "content": "Hi — do you offer…"
      }'
  4. 4

    Wire it into your form handler

    When a submission comes in, send its fields to /api/evaluate. If is_spam is true, drop it (or stash it for review). Otherwise, carry on.

  5. 5

    Watch it on the dashboard

    Every call shows up in your dashboard with the score, reasons and which team member it was attributed to. Something flagged that shouldn’t have been? Let us know and we’ll tune the rules.

API reference

POST /api/evaluate

Submit a single piece of content for spam scoring.

Headers

Authorization Bearer <your-token> — required
Content-Type application/json — required
Accept application/json — recommended

Body fields

content Required. The main message body.
subject Optional. Subject line, if your form has one.
email Optional. Sender email — used for domain / pattern checks.

Response

what you get back

A 200 OK with a JSON body:

{
  "is_spam":   true,
  "score":     270,
  "threshold": 100,
  "reasons": [
    "Spam phrases detected: \"business proposal\"",
    "Non-professional email domain"
  ]
}
  • is_spam — boolean. True when score > threshold.
  • score — integer. The summed weight of every rule that fired.
  • threshold — integer. Currently 100. The line above which we flag spam.
  • reasons — array of plain-english strings. One entry per rule that fired.

Reason catalogue

why a message got flagged

Every reason is a plain-english string. Wording can change — match on the prefix rather than the whole string if you’re doing programmatic handling.

  • “Spam phrases detected: …”
  • “Too many links detected: N links found (max allowed: M)”
  • “Suspicious HTML tags detected: <script>, <iframe>”
  • “Non-professional or suspicious email domain(s) detected: …”
  • “Cyrillic characters detected”
  • “Content too short: only N words (minimum M expected)”
  • “Cold pitch detected: service offering language”
  • “Malicious link detected: dark web marketplace domain”
  • “Bot-generated name pattern detected”

Errors

what can go wrong

Status When
401 Missing, malformed or revoked token.
402 Your team’s monthly quota is spent. Response body includes plan, limit and used.
422 Validation failed — most commonly a missing content field.
500 Something unexpected on our end. Retry with exponential backoff; if it persists, shout.

Statamic

drop-in addon

If your site runs on Statamic, the addon takes care of wiring submissions through riffraff, stashing spam reasons on the form submission, and keeping your inbox clean. Install it, paste your token, done.

Get in touch at [email protected] for the current addon package details.

Teams & billing

share the plan with your team

Every account comes with a team. Invite colleagues from Settings → Team and they all get their own login and their own API tokens, but share the plan, usage quota and dashboard.

Need more than pro’s 250k / month? Drop us a line and we’ll size something up.

FAQ

quick questions

Do you store the content I send?

Only the metadata we need to show you your usage: email, subject, score, reasons, timestamp. The full message body isn’t kept.

How is the score calculated?

A stack of deterministic rules, each with a weight. They run in isolation, scores are summed, and if the total exceeds threshold the message is flagged. No opaque ML — you get a reason for every point.

What happens if I hit my limit mid-month?

Calls return 402 with your plan’s limit and used count. Upgrade from Settings → Billing and you’re back in within a minute.

Can I run this in front of something other than Statamic?

Yes — the API is plain HTTP. The Statamic addon is a convenience; plenty of customers call the API directly from Laravel, Node, Go, or whatever stack they’re on.

Something got flagged that shouldn’t have.

Send the details to [email protected]. We tune rules continuously based on real false-positive reports.

ready to stop reading junk?

free tier, no card, ~30 seconds to first evaluation.