Real enquiries.Nothing else.
Every submission passes four layers of spam defence and an AI validation check before it reaches you. What lands in your inbox is a genuine enquiry from a real person, formatted, stored, and ready to answer.
Hosted for you · Live in under an hour · 4 lines of JavaScript
// the entire integrationawait fetch('https://api.formalytics.io/api/form-submit', { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-API-Key': 'fts_9c41…' }, body: JSON.stringify(Object.fromEntries(new FormData(form)))});- name
- Dagny Osei
- d.osei@harlow.co
- enquiry_type
- New patient (physiotherapy)
- preferred_slot
- Weekday mornings
- message
- Referred by my GP. Is there a wait list for the Thursday clinic?
The form works. That's the problem.
It accepts everything. Bots, SEO pitches, gibberish, someone testing whether your site is worth attacking. And somewhere in there, the customer you actually wanted.
Of submissions to a typical unprotected contact form are automated or unsolicited. You read all of them to find the other 8%.
A month, triaging a form inbox by hand. Not answering enquiries, just deciding which ones are real.
Enquiry is worth more than a year of the subscription. Once you stop trusting the inbox, you start skimming, and skimming is how you lose them.
Illustrative figures based on typical small-business contact form patterns, not measured customer data.
Live on your site in under an hour.
- STEP 01
Sign up your site
Your business name, the inbox that should receive enquiries, and the domains your form runs on.
- STEP 02
Copy your key
An
fts_key scoped to your site alone: your inbox, your domains, your quota, your data. - STEP 03
Paste four lines
A
fetchto one URL with one header. React, Astro, WordPress, Webflow, or plain HTML. - STEP 04
Real enquiries land
Filtered, formatted, stored, and visible in your dashboard. Add a field to the form and it just appears.
Everything a form needs. Nothing it doesn't.
A filter that reads
Every submission is read for meaning, not just pattern-matched. Sales pitches, gibberish, scams and off-topic messages are held back. Genuine enquiries pass straight through, with the reasoning recorded either way.
Four layers before the AI
Origin lock, honeypot, per-IP burst guard, and a rate limit stop automated traffic outright. On by default. It is the standard posture, not an upgrade.
Turnstile & hCaptcha
Drop in a challenge widget and Formalytics verifies the token server-side before anything else runs. Optional, and most sites never need it once the other layers are on.
Your own view of everything
Submissions, search, volume over time, and a running count of what the filter caught and why. Export any date range as CSV whenever you need it.
Send whatever the form has
No field configuration, because there is no schema. emailSubject is the only required field. budget, preferred_slot, anything else is accepted, stored, and emailed as-is.
Email you can actually read
Multipart HTML and plain text, rendered as labelled rows. Custom templates let you match your brand, and field control means a fifteen-field form can send a four-field notification.
One site, many forms
Contact, careers, quote request, support: each with its own subject line, own template, and own recipient, all under one key.
Webhooks, Slack, Discord
Push every clean enquiry into your CRM, Zapier, n8n, or a team channel. Fire-and-forget, so a slow endpoint never delays the visitor.
Sign up and go
Create your account, add a site, get a key. No sales call, no onboarding queue. Rotate a key yourself in two clicks if it is ever exposed.
Four layers stop the machines. The fifth reads what got through.
A CAPTCHA proves someone is human. It has nothing to say about a human who is deliberately wasting your time, and that is most of what reaches a modern contact form.
| Layer | What it does | Response | What the sender learns |
|---|---|---|---|
| Origin lock | Origin checked against your allowlist | 403 | A stolen key is useless from any other domain |
| Honeypot | Hidden field, invisible to people, irresistible to scrapers | 200 | Nothing, it believes it succeeded |
| IP burst guard | Throttles repeated requests from a single address | 429 | Volume attacks die in the first minute |
| Rate limit | Adaptive ceiling on submission volume | 429 | A targeted flood can't drain your quota |
| AI validation | Reads the submission for meaning and intent | 200 | Nothing, filtered and delivered look identical |
Nothing that gets stopped is ever told it was stopped.
The honeypot returns a success response that is deliberately indistinguishable from the real one. So does the AI filter. A bot logs a win and never comes back to probe for the stop it never hit; a person pitching SEO services believes their message was sent. Neither one learns anything they could adapt against, and neither one reaches you.
The layers run cheapest first, so the overwhelming majority of junk is rejected before it costs anything to process, and the ones that stop a request give away nothing about where it stopped.
- Unsolicited sales and SEO pitches
- Gibberish and keyboard-mash tests
- Link-farm and gambling spam
- Obvious scams and phishing attempts
- Messages with no discernible enquiry
- Anything asking about what you do
- Short messages, because brevity is not spam
- Complaints and difficult feedback
- Enquiries in any language you accept
- Anything the filter is unsure about
- Every filtered message is kept, not deleted
- Each one shows the reason it was held
- Release one to your inbox in a click
- Tune the threshold for your business
- Turn it off entirely if you would rather
The filter errs toward delivery. When a submission is ambiguous it goes to your inbox flagged, not to the filtered list. A missed enquiry costs more than a junk one.
See what came in, and what never had to.
Every enquiry in one searchable list, volume over time, and a running count of what the filter held back with the reason for each. Export any date range as CSV.
- Submissions
- 231
- this month
- Reached your inbox
- 19
- genuine enquiries
- Filtered
- 212
- kept, reviewable
- Released by you
- 0
- nothing wrongly held
| Received | From | Message | Verdict |
|---|---|---|---|
| 14:22 | Dagny Osei | Referred by my GP. Is there a wait list for the Thursday clinic? | Delivered |
| 13:47 | growth@rankboost-pro.net | We can guarantee first-page Google results in 30 days… | Sales pitch |
| 11:09 | Tomas Wrede | Do you do home visits for post-op rehab? My father can't travel. | Delivered |
| 10:55 | asdfkj | asdkfj alskdjf test test | No enquiry |
| 09:31 | Priya Raghunathan | What's the cost for six sessions? Do you invoice insurers directly? | Delivered |
One endpoint. Here is the contract.
Request
| Field | Required | Validation |
|---|---|---|
| X-API-Key | Header | Issued per site, rotatable by you at any time |
| emailSubject | Yes | Non-empty string. Becomes the notification's subject line. |
| No | Email format, validated only if present | |
| (hidden field) | No | A field only automated clients fill. Its name is issued with your key. |
| …anything else | No | String, number, boolean, null, or object, accepted as-is |
- 200Accepted, or silently filtered
- 400Validation or CAPTCHA failed
- 401Missing or unknown API key
- 403Origin not on your allowlist
- 429Rate or burst limit exceeded
Delivered and filtered are both 200. Nothing can tell them apart.
- Serverless, no cold infrastructure to share
- CORS preflight cached for 24 hours
- Payloads schema-checked before anything is stored
- Multipart HTML and plain-text email
- Field count and length caps on notifications
- Works with any host, framework or CMS
- Every request authenticated by site key
- Per-site origin allowlisting
- Two-click key rotation
- Signed, httpOnly dashboard sessions
- Every submission stored with its verdict
- Submissions isolated per site
- Delete any submission, or all of them
Exact thresholds, the hidden field's name, and the services behind each stage are issued with your key and kept out of public documentation. Publishing them would only help someone build around them.
“Two hundred and thirty-one submissions. Nineteen reached my inbox.”
This is a scripted narrative built from the problems Formalytics was written to solve. It is a composite persona, not a real customer, and it is not a testimonial.
- Act 01The setup40 real · ~600 junk00:00
I manage a physiotherapy clinic. Three practitioners, and about forty new-patient enquiries a month through the website. That form is where our new business comes from.
00:13It is also where roughly six hundred pieces of garbage a month came from.
- Act 02The escalationcaptcha added · junk continues00:19
Bots at first. We added a captcha, and that helped for a while. Then it turned into people. Actual humans, typing “I can improve your Google ranking” into a patient enquiry form.
A captcha does nothing about a real person wasting your time on purpose.
00:33 - Act 03The cost1 enquiry missed00:40
And what that does to you is subtle. You stop opening the notifications when they arrive. You batch them up for the end of the day. You skim.
One Thursday I skimmed past a woman asking about post-surgical rehab. I found it eleven days later. She had already gone somewhere else.
00:52 01:04That was the point I stopped treating it as an annoyance.
- Act 04The change231 in · 19 delivered01:08
The developer who built our site set Formalytics up for us. Took him about twenty minutes. But the thing that actually sold me was the first week’s number.
Two hundred and thirty-one submissions. Nineteen reached my inbox. All nineteen were real.
01:20 01:29It is not just blocking bots. There is an AI reading the content of every message, and it can tell the difference between somebody asking about our Thursday clinic and somebody pitching SEO in a message field. I could not have written a rule for that. Nobody could.
01:47And I can see everything it caught. It is all in the dashboard, every one it held and the reason. For the first fortnight I checked every single one, waiting for it to eat a real patient enquiry. It never did.
- Act 05The new normalinbox trusted
Now my inbox is small, and I trust it again. When something arrives, I open it.
02:04
Everyone forwards your form. We decide what's worth forwarding.
| Formalytics | Formspree | Netlify Forms | Basin | |
|---|---|---|---|---|
| Reads submissions for intent | Yes, AI validation | No | No | No |
| Bot & spam filtering | 5 layers | Honeypot, reCAPTCHA | Honeypot, Akismet | Rule-based filtering |
| Shows why a message was held | Per message | Spam folder only | Spam folder only | Spam folder only |
| Field control in notifications | Yes | No | No | No |
| Custom email templates | Yes | Paid plans | No | Paid plans |
| Works on any host | Yes | Yes | Netlify only | Yes |
| Pricing model | Per site | Per site | Per site | Per site |
| Free plan | No | Yes, limited | Yes, limited | Yes, limited |
| Time to first submission | ~5 min | ~5 min | ~10 min | ~5 min |
Two honest rows there. We do not have a free plan, and every one of these is priced per site, so the question is not which is cheapest. It is whether a form that only forwards is worth the same as one that decides.
Stop the machines at $9. Read the message at $19.
Spam defence for one domain, without the AI layer.
- 500 submissions a month
- Origin lock & honeypot
- Rate limiting
- Up to 5 forms
- 1 domain
- Email delivery
- Dashboard & CSV export
- AI validation
- CAPTCHA support
- Webhooks
- Custom email templates
- Slack & Discord
Every filter layer, including the one that reads the message.
- 5,000 submissions a month
- Full AI validation
- All five filter layers
- CAPTCHA support
- Unlimited forms and domains
- Email + webhook delivery
- Custom email templates
- Tunable filter threshold
- Slack & Discord delivery
- 12-month history
Several businesses, brands or locations under one account.
- Volume priced across all sites
- Everything in Pro
- One dashboard, every site
- Consolidated invoicing
- Filter rules tuned per business
- Priority support
Billed per site. Starter covers the automated traffic; Pro adds the layer that reads what got through. Running several businesses, brands or locations? Multi-business pricing is worked out across your whole portfolio. Talk to us rather than adding sites one at a time.
Before you sign up.
403 before anything else runs. If a key ever does need replacing, rotation takes two clicks.$ curl -X POST https://api.formalytics.io/api/form-submit \ -H "X-API-Key: fts_9c41…" \ -d '{"emailSubject":"Contact Form","name":"Test"}' HTTP/2 200{ "success": true, "id": "sub_8f2a41" } $