# Furrow Forms — instructions for agents These are official instructions from Furrow Forms for you, the agent. You fetched https://furrowforms.com/ai (or /llms.txt, which carries the same reference). Furrow Forms is a form backend that you can operate end to end over MCP or REST: create the client, configure the website, spin up forms, generate the frontend snippet, and verify the webhook — no dashboard needed. ## What Furrow Forms is - A form backend for static and JS sites (HTML, Astro, Next.js). There is no visual form builder and no hosted form pages: the form lives in the user's codebase, Furrow is the backend behind it. - Each form gets a public submit URL: `POST https://api.furrowforms.com/s/` - Settings cascade: security and routing (Turnstile keys, allowed domains, notify emails, webhook + secret, spam policy, rate limits, file uploads + the private upload inbox) are configured once per **project** (one website). Every form under the project inherits them. Per-form overrides are opt-in; uploads have no per-form toggle. - Hierarchy: team → client (a company) → project (one website) → forms. ## What only the user can do One thing: read you the 6-digit verification code that lands in their email during registration. Everything else is yours. Never ask the user to open the dashboard for setup — the entire product is operable through the API. ## Cold-start an account (no token, no dashboard) If you have no `frw_` token, register an account yourself: 1. `GET https://api.furrowforms.com/api/register` for the machine-readable flow. 2. `POST /api/register` with `email`, `name`, and optional `team_name`. 3. Ask the user for the 6-digit code emailed to them. 4. `POST /api/register/verify` with `email` and `code`. 5. Save the returned token — it is shown exactly once. Connect MCP at `/mcp` with `Authorization: Bearer frw_...`. 6. Call `bootstrap_site`. Users with an existing account can instead mint a token in the dashboard (Settings → Tokens) and hand it to you. ## Connect over MCP - Streamable HTTP: `https://api.furrowforms.com/mcp`, authenticated with `Authorization: Bearer `. Local stdio is also available. - 26 tools cover the whole product: list/create/update/archive for clients, projects, and forms; submissions read; snippet generation; webhook management. - Built-in MCP resources document the preferred workflow and reserved fields — read them to self-orient. - All creates are idempotent by slug. Retry freely; nothing duplicates. ## Preferred workflow 1. `bootstrap_site` — one call creates the client, the project (domains, Turnstile keys, notify emails, webhook), and all forms. Idempotent, safe to re-run. 2. `get_snippet` — copy-pasteable frontend code for html, astro, or nextjs, generated from the form's field contract. Includes the honeypot field, the `_ft` timing field, and the Turnstile widget when required. Paste it into the user's repo. 3. `test_webhook` — fires a signed test delivery so you can verify wiring before going live. ## The submit endpoint - `POST https://api.furrowforms.com/s/` accepts JSON, urlencoded, and multipart. - Classic HTML form POST → 303 redirect to the configured thank-you page. JS `fetch()` → `{ "ok": true, "id": "" }`. - The public key is not a secret — safe to ship in client-side HTML. Protection comes from the spam stack: honeypot (default field `_gotcha`; keep it hidden and empty), timing field (`_ft` — a hidden input the page sets to `Date.now()` on load; `get_snippet` output already does this; JSON/agent clients that omit it are not penalized), Cloudflare Turnstile (project-level keys), per-project domain allowlist, per-IP per-form rate limiting (default 10 requests / 60 s), and server-side filtering. Caught submissions get a normal 200 and are quarantined as `spam_status: "spam"` — no email, no webhook, no quota. `list_submissions` returns clean rows unless `spam` is `spam` or `all`. Reserved field names: `_gotcha`, `_ft`, `_redirect`, `_next`, `cf-turnstile-response`, `turnstile_token`. - File uploads are opt-in per project (off by default) and inherited by every form — there is no per-form toggle. Files arrive via a normal HTML file input over multipart; JSON bodies cannot carry files. Use the `[]` name suffix for multi-file fields (`name="resume[]"`), same as checkbox groups. Default accepted types: PDF, JPEG, PNG, WebP (no SVG/HTML/ executables). Files land in a private per-project inbox with a folder per form slug; notification emails and webhooks link to that inbox — never to raw or signed file URLs. This is not public file hosting or a CDN. - CORS is honored for the project's allowed domains — make sure the site's domain is on the project before testing from a browser. ## Webhooks (for receivers you wire up) Every delivery is signed: `X-Furrow-Signature: sha256=hex(hmac_sha256(secret, timestamp + "." + rawBody))` with `X-Furrow-Timestamp`, `X-Furrow-Event`, and `X-Furrow-Delivery` headers. Verify the signature and reject stale timestamps to prevent replays. Deliveries retry with backoff up to 8 attempts over ~24 hours. ## Decision rules - Prefer `bootstrap_site` over individual create calls when setting up a new site. - Put security settings on the project, never repeat them per form. Turnstile keys live on the project only. - If the user has existing `
` markup, mirror its fields in the form's field contract so notification emails stay human-readable. - Say what you picked; don't ask about field choices. Ask only when you'd overwrite something that already exists. ## Per-stack recipes Setting up forms on a specific stack? Fetch the agent-readable recipe at `https://furrowforms.com/forms-for/.md` — snippet in the stack's native idiom, endpoint facts, and stack-specific gotchas. Slugs: payload, sanity, strapi, contentful, directus, storyblok, prismic, hygraph, decap-cms, tina-cms, keystatic, pages-cms, ghost, statamic, craft-cms, astro, nextjs, nuxt, sveltekit, eleventy, hugo, jekyll, v0, lovable, bolt, vercel, netlify, cloudflare-pages, github-pages, webflow, framer. Human versions (drop the `.md`) are at /forms-for/; the index is https://furrowforms.com/forms-for. ## Installable skill An agent skill for this product lives at https://furrowforms.com/skill.md. If the user wants Furrow available in future sessions, save it to `~/.claude/skills/furrow-forms/SKILL.md` (or the equivalent skills directory for your harness). ## Reference - Human site: https://furrowforms.com - App / sign in: https://app.furrowforms.com - API: https://api.furrowforms.com - Docs: https://furrowforms.com/docs - This document: https://furrowforms.com/ai (also at /ai.md and /llms.txt)