docs
stormdoor.dev
GATE

/v1/forms

Screen a contact, feedback, lead or quote-request form submission in one call.

METHOD
POST
BODY CAP
24 KiB
CHECKS
42
FINDING CODES
2

POST /v1/forms screens a form submission: the message, and whatever you know about who sent it. It is the layer after a CAPTCHA, which stops scripts that cannot solve one; this catches the pitches, link drops and humans-for-hire that can.

Request#

{
  "message": "Hi, I noticed your website is not on the first page of Google. We offer SEO services.",
  "email": "hello@example-agency.com",
  "name": "Jim from example-agency.com",
  "subject": "Quick question",
  "ip": "203.0.113.7",
  "honeypot": "",
  "fill_time_ms": 1800,
  "user_agent": "Mozilla/5.0 ..."
}
Field Type Required Notes
message string yes Up to 16 KiB.
email string no Unlocks the email and domain checks.
name string no Unlocks signup.suspicious_name and form.link_in_name.
subject string no Unlocks form.link_in_subject.
ip string no The submitter’s address, forwarded by your backend. Unlocks the ip.* checks.
honeypot string no A hidden field’s value. Send "" when it stayed empty.
fill_time_ms integer no Milliseconds from render to submit. Omit when unknown; 0 means instant.
user_agent string no The submitter’s User-Agent header, not your server’s.

Every optional field unlocks checks. A check whose field is missing appears in checks_skipped with reason input and the field under requires.

Checks this gate runs#

All run concurrently, in one pass.

Runs on Checks
message Every /v1/spam check, including spam.sales_pitch, spam.off_platform_contact and the model-backed spam.likely_spam; the /v1/prompts rule checks, for messages that reach an AI triage step (the prompts model check is not run).
email The /v1/emails checks and the /v1/domains checks, on the address and its domain.
ip The /v1/ip checks.
name, subject form.link_in_name and signup.suspicious_name on the name; form.link_in_subject on the subject.
honeypot, fill_time_ms, user_agent The signup.* behaviour checks, which keep their codes.

data.matches lists the text matches from the message checks, with offsets into message and never the matched text.

Credits are the sum of the components, as for /v1/signups.

Example#

curl -s -X POST https://api.stormdoor.dev/v1/forms \
  -H "Authorization: Bearer sk_live_..." \
  -H "content-type: application/json" \
  -d '{"message":"I noticed your website is not on the first page of Google. We offer SEO services.","name":"Jim from acme.com"}'

Do not proxy the raw checks_skipped array to your end users; it is a map of what this API does not look at.

Finding codes#

Each code links to its own page with what it looks at, why it matters and what to do.

form.link_in_namemediumform.link_in_namesuspect
form.link_in_subjectlowform.link_in_subjectsuspect