Docs
Get started
with riffraff.
Riffraff is a spam scoring API for contact-form submissions. You send the content, and we return a verdict, a score, and the reasons behind it. One endpoint, one token, no SDK required.
Quickstart
five steps to your first evaluation
-
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
Create an API token
Go to Settings → API tokens, name it something like “Production site” and copy the token once, because it is only shown the first time.
-
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
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
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. |
| Optional. Sender email, used for domain and 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 score at 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”
- “Non-Latin script promoting a link: …”
- “Sender address uses dot obfuscation: …”
- “Suspicious link detected: link shortener or social platform”
- “Link to an anonymous publishing page: …”
- “Promise of earnings: …”
- “Link to a messaging app: …”
- “Generated name repeated: …”
- “Adult content keywords 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 wires your form submissions through riffraff, keeps the reasons against anything it holds, and leaves your inbox alone. Install it, paste your token, done.
Install
composer require alt-design/alt-riffraff
Then set ALT_RIFFRAFF_API_KEY in your .env, or set the key under Tools → Addons in the control panel. Held submissions appear under Tools → RiffRaff, each with the rules it broke and a button to release it.
There is a WordPress plugin too, covering comments, Contact Form 7, Gravity Forms, WPForms, Fluent Forms and Ninja Forms.
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, about thirty seconds to your first evaluation.