Create project
create_projectUse 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.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | Project (website) display name. | |
| slug | Yes | Lowercase hyphenated identifier, unique per client. Used for idempotent re-runs. | |
| No | Notification email template for the project: subject, from_name, intro, footer_mode, include_meta. | ||
| strict | No | When true, fail if the slug already exists instead of returning the existing record. | |
| client_id | Yes | Client id from list_clients or create_client. | |
| from_name | No | Legacy From display name. Prefer email.from_name. | |
| webhook_url | No | Public https endpoint that receives a signed JSON POST per clean submission. Null disables it. | |
| notify_emails | No | Addresses that receive each clean submission (max 10). Inherited by every form. | |
| honeypot_field | No | Name of the hidden honeypot input the snippet emits. Defaults to _gotcha. | |
| webhook_secret | No | HMAC-SHA256 secret for the X-Furrow-Signature header. Omit to have one generated and returned. | |
| allowed_domains | No | Hostnames allowed to post to this project's forms (example.com, www.example.com). Empty accepts any origin. | |
| uploads_enabled | No | Accept multipart file fields on this project's forms. | |
| turnstile_secret | No | Cloudflare Turnstile secret used to verify tokens server-side. Null removes it. | |
| upload_max_files | No | Max files per submission (up to 20). | |
| rate_limit_per_ip | No | Max submissions per IP within rate_limit_window_s. | |
| require_turnstile | No | Reject submissions that lack a valid Turnstile token. | |
| turnstile_site_key | No | Cloudflare Turnstile site key for the frontend widget. Null removes it. | |
| rate_limit_window_s | No | Rate-limit window in seconds (max 86400). | |
| default_redirect_url | No | Where classic HTML posts redirect after success. Null returns JSON/inline success instead. | |
| upload_allowed_types | No | Allowed upload MIME types, e.g. application/pdf or image/*. | |
| upload_max_file_bytes | No | Max bytes per file (up to 25 MB). | |
| upload_max_total_bytes | No | Max total upload bytes per submission (up to 50 MB). |