Furrow Forms

built for Cursor · Claude Code · Lovable · Bolt · v0

Your agent built the site. Let it finish the forms.

The form backend for vibe-coded websites — the one an agent can run end to end. Register, provision, wire, verify, over MCP and REST, so "make the contact form work" is a prompt, not a project.

paste this into your agent

Fetch furrowforms.com/ai and set up forms for this site.
agent · claude-code
[ mcp ]

› Set up forms for the Acme Astro site. Domain acmeroofing.com, these Turnstile keys, webhook to our CRM. Contact form and quote form.

⚙ bootstrap_site · client ✓ project ✓ forms (contact, quote) ✓

✎ edit src/pages/contact.astro

+ <form action="https://api.furrowforms.com/s/fp_k7m2" method="POST">
+   <div class="cf-turnstile" data-sitekey="0x4AAA…"></div>

⚙ test_webhook ·200 OK · signature verified

Done — both forms live, webhook verified.✓

Where agents get stuck

The form is where every AI-built site needs a human. Not anymore.

Every other form backend makes the agent stop and ask you to open a tab, make an account, and paste an endpoint back. Furrow is the one it can finish on its own.

01[ /api/register ]

"The agent got to the form and said: now sign up for a form service."

It doesn't have to hand off. Cold-start registration means the agent creates the account too — you read one 6-digit email code, and it keeps going.

› Set up a contact form for this site. I don't have a Furrow account yet.

02[ spam ]

"Spam hit before the first real lead did."

Honeypot, timing field, and quarantine ship in every snippet the agent writes. Add Turnstile keys and it wires those in as well.

› Add Turnstile to every form on this site with these keys.

03[ inherit ]

"Now I've got five sites and five different form setups."

One workspace, project-level inheritance. Spam rules, notification email, and webhooks are set once per site and every form picks them up — the same way, every time.

› Bootstrap forms for the new site, same setup as the last one.

How it works

You paste one prompt. Your agent does the rest.

01[ /api/register ]

It opens the account and configures the site

Your agent registers over the API — you read it one 6-digit code from your email — then sets security once on the project: Turnstile keys, allowed domains, notify emails, webhook, rate limits, file uploads.

02[ bootstrap_site ]

It spins up every form you asked for

Contact, quote, careers, newsletter — one idempotent bootstrap_site call. Each form gets a POST URL and inherits the site’s configuration automatically. Overrides only where you said so.

03[ test_webhook ]

It ships the snippet and proves it works

Generated frontend code for HTML, Astro, or Next.js — honeypot, timing field, and Turnstile included — pasted into your repo. Then a signed test delivery: 200 OK, signature verified, before it says “done.”

[ or ] prefer hands-on? The dashboard does all three with clicks — same API underneath. Open the dashboard →

Settings inheritance

Configure the website, not every form

Other form backends make you repeat configuration on every single form. In Furrow, security and routing live on the project — one website — and every form under it inherits automatically. Overrides exist, but they're opt-in.

  • [ 01 ]Rotate Turnstile keys once — every form on the site uses the new ones immediately.
  • [ 02 ]Change the notification list on the project — all forms pick it up. No sweep, no drift.
  • [ 03 ]Agencies: one client, many websites, zero repeated setup across the roster.
acme — hierarchy
[ cascade ]
client/acme-roofing

project/acmeroofing.com

  • turnstile keys
  • allowed domains
  • notify emails
  • webhook + secret
  • rate limits
  • honeypot
  • uploads + inbox
form/contactinherits all
form/quoteinherits all
form/careersinherits alloverride: notify → hr@acme.com

Agent control plane

Every product surface, operable over MCP and REST

MCP and REST share the exact same domain logic — there is no drift between what agents and humans can do. The dashboard is a thin viewer over the same API. 26 tools cover the entire product, every create is idempotent by slug, and built-in MCP resources let agents self-orient.

level 1 — the baseline

Readable by agents

An llms.txt tells agents what the product is. Most form backends stop here.

level 2 — most of the field

Specifiable by agents

An agent assembles a setup link — then hands off to a human to click, sign in, and paste an endpoint back.

level 3 — Furrow Forms

Operable by agents

An agent registers the account, creates the client, configures the site, spins up every form, pulls the snippet, and verifies the webhook. Zero clicks — starting from no account.

[ you are here ]
mcp · bootstrap_site
[ idempotent ]
{
  "client": { "name": "Acme Roofing" },
  "project": {
    "domain": "acmeroofing.com",
    "turnstile": { "site_key": "0x4AAA…", "secret": "•••" },
    "notify": ["leads@acmeroofing.com"],
    "webhook": { "url": "https://crm.example.com/hooks/furrow" }
  },
  "forms": [
    { "slug": "contact", "fields": ["name", "email", "message"] },
    { "slug": "quote",   "fields": ["name", "email", "sqft", "zip"] }
  ]
}

26 tools · a sample

  • bootstrap_site
  • create_client
  • create_project
  • update_project
  • create_form
  • update_form
  • get_snippet
  • list_submissions
  • test_webhook
  • archive_form
  • +16 more

Streamable HTTP at /mcp or local stdio, authenticated with a bearer token your agent can mint itself — cold-start registration lives at /api/register. Retries never duplicate; creates are idempotent by slug.

MCP server docs →

Spam stack

Four layers deep. On by default.

[ spam never counts toward quota ]

01[ _gotcha · _ft ]

Hidden fields

Two inputs in every generated snippet: a honeypot bots can’t resist, and a timing field that catches bot-speed submits. Caught posts are quarantined — never emailed, never counted.

02[ project-level ]

Cloudflare Turnstile

Privacy-friendly challenge, on by default. Keys live on the project — rotate once, every form follows.

03[ origin check ]

Domain allowlist

Submissions are only accepted from origins you list per project. Everything else bounces.

04[ 429 ]

Rate limiting

Per-IP, per-form. 10 requests per 60 seconds by default, configurable when you need it.

Delivery

Every submission lands twice: inbox and webhook

Email that reads like a human wrote it

Notifications go to the project's list — forms can override. Subjects and intros take template tokens with fallbacks, and your field contract keeps every email human-readable.

notification template
subject: New lead from {{project.name}} — {{name | "someone"}}
intro:   Submission #{{count}} on {{form.name}}
fields:  your form's fields, human-readable
meta:    page URL · origin · UTM · submission ID

Recipients are set per project — change the list once, every form follows.

Webhooks you can actually trust

Every delivery is HMAC-SHA256 signed with timestamp, event, and delivery-ID headers — verify authenticity, reject replays. Automatic retries with backoff, up to 8 attempts over ~24 hours, with a full delivery log per project.

delivery headers
[ verified ]
X-Furrow-Signature: sha256=9f2b41…
X-Furrow-Timestamp: 1755712803
X-Furrow-Event:     submission.created
X-Furrow-Delivery:  dlv_2mq8…

One call to test_webhook verifies the wiring before you go live.

File uploads follow the same rule. Enable them once per site and visitors attach files on the form; you — or your agent — open them in a private per-site inbox. The email and the webhook link to that inbox, never to a public download URL.

Your form, your markup

No form builder. Your form lives in your codebase.

Classic HTML POSTs redirect to your thank-you page; fetch calls get JSON back. Snippets are generated from your form's field contract — honeypot, timing field, and Turnstile included — for HTML, Astro, and Next.js.

<form action="https://api.furrowforms.com/s/fp_k7m2" method="POST">
  <input type="text" name="_gotcha" style="display:none" tabindex="-1" />
  <input type="hidden" name="_ft" value="" />
  <script>document.currentScript.previousElementSibling.value = Date.now();</script>
  <input name="name" type="text" required />
  <input name="email" type="email" required />
  <textarea name="message" required></textarea>
  <div class="cf-turnstile" data-sitekey="0x4AAA…"></div>
  <button>Send</button>
</form>

Built responsibly

Boring security, done properly

[ typescript end to end ]

IPs never stored raw

Only HMAC hashes — rate limiting works without keeping visitor IPs.

Secrets encrypted at rest

Turnstile and webhook secrets under AES-256-GCM; API responses never leak them.

Tokens shown once

API tokens are stored as hashes. Mint, copy, done — nothing to exfiltrate later.

No open redirects

Thank-you redirect targets are validated against your allowed domains.

Pricing

Two prices. No ladder.

Full pricing →

[ free ]

$0forever

The whole product — full MCP + REST, signed webhooks, the cascade. 100 submissions a month.

[ pro ]

$199per year, per workspace

10,000 submissions a month. Unlimited clients, projects, and forms. Nothing gated.

Expansion packs

[ +5,000 subs/mo each ]

Outgrow 10,000 submissions? Stack packs on Pro — no tier jumps, no overage math.

$99per year, per pack

No feature gates, no per-form fees, no "contact sales."

[ POST /s/fp_xxxx ]

Point a form at a URL.
Or point your agent at us.

Other form backends make you configure every form. Furrow configures the website — and your agent can do it for you.

paste this into your agent

Fetch furrowforms.com/ai and set up forms for this site.

Setup for agents →