{"data":{"slug":"furrow-forms","verdict":"passed","scannedAt":"2026-10-26T05:58:58.999Z","scannerVersion":"1.2.1","latest":{"id":"3cd269ff-78f3-4c8e-bb61-8e961237641a","createdAt":"2026-10-26T05:58:58.999Z","version":"1.0.1","trigger":"tools_changed","scannerVersion":"1.2.1","verdict":"passed","checks":[{"id":"hidden_instructions","status":"passed","findings":0,"label":"Hidden instructions"},{"id":"hidden_text","status":"passed","findings":0,"label":"Invisible text"},{"id":"sensitive_access","status":"passed","findings":0,"label":"Access to credentials"},{"id":"remote_code","status":"passed","findings":0,"label":"Downloads and runs code"},{"id":"exfiltration","status":"passed","findings":0,"label":"Sends data out"},{"id":"secrets","status":"passed","findings":0,"label":"Leaked secrets"}],"findings":[],"toolCount":27},"history":[{"id":"3cd269ff-78f3-4c8e-bb61-8e961237641a","createdAt":"2026-10-26T05:58:58.999Z","version":"1.0.1","trigger":"tools_changed","scannerVersion":"1.2.1","verdict":"passed","checks":[{"id":"hidden_instructions","status":"passed","findings":0,"label":"Hidden instructions"},{"id":"hidden_text","status":"passed","findings":0,"label":"Invisible text"},{"id":"sensitive_access","status":"passed","findings":0,"label":"Access to credentials"},{"id":"remote_code","status":"passed","findings":0,"label":"Downloads and runs code"},{"id":"exfiltration","status":"passed","findings":0,"label":"Sends data out"},{"id":"secrets","status":"passed","findings":0,"label":"Leaked secrets"}],"findings":[],"toolCount":27},{"id":"9057992a-9aaf-472e-838e-216433dce671","createdAt":"2026-10-25T22:45:39.999Z","version":"1.0.1","trigger":"new","scannerVersion":"1.2.1","verdict":"passed","checks":[{"id":"hidden_instructions","status":"passed","findings":0,"label":"Hidden instructions"},{"id":"hidden_text","status":"passed","findings":0,"label":"Invisible text"},{"id":"sensitive_access","status":"passed","findings":0,"label":"Access to credentials"},{"id":"remote_code","status":"passed","findings":0,"label":"Downloads and runs code"},{"id":"exfiltration","status":"passed","findings":0,"label":"Sends data out"},{"id":"secrets","status":"passed","findings":0,"label":"Leaked secrets"}],"findings":[],"toolCount":null}],"endpoint":{"url":"https://api.furrowforms.com/mcp","transport":"streamable-http","status":"ok","checkedAt":"2026-10-26T05:57:49.558Z","toolCount":27,"latencyMs":749,"error":null},"tools":[{"name":"archive_client","title":"Archive client","description":"Use to archive a client. Do not use this as a hard delete. There is no unarchive tool in v1.","access":"delete","accessDeclared":true,"hash":"252eb30d5c21f6cb873f2a1146de7c319dbce90b8ff0ef6abf7f418d695c15b2","inputSchema":"{\n  \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n  \"properties\": {\n    \"client_id\": {\n      \"description\": \"Client id from list_clients or create_client.\",\n      \"format\": \"uuid\",\n      \"pattern\": \"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$\",\n      \"type\": \"string\"\n    }\n  },\n  \"required\": [\n    \"client_id\"\n  ],\n  \"type\": \"object\"\n}"},{"name":"archive_form","title":"Archive form","description":"Use to archive a form so public submit returns 404. Do not use this as a hard delete.","access":"delete","accessDeclared":true,"hash":"02e2c8cd17060a559850deca0172fb801d6087fa1c57c26733acb1b98c99e5e8","inputSchema":"{\n  \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n  \"properties\": {\n    \"form_id\": {\n      \"description\": \"Form id from list_forms, create_form, or bootstrap_site.\",\n      \"format\": \"uuid\",\n      \"pattern\": \"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$\",\n      \"type\": \"string\"\n    }\n  },\n  \"required\": [\n    \"form_id\"\n  ],\n  \"type\": \"object\"\n}"},{"name":"archive_project","title":"Archive project","description":"Use to archive a website. Archived projects reject public submit. Do not use this as a hard delete. There is no unarchive tool in v1.","access":"delete","accessDeclared":true,"hash":"29c628305c3c276e498ffb8a46baca453adeb6629187a9ed98428fcd67629dea","inputSchema":"{\n  \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n  \"properties\": {\n    \"project_id\": {\n      \"description\": \"Project (website) id from list_projects, create_project, or bootstrap_site.\",\n      \"format\": \"uuid\",\n      \"pattern\": \"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$\",\n      \"type\": \"string\"\n    }\n  },\n  \"required\": [\n    \"project_id\"\n  ],\n  \"type\": \"object\"\n}"},{"name":"bootstrap_site","title":"Bootstrap site","description":"Use this to stand up a client, one website (project), and its forms in a single call. name/slug are the client; optional project_name/project_slug default to the same. Free accounts cannot create a fourth active project — call create_upgrade_link if bootstrap_site returns plan_limit. Operator tokens (all workspaces) must pass team_id from list_teams. Team-scoped tokens may omit team_id and cannot target another workspace. Idempotent on client, project, and form slugs. Site settings (domains, Turnstile, notify emails, webhook, email templates, uploads) live on the project. Email templates support {{project.name}}, {{project.slug}}, {{form.name}}, {{form.slug}}, {{count}} (1-based clean submissions on this form, including the current one), and any submission field such as {{name}} or {{email}}. Use a fallback with {{name | \"New submission\"}}. Missing fields render empty and never error. Do not pass HTML; Furrow renders one owned layout. Plans are capacity, not a feature ladder. Free: one workspace, 100 clean submissions/month pooled on the team, 3 active (non-archived) projects, 30-day submission retention, and email.footer_mode / branding.mode stay furrow. Yearly ($199/year): extra workspaces, 10,000 submissions/month, unlimited projects, 730-day retention, branding.mode furrow | off | agency. Expansion packs are $99/year each and add 5,000 submissions/month on a yearly account. MCP, webhooks, snippets, inheritance, Turnstile, and email templates stay available on free. Spam, honeypot, and rejected posts do not count. Use create_upgrade_link to hand a human a Stripe Checkout (or Customer Portal) URL. Pass product=expansion on a yearly team to add a pack. Checkbox groups, select multiple, and other multi-value HTML fields must use a [] suffix on the name (name=\"services[]\") or only the last checked value is stored. Put services[] on field_contract.name too. JSON/fetch should send a real array without brackets ({ \"services\": [\"a\", \"b\"] }) and must not use Object.fromEntries(formData) — use formData.getAll(\"services\"). Single checkbox, select, or combobox: no brackets. File inputs use multipart POST (name=\"resume[]\" for multiple). Enable uploads on the project first. Downloads are the project inbox at files_url, with the form slug as a folder — never put that URL in a public snippet. Do not use when you only need to patch an existing form — call update_form.","access":"write","accessDeclared":true,"hash":"632dfac652b6a90e9f321769474ec45e230ea395978df8dd49d6c68798c36360","inputSchema":"{\n  \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n  \"properties\": {\n    \"allowed_domains\": {\n      \"description\": \"Hostnames allowed to post to this project's forms (example.com, www.example.com). Empty accepts any origin.\",\n      \"items\": {\n        \"maxLength\": 253,\n        \"minLength\": 1,\n        \"type\": \"string\"\n      },\n      \"type\": \"array\"\n    },\n    \"default_redirect_url\": {\n      \"anyOf\": [\n        {\n          \"format\": \"uri\",\n          \"type\": \"string\"\n        },\n        {\n          \"type\": \"null\"\n        }\n      ],\n      \"description\": \"Where classic HTML posts redirect after success. Null returns JSON/inline success instead.\"\n    },\n    \"email\": {\n      \"description\": \"Notification email template for the project: subject, from_name, intro, footer_mode, include_meta.\",\n      \"properties\": {\n        \"footer_mode\": {\n          \"description\": \"furrow shows the Furrow footer, minimal shows a one-line footer, off hides it (yearly plans only).\",\n          \"enum\": [\n            \"furrow\",\n            \"minimal\",\n            \"off\"\n          ],\n          \"type\": \"string\"\n        },\n        \"from_name\": {\n          \"description\": \"Display name on the From line of notification emails.\",\n          \"maxLength\": 120,\n          \"minLength\": 1,\n          \"type\": \"string\"\n        },\n        \"include_meta\": {\n          \"description\": \"Include submission metadata (IP, user agent, referrer, timestamp) below the fields.\",\n          \"type\": \"boolean\"\n        },\n        \"intro\": {\n          \"anyOf\": [\n            {\n              \"maxLength\": 4000,\n              \"type\": \"string\"\n            },\n            {\n              \"type\": \"null\"\n            }\n          ],\n          \"description\": \"Plain-text paragraph above the submitted fields. Supports {{tokens}}. Null removes it.\"\n        },\n        \"subject\": {\n          \"description\": \"Notification email subject. Supports {{tokens}} such as {{form.name}} or {{name}}.\",\n          \"maxLength\": 300,\n          \"minLength\": 1,\n          \"type\": \"string\"\n        }\n      },\n      \"type\": \"object\"\n    },\n    \"forms\": {\n      \"default\": [],\n      \"description\": \"Forms to create or update on the site, matched by slug. Re-running is safe.\",\n      \"items\": {\n        \"properties\": {\n          \"email\": {\n            \"description\": \"Per-form subject and intro overrides for the notification email.\",\n            \"properties\": {\n              \"intro\": {\n                \"anyOf\": [\n                  {\n                    \"maxLength\": 4000,\n                    \"type\": \"string\"\n                  },\n                  {\n                    \"type\": \"null\"\n                  }\n                ],\n                \"description\": \"Per-form intro override. Supports {{tokens}}. Null falls back to the project intro.\"\n              },\n              \"subject\": {\n                \"anyOf\": [\n                  {\n                    \"maxLength\": 300,\n                    \"minLength\": 1,\n                    \"type\": \"string\"\n                  },\n                  {\n                    \"type\": \"null\"\n                  }\n                ],\n                \"description\": \"Per-form subject override. Supports {{tokens}}. Null falls back to the project subject.\"\n              }\n            },\n            \"type\": \"object\"\n          },\n          \"field_contract\": {\n            \"anyOf\": [\n              {\n                \"items\": {\n                  \"properties\": {\n                    \"label\": {\n                      \"anyOf\": [\n                        {\n                          \"maxLength\": 120,\n                          \"minLength\": 1,\n                          \"type\": \"string\"\n                        },\n                        {\n                          \"type\": \"null\"\n                        }\n                      ],\n                      \"description\": \"Human label used in the snippet and notification email. Defaults to the field name.\"\n                    },\n                    \"name\": {\n                      \"description\": \"Posted field name. HTML checkbox groups / multi-select must end in [] (services[]) or only the last value is stored. JSON arrays omit the brackets.\",\n                      \"maxLength\": 80,\n                      \"minLength\": 1,\n                      \"type\": \"string\"\n                    },\n                    \"report\": {\n                      \"default\": false,\n                      \"description\": \"Include this field in dashboard summaries and reports.\",\n                      \"type\": \"boolean\"\n                    },\n                    \"type\": {\n                      \"description\": \"text, email, textarea, file, etc. type=file emits a file input in get_snippet.\",\n                      \"maxLength\": 40,\n                      \"minLength\": 1,\n                      \"type\": \"string\"\n                    }\n                  },\n                  \"required\": [\n                    \"name\",\n                    \"type\"\n                  ],\n                  \"type\": \"object\"\n                },\n                \"type\": \"array\"\n              },\n              {\n                \"type\": \"null\"\n              }\n            ],\n            \"description\": \"Declared fields (name, type, label, report). Drives get_snippet and the email layout. Null clears it.\"\n          },\n          \"fields\": {\n            \"description\": \"Shorthand for field_contract: the fields this form posts.\",\n            \"items\": {\n              \"properties\": {\n                \"label\": {\n                  \"anyOf\": [\n                    {\n                      \"maxLength\": 120,\n                      \"minLength\": 1,\n                      \"type\": \"string\"\n                    },\n                    {\n                      \"type\": \"null\"\n                    }\n                  ],\n                  \"description\": \"Human label used in the snippet and notification email. Defaults to the field name.\"\n                },\n                \"name\": {\n                  \"description\": \"Posted field name. HTML checkbox groups / multi-select must end in [] (services[]) or only the last value is stored. JSON arrays omit the brackets.\",\n                  \"maxLength\": 80,\n                  \"minLength\": 1,\n                  \"type\": \"string\"\n                },\n                \"report\": {\n                  \"default\": false,\n                  \"description\": \"Include this field in dashboard summaries and reports.\",\n                  \"type\": \"boolean\"\n                },\n                \"type\": {\n                  \"description\": \"text, email, textarea, file, etc. type=file emits a file input in get_snippet.\",\n                  \"maxLength\": 40,\n                  \"minLength\": 1,\n                  \"type\": \"string\"\n                }\n              },\n              \"required\": [\n                \"name\",\n                \"type\"\n              ],\n              \"type\": \"object\"\n            },\n            \"type\": \"array\"\n          },\n          \"name\": {\n            \"description\": \"Form display name, e.g. Contact or Quote request.\",\n            \"maxLength\": 120,\n            \"minLength\": 1,\n            \"type\": \"string\"\n          },\n          \"notify_emails_override\": {\n            \"anyOf\": [\n              {\n                \"items\": {\n                  \"format\": \"email\",\n                  \"pattern\": \"^(?!\\\\.)(?!.*\\\\.\\\\.)([A-Za-z0-9_'+\\\\-\\\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\\\-]*\\\\.)+[A-Za-z]{2,}$\",\n                  \"type\": \"string\"\n                },\n                \"maxItems\": 10,\n                \"type\": \"array\"\n              },\n              {\n                \"type\": \"null\"\n              }\n            ],\n            \"description\": \"Recipients for this form only. Null inherits the project's notify_emails.\"\n          },\n          \"redirect_url_override\": {\n            \"anyOf\": [\n              {\n                \"format\": \"uri\",\n                \"type\": \"string\"\n              },\n              {\n                \"type\": \"null\"\n              }\n            ],\n            \"description\": \"Success redirect for this form only. Null inherits default_redirect_url.\"\n          },\n          \"require_turnstile_override\": {\n            \"anyOf\": [\n              {\n                \"type\": \"boolean\"\n              },\n              {\n                \"type\": \"null\"\n              }\n            ],\n            \"description\": \"Force Turnstile on or off for this form. Null inherits the project setting.\"\n          },\n          \"slug\": {\n            \"description\": \"Lowercase hyphenated identifier, unique per project. Used for idempotent re-runs.\",\n            \"maxLength\": 80,\n            \"minLength\": 1,\n            \"pattern\": \"^[a-z0-9]+(?:-[a-z0-9]+)*$\",\n            \"type\": \"string\"\n          },\n          \"webhook_secret_override\": {\n            \"anyOf\": [\n              {\n                \"minLength\": 1,\n                \"type\": \"string\"\n              },\n              {\n                \"type\": \"null\"\n              }\n            ],\n            \"description\": \"HMAC secret for this form's webhook. Null inherits the project secret.\"\n          },\n          \"webhook_url_override\": {\n            \"anyOf\": [\n              {\n                \"format\": \"uri\",\n                \"type\": \"string\"\n              },\n              {\n                \"type\": \"null\"\n              }\n            ],\n            \"description\": \"Webhook endpoint for this form only. Null inherits the project webhook.\"\n          }\n        },\n        \"required\": [\n          \"name\",\n          \"slug\"\n        ],\n        \"type\": \"object\"\n      },\n      \"type\": \"array\"\n    },\n    \"from_name\": {\n      \"anyOf\": [\n        {\n          \"maxLength\": 120,\n          \"minLength\": 1,\n          \"type\": \"string\"\n        },\n        {\n          \"type\": \"null\"\n        }\n      ],\n      \"description\": \"Legacy From display name. Prefer email.from_name.\"\n    },\n    \"honeypot_field\": {\n      \"description\": \"Name of the hidden honeypot input the snippet emits. Defaults to _gotcha.\",\n      \"maxLength\": 80,\n      \"minLength\": 1,\n      \"type\": \"string\"\n    },\n    \"name\": {\n      \"description\": \"Client (company) display name.\",\n      \"maxLength\": 120,\n      \"minLength\": 1,\n      \"type\": \"string\"\n    },\n    \"notify_emails\": {\n      \"default\": [],\n      \"description\": \"Addresses that receive each clean submission (max 10). Inherited by every form.\",\n      \"items\": {\n        \"format\": \"email\",\n        \"pattern\": \"^(?!\\\\.)(?!.*\\\\.\\\\.)([A-Za-z0-9_'+\\\\-\\\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\\\-]*\\\\.)+[A-Za-z]{2,}$\",\n        \"type\": \"string\"\n      },\n      \"maxItems\": 10,\n      \"type\": \"array\"\n    },\n    \"project_name\": {\n      \"description\": \"Website display name. Defaults to the client name.\",\n      \"maxLength\": 120,\n      \"minLength\": 1,\n      \"type\": \"string\"\n    },\n    \"project_slug\": {\n      \"description\": \"Website slug. Defaults to the client slug.\",\n      \"maxLength\": 80,\n      \"minLength\": 1,\n      \"pattern\": \"^[a-z0-9]+(?:-[a-z0-9]+)*$\",\n      \"type\": \"string\"\n    },\n    \"rate_limit_per_ip\": {\n      \"description\": \"Max submissions per IP within rate_limit_window_s.\",\n      \"exclusiveMinimum\": 0,\n      \"maximum\": 1000,\n      \"type\": \"integer\"\n    },\n    \"rate_limit_window_s\": {\n      \"description\": \"Rate-limit window in seconds (max 86400).\",\n      \"exclusiveMinimum\": 0,\n      \"maximum\": 86400,\n      \"type\": \"integer\"\n    },\n    \"require_turnstile\": {\n      \"description\": \"Reject submissions that lack a valid Turnstile token.\",\n      \"type\": \"boolean\"\n    },\n    \"slug\": {\n      \"description\": \"Lowercase hyphenated identifier, unique per team. Used for idempotent re-runs.\",\n      \"maxLength\": 80,\n      \"minLength\": 1,\n      \"pattern\": \"^[a-z0-9]+(?:-[a-z0-9]+)*$\",\n      \"type\": \"string\"\n    },\n    \"team_id\": {\n      \"description\": \"Team id from list_teams. Required for operator tokens and OAuth logins; team-scoped frw_ tokens may omit it.\",\n      \"format\": \"uuid\",\n      \"pattern\": \"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$\",\n      \"type\": \"string\"\n    },\n    \"turnstile_secret\": {\n      \"anyOf\": [\n        {\n          \"minLength\": 1,\n          \"type\": \"string\"\n        },\n        {\n          \"type\": \"null\"\n        }\n      ],\n      \"description\": \"Cloudflare Turnstile secret used to verify tokens server-side. Null removes it.\"\n    },\n    \"turnstile_site_key\": {\n      \"anyOf\": [\n        {\n          \"minLength\": 1,\n          \"type\": \"string\"\n        },\n        {\n          \"type\": \"null\"\n        }\n      ],\n      \"description\": \"Cloudflare Turnstile site key for the frontend widget. Null removes it.\"\n    },\n    \"upload_allowed_types\": {\n      \"description\": \"Allowed upload MIME types, e.g. application/pdf or image/*.\",\n      \"items\": {\n        \"maxLength\": 80,\n        \"minLength\": 3,\n        \"pattern\": \"^[a-z0-9.+-]+\\\\/[a-z0-9.+*-]+$\",\n        \"type\": \"string\"\n      },\n      \"maxItems\": 20,\n      \"minItems\": 1,\n      \"type\": \"array\"\n    },\n    \"upload_max_file_bytes\": {\n      \"description\": \"Max bytes per file (up to 25 MB).\",\n      \"exclusiveMinimum\": 0,\n      \"maximum\": 26214400,\n      \"type\": \"integer\"\n    },\n    \"upload_max_files\": {\n      \"description\": \"Max files per submission (up to 20).\",\n      \"exclusiveMinimum\": 0,\n      \"maximum\": 20,\n      \"type\": \"integer\"\n    },\n    \"upload_max_total_bytes\": {\n      \"description\": \"Max total upload bytes per submission (up to 50 MB).\",\n      \"exclusiveMinimum\": 0,\n      \"maximum\": 52428800,\n      \"type\": \"integer\"\n    },\n    \"uploads_enabled\": {\n      \"description\": \"Accept multipart file fields on this project's forms.\",\n      \"type\": \"boolean\"\n    },\n    \"webhook_secret\": {\n      \"anyOf\": [\n        {\n          \"minLength\": 1,\n          \"type\": \"string\"\n        },\n        {\n          \"type\": \"null\"\n        }\n      ],\n      \"description\": \"HMAC-SHA256 secret for the X-Furrow-Signature header. Omit to have one generated and returned.\"\n    },\n    \"webhook_url\": {\n      \"anyOf\": [\n        {\n          \"format\": \"uri\",\n          \"type\": \"string\"\n        },\n        {\n          \"type\": \"null\"\n        }\n      ],\n      \"description\": \"Public https endpoint that receives a signed JSON POST per clean submission. Null disables it.\"\n    }\n  },\n  \"required\": [\n    \"name\",\n    \"slug\"\n  ],\n  \"type\": \"object\"\n}"},{"name":"create_client","title":"Create client","description":"Use to add a client (company) by slug. Idempotent on slug unless strict is true. Operator tokens (all workspaces) must pass team_id from list_teams. Team-scoped tokens may omit team_id and cannot target another workspace. Prefer bootstrap_site when also creating a website and forms. Do not put Turnstile or webhooks on a client — those live on the project.","access":"write","accessDeclared":true,"hash":"52b10ff5b4f77c07007ca5d2801321aef5b16c5cda4b837fdc78515efbc66c42","inputSchema":"{\n  \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n  \"properties\": {\n    \"name\": {\n      \"description\": \"Client (company) display name.\",\n      \"maxLength\": 120,\n      \"minLength\": 1,\n      \"type\": \"string\"\n    },\n    \"slug\": {\n      \"description\": \"Lowercase hyphenated identifier, unique per team. Used for idempotent re-runs.\",\n      \"maxLength\": 80,\n      \"minLength\": 1,\n      \"pattern\": \"^[a-z0-9]+(?:-[a-z0-9]+)*$\",\n      \"type\": \"string\"\n    },\n    \"strict\": {\n      \"default\": false,\n      \"description\": \"When true, fail if the slug already exists instead of returning the existing record.\",\n      \"type\": \"boolean\"\n    },\n    \"team_id\": {\n      \"description\": \"Team id from list_teams. Required for operator tokens and OAuth logins; team-scoped frw_ tokens may omit it.\",\n      \"format\": \"uuid\",\n      \"pattern\": \"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$\",\n      \"type\": \"string\"\n    }\n  },\n  \"required\": [\n    \"name\",\n    \"slug\"\n  ],\n  \"type\": \"object\"\n}"},{"name":"create_form","title":"Create form","description":"Use to add a form under an existing project_id. Idempotent on slug unless strict is true. Overrides are nullable; omit them to inherit project notify emails, webhook, redirect, require_turnstile, and email templates. Pass email.subject / email.intro to override notification copy for this form only. Pass webhook_url_override to send this form to a different URL. Field contract labels (label) are used on notification emails. Checkbox groups, select multiple, and other multi-value HTML fields must use a [] suffix on the name (name=\"services[]\") or only the last checked value is stored. Put services[] on field_contract.name too. JSON/fetch should send a real array without brackets ({ \"services\": [\"a\", \"b\"] }) and must not use Object.fromEntries(formData) — use formData.getAll(\"services\"). Single checkbox, select, or combobox: no brackets. File inputs use multipart POST (name=\"resume[]\" for multiple). Enable uploads on the project first. Downloads are the project inbox at files_url, with the form slug as a folder — never put that URL in a public snippet.","access":"write","accessDeclared":true,"hash":"27cc9701486383cef3502266271d497b92759c35886c8b18d34bed5360da7fa2","inputSchema":"{\n  \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n  \"properties\": {\n    \"email\": {\n      \"description\": \"Per-form subject and intro overrides for the notification email.\",\n      \"properties\": {\n        \"intro\": {\n          \"anyOf\": [\n            {\n              \"maxLength\": 4000,\n              \"type\": \"string\"\n            },\n            {\n              \"type\": \"null\"\n            }\n          ],\n          \"description\": \"Per-form intro override. Supports {{tokens}}. Null falls back to the project intro.\"\n        },\n        \"subject\": {\n          \"anyOf\": [\n            {\n              \"maxLength\": 300,\n              \"minLength\": 1,\n              \"type\": \"string\"\n            },\n            {\n              \"type\": \"null\"\n            }\n          ],\n          \"description\": \"Per-form subject override. Supports {{tokens}}. Null falls back to the project subject.\"\n        }\n      },\n      \"type\": \"object\"\n    },\n    \"field_contract\": {\n      \"anyOf\": [\n        {\n          \"items\": {\n            \"properties\": {\n              \"label\": {\n                \"anyOf\": [\n                  {\n                    \"maxLength\": 120,\n                    \"minLength\": 1,\n                    \"type\": \"string\"\n                  },\n                  {\n                    \"type\": \"null\"\n                  }\n                ],\n                \"description\": \"Human label used in the snippet and notification email. Defaults to the field name.\"\n              },\n              \"name\": {\n                \"description\": \"Posted field name. HTML checkbox groups / multi-select must end in [] (services[]) or only the last value is stored. JSON arrays omit the brackets.\",\n                \"maxLength\": 80,\n                \"minLength\": 1,\n                \"type\": \"string\"\n              },\n              \"report\": {\n                \"default\": false,\n                \"description\": \"Include this field in dashboard summaries and reports.\",\n                \"type\": \"boolean\"\n              },\n              \"type\": {\n                \"description\": \"text, email, textarea, file, etc. type=file emits a file input in get_snippet.\",\n                \"maxLength\": 40,\n                \"minLength\": 1,\n                \"type\": \"string\"\n              }\n            },\n            \"required\": [\n              \"name\",\n              \"type\"\n            ],\n            \"type\": \"object\"\n          },\n          \"type\": \"array\"\n        },\n        {\n          \"type\": \"null\"\n        }\n      ],\n      \"description\": \"Declared fields (name, type, label, report). Drives get_snippet and the email layout. Null clears it.\"\n    },\n    \"name\": {\n      \"description\": \"Form display name, e.g. Contact or Quote request.\",\n      \"maxLength\": 120,\n      \"minLength\": 1,\n      \"type\": \"string\"\n    },\n    \"notify_emails_override\": {\n      \"anyOf\": [\n        {\n          \"items\": {\n            \"format\": \"email\",\n            \"pattern\": \"^(?!\\\\.)(?!.*\\\\.\\\\.)([A-Za-z0-9_'+\\\\-\\\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\\\-]*\\\\.)+[A-Za-z]{2,}$\",\n            \"type\": \"string\"\n          },\n          \"maxItems\": 10,\n          \"type\": \"array\"\n        },\n        {\n          \"type\": \"null\"\n        }\n      ],\n      \"description\": \"Recipients for this form only. Null inherits the project's notify_emails.\"\n    },\n    \"project_id\": {\n      \"description\": \"Project (website) id from list_projects, create_project, or bootstrap_site.\",\n      \"format\": \"uuid\",\n      \"pattern\": \"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$\",\n      \"type\": \"string\"\n    },\n    \"redirect_url_override\": {\n      \"anyOf\": [\n        {\n          \"format\": \"uri\",\n          \"type\": \"string\"\n        },\n        {\n          \"type\": \"null\"\n        }\n      ],\n      \"description\": \"Success redirect for this form only. Null inherits default_redirect_url.\"\n    },\n    \"require_turnstile_override\": {\n      \"anyOf\": [\n        {\n          \"type\": \"boolean\"\n        },\n        {\n          \"type\": \"null\"\n        }\n      ],\n      \"description\": \"Force Turnstile on or off for this form. Null inherits the project setting.\"\n    },\n    \"slug\": {\n      \"description\": \"Lowercase hyphenated identifier, unique per project. Used for idempotent re-runs.\",\n      \"maxLength\": 80,\n      \"minLength\": 1,\n      \"pattern\": \"^[a-z0-9]+(?:-[a-z0-9]+)*$\",\n      \"type\": \"string\"\n    },\n    \"strict\": {\n      \"default\": false,\n      \"description\": \"When true, fail if the slug already exists instead of returning the existing record.\",\n      \"type\": \"boolean\"\n    },\n    \"webhook_secret_override\": {\n      \"anyOf\": [\n        {\n          \"minLength\": 1,\n          \"type\": \"string\"\n        },\n        {\n          \"type\": \"null\"\n        }\n      ],\n      \"description\": \"HMAC secret for this form's webhook. Null inherits the project secret.\"\n    },\n    \"webhook_url_override\": {\n      \"anyOf\": [\n        {\n          \"format\": \"uri\",\n          \"type\": \"string\"\n        },\n        {\n          \"type\": \"null\"\n        }\n      ],\n      \"description\": \"Webhook endpoint for this form only. Null inherits the project webhook.\"\n    }\n  },\n  \"required\": [\n    \"name\",\n    \"slug\",\n    \"project_id\"\n  ],\n  \"type\": \"object\"\n}"},{"name":"create_project","title":"Create project","description":"Use to add one website under an existing client_id. Idempotent on slug unless strict is true. Free accounts are limited to 3 active (non-archived) projects; yearly is unlimited. If create_project returns plan_limit, call create_upgrade_link and hand the human the Stripe URL. Prefer bootstrap_site when the client does not exist yet. Optional email sets notification templates (subject, from_name, intro, footer_mode, include_meta). Free accounts cannot set footer_mode off. Set uploads_enabled on the project to accept files. Email templates support {{project.name}}, {{project.slug}}, {{form.name}}, {{form.slug}}, {{count}} (1-based clean submissions on this form, including the current one), and any submission field such as {{name}} or {{email}}. Use a fallback with {{name | \"New submission\"}}. Missing fields render empty and never error. Do not pass HTML; Furrow renders one owned layout. Plans are capacity, not a feature ladder. Free: one workspace, 100 clean submissions/month pooled on the team, 3 active (non-archived) projects, 30-day submission retention, and email.footer_mode / branding.mode stay furrow. Yearly ($199/year): extra workspaces, 10,000 submissions/month, unlimited projects, 730-day retention, branding.mode furrow | off | agency. Expansion packs are $99/year each and add 5,000 submissions/month on a yearly account. MCP, webhooks, snippets, inheritance, Turnstile, and email templates stay available on free. Spam, honeypot, and rejected posts do not count. Use create_upgrade_link to hand a human a Stripe Checkout (or Customer Portal) URL. Pass product=expansion on a yearly team to add a pack. File inputs use multipart POST (name=\"resume[]\" for multiple). Enable uploads on the project first. Downloads are the project inbox at files_url, with the form slug as a folder — never put that URL in a public snippet. Do not put Turnstile keys on a form.","access":"write","accessDeclared":true,"hash":"d70a64190f692757ef3021479c193bc867f7d7331b7e37bdf103bdf15b06de36","inputSchema":"{\n  \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n  \"properties\": {\n    \"allowed_domains\": {\n      \"description\": \"Hostnames allowed to post to this project's forms (example.com, www.example.com). Empty accepts any origin.\",\n      \"items\": {\n        \"maxLength\": 253,\n        \"minLength\": 1,\n        \"type\": \"string\"\n      },\n      \"type\": \"array\"\n    },\n    \"client_id\": {\n      \"description\": \"Client id from list_clients or create_client.\",\n      \"format\": \"uuid\",\n      \"pattern\": \"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$\",\n      \"type\": \"string\"\n    },\n    \"default_redirect_url\": {\n      \"anyOf\": [\n        {\n          \"format\": \"uri\",\n          \"type\": \"string\"\n        },\n        {\n          \"type\": \"null\"\n        }\n      ],\n      \"description\": \"Where classic HTML posts redirect after success. Null returns JSON/inline success instead.\"\n    },\n    \"email\": {\n      \"description\": \"Notification email template for the project: subject, from_name, intro, footer_mode, include_meta.\",\n      \"properties\": {\n        \"footer_mode\": {\n          \"description\": \"furrow shows the Furrow footer, minimal shows a one-line footer, off hides it (yearly plans only).\",\n          \"enum\": [\n            \"furrow\",\n            \"minimal\",\n            \"off\"\n          ],\n          \"type\": \"string\"\n        },\n        \"from_name\": {\n          \"description\": \"Display name on the From line of notification emails.\",\n          \"maxLength\": 120,\n          \"minLength\": 1,\n          \"type\": \"string\"\n        },\n        \"include_meta\": {\n          \"description\": \"Include submission metadata (IP, user agent, referrer, timestamp) below the fields.\",\n          \"type\": \"boolean\"\n        },\n        \"intro\": {\n          \"anyOf\": [\n            {\n              \"maxLength\": 4000,\n              \"type\": \"string\"\n            },\n            {\n              \"type\": \"null\"\n            }\n          ],\n          \"description\": \"Plain-text paragraph above the submitted fields. Supports {{tokens}}. Null removes it.\"\n        },\n        \"subject\": {\n          \"description\": \"Notification email subject. Supports {{tokens}} such as {{form.name}} or {{name}}.\",\n          \"maxLength\": 300,\n          \"minLength\": 1,\n          \"type\": \"string\"\n        }\n      },\n      \"type\": \"object\"\n    },\n    \"from_name\": {\n      \"anyOf\": [\n        {\n          \"maxLength\": 120,\n          \"minLength\": 1,\n          \"type\": \"string\"\n        },\n        {\n          \"type\": \"null\"\n        }\n      ],\n      \"description\": \"Legacy From display name. Prefer email.from_name.\"\n    },\n    \"honeypot_field\": {\n      \"description\": \"Name of the hidden honeypot input the snippet emits. Defaults to _gotcha.\",\n      \"maxLength\": 80,\n      \"minLength\": 1,\n      \"type\": \"string\"\n    },\n    \"name\": {\n      \"description\": \"Project (website) display name.\",\n      \"maxLength\": 120,\n      \"minLength\": 1,\n      \"type\": \"string\"\n    },\n    \"notify_emails\": {\n      \"default\": [],\n      \"description\": \"Addresses that receive each clean submission (max 10). Inherited by every form.\",\n      \"items\": {\n        \"format\": \"email\",\n        \"pattern\": \"^(?!\\\\.)(?!.*\\\\.\\\\.)([A-Za-z0-9_'+\\\\-\\\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\\\-]*\\\\.)+[A-Za-z]{2,}$\",\n        \"type\": \"string\"\n      },\n      \"maxItems\": 10,\n      \"type\": \"array\"\n    },\n    \"rate_limit_per_ip\": {\n      \"description\": \"Max submissions per IP within rate_limit_window_s.\",\n      \"exclusiveMinimum\": 0,\n      \"maximum\": 1000,\n      \"type\": \"integer\"\n    },\n    \"rate_limit_window_s\": {\n      \"description\": \"Rate-limit window in seconds (max 86400).\",\n      \"exclusiveMinimum\": 0,\n      \"maximum\": 86400,\n      \"type\": \"integer\"\n    },\n    \"require_turnstile\": {\n      \"description\": \"Reject submissions that lack a valid Turnstile token.\",\n      \"type\": \"boolean\"\n    },\n    \"slug\": {\n      \"description\": \"Lowercase hyphenated identifier, unique per client. Used for idempotent re-runs.\",\n      \"maxLength\": 80,\n      \"minLength\": 1,\n      \"pattern\": \"^[a-z0-9]+(?:-[a-z0-9]+)*$\",\n      \"type\": \"string\"\n    },\n    \"strict\": {\n      \"default\": false,\n      \"description\": \"When true, fail if the slug already exists instead of returning the existing record.\",\n      \"type\": \"boolean\"\n    },\n    \"turnstile_secret\": {\n      \"anyOf\": [\n        {\n          \"minLength\": 1,\n          \"type\": \"string\"\n        },\n        {\n          \"type\": \"null\"\n        }\n      ],\n      \"description\": \"Cloudflare Turnstile secret used to verify tokens server-side. Null removes it.\"\n    },\n    \"turnstile_site_key\": {\n      \"anyOf\": [\n        {\n          \"minLength\": 1,\n          \"type\": \"string\"\n        },\n        {\n          \"type\": \"null\"\n        }\n      ],\n      \"description\": \"Cloudflare Turnstile site key for the frontend widget. Null removes it.\"\n    },\n    \"upload_allowed_types\": {\n      \"description\": \"Allowed upload MIME types, e.g. application/pdf or image/*.\",\n      \"items\": {\n        \"maxLength\": 80,\n        \"minLength\": 3,\n        \"pattern\": \"^[a-z0-9.+-]+\\\\/[a-z0-9.+*-]+$\",\n        \"type\": \"string\"\n      },\n      \"maxItems\": 20,\n      \"minItems\": 1,\n      \"type\": \"array\"\n    },\n    \"upload_max_file_bytes\": {\n      \"description\": \"Max bytes per file (up to 25 MB).\",\n      \"exclusiveMinimum\": 0,\n      \"maximum\": 26214400,\n      \"type\": \"integer\"\n    },\n    \"upload_max_files\": {\n      \"description\": \"Max files per submission (up to 20).\",\n      \"exclusiveMinimum\": 0,\n      \"maximum\": 20,\n      \"type\": \"integer\"\n    },\n    \"upload_max_total_bytes\": {\n      \"description\": \"Max total upload bytes per submission (up to 50 MB).\",\n      \"exclusiveMinimum\": 0,\n      \"maximum\": 52428800,\n      \"type\": \"integer\"\n    },\n    \"uploads_enabled\": {\n      \"description\": \"Accept multipart file fields on this project's forms.\",\n      \"type\": \"boolean\"\n    },\n    \"webhook_secret\": {\n      \"anyOf\": [\n        {\n          \"minLength\": 1,\n          \"type\": \"string\"\n        },\n        {\n          \"type\": \"null\"\n        }\n      ],\n      \"description\": \"HMAC-SHA256 secret for the X-Furrow-Signature header. Omit to have one generated and returned.\"\n    },\n    \"webhook_url\": {\n      \"anyOf\": [\n        {\n          \"format\": \"uri\",\n          \"type\": \"string\"\n        },\n        {\n          \"type\": \"null\"\n        }\n      ],\n      \"description\": \"Public https endpoint that receives a signed JSON POST per clean submission. Null disables it.\"\n    }\n  },\n  \"required\": [\n    \"name\",\n    \"slug\",\n    \"client_id\"\n  ],\n  \"type\": \"object\"\n}"},{"name":"create_upgrade_link","title":"Create upgrade link","description":"Use when a free team is blocked on the 3-project, 100-submission, or one-workspace limit, or when a human should upgrade to yearly ($199/year) so you can keep adding projects, workspaces, and storing new submissions. Returns a Stripe Checkout URL to hand the human. If the team is already yearly, omit product to get a Stripe Customer Portal URL, or pass product=expansion for a $99/year pack that adds 5,000 submissions/month. Do not change plan in the database — Stripe webhooks do that. Plans are capacity, not a feature ladder. Free: one workspace, 100 clean submissions/month pooled on the team, 3 active (non-archived) projects, 30-day submission retention, and email.footer_mode / branding.mode stay furrow. Yearly ($199/year): extra workspaces, 10,000 submissions/month, unlimited projects, 730-day retention, branding.mode furrow | off | agency. Expansion packs are $99/year each and add 5,000 submissions/month on a yearly account. MCP, webhooks, snippets, inheritance, Turnstile, and email templates stay available on free. Spam, honeypot, and rejected posts do not count. Use create_upgrade_link to hand a human a Stripe Checkout (or Customer Portal) URL. Pass product=expansion on a yearly team to add a pack. Operator tokens (all workspaces) must pass team_id from list_teams. Team-scoped tokens may omit team_id and cannot target another workspace.","access":"write","accessDeclared":true,"hash":"8c005f8a72f8ec2366b18508dde0d8b88c9f199a94c4fe3c3ee25c64a5849600","inputSchema":"{\n  \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n  \"properties\": {\n    \"product\": {\n      \"description\": \"yearly starts the $199/year plan; expansion adds a $99/year 5,000-submission pack to a yearly team.\",\n      \"enum\": [\n        \"yearly\",\n        \"expansion\"\n      ],\n      \"type\": \"string\"\n    },\n    \"team_id\": {\n      \"description\": \"Team id from list_teams. Required for operator tokens and OAuth logins; team-scoped frw_ tokens may omit it.\",\n      \"format\": \"uuid\",\n      \"pattern\": \"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$\",\n      \"type\": \"string\"\n    }\n  },\n  \"type\": \"object\"\n}"},{"name":"get_account","title":"Get account","description":"Use to read the team's plan, usage this month, limits, expansion_packs, retention_days, branding, and AI spam filter (ai.typesafe_key_set, ai.notify_suspected_spam). The TypeSafe key itself is never returned. Plans are capacity, not a feature ladder. Free: one workspace, 100 clean submissions/month pooled on the team, 3 active (non-archived) projects, 30-day submission retention, and email.footer_mode / branding.mode stay furrow. Yearly ($199/year): extra workspaces, 10,000 submissions/month, unlimited projects, 730-day retention, branding.mode furrow | off | agency. Expansion packs are $99/year each and add 5,000 submissions/month on a yearly account. MCP, webhooks, snippets, inheritance, Turnstile, and email templates stay available on free. Spam, honeypot, and rejected posts do not count. Use create_upgrade_link to hand a human a Stripe Checkout (or Customer Portal) URL. Pass product=expansion on a yearly team to add a pack. Operator tokens (all workspaces) must pass team_id from list_teams. Team-scoped tokens may omit team_id and cannot target another workspace. Do not use this to list projects — call list_projects.","access":"read","accessDeclared":true,"hash":"a4400f401d0969663467b2f7153567e6a5aa44b7211e29342353f6c10a211465","inputSchema":"{\n  \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n  \"properties\": {\n    \"team_id\": {\n      \"description\": \"Team id from list_teams. Required for operator tokens and OAuth logins; team-scoped frw_ tokens may omit it.\",\n      \"format\": \"uuid\",\n      \"pattern\": \"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$\",\n      \"type\": \"string\"\n    }\n  },\n  \"type\": \"object\"\n}"},{"name":"get_client","title":"Get client","description":"Use to inspect one client. Do not use to list that client's sites — call list_projects with client_id.","access":"read","accessDeclared":true,"hash":"d4e8a84e75cb0870e22f899a0091de7917abb4097f623dcf3fa417c0f780d939","inputSchema":"{\n  \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n  \"properties\": {\n    \"client_id\": {\n      \"description\": \"Client id from list_clients or create_client.\",\n      \"format\": \"uuid\",\n      \"pattern\": \"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$\",\n      \"type\": \"string\"\n    }\n  },\n  \"required\": [\n    \"client_id\"\n  ],\n  \"type\": \"object\"\n}"},{"name":"get_form","title":"Get form","description":"Use to read a form plus resolved and inherited settings, including resolved.email and resolved.uploads. files_url is the private inbox folder for this form under the project inbox (do not put it in a public snippet). Turnstile always inherits from the project (inherited.turnstile is true). Form webhook_url_override is nullable; null means inherit the project webhook. Forms may override email.subject and email.intro only. Do not use to generate embed code — call get_snippet.","access":"read","accessDeclared":true,"hash":"9c4869d56e4654feea018be5fe364c67c7040887d1204a09d31265c3cd528665","inputSchema":"{\n  \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n  \"properties\": {\n    \"form_id\": {\n      \"description\": \"Form id from list_forms, create_form, or bootstrap_site.\",\n      \"format\": \"uuid\",\n      \"pattern\": \"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$\",\n      \"type\": \"string\"\n    }\n  },\n  \"required\": [\n    \"form_id\"\n  ],\n  \"type\": \"object\"\n}"},{"name":"get_project","title":"Get project","description":"Use to inspect one website's settings, domains, webhook URL, email templates, upload policy, plan, usage this month, limits, retention_days, and branding. Returns stored values plus resolved.email. Secrets are never returned. Plans are capacity, not a feature ladder. Free: one workspace, 100 clean submissions/month pooled on the team, 3 active (non-archived) projects, 30-day submission retention, and email.footer_mode / branding.mode stay furrow. Yearly ($199/year): extra workspaces, 10,000 submissions/month, unlimited projects, 730-day retention, branding.mode furrow | off | agency. Expansion packs are $99/year each and add 5,000 submissions/month on a yearly account. MCP, webhooks, snippets, inheritance, Turnstile, and email templates stay available on free. Spam, honeypot, and rejected posts do not count. Use create_upgrade_link to hand a human a Stripe Checkout (or Customer Portal) URL. Pass product=expansion on a yearly team to add a pack. Do not use to list forms — call list_forms.","access":"read","accessDeclared":true,"hash":"9546f5f56f1e40bf6288fb753f7c1029b425a443cc5238667e2676fea812042e","inputSchema":"{\n  \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n  \"properties\": {\n    \"project_id\": {\n      \"description\": \"Project (website) id from list_projects, create_project, or bootstrap_site.\",\n      \"format\": \"uuid\",\n      \"pattern\": \"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$\",\n      \"type\": \"string\"\n    }\n  },\n  \"required\": [\n    \"project_id\"\n  ],\n  \"type\": \"object\"\n}"},{"name":"get_snippet","title":"Get form snippet","description":"Use after the form exists to get copy-paste html, astro, or next code that posts to /s/:publicKey. Do not invent a submit URL — this tool returns it. Snippets are single-value inputs; write checkbox groups and multi-selects yourself. Checkbox groups, select multiple, and other multi-value HTML fields must use a [] suffix on the name (name=\"services[]\") or only the last checked value is stored. Put services[] on field_contract.name too. JSON/fetch should send a real array without brackets ({ \"services\": [\"a\", \"b\"] }) and must not use Object.fromEntries(formData) — use formData.getAll(\"services\"). Single checkbox, select, or combobox: no brackets. File inputs use multipart POST (name=\"resume[]\" for multiple). Enable uploads on the project first. Downloads are the project inbox at files_url, with the form slug as a folder — never put that URL in a public snippet. After dropping the snippet, add visitor-facing success UI: a thank-you page plus default_redirect_url for classic HTML POST, or an on-page message when using fetch/{ok:true}. Do not leave visitors looking at JSON. See furrow://docs/submit-success.","access":"read","accessDeclared":true,"hash":"5c4654394aa21a4d73b0bd0a0b90f4f9fc406e5c608fe13a86ca5f73fdbc4128","inputSchema":"{\n  \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n  \"properties\": {\n    \"form_id\": {\n      \"description\": \"Form id from list_forms, create_form, or bootstrap_site.\",\n      \"format\": \"uuid\",\n      \"pattern\": \"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$\",\n      \"type\": \"string\"\n    },\n    \"framework\": {\n      \"description\": \"Snippet flavor: html (plain form), astro (component), or next (React client component).\",\n      \"enum\": [\n        \"html\",\n        \"astro\",\n        \"next\"\n      ],\n      \"type\": \"string\"\n    }\n  },\n  \"required\": [\n    \"form_id\",\n    \"framework\"\n  ],\n  \"type\": \"object\"\n}"},{"name":"get_submission","title":"Get submission","description":"Use to read one stored submission by id, including file metadata and files_url (the form inbox). Do not use this for live submit tests — POST to /s/:publicKey instead. Do not expect signed bucket URLs — download from the inbox.","access":"read","accessDeclared":true,"hash":"3c963a03f7b20fd23515ba32b2f2ef11e7c7c33415a185476427fb3124163c87","inputSchema":"{\n  \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n  \"properties\": {\n    \"submission_id\": {\n      \"description\": \"Submission id from list_submissions or a webhook payload.\",\n      \"format\": \"uuid\",\n      \"pattern\": \"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$\",\n      \"type\": \"string\"\n    }\n  },\n  \"required\": [\n    \"submission_id\"\n  ],\n  \"type\": \"object\"\n}"},{"name":"list_clients","title":"List clients","description":"Use to browse clients (companies). Operator tokens (all workspaces) must pass team_id from list_teams. Team-scoped tokens may omit team_id and cannot target another workspace. Do not use to list websites — call list_projects with client_id. Archived clients are hidden unless status=all or archived.","access":"read","accessDeclared":true,"hash":"11a0e55f818d3d83d4c2df8597cab3ef41efd00e909d6b586b090bd1cf74c8bd","inputSchema":"{\n  \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n  \"properties\": {\n    \"cursor\": {\n      \"description\": \"Opaque cursor from the previous page's next_cursor.\",\n      \"minLength\": 1,\n      \"type\": \"string\"\n    },\n    \"limit\": {\n      \"description\": \"Page size, max 100.\",\n      \"exclusiveMinimum\": 0,\n      \"maximum\": 100,\n      \"type\": \"integer\"\n    },\n    \"status\": {\n      \"description\": \"Filter by archive state. Defaults to active.\",\n      \"enum\": [\n        \"active\",\n        \"archived\",\n        \"all\"\n      ],\n      \"type\": \"string\"\n    },\n    \"team_id\": {\n      \"description\": \"Team id from list_teams. Required for operator tokens and OAuth logins; team-scoped frw_ tokens may omit it.\",\n      \"format\": \"uuid\",\n      \"pattern\": \"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$\",\n      \"type\": \"string\"\n    }\n  },\n  \"type\": \"object\"\n}"},{"name":"list_forms","title":"List forms","description":"Use to list forms. Pass project_id for one website or client_id for one company (team is inferred). Otherwise Operator tokens (all workspaces) must pass team_id from list_teams. Team-scoped tokens may omit team_id and cannot target another workspace. Do not use to read resolved inheritance — call get_form.","access":"read","accessDeclared":true,"hash":"4a48f57a39f6ae03125aa41fdc6a1729f163f9245036100c882e507f1ec4d7c2","inputSchema":"{\n  \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n  \"properties\": {\n    \"client_id\": {\n      \"description\": \"Only forms under this client's projects.\",\n      \"format\": \"uuid\",\n      \"pattern\": \"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$\",\n      \"type\": \"string\"\n    },\n    \"cursor\": {\n      \"description\": \"Opaque cursor from the previous page's next_cursor.\",\n      \"minLength\": 1,\n      \"type\": \"string\"\n    },\n    \"limit\": {\n      \"description\": \"Page size, max 100.\",\n      \"exclusiveMinimum\": 0,\n      \"maximum\": 100,\n      \"type\": \"integer\"\n    },\n    \"project_id\": {\n      \"description\": \"Only forms in this project.\",\n      \"format\": \"uuid\",\n      \"pattern\": \"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$\",\n      \"type\": \"string\"\n    },\n    \"status\": {\n      \"description\": \"Filter by archive state. Defaults to active.\",\n      \"enum\": [\n        \"active\",\n        \"archived\",\n        \"all\"\n      ],\n      \"type\": \"string\"\n    },\n    \"team_id\": {\n      \"description\": \"Team id from list_teams. Required for operator tokens and OAuth logins; team-scoped frw_ tokens may omit it.\",\n      \"format\": \"uuid\",\n      \"pattern\": \"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$\",\n      \"type\": \"string\"\n    }\n  },\n  \"type\": \"object\"\n}"},{"name":"list_projects","title":"List projects","description":"Use to browse websites. Pass client_id to list one client's sites (team is inferred). Without client_id, Operator tokens (all workspaces) must pass team_id from list_teams. Team-scoped tokens may omit team_id and cannot target another workspace. Do not use to read one project's settings — call get_project. Archived projects are hidden unless status=all or archived.","access":"read","accessDeclared":true,"hash":"1ae73dcaec06d26cb09f349af04bceea9237d780040f21cb6ceb73107a84b713","inputSchema":"{\n  \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n  \"properties\": {\n    \"client_id\": {\n      \"description\": \"Only projects under this client.\",\n      \"format\": \"uuid\",\n      \"pattern\": \"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$\",\n      \"type\": \"string\"\n    },\n    \"cursor\": {\n      \"description\": \"Opaque cursor from the previous page's next_cursor.\",\n      \"minLength\": 1,\n      \"type\": \"string\"\n    },\n    \"limit\": {\n      \"description\": \"Page size, max 100.\",\n      \"exclusiveMinimum\": 0,\n      \"maximum\": 100,\n      \"type\": \"integer\"\n    },\n    \"status\": {\n      \"description\": \"Filter by archive state. Defaults to active.\",\n      \"enum\": [\n        \"active\",\n        \"archived\",\n        \"all\"\n      ],\n      \"type\": \"string\"\n    },\n    \"team_id\": {\n      \"description\": \"Team id from list_teams. Required for operator tokens and OAuth logins; team-scoped frw_ tokens may omit it.\",\n      \"format\": \"uuid\",\n      \"pattern\": \"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$\",\n      \"type\": \"string\"\n    }\n  },\n  \"type\": \"object\"\n}"},{"name":"list_submissions","title":"List submissions","description":"Use to inspect recent posts. Available on free and yearly. Pass project_id or form_id to infer the team; omit both and Operator tokens (all workspaces) must pass team_id from list_teams. Team-scoped tokens may omit team_id and cannot target another workspace. Free teams prune submissions after 30 days; yearly after 730 days. Do not use to read a single submission — call get_submission.","access":"read","accessDeclared":true,"hash":"e4f5a52bf62864f5881fbf4997f054ba8ad44e5515aa54b1e4ff16dcf4e702ba","inputSchema":"{\n  \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n  \"properties\": {\n    \"cursor\": {\n      \"description\": \"Opaque cursor from the previous page's next_cursor.\",\n      \"minLength\": 1,\n      \"type\": \"string\"\n    },\n    \"form_id\": {\n      \"description\": \"Only submissions to this form.\",\n      \"format\": \"uuid\",\n      \"pattern\": \"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$\",\n      \"type\": \"string\"\n    },\n    \"limit\": {\n      \"description\": \"Page size, max 100.\",\n      \"exclusiveMinimum\": 0,\n      \"maximum\": 100,\n      \"type\": \"integer\"\n    },\n    \"project_id\": {\n      \"description\": \"Only submissions in this project.\",\n      \"format\": \"uuid\",\n      \"pattern\": \"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$\",\n      \"type\": \"string\"\n    },\n    \"since\": {\n      \"description\": \"ISO 8601 timestamp; only submissions created after this instant.\",\n      \"minLength\": 1,\n      \"type\": \"string\"\n    },\n    \"spam\": {\n      \"default\": \"clean\",\n      \"description\": \"Which submissions to return. Defaults to clean.\",\n      \"enum\": [\n        \"clean\",\n        \"spam\",\n        \"unknown\",\n        \"all\"\n      ],\n      \"type\": \"string\"\n    },\n    \"team_id\": {\n      \"description\": \"Team id from list_teams. Required for operator tokens and OAuth logins; team-scoped frw_ tokens may omit it.\",\n      \"format\": \"uuid\",\n      \"pattern\": \"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$\",\n      \"type\": \"string\"\n    }\n  },\n  \"type\": \"object\"\n}"},{"name":"list_teams","title":"List teams","description":"Use to see workspaces this token can act on. A team-scoped frw_ token returns that team only. An operator token or an MCP OAuth login returns every team you belong to — pass team_id on list_clients, create_client, and bootstrap_site. Creating another workspace is dashboard-only after signing in and requires a yearly plan; free accounts stay on one team. Do not use this to list clients — call list_clients.","access":"read","accessDeclared":true,"hash":"f8227251d68828716781d9eb744a2785656a4014ddbed5b23f94b4eed835607d","inputSchema":"{\n  \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n  \"properties\": {},\n  \"type\": \"object\"\n}"},{"name":"rotate_project_inbox","title":"Rotate project inbox link","description":"Use when a project's private inbox URL may have leaked. Issues a new inbox key; every previously shared inbox link stops working immediately. get_project returns the new files_url.","access":"delete","accessDeclared":true,"hash":"cb89217a6d9eef208bab881e587d1436f8dbe0a0589241466176a2540b2bd0ae","inputSchema":"{\n  \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n  \"properties\": {\n    \"project_id\": {\n      \"description\": \"Project (website) id from list_projects, create_project, or bootstrap_site.\",\n      \"format\": \"uuid\",\n      \"pattern\": \"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$\",\n      \"type\": \"string\"\n    }\n  },\n  \"required\": [\n    \"project_id\"\n  ],\n  \"type\": \"object\"\n}"},{"name":"test_webhook","title":"Test webhook","description":"Use to POST a signed webhook.test event to the project's webhook URL. Available on free and yearly. Do not use this to inspect past deliveries — that is REST GET /api/projects/:id/webhook-deliveries. Fails if no webhook URL and secret are set.","access":"write","accessDeclared":true,"hash":"e276ca70c02a5ffde247475135305a666d45e4b29341bfb2409da074b38954d4","inputSchema":"{\n  \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n  \"properties\": {\n    \"project_id\": {\n      \"description\": \"Project (website) id from list_projects, create_project, or bootstrap_site.\",\n      \"format\": \"uuid\",\n      \"pattern\": \"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$\",\n      \"type\": \"string\"\n    }\n  },\n  \"required\": [\n    \"project_id\"\n  ],\n  \"type\": \"object\"\n}"},{"name":"update_account","title":"Update account","description":"Use to rename the workspace, set branding, or configure the AI spam filter. Pass ai.typesafe_api_key to save this team's TypeSafe key (null clears it; the key is write-only). ai.notify_suspected_spam (default true) emails notify addresses with a Potential spam label when Jev flags a submission; no webhook is sent either way. Heuristic spam stays silent. Free accounts cannot set branding.mode or email.footer_mode to anything but furrow — those writes are ignored. Yearly may set branding.mode to furrow, off, or agency (name + optional link + optional logo; Furrow keeps the layout, no raw HTML). Plans are capacity, not a feature ladder. Free: one workspace, 100 clean submissions/month pooled on the team, 3 active (non-archived) projects, 30-day submission retention, and email.footer_mode / branding.mode stay furrow. Yearly ($199/year): extra workspaces, 10,000 submissions/month, unlimited projects, 730-day retention, branding.mode furrow | off | agency. Expansion packs are $99/year each and add 5,000 submissions/month on a yearly account. MCP, webhooks, snippets, inheritance, Turnstile, and email templates stay available on free. Spam, honeypot, and rejected posts do not count. Use create_upgrade_link to hand a human a Stripe Checkout (or Customer Portal) URL. Pass product=expansion on a yearly team to add a pack. Operator tokens (all workspaces) must pass team_id from list_teams. Team-scoped tokens may omit team_id and cannot target another workspace. Do not use this to change the plan — call create_upgrade_link.","access":"write","accessDeclared":true,"hash":"8ca65c58d089db3872ea6cedaf17b8a6c1821ee0d6e3e18dac7039288a7b8d88","inputSchema":"{\n  \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n  \"properties\": {\n    \"ai\": {\n      \"description\": \"AI spam filter. Off until this team saves its own TypeSafe key. One Jev call per heuristics-clean submission.\",\n      \"properties\": {\n        \"notify_suspected_spam\": {\n          \"description\": \"When true (the default), submissions the AI flags as spam still email notify addresses with a Potential spam label and send no webhook. Set false to silence those emails.\",\n          \"type\": \"boolean\"\n        },\n        \"typesafe_api_key\": {\n          \"anyOf\": [\n            {\n              \"maxLength\": 500,\n              \"type\": \"string\"\n            },\n            {\n              \"type\": \"null\"\n            }\n          ],\n          \"description\": \"TypeSafe API key for the AI spam filter. Send null or an empty string to remove it. The key is write-only and never returned.\"\n        }\n      },\n      \"type\": \"object\"\n    },\n    \"branding\": {\n      \"description\": \"Account-wide branding for notification emails and hosted pages.\",\n      \"properties\": {\n        \"agency_name\": {\n          \"anyOf\": [\n            {\n              \"maxLength\": 120,\n              \"minLength\": 1,\n              \"type\": \"string\"\n            },\n            {\n              \"type\": \"null\"\n            }\n          ],\n          \"description\": \"Agency name shown when mode is agency. Null clears it.\"\n        },\n        \"agency_url\": {\n          \"anyOf\": [\n            {\n              \"format\": \"uri\",\n              \"type\": \"string\"\n            },\n            {\n              \"type\": \"null\"\n            }\n          ],\n          \"description\": \"Optional http(s) link for the agency name when mode is agency. Null clears it.\"\n        },\n        \"logo_url\": {\n          \"anyOf\": [\n            {\n              \"format\": \"uri\",\n              \"type\": \"string\"\n            },\n            {\n              \"type\": \"null\"\n            }\n          ],\n          \"description\": \"Optional http(s) logo image URL when mode is agency. Null clears it.\"\n        },\n        \"mode\": {\n          \"description\": \"furrow shows Furrow branding, off hides it, agency shows your own name/link/logo. Only yearly plans may change this.\",\n          \"enum\": [\n            \"furrow\",\n            \"off\",\n            \"agency\"\n          ],\n          \"type\": \"string\"\n        }\n      },\n      \"type\": \"object\"\n    },\n    \"name\": {\n      \"description\": \"New workspace display name.\",\n      \"maxLength\": 120,\n      \"minLength\": 1,\n      \"type\": \"string\"\n    },\n    \"team_id\": {\n      \"description\": \"Team id from list_teams. Required for operator tokens and OAuth logins; team-scoped frw_ tokens may omit it.\",\n      \"format\": \"uuid\",\n      \"pattern\": \"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$\",\n      \"type\": \"string\"\n    }\n  },\n  \"type\": \"object\"\n}"},{"name":"update_client","title":"Update client","description":"Use to rename a client. Do not use this to change domains, Turnstile, or webhooks — call update_project.","access":"write","accessDeclared":true,"hash":"728907c733f76249d4cd984e349793ab939acee12cddfe87f5c4ebbe36e741f7","inputSchema":"{\n  \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n  \"properties\": {\n    \"client_id\": {\n      \"description\": \"Client id from list_clients or create_client.\",\n      \"format\": \"uuid\",\n      \"pattern\": \"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$\",\n      \"type\": \"string\"\n    },\n    \"name\": {\n      \"description\": \"New client display name.\",\n      \"maxLength\": 120,\n      \"minLength\": 1,\n      \"type\": \"string\"\n    }\n  },\n  \"required\": [\n    \"client_id\"\n  ],\n  \"type\": \"object\"\n}"},{"name":"update_form","title":"Update form","description":"Use to patch form overrides. Pass null on an override to inherit again. Set email.subject or email.intro to override project notification copy for this form only; from_name, footer_mode, and include_meta stay on the project. Email templates support {{project.name}}, {{project.slug}}, {{form.name}}, {{form.slug}}, {{count}} (1-based clean submissions on this form, including the current one), and any submission field such as {{name}} or {{email}}. Use a fallback with {{name | \"New submission\"}}. Missing fields render empty and never error. Do not pass HTML; Furrow renders one owned layout. Set webhook_url_override to override the project webhook for this form. Do not use this to change Turnstile keys — those live on the project. Checkbox groups, select multiple, and other multi-value HTML fields must use a [] suffix on the name (name=\"services[]\") or only the last checked value is stored. Put services[] on field_contract.name too. JSON/fetch should send a real array without brackets ({ \"services\": [\"a\", \"b\"] }) and must not use Object.fromEntries(formData) — use formData.getAll(\"services\"). Single checkbox, select, or combobox: no brackets. File inputs use multipart POST (name=\"resume[]\" for multiple). Enable uploads on the project first. Downloads are the project inbox at files_url, with the form slug as a folder — never put that URL in a public snippet.","access":"write","accessDeclared":true,"hash":"3796ff46bbb13aaff5cca56975230de80c03c34525248b28c6ac20a7c96d8b1f","inputSchema":"{\n  \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n  \"properties\": {\n    \"email\": {\n      \"description\": \"Per-form subject and intro overrides for the notification email.\",\n      \"properties\": {\n        \"intro\": {\n          \"anyOf\": [\n            {\n              \"maxLength\": 4000,\n              \"type\": \"string\"\n            },\n            {\n              \"type\": \"null\"\n            }\n          ],\n          \"description\": \"Per-form intro override. Supports {{tokens}}. Null falls back to the project intro.\"\n        },\n        \"subject\": {\n          \"anyOf\": [\n            {\n              \"maxLength\": 300,\n              \"minLength\": 1,\n              \"type\": \"string\"\n            },\n            {\n              \"type\": \"null\"\n            }\n          ],\n          \"description\": \"Per-form subject override. Supports {{tokens}}. Null falls back to the project subject.\"\n        }\n      },\n      \"type\": \"object\"\n    },\n    \"field_contract\": {\n      \"anyOf\": [\n        {\n          \"items\": {\n            \"properties\": {\n              \"label\": {\n                \"anyOf\": [\n                  {\n                    \"maxLength\": 120,\n                    \"minLength\": 1,\n                    \"type\": \"string\"\n                  },\n                  {\n                    \"type\": \"null\"\n                  }\n                ],\n                \"description\": \"Human label used in the snippet and notification email. Defaults to the field name.\"\n              },\n              \"name\": {\n                \"description\": \"Posted field name. HTML checkbox groups / multi-select must end in [] (services[]) or only the last value is stored. JSON arrays omit the brackets.\",\n                \"maxLength\": 80,\n                \"minLength\": 1,\n                \"type\": \"string\"\n              },\n              \"report\": {\n                \"default\": false,\n                \"description\": \"Include this field in dashboard summaries and reports.\",\n                \"type\": \"boolean\"\n              },\n              \"type\": {\n                \"description\": \"text, email, textarea, file, etc. type=file emits a file input in get_snippet.\",\n                \"maxLength\": 40,\n                \"minLength\": 1,\n                \"type\": \"string\"\n              }\n            },\n            \"required\": [\n              \"name\",\n              \"type\"\n            ],\n            \"type\": \"object\"\n          },\n          \"type\": \"array\"\n        },\n        {\n          \"type\": \"null\"\n        }\n      ],\n      \"description\": \"Declared fields (name, type, label, report). Drives get_snippet and the email layout. Null clears it.\"\n    },\n    \"form_id\": {\n      \"description\": \"Form id from list_forms, create_form, or bootstrap_site.\",\n      \"format\": \"uuid\",\n      \"pattern\": \"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$\",\n      \"type\": \"string\"\n    },\n    \"name\": {\n      \"description\": \"New form display name.\",\n      \"maxLength\": 120,\n      \"minLength\": 1,\n      \"type\": \"string\"\n    },\n    \"notify_emails_override\": {\n      \"anyOf\": [\n        {\n          \"items\": {\n            \"format\": \"email\",\n            \"pattern\": \"^(?!\\\\.)(?!.*\\\\.\\\\.)([A-Za-z0-9_'+\\\\-\\\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\\\-]*\\\\.)+[A-Za-z]{2,}$\",\n            \"type\": \"string\"\n          },\n          \"maxItems\": 10,\n          \"type\": \"array\"\n        },\n        {\n          \"type\": \"null\"\n        }\n      ],\n      \"description\": \"Recipients for this form only. Null inherits the project's notify_emails.\"\n    },\n    \"redirect_url_override\": {\n      \"anyOf\": [\n        {\n          \"format\": \"uri\",\n          \"type\": \"string\"\n        },\n        {\n          \"type\": \"null\"\n        }\n      ],\n      \"description\": \"Success redirect for this form only. Null inherits default_redirect_url.\"\n    },\n    \"require_turnstile_override\": {\n      \"anyOf\": [\n        {\n          \"type\": \"boolean\"\n        },\n        {\n          \"type\": \"null\"\n        }\n      ],\n      \"description\": \"Force Turnstile on or off for this form. Null inherits the project setting.\"\n    },\n    \"webhook_secret_override\": {\n      \"anyOf\": [\n        {\n          \"minLength\": 1,\n          \"type\": \"string\"\n        },\n        {\n          \"type\": \"null\"\n        }\n      ],\n      \"description\": \"HMAC secret for this form's webhook. Null inherits the project secret.\"\n    },\n    \"webhook_url_override\": {\n      \"anyOf\": [\n        {\n          \"format\": \"uri\",\n          \"type\": \"string\"\n        },\n        {\n          \"type\": \"null\"\n        }\n      ],\n      \"description\": \"Webhook endpoint for this form only. Null inherits the project webhook.\"\n    }\n  },\n  \"required\": [\n    \"form_id\"\n  ],\n  \"type\": \"object\"\n}"},{"name":"update_project","title":"Update project","description":"Use to patch website settings. Nested email sets notification templates: email.subject, email.from_name, email.intro, email.footer_mode (furrow | minimal | off), email.include_meta. Optional branding updates the team (mode furrow | off | agency on yearly only; ignored on free except furrow). Set uploads_enabled and upload_allowed_types here — forms inherit them. Email templates support {{project.name}}, {{project.slug}}, {{form.name}}, {{form.slug}}, {{count}} (1-based clean submissions on this form, including the current one), and any submission field such as {{name}} or {{email}}. Use a fallback with {{name | \"New submission\"}}. Missing fields render empty and never error. Do not pass HTML; Furrow renders one owned layout. Plans are capacity, not a feature ladder. Free: one workspace, 100 clean submissions/month pooled on the team, 3 active (non-archived) projects, 30-day submission retention, and email.footer_mode / branding.mode stay furrow. Yearly ($199/year): extra workspaces, 10,000 submissions/month, unlimited projects, 730-day retention, branding.mode furrow | off | agency. Expansion packs are $99/year each and add 5,000 submissions/month on a yearly account. MCP, webhooks, snippets, inheritance, Turnstile, and email templates stay available on free. Spam, honeypot, and rejected posts do not count. Use create_upgrade_link to hand a human a Stripe Checkout (or Customer Portal) URL. Pass product=expansion on a yearly team to add a pack. File inputs use multipart POST (name=\"resume[]\" for multiple). Enable uploads on the project first. Downloads are the project inbox at files_url, with the form slug as a folder — never put that URL in a public snippet. Null Turnstile or webhook fields clear them. Do not use this to create forms. Updating project keys changes resolved settings on existing forms unless a form override is set.","access":"write","accessDeclared":true,"hash":"97655627df2a4b7cf51ef564115487d1fb82c2eb38d96339924cda207a5b5a83","inputSchema":"{\n  \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n  \"properties\": {\n    \"allowed_domains\": {\n      \"description\": \"Replace the allowed hostnames. Empty array accepts any origin.\",\n      \"items\": {\n        \"maxLength\": 253,\n        \"minLength\": 1,\n        \"type\": \"string\"\n      },\n      \"type\": \"array\"\n    },\n    \"branding\": {\n      \"description\": \"Per-project branding override for notification emails and hosted pages.\",\n      \"properties\": {\n        \"agency_name\": {\n          \"anyOf\": [\n            {\n              \"maxLength\": 120,\n              \"minLength\": 1,\n              \"type\": \"string\"\n            },\n            {\n              \"type\": \"null\"\n            }\n          ],\n          \"description\": \"Agency name shown when mode is agency. Null clears it.\"\n        },\n        \"agency_url\": {\n          \"anyOf\": [\n            {\n              \"format\": \"uri\",\n              \"type\": \"string\"\n            },\n            {\n              \"type\": \"null\"\n            }\n          ],\n          \"description\": \"Optional http(s) link for the agency name when mode is agency. Null clears it.\"\n        },\n        \"logo_url\": {\n          \"anyOf\": [\n            {\n              \"format\": \"uri\",\n              \"type\": \"string\"\n            },\n            {\n              \"type\": \"null\"\n            }\n          ],\n          \"description\": \"Optional http(s) logo image URL when mode is agency. Null clears it.\"\n        },\n        \"mode\": {\n          \"description\": \"furrow shows Furrow branding, off hides it, agency shows your own name/link/logo. Only yearly plans may change this.\",\n          \"enum\": [\n            \"furrow\",\n            \"off\",\n            \"agency\"\n          ],\n          \"type\": \"string\"\n        }\n      },\n      \"type\": \"object\"\n    },\n    \"default_redirect_url\": {\n      \"anyOf\": [\n        {\n          \"format\": \"uri\",\n          \"type\": \"string\"\n        },\n        {\n          \"type\": \"null\"\n        }\n      ],\n      \"description\": \"Where classic HTML posts redirect after success. Null returns JSON/inline success instead.\"\n    },\n    \"email\": {\n      \"description\": \"Notification email template for the project: subject, from_name, intro, footer_mode, include_meta.\",\n      \"properties\": {\n        \"footer_mode\": {\n          \"description\": \"furrow shows the Furrow footer, minimal shows a one-line footer, off hides it (yearly plans only).\",\n          \"enum\": [\n            \"furrow\",\n            \"minimal\",\n            \"off\"\n          ],\n          \"type\": \"string\"\n        },\n        \"from_name\": {\n          \"description\": \"Display name on the From line of notification emails.\",\n          \"maxLength\": 120,\n          \"minLength\": 1,\n          \"type\": \"string\"\n        },\n        \"include_meta\": {\n          \"description\": \"Include submission metadata (IP, user agent, referrer, timestamp) below the fields.\",\n          \"type\": \"boolean\"\n        },\n        \"intro\": {\n          \"anyOf\": [\n            {\n              \"maxLength\": 4000,\n              \"type\": \"string\"\n            },\n            {\n              \"type\": \"null\"\n            }\n          ],\n          \"description\": \"Plain-text paragraph above the submitted fields. Supports {{tokens}}. Null removes it.\"\n        },\n        \"subject\": {\n          \"description\": \"Notification email subject. Supports {{tokens}} such as {{form.name}} or {{name}}.\",\n          \"maxLength\": 300,\n          \"minLength\": 1,\n          \"type\": \"string\"\n        }\n      },\n      \"type\": \"object\"\n    },\n    \"from_name\": {\n      \"anyOf\": [\n        {\n          \"maxLength\": 120,\n          \"minLength\": 1,\n          \"type\": \"string\"\n        },\n        {\n          \"type\": \"null\"\n        }\n      ],\n      \"description\": \"Legacy From display name. Prefer email.from_name.\"\n    },\n    \"honeypot_field\": {\n      \"description\": \"Name of the hidden honeypot input the snippet emits. Defaults to _gotcha.\",\n      \"maxLength\": 80,\n      \"minLength\": 1,\n      \"type\": \"string\"\n    },\n    \"name\": {\n      \"description\": \"New project display name.\",\n      \"maxLength\": 120,\n      \"minLength\": 1,\n      \"type\": \"string\"\n    },\n    \"notify_emails\": {\n      \"description\": \"Replace the notification recipients (max 10).\",\n      \"items\": {\n        \"format\": \"email\",\n        \"pattern\": \"^(?!\\\\.)(?!.*\\\\.\\\\.)([A-Za-z0-9_'+\\\\-\\\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\\\-]*\\\\.)+[A-Za-z]{2,}$\",\n        \"type\": \"string\"\n      },\n      \"maxItems\": 10,\n      \"type\": \"array\"\n    },\n    \"project_id\": {\n      \"description\": \"Project (website) id from list_projects, create_project, or bootstrap_site.\",\n      \"format\": \"uuid\",\n      \"pattern\": \"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$\",\n      \"type\": \"string\"\n    },\n    \"rate_limit_per_ip\": {\n      \"description\": \"Max submissions per IP within rate_limit_window_s.\",\n      \"exclusiveMinimum\": 0,\n      \"maximum\": 1000,\n      \"type\": \"integer\"\n    },\n    \"rate_limit_window_s\": {\n      \"description\": \"Rate-limit window in seconds (max 86400).\",\n      \"exclusiveMinimum\": 0,\n      \"maximum\": 86400,\n      \"type\": \"integer\"\n    },\n    \"require_turnstile\": {\n      \"description\": \"Reject submissions that lack a valid Turnstile token.\",\n      \"type\": \"boolean\"\n    },\n    \"turnstile_secret\": {\n      \"anyOf\": [\n        {\n          \"minLength\": 1,\n          \"type\": \"string\"\n        },\n        {\n          \"type\": \"null\"\n        }\n      ],\n      \"description\": \"Cloudflare Turnstile secret used to verify tokens server-side. Null removes it.\"\n    },\n    \"turnstile_site_key\": {\n      \"anyOf\": [\n        {\n          \"minLength\": 1,\n          \"type\": \"string\"\n        },\n        {\n          \"type\": \"null\"\n        }\n      ],\n      \"description\": \"Cloudflare Turnstile site key for the frontend widget. Null removes it.\"\n    },\n    \"upload_allowed_types\": {\n      \"description\": \"Allowed upload MIME types, e.g. application/pdf or image/*.\",\n      \"items\": {\n        \"maxLength\": 80,\n        \"minLength\": 3,\n        \"pattern\": \"^[a-z0-9.+-]+\\\\/[a-z0-9.+*-]+$\",\n        \"type\": \"string\"\n      },\n      \"maxItems\": 20,\n      \"minItems\": 1,\n      \"type\": \"array\"\n    },\n    \"upload_max_file_bytes\": {\n      \"description\": \"Max bytes per file (up to 25 MB).\",\n      \"exclusiveMinimum\": 0,\n      \"maximum\": 26214400,\n      \"type\": \"integer\"\n    },\n    \"upload_max_files\": {\n      \"description\": \"Max files per submission (up to 20).\",\n      \"exclusiveMinimum\": 0,\n      \"maximum\": 20,\n      \"type\": \"integer\"\n    },\n    \"upload_max_total_bytes\": {\n      \"description\": \"Max total upload bytes per submission (up to 50 MB).\",\n      \"exclusiveMinimum\": 0,\n      \"maximum\": 52428800,\n      \"type\": \"integer\"\n    },\n    \"uploads_enabled\": {\n      \"description\": \"Accept multipart file fields on this project's forms.\",\n      \"type\": \"boolean\"\n    },\n    \"webhook_secret\": {\n      \"anyOf\": [\n        {\n          \"minLength\": 1,\n          \"type\": \"string\"\n        },\n        {\n          \"type\": \"null\"\n        }\n      ],\n      \"description\": \"HMAC-SHA256 secret for the X-Furrow-Signature header. Omit to have one generated and returned.\"\n    },\n    \"webhook_url\": {\n      \"anyOf\": [\n        {\n          \"format\": \"uri\",\n          \"type\": \"string\"\n        },\n        {\n          \"type\": \"null\"\n        }\n      ],\n      \"description\": \"Public https endpoint that receives a signed JSON POST per clean submission. Null disables it.\"\n    }\n  },\n  \"required\": [\n    \"project_id\"\n  ],\n  \"type\": \"object\"\n}"},{"name":"update_team","title":"Update team","description":"Use to rename a team. Operator tokens (all workspaces) must pass team_id from list_teams. Team-scoped tokens may omit team_id and cannot target another workspace. Do not use this to create another workspace — that is dashboard-only and requires yearly. For plan, usage, retention, and branding, call get_account / update_account. Do not use this to change clients or projects.","access":"write","accessDeclared":true,"hash":"087174a4bad2641af44559f2eef6223f69efcbfec21586b9fa9a4c5e40d3ba07","inputSchema":"{\n  \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n  \"properties\": {\n    \"name\": {\n      \"description\": \"New team (workspace) display name.\",\n      \"maxLength\": 120,\n      \"minLength\": 1,\n      \"type\": \"string\"\n    },\n    \"team_id\": {\n      \"description\": \"Team id from list_teams. Required for operator tokens and OAuth logins; team-scoped frw_ tokens may omit it.\",\n      \"format\": \"uuid\",\n      \"pattern\": \"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$\",\n      \"type\": \"string\"\n    }\n  },\n  \"required\": [\n    \"name\"\n  ],\n  \"type\": \"object\"\n}"},{"name":"upsert_project_webhook","title":"Upsert project webhook","description":"Use to set or replace the project webhook URL. Available on free and yearly. A signing secret is generated once if the project has none. Forms inherit this unless webhook_url_override is set. Do not use this for a one-off delivery — call test_webhook.","access":"write","accessDeclared":true,"hash":"5bdc51d4fcd1c7756dce2e9f02779d9fa4d9095468b159530c6e677c9bf5bff4","inputSchema":"{\n  \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n  \"properties\": {\n    \"project_id\": {\n      \"description\": \"Project (website) id from list_projects, create_project, or bootstrap_site.\",\n      \"format\": \"uuid\",\n      \"pattern\": \"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$\",\n      \"type\": \"string\"\n    },\n    \"webhook_secret\": {\n      \"anyOf\": [\n        {\n          \"minLength\": 1,\n          \"type\": \"string\"\n        },\n        {\n          \"type\": \"null\"\n        }\n      ],\n      \"description\": \"HMAC-SHA256 secret for X-Furrow-Signature. Omit to have one generated and returned.\"\n    },\n    \"webhook_url\": {\n      \"anyOf\": [\n        {\n          \"format\": \"uri\",\n          \"type\": \"string\"\n        },\n        {\n          \"type\": \"null\"\n        }\n      ],\n      \"description\": \"Public https endpoint that receives a signed JSON POST per clean submission. Null disables it.\"\n    }\n  },\n  \"required\": [\n    \"webhook_url\",\n    \"project_id\"\n  ],\n  \"type\": \"object\"\n}"}],"toolsHash":"48bfce709144f66f9e0460f330a94d0129869093a07fd1b345cfdd01960d8242","toolsPinnedAt":"2026-10-26T05:57:49.571Z","toolsLastSeenAt":"2026-10-26T05:57:49.558Z","toolChanges":[]}}