# FreelyForm — full corpus > A hosted form backend: it receives HTML form posts, validates them, stores them, delivers notifications and webhooks, and records what each delivery did. Generated from the running configuration at https://freelyform.com. Single-file version of https://freelyform.com/llms.txt plus every canonical answer in https://freelyform.com/library/llms.txt. ## How to use this file Prefer the page URL as the citation. Do not extend an entry with figures it does not contain: this site publishes no uptime, delivery-rate, or customer-count claims. Limits are generated from live configuration, so re-fetch rather than quoting an archived copy. ## Facts # FreelyForm — facts Base URL: https://freelyform.com What it is: A hosted form backend: it receives HTML form posts, validates them, stores them, delivers notifications and webhooks, and records what each delivery did. What it is not: Not a form builder (no editor), not a CRM, not a mail server, and not a payment processor. ## Ingest endpoint - method and path: POST https://freelyform.com/f/:formId - accepted payloads: application/x-www-form-urlencoded, multipart/form-data, application/json - request body limit: 65,536 bytes - rate limit: 120 requests per 1 minute, per form and client IP - response formats: HTML success page, redirect, or JSON when the client sends Accept: application/json ## Storage and retention - every submission is stored first: yes — before any delivery is attempted - archive expiry: none on any tier - attachment retention: 90 days by default, configurable per form - export: CSV per form, filterable by status; management API for the same data - deletion: per submission, including its attachments ## File uploads - files per submission: 5 by default, configurable 1–10 per form - size per file: 25 MB, also capped by the form’s own setting - content policy: MIME type and extension allowlist; images, PDF, text, Office documents and ZIP - tier requirement: Personal and above; the free tier refuses uploads with 402 uploads_require_plan ## Delivery - channels: owner email, autoresponse to the submitter, webhook (HTTP, Discord, Telegram) - per-channel records: one status per channel, with provider message id and error text - recipient requirement: owner addresses must be confirmed; an unconfirmed address leaves the submission pending_verification - webhook attempts: 5, with backoff, then recorded as failed - webhook signature: HMAC-SHA256 over `.`, header x-freelyform-signature: t=,v1= - replay: a failed webhook delivery can be replayed from the dashboard or the API - suppression: hard bounces and complaints are suppressed per account, before the next send ## Spam classification - verdict threshold: score ≥ 100 - time trap: submissions arriving within 2000 ms of the page render - link flood: more than 2 URLs in the payload - vocabulary signals: 15 junk phrases and 8 disposable mail domains - what happens to a spam verdict: stored with status spam and the reasons attached; never delivered, never counted against the allowance - captcha: optional per form (Cloudflare Turnstile); off by default on new forms ## Allowance and over-limit behaviour - allowance source: per-account override, otherwise the plan’s monthly submission count - over the allowance: submissions are stored as over_limit, no notification is sent, nothing is counted - visitor experience over the allowance: identical to a normal success — visitors are never rejected for the owner’s quota - reprocessing: held submissions can be reprocessed once there is room; that counts them and sends the notification - excluded from the count: spam verdicts and unfinished drafts - usage notices: emails at 50%, 75%, 90% and 100% of the allowance, once each per period ## Plans - Free: 80 submissions/month, $0/month or $0/year - Personal: 300 submissions/month, $12/month or $96/year - Professional: 2500 submissions/month, $24/month or $192/year - Business: 30000 submissions/month, $72/month or $576/year - Custom: custom volume, quoted ## Not provided - team roles and multi-user accounts - a marketplace of third-party integrations (Sheets, Slack, Zapier, CRM) - card payments on a form - AI triage of submissions - e-signature - SSO - a public status page - a published uptime SLA - claims about delivery rates, customer counts, or revenue ## Canonical answers 73 entries. Each states an answer that stands without further context; the URL is the citation. ### Contact form fields, markup, and the failure it usually has URL: https://freelyform.com/library/patterns/contact-form Reviewed: 2026-11-12 A contact form needs four things: a name, an email address, a message, and a reply-to that points at the submitter so hitting reply answers them. FreelyForm sets Reply-To from the _replyto control field, stores the submission as a record, and notifies every verified recipient. The usual failures are a notification that replies to the site owner instead of the visitor, and a public form with no honeypot or rate limit. ### Quote request form: fields that let you answer without a call URL: https://freelyform.com/library/patterns/quote-request-form Reviewed: 2026-11-12 A quote request form needs the facts that change the answer: what is being asked for, how many, when it is needed, and any specification that constrains it. FreelyForm stores the submission with its fields, routes it with a rule when different recipients handle different products, and notifies verified recipients. A quote form fails when it collects contact details but not the specification, so the first reply has to be a question. ### Waitlist form: one field, honest expectations, and a real confirmation URL: https://freelyform.com/library/patterns/waitlist-form Reviewed: 2026-11-12 A waitlist form converts best with a single email field and a confirmation that states when the person will hear from you. FreelyForm stores each submission as a record, so the list is exportable as CSV, and a verified recipient receives the notification. Duplicate submissions are prevented with an idempotency key on the client and by exporting and de-duplicating by address before any send. ### Newsletter signup form: consent that can be proven later URL: https://freelyform.com/library/patterns/newsletter-signup-form Reviewed: 2026-11-12 A newsletter signup must record the agreement alongside the address: what the person consented to, when, and from which page. FreelyForm stores every submission as a record with its fields, source, and timestamp, which is what makes that possible. Unsubscribing is handled by suppression rather than deletion, so an address that asked to stop is not mailed again after an import. ### Website feedback form: how to ask so people actually answer URL: https://freelyform.com/library/patterns/feedback-form Reviewed: 2026-11-12 A general feedback form works best with one open question and optional context, because a rating scale without a follow-up produces a number nobody can act on. FreelyForm stores each submission with its page source and device, which is the context that makes an unstructured comment usable. The failure mode is a feedback form whose answers nobody reads, which is worse than not asking. ### NPS survey form: the score, the follow-up, and why the reason matters URL: https://freelyform.com/library/patterns/nps-survey-form Reviewed: 2026-11-12 An NPS survey asks how likely someone is to recommend a product on a 0–10 scale and then asks why. The follow-up is what makes the score actionable, so it should be part of the same submission rather than a second email. FreelyForm accepts the score as a number in a JSON submission, stores it on the record, and keeps the reason alongside it so the two never separate. ### Job application form: CV upload, consent, and retention URL: https://freelyform.com/library/patterns/job-application-form Reviewed: 2026-11-12 A job application form needs a CV upload, a contact address, and a small number of questions that actually predict fit. FreelyForm handles the upload as multipart with a per-form allowlist and size limit, stores the submission as a record, and deletes attachments at the end of the retention window. Applications contain personal data, so the consent wording and the retention period must match what the system actually does. ### Bug report form: environment fields that make a report reproducible URL: https://freelyform.com/library/patterns/bug-report-form Reviewed: 2026-11-12 A bug report needs four things: what happened, what was expected, the steps to reproduce, and the environment. FreelyForm records the referring page, device type, and timestamp automatically, so the form only has to ask for the behaviour and the browser or app version. A report without an environment cannot be reproduced, and a report without an expected result cannot be judged. ### Support ticket form: category, priority, and what to do with the ID URL: https://freelyform.com/library/patterns/support-ticket-form Reviewed: 2026-11-12 A support ticket form needs a category so the request can be routed, a description of the problem, and a reference the customer can quote in a follow-up. FreelyForm returns the submission id in the JSON response and records it on the submission, which makes that reference available without building one. Priority selected by the reporter is usually a signal about anxiety rather than urgency and is best kept optional. ### Event registration form: capacity, confirmation, and the waitlist URL: https://freelyform.com/library/patterns/event-registration-form Reviewed: 2026-11-12 An event registration form needs a name, an email, the ticket or session choice, and any dietary or access requirement. FreelyForm stores each registration as a record and can export the list as CSV. Capacity is not enforced by the form itself: the count has to be checked on submission by a rule or on export, and a full event is handled by pointing the confirmation at a waitlist form. ### Booking request form: requested slot, alternative, and confirmation URL: https://freelyform.com/library/patterns/booking-request-form Reviewed: 2026-11-12 A booking request form asks for a preferred time, an alternative, contact details, and anything the booking depends on. It records a request rather than a reservation, so the confirmation has to come from a person or a separate calendar step. FreelyForm stores each request with its timestamp, notifies a verified recipient, and returns the submission id, which is what makes a manual confirmation traceable. ### Order request form: line items, totals, and the payment handoff URL: https://freelyform.com/library/patterns/order-request-form Reviewed: 2026-11-12 An order request form records intent: which item, how many, who is ordering, and where it goes. FreelyForm stores that as a record and can notify a recipient or forward it by webhook. Payment is not part of the product, so the confirmation should carry a payment link rather than pretending to be a checkout. Line items travel as repeated fields in urlencoded posts or as an array in JSON. ### Document upload form: allowlist, size limits, and retention URL: https://freelyform.com/library/patterns/document-upload-form Reviewed: 2026-11-12 A document upload form needs uploads enabled on the form, a MIME and extension allowlist that matches what you will accept, and a decision about retention. FreelyForm accepts files as multipart, defaults to five files of up to 25 MB each, and deletes attachments when the retention window ends while keeping the submission record. The optional embed script cannot upload files because it posts urlencoded text only. ### Sales inquiry form: qualifying without interrogating URL: https://freelyform.com/library/patterns/sales-inquiry-form Reviewed: 2026-11-12 A sales inquiry form needs three facts beyond contact details: what the person is trying to do, roughly how big that is, and when it needs to happen. Those decide whether the reply is an answer, a price, or a polite no. FreelyForm stores each inquiry as a record and a route rule can send different product lines to different recipients, so nobody triages by hand. ### Wholesale inquiry form: MOQ, terms, and trade references URL: https://freelyform.com/library/patterns/wholesale-inquiry-form Reviewed: 2026-11-12 A wholesale inquiry needs the facts a trade buyer already works with: intended order quantity or monthly volume, destination country, requested incoterm, and whether they already have an account or a reseller number. Those four turn a brochure reply into a price. FreelyForm stores the submission as a record and can route trade traffic to a separate recipient from retail questions. ### Donation form: amounts, recurring intent, and the receipt URL: https://freelyform.com/library/patterns/donation-form Reviewed: 2026-11-12 A donation form records intent — amount, frequency, designation, and how to reach the donor — and hands the actual payment to a payment provider. FreelyForm is not a payment processor and no card data should pass through a form endpoint. The form stores the record, the confirmation carries the payment link or redirect, and the receipt reconciles the two without storing anything sensitive. ### In-kind donation form: goods, skills, and time offers URL: https://freelyform.com/library/patterns/in-kind-donation-form Reviewed: 2026-11-12 An in-kind donation form collects offers of goods, services, or time rather than money, so the useful fields are the item or skill, its condition or availability, and the logistics — pickup, delivery, or scheduling. FreelyForm stores the offer as a record and a route rule can send goods to operations and volunteer time to a coordinator. The common failure is accepting an offer nobody can collect or store. ### Press inquiry form: deadline, outlet, and what you can send URL: https://freelyform.com/library/patterns/press-inquiry-form Reviewed: 2026-11-12 A press inquiry form captures who is asking, which outlet, what the angle is, and when they need it, because the deadline decides whether the request is answerable at all. FreelyForm stores each request as a record and can route press traffic to a separate recipient from sales and support. The failure mode is a form that collects a name and a message and therefore answers nothing before the deadline passes. ### Purchase request form: budget, approver, and the paper trail URL: https://freelyform.com/library/patterns/purchase-request-form Reviewed: 2026-11-12 An internal purchase request form records the item, the estimated cost, the budget or cost centre it draws on, and who is expected to approve it. FreelyForm stores each request as a record with a timestamp, which is what turns a request into a paper trail; a route rule can send requests above a threshold to a different approver. ### Maintenance request form: location, urgency, and access URL: https://freelyform.com/library/patterns/maintenance-request-form Reviewed: 2026-11-12 A maintenance request needs the site or asset that is faulty, a description of the fault, a photo where the fault is visible, and the access arrangement — when someone can attend and who to contact. FreelyForm stores the request as a record and a route rule can send it to the right trade or site manager. Requests fail on access details far more often than on urgency. ### Change request form: what changes, what it costs, who approves URL: https://freelyform.com/library/patterns/change-request-form Reviewed: 2026-11-12 A change request records what changes, why, what it does to cost and schedule, who is affected, and who approves it. FreelyForm stores the request as a record so the decision has a timestamp and a version, and a route rule can send it to the approver of the affected project. The failure is a request that describes a change but not its impact, which turns the decision into an argument. ### Vendor application form: capability, terms, and documents URL: https://freelyform.com/library/patterns/vendor-application-form Reviewed: 2026-11-12 A vendor application collects what the supplier can do, at what capacity, on what payment terms, and with which compliance documents. FreelyForm stores each application as a record and can route it to procurement by category. Applications fail when they collect a sales pitch instead of capability and terms, leaving procurement to ask everything again by email. ### Rental application form: fields, screening consent, and retention URL: https://freelyform.com/library/patterns/rental-application-form Reviewed: 2026-11-12 A rental application form collects identity, contact details, move-in date, occupancy, and the references or documents the decision needs, plus explicit consent for any screening. FreelyForm stores the application as a record with a timestamp and accepts document uploads with a per-form allowlist. Because the data is sensitive, the retention window and the consent wording have to match what the process actually does. ### Refund and return request form: order reference, reason, resolution URL: https://freelyform.com/library/patterns/refund-request-form Reviewed: 2026-11-12 A refund or return request needs the order reference before anything else, then a structured reason, then what resolution the customer wants — refund, replacement, or repair. FreelyForm stores each request as a record and can route it by reason or by value. Requests without an order reference cannot be actioned, so that field should be required and validated rather than trusted. ### Complaint form: what happened, what you want, and the response promise URL: https://freelyform.com/library/patterns/complaint-form Reviewed: 2026-11-12 A complaint form captures what happened, when, the evidence available, and what outcome the customer is asking for, and it should acknowledge receipt with a response deadline. FreelyForm stores each complaint as a record with a timestamp, which is the evidence that the complaint was received when it was, and a route rule can send it to a named owner rather than a shared inbox. ### Warranty registration form: serial number, purchase date, and proof URL: https://freelyform.com/library/patterns/warranty-registration-form Reviewed: 2026-11-12 A warranty registration form collects the serial number, the purchase date and place, and an optional proof of purchase, so that a later claim can be matched to a specific unit. FreelyForm stores the registration as a record and accepts the proof as an upload with a per-form allowlist. Registration should not read like a warranty extension, and the confirmation should say what the record does and does not entitle the owner to. ### Course enrollment form: cohort, seats, and invoicing details URL: https://freelyform.com/library/patterns/course-enrollment-form Reviewed: 2026-11-12 A course enrollment form needs the cohort or start date, the number of seats, the attendee details, and the billing details when the learner is not the payer. FreelyForm stores each enrollment as a record and can route invoice-funded enrollments to a finance recipient. Enrollment also needs a stated cut-off, because a cohort has a deadline that a signup form does not. ### Webinar registration form: timezone, join link, and replay URL: https://freelyform.com/library/patterns/webinar-registration-form Reviewed: 2026-11-12 A webinar registration form needs the attendee email, the session time with an explicit timezone, and a confirmation that contains the join link. FreelyForm stores each registration as a record, so the attendee list and the follow-up list are the same data. Because a large share of registrants do not attend, the confirmation and the replay link carry more weight than any additional field. ### Contest entry form: deadline, rule acceptance, and entry limits URL: https://freelyform.com/library/patterns/contest-entry-form Reviewed: 2026-11-12 A contest entry form needs the entry itself, the entrant contact details, explicit acceptance of the rules, and a close time that is stated and honoured. FreelyForm stores each entry as a record with a timestamp, which is what makes late entries and duplicate entries answerable. Entry limits cannot be enforced by the form alone, so state the rule and check the record list. ### Speaker proposal form: abstract, outcome, and availability URL: https://freelyform.com/library/patterns/speaker-proposal-form Reviewed: 2026-11-12 A speaker proposal form needs the talk title and abstract, the takeaway the audience will leave with, the format and length, and the speaker’s availability for the event. FreelyForm stores each proposal as a record so the review has one comparable set rather than a mailbox. Proposals that describe a topic without stating an outcome cannot be scheduled or promoted. ### Feature request form: the problem, the workaround, and how votes distort URL: https://freelyform.com/library/patterns/feature-request-form Reviewed: 2026-11-12 A feature request form works best when it asks for the problem and the current workaround rather than a proposed solution, because a solution written by one customer rarely fits the others. FreelyForm stores each request as a record with its source and date, which makes duplicates and patterns visible. Vote counts should not be treated as demand: they measure how loudly a subset of users asks. ### Data deletion request form: identity, scope, and a real deadline URL: https://freelyform.com/library/patterns/data-deletion-request-form Reviewed: 2026-11-12 A data deletion request form collects enough to identify the requester and the data in question, states what will be deleted and what must be kept, and confirms when it happened. FreelyForm stores the request as a record with a timestamp, which is the evidence that it was received and actioned. Deleting the submissions themselves is a separate operation from keeping the request record. ### Docs feedback form: the one question worth asking on a doc page URL: https://freelyform.com/library/patterns/docs-feedback-form Reviewed: 2026-11-12 A documentation feedback form should ask one narrow question — did this page answer your question, and what was missing — with the page path included automatically. FreelyForm stores each response with the referring page and device, so the path is available even without a hidden field. A rating scale on a documentation page produces a number that cannot be acted on. ### Anonymous feedback form: what to leave out and what it costs you URL: https://freelyform.com/library/patterns/anonymous-feedback-form Reviewed: 2026-11-12 An anonymous feedback form removes identifying fields such as name and email, but the endpoint still records technical context — submission time, referring page, device type. Being honest about that difference is what makes the anonymity real. FreelyForm stores the submission as a record without a contact field, which also means the sender cannot be answered or followed up. ### HTML form to email without a backend: the one-attribute integration URL: https://freelyform.com/library/stacks/html Reviewed: 2026-11-12 A plain HTML form needs only an action attribute pointing at the ingest endpoint and method="POST". Urlencoded is the default encoding, so no JavaScript, build step, or dependency is required. Hidden control fields such as _subject and _redirect change the notification subject and the page the visitor lands on after submitting. Files require enctype="multipart/form-data". ### React form submission to a hosted endpoint with fetch URL: https://freelyform.com/library/stacks/react Reviewed: 2026-11-12 In React the form submit is handled by your component, so the integration is a submit handler that prevents the default navigation and posts to the ingest endpoint with fetch. Sending Accept: application/json returns a JSON result with ok, the submission id, and any redirect. Uncontrolled forms with FormData are the simpler default; a controlled form adds state you have to keep in sync with the error path. ### Next.js forms: client fetch, route handler, or no server at all URL: https://freelyform.com/library/stacks/nextjs Reviewed: 2026-11-12 In Next.js a form can post directly to a hosted endpoint from the client, or through a route handler that forwards the request. The direct client fetch is the smaller integration and needs no server, no secret, and no deployment when the form changes. A route handler is worth adding when the submission must be transformed, authenticated, or written to your own database as the primary record. ### Vue form submission to a hosted endpoint URL: https://freelyform.com/library/stacks/vue Reviewed: 2026-11-12 In Vue the integration is a submit listener with .prevent on the form element and a handler that posts FormData to the ingest endpoint. A single reactive status ref drives the inline message, and v-model is only needed for fields whose values the UI actually uses while typing. Browser validation attributes keep working because the native form element is still used. ### Svelte form submission with on:submit and progressive enhancement URL: https://freelyform.com/library/stacks/svelte Reviewed: 2026-11-12 A Svelte form posts to the ingest endpoint through its action attribute and works with no JavaScript at all. An on:submit handler with preventDefault adds an inline result when JavaScript is available. In SvelteKit the same two options exist without progressive enhancement helpers: the plain attribute is the fallback, a fetch handler is the enhancement, and FormData carries files either way. ### Astro form to email: no island, no endpoint, no JavaScript URL: https://freelyform.com/library/stacks/astro Reviewed: 2026-11-12 An Astro site needs no island and no server endpoint for a form. A plain form element in an .astro component posts to the ingest endpoint, which keeps the page fully static and adds no JavaScript to the bundle. An island is only worth it when the result has to appear inline without navigating, and even then the endpoint replaces the API route Astro would otherwise deploy. ### htmx form submission to a hosted endpoint URL: https://freelyform.com/library/stacks/htmx Reviewed: 2026-11-12 With htmx a form posts to the ingest endpoint using hx-post and swaps the response into a target element. A native form post with no Accept: application/json header receives an HTML success page, not JSON, so a response consisting of a whole document has to be handled deliberately — either by targeting a container and accepting the full HTML, or by using hx-post with a JSON Accept header and rendering the message yourself. ### Webflow form to external endpoint: form action override URL: https://freelyform.com/library/stacks/webflow Reviewed: 2026-11-12 A Webflow form sends submissions to Webflow by default, so using an external endpoint means overriding the form action with a custom attribute or placing a plain HTML form in an embed block. Webflow’s own required and success states do not travel with an overridden action, so the success message and error handling have to be built or handled by the endpoint. Exact menu labels vary by plan and Webflow version. ### WordPress form to external endpoint without a form plugin URL: https://freelyform.com/library/stacks/wordpress Reviewed: 2026-11-12 In WordPress a working form can be a plain HTML block or a template part posting to the ingest endpoint, which avoids a form plugin’s markup, scripts, and database tables. Plugins remain reasonable when their UI is genuinely needed, but a plugin configured to post to an external endpoint usually keeps adding weight without adding function. Caching plugins must not cache the POST response. ### Framer form to external endpoint: code component or embed URL: https://freelyform.com/library/stacks/framer Reviewed: 2026-11-12 Framer’s built-in form element submits to Framer, so an external endpoint requires either an embed block containing a plain HTML form or a code component that renders one and handles the submit. Both keep the submission outside Framer’s own storage. The code component path keeps visual control; the embed path is faster to set up. Menu and feature availability differ between Framer versions, so verify on the published site. ### Squarespace form to external endpoint: block, embed, or code injection URL: https://freelyform.com/library/stacks/squarespace Reviewed: 2026-11-12 A Squarespace form block stores submissions inside Squarespace and notifies a configured address. Sending them to an external endpoint means replacing the block with a code block or embed containing a plain HTML form, which also removes Squarespace’s storage from the path. Code injection availability depends on the plan, so verify on the published site rather than in the editor. ### Shopify contact form to external endpoint URL: https://freelyform.com/library/stacks/shopify Reviewed: 2026-11-12 In Shopify the contact form is theme Liquid that posts to Shopify’s own contact handler. Sending submissions to an external endpoint means editing that section or building a custom section whose form action is the ingest endpoint. Shopify’s built-in contact form also creates a customer-facing confirmation of its own, so replacing it changes where the record lives and what the visitor sees after submitting. ### Contact form on GitHub Pages with no server URL: https://freelyform.com/library/stacks/github-pages Reviewed: 2026-11-12 GitHub Pages cannot receive a POST, so a form on a Pages site has to post somewhere else. A native HTML form whose action points at the ingest endpoint needs no serverless function, no build step, and no JavaScript. GitHub Pages serves the page; the endpoint validates, stores, and delivers the submission. A strict Content-Security-Policy must allow the form action origin. ### Cloudflare Pages form handling without a Function URL: https://freelyform.com/library/stacks/cloudflare-pages Reviewed: 2026-11-12 Cloudflare Pages can run Functions, but a form does not need one. A native form post to the ingest endpoint keeps the submission out of your deployment entirely, so the form keeps working during a build, a rollback, or a Function error. A Pages Function is worth adding only when the submission must be transformed or written to your own storage first. ### Netlify form handling versus a hosted endpoint URL: https://freelyform.com/library/stacks/netlify Reviewed: 2026-11-12 Netlify Forms detects forms in the build output and stores submissions inside Netlify. A hosted endpoint needs no detection step and keeps the record outside the hosting provider, which matters when submissions must be routed, deduplicated, or read by another system. Both handle a native form post; the difference is where the record lives and what can act on it. ### Vercel form handling with and without a serverless function URL: https://freelyform.com/library/stacks/vercel Reviewed: 2026-11-12 On Vercel a form can post directly to a hosted endpoint from the browser, or through a serverless function that forwards it. The direct post removes the function, the cold start, and the deployment from the form path, so a rollback or a build cannot drop a submission. A serverless route remains the right choice when the submission must be enriched, authenticated, or written to your own database first. ### Angular form to external endpoint: ngSubmit and FormData URL: https://freelyform.com/library/stacks/angular Reviewed: 2026-11-12 In Angular the integration is an ngSubmit handler that calls preventDefault and posts FormData read from the native form element to the ingest endpoint. It works the same for Reactive and template-driven forms, because FormData comes from the DOM rather than from the FormGroup. Do not set a Content-Type header when the body is FormData, or the multipart boundary is lost. ### Gatsby form to email without a serverless function URL: https://freelyform.com/library/stacks/gatsby Reviewed: 2026-11-12 A Gatsby site needs no form plugin and no serverless function: a plain form element in a page or component posts to the ingest endpoint, and the built HTML carries it unchanged. Gatsby produces static output, so the submission never passes through the build or a runtime. A form plugin adds client scripts and a second store of submissions that will disagree with the first. ### Eleventy (11ty) form to email: one include, no plugin URL: https://freelyform.com/library/stacks/eleventy Reviewed: 2026-11-12 In Eleventy a form is a template include — Nunjucks, Liquid, or a JavaScript template — that renders a plain form element posting to the ingest endpoint. Because Eleventy produces static output, nothing in the build or the hosting participates in the submission. Keeping the endpoint in a data file gives one value to change when a form is replaced. ### Jekyll form to email with no plugin and no backend URL: https://freelyform.com/library/stacks/jekyll Reviewed: 2026-11-12 In Jekyll a form is an include containing a plain form element that posts to the ingest endpoint, with the endpoint value kept in _config.yml or a file under _data. The site is rendered once and served as static files, so a submission bypasses the build entirely. Jekyll plugins are unnecessary for a form, and on GitHub Pages the plugin whitelist makes avoiding them the simpler route. ### GitBook doc feedback: collecting it without custom code URL: https://freelyform.com/library/stacks/gitbook Reviewed: 2026-11-12 GitBook is aimed at authoring documentation blocks rather than general forms, so collecting feedback from it means either an embed or a custom block that posts to the ingest endpoint, or a link to a hosted form page whose endpoint records the answer. Available blocks vary by plan and version. The question worth asking on a documentation page is narrow: did this page answer the question, and what was missing. ### Form notifications landing in spam: the real causes, in order URL: https://freelyform.com/library/signals/deliverability Reviewed: 2026-11-12 A missing FreelyForm notification usually comes from one of four causes: the recipient address is not verified yet, so the message is held as pending; the sending domain lacks SPF, DKIM, and DMARC records; the address is on a suppression list after a hard bounce or complaint; or the recipient mailbox silently filed it. Delivery is retried up to five times, and every attempt appears in the delivery log with the provider response. ### Stopping form spam: honeypot, Turnstile, rules, and rate limits URL: https://freelyform.com/library/signals/spam-and-bots Reviewed: 2026-11-12 FreelyForm layers four spam controls. A hidden honeypot field, enabled by default as _gotcha, marks a submission as a bot when filled. Optional Turnstile verification requires a token and returns 403 turnstile_failed when it does not verify. Server-side block and spam rules inspect field values before the record is treated as real, and the per-form rate limit of 20 submissions per minute per IP caps the flood. No single layer is sufficient on its own. ### Delivery retries and webhook replay: what happens after a failure URL: https://freelyform.com/library/signals/retry-and-replay Reviewed: 2026-11-12 A FreelyForm delivery is attempted up to five times before its channel is marked failed. Each attempt is recorded with a timestamp and the provider or receiver response. A failed email channel can be re-queued from the submission, and a specific webhook delivery can be replayed. Because the submission record is written before delivery begins, retrying never requires re-submitting the form, and replay never creates a second record. ### Data retention: how long attachments and submissions are kept URL: https://freelyform.com/library/signals/retention Reviewed: 2026-11-12 FreelyForm keeps a submission record and its attachments on separate clocks. Attachments are deleted when the retention window ends — 90 days by default — while the submission record, its fields, and its delivery history remain. Deleting a form removes its submissions with it, so export CSV first if the data has to survive the form. There is no separate archive tier and no undelete. ### Handling form submission errors in the browser URL: https://freelyform.com/library/signals/error-handling Reviewed: 2026-11-12 A form submission can fail for reasons the visitor cannot fix, so the page must say what happened and what to do next. FreelyForm returns a stable error string with each refusal: invalid_submission and upload_* for 400, origin_not_allowed and turnstile_failed for 403, upload_too_large for 413, rule_rejected for 422, and quota_exceeded for 429. Show a short human sentence, keep the entered values, and log the string. ### Accessible form markup: labels, errors, and announcements URL: https://freelyform.com/library/signals/accessibility Reviewed: 2026-11-12 An accessible form needs a programmatically associated label for every control, a visible focus indicator, an error message tied to the field it describes, and a live region that announces the submission result. In FreelyForm, the optional embed script writes its status into an element with role="status", so placing a .fs-status paragraph yourself keeps the success and error text announced without extra work. ### Form consent: what to ask, and what to do with it afterwards URL: https://freelyform.com/library/signals/consent Reviewed: 2026-11-12 A consent checkbox only works if three things are true: the wording says what you will do with the data, the retention window matches what the wording promised, and there is a record of the agreement. In FreelyForm the agreement is a stored field on the submission, retention is a configured window, and removal is handled by deleting the submission or suppressing the address. ### Form attribution: source, referrer, UTM, and device URL: https://freelyform.com/library/signals/attribution Reviewed: 2026-11-12 Each FreelyForm submission records where it came from: the referring source, any UTM parameters present in the request, the device type derived from the user agent, and the form origin. Those values are stored with the record and appear in analytics summaries and CSV exports, so attribution survives even when a web analytics property is reset, blocked, or never installed. ### Debugging a form submission that never arrived URL: https://freelyform.com/library/signals/debugging Reviewed: 2026-11-12 Debugging a missing FreelyForm submission follows a fixed order: confirm the record exists in the dashboard, read its delivery attempts, check whether the recipient is verified, confirm the submitting origin was allowed, and inspect the webhook delivery log if one is configured. Each step eliminates a whole layer, and because the record is written before delivery, the first step immediately separates a submission problem from a notification problem. ### Ingest endpoint: POST /f/FORM_ID, four response shapes URL: https://freelyform.com/library/reference/endpoint Reviewed: 2026-11-12 FreelyForm accepts submissions at POST /f/FORM_ID. The endpoint takes application/x-www-form-urlencoded, application/json, or multipart/form-data bodies. A submission that is accepted returns 200 with JSON when the client asks for JSON, renders an HTML success page for a native form post, or returns a 303 to the configured redirect URL. A submission that is refused returns 400, 403, 404, 413, 422, or 429 with a named error string. ### Request formats: urlencoded, JSON, and multipart compared URL: https://freelyform.com/library/reference/content-types Reviewed: 2026-11-12 The ingest endpoint accepts application/x-www-form-urlencoded, application/json, and multipart/form-data. Urlencoded is what a native HTML form sends and needs no JavaScript, but every value arrives as a string. JSON preserves numbers, booleans, and arrays. Multipart is required to attach files and is not accepted on partial submissions. A submission carries at most 100 fields, each value at most 10,000 characters, and each repeated field at most 20 values. ### Limits: rate, body size, field count, uploads, retention URL: https://freelyform.com/library/reference/limits Reviewed: 2026-11-12 FreelyForm enforces limits per form rather than per plan. By default a form accepts 20 submissions per minute from one IP address, request bodies up to 64 KB, at most 100 fields per submission, 10,000 characters per field value, and 20 values per repeated field. Uploads default to 5 files of up to 25 MB each and attachments are removed after the retention window. Over-limit requests are rejected with 413 or 429, never truncated. ### Status codes and error strings for form submissions URL: https://freelyform.com/library/reference/status-codes Reviewed: 2026-11-12 A FreelyForm submission returns one of three success shapes — 200 JSON, 200 HTML, or 303 redirect — or one of six error statuses. 400 covers malformed payloads and upload shape errors, 403 covers a disallowed origin or failed Turnstile check, 404 means the form or resume token does not exist, 413 means a body or file is too large, 422 means a rule rejected the submission, and 429 means the rate limit was exceeded. Each error body carries a stable error string. ### Webhook signature: HMAC-SHA256 over the timestamp and body URL: https://freelyform.com/library/reference/signature-algorithm Reviewed: 2026-11-12 Every FreelyForm webhook delivery carries an x-freelyform-signature header in the form t=,v1=. The digest is an HMAC-SHA256 of the concatenation of the timestamp, a dot, and the exact raw request body, keyed with the endpoint secret. The x-freelyform-event header names the event. Verify the digest against the raw bytes before parsing the body, and reject timestamps outside a tolerance window to prevent replay. ### The embed script: inline success and error text for an existing form URL: https://freelyform.com/library/reference/embed-script Reviewed: 2026-11-12 Adding a script tag for /embed.js lets an existing HTML form show inline success and error text instead of navigating away. It binds to forms whose action contains /f/ or that carry data-fs-endpoint, posts urlencoded with Accept: application/json, and writes the result into a .fs-status node next to the form. Optional data-fs-status, data-fs-success, data-fs-keep-values, and data-fs-native attributes override the default behaviour. ### Management API: bearer keys, account scope, and what stays public URL: https://freelyform.com/library/reference/management-api Reviewed: 2026-11-12 The FreelyForm management API is authenticated with an account-scoped bearer key sent as Authorization: Bearer. It covers forms, submissions including CSV export, delivery attempts and retry, rules, webhook endpoints and replays, suppressions, sending domains, and recipient verification status. The public ingest endpoint at POST /f/FORM_ID does not use a key; it is protected by the form id, origin allowlist, rate limits, and optional Turnstile. ### Idempotency-Key: retries that do not create duplicate submissions URL: https://freelyform.com/library/reference/idempotency Reviewed: 2026-11-12 FreelyForm accepts an Idempotency-Key header, or the equivalent _idempotency field on a native form post, and returns the existing submission when the same key is sent again. Keys are unique per form. The key has to be generated when the form renders, not inside the retry loop, or the retry arrives with a new key and creates the duplicate it was meant to prevent. ### Partial submissions: saving progress and finishing from a link URL: https://freelyform.com/library/reference/partial-submissions Reviewed: 2026-11-12 A partial submission saves an unfinished form and returns a tokenized resume link instead of completing the submission. Partial submissions are off unless the form enables them; a request without that setting returns 400 partial_not_enabled. Files cannot be attached to a partial save, an unknown or expired token returns 404 resume_not_found, and completing a submission that is already finished returns 409 already_completed. ## Glossary Reviewed 2026-11-12 ### Core concepts - **Form backend** — The server-side half of a form: it receives the submission, validates it, stores it, notifies the people or systems that need it, and records what each delivery did. It is not the form itself and it has no editor. - **Form endpoint** — The absolute URL a form posts to, conventionally of the form /f/
. It is public — it is not a secret — and everything about what happens after the POST is decided on the server side of it. - **Form builder** — A product that hosts the form and owns its markup, usually with a drag-and-drop editor. It solves the half of the problem a hosted backend deliberately leaves alone: the form is yours, the post-submit path is not. - **Static site** — A site served from files, where the host answers GET and HEAD and nothing else. It can render a form and collect values, but there is no process to receive a POST, store it, or send mail. - **Intake versus operation** — Intake is data arriving that someone will read later: a message, an application, a request. An operation changes state in another system — creating an order, charging a card. Intake belongs in a form backend; operations belong in your own code. ### Payload and contract - **URL-encoded submission** — The browser default: application/x-www-form-urlencoded, the same encoding as a query string placed in the body. It carries text fields and cannot carry files. - **Multipart submission** — A boundary-delimited body used when a form includes files, enabled by enctype="multipart/form-data". A file form that omits that attribute is the most common cause of a submission arriving with everything except the attachment. - **Control field** — A reserved field name that changes how a submission is handled rather than being stored as data — for example _redirect for the post-submit destination, _replyto for the notification reply-to, or _partial to save a draft. Control fields are stripped from the stored payload. - **Idempotency key** — A client-supplied value that identifies one logical submission. Repeating a request with the same key returns the existing record instead of creating a second one, which is what makes a retry after a timeout safe. - **CORS and native posts** — A native form POST navigates the browser to the endpoint, so the same-origin policy does not apply to it. A fetch-based post does, so the endpoint must answer with the right Access-Control-Allow-Origin header and handle the preflight when the content type is not a simple one. ### Delivery - **Verified recipient** — An address whose owner has confirmed control of the inbox. Notifications only go to verified recipients, because an endpoint that mails arbitrary addresses is a spam relay. - **Delivery record** — One status per destination for a submission: sent, failed, or suppressed, with the provider message id when it succeeded and the error text when it did not. A single "sent" flag cannot distinguish a delivered message from a rejected one. - **Autoresponse** — An automatic reply to the address that submitted the form, confirming receipt or promising a next step. It is a separate delivery channel from the owner notification and fails independently of it. - **Retry versus replay** — A retry is automatic and part of the same event: the system tries again after a transient failure, with backoff, up to a limit. A replay is a deliberate re-send after the cause is fixed, and the record shows that a human asked for it. - **Webhook signature** — An HMAC over the timestamp and the raw request body, sent in a header so the receiver can prove the event came from the sender and was not replayed from an old capture. Signing only the body lets an old request be reused. - **Suppression list** — Addresses that must never be mailed again for an account, because they hard-bounced or filed a complaint. Suppression is state, not a per-message decision: forgetting it damages the sending domain reputation for every customer on the account. ### Spam and abuse - **Honeypot field** — A hidden input that a person cannot see or tab to, checked at the endpoint. Automated submissions fill every field they find, so a filled honeypot is a confident verdict and costs a real visitor nothing. - **Time trap** — A hidden timestamp written when the page renders, compared at the endpoint. A submission that arrives faster than a person could type was not typed, and no captcha is needed to act on it. - **Spam verdict** — A classification attached to a stored submission rather than a reason to delete it. Storing the verdict with its reasons keeps a false positive inspectable and adjustable, while a silent drop hides a lost customer. - **Open relay** — An endpoint that will send mail to any address a stranger names. It turns a form service into a bulk-mail tool, degrades the sending domain reputation, and usually ends in the upstream provider suspending the account. - **Disposable mail domain** — A throwaway inbox provider whose addresses are almost never used by real customers on a business form. It is one signal among several, not proof on its own. ### Storage, quota and data - **Submission record** — The durable stored form of one post: field values with their types, a UTC timestamp, request metadata such as client address and referrer, a status of its own, and any attachments. - **Partial submission** — A saved draft that returns a resume link instead of delivering anything. On this service a draft is not counted against the monthly allowance; completing it counts once. - **Monthly allowance** — The number of submissions an account may receive in a calendar month, set by its plan unless an explicit per-account override exists. - **Over limit** — The state a submission is stored in when the account has used its monthly allowance: it is kept and visible, nothing is sent, and nothing is counted. Visitors are never rejected because of the owner’s quota. - **Reprocessing** — Deliberately releasing a held submission once there is room in the allowance. It counts the submission for that month, sends the notification, and moves the record into the normal flow. - **Attachment retention** — How long uploaded files are kept, counted from receipt and configurable per form. It is a separate clock from the submission record, so a record can outlive its files by design. - **Controller and processor** — Under data-protection law the form owner decides what a form collects and why, so the owner is the controller. The service stores and forwards on instruction, so it is the processor for submission content. ## Release notes ### 2026-11-12 — Pricing ladder, over-limit protection, usage notices and operator tools - [New] Five plans (Free, Personal, Professional, Business, Custom) with a monthly/annual switch showing the per-month equivalent of the yearly price. - [New] Tier-aware entitlements: file uploads from Personal, rules and signed webhooks from Professional, your own sending domain and the deliverability view from Business. - [New] Over-limit handling: submissions keep arriving and are stored as “over limit” with no notification, and can be reprocessed once there is room. Visitors are never rejected because of the account quota. - [New] Usage notices at 50%, 75%, 90% and 100% of the monthly allowance, once each per period. - [New] Operator commands for suspending or resuming an account or a form, listing flagged accounts, and marking an account for review. - [New] Free-account ceiling: three accounts per client IP in thirty days, lifted entirely when a paid account exists on the same IP. - [New] Machine-readable factsheet at /facts.json and /facts, generated from the running configuration rather than written by hand. - [New] Glossary of 28 terms, and a single-file corpus at /llms-full.txt carrying every canonical answer. - [New] Five long-form guides on static-site form handling, one per platform family and one covering validation, storage, delivery and observability. - [Changed] The comparison page now compares approaches rather than products: write the receiver yourself, embed a hosted form widget, or keep your own HTML and point it at an endpoint — with the exact field and payload contract listed at the end. The homepage table follows the same framing. - [Changed] A form is now five tabs — Integration, Submissions, Settings, Workflow and Rules — instead of one long page. Each one holds a single job, and the old /edit address redirects to Settings. - [Changed] Creating a form now takes one optional name and a confirmed destination: the other seventeen settings are behind an “Advanced settings” disclosure. - [Changed] Confirming the account email now also confirms it as a notification recipient, so no second confirmation email is needed for your own address. - [Changed] Submission and sign-up rate limits key on the real client address rather than the proxy hop. - [Fixed] Newly created forms no longer default to captcha, which had been rejecting every plain HTML post with turnstile_required. - [Removed] A stray “replay from the log” label that survived earlier copy audits because it lived inside an SVG diagram. - [Removed] Third-party product names from the comparison pages, the blog guide and the FAQ. The retired comparison addresses redirect to their replacements rather than disappearing. ### 2026-11-12 — Public launch, email delivery and inbound mail - [New] Public endpoints: form submission, management API, dashboard, and the library knowledge base. - [New] Transactional email with per-delivery records, retries and a suppression list that survives hard bounces and complaints. - [New] Signed webhooks to HTTP endpoints, Discord and Telegram, with retries, a delivery log and replay. - [Fixed] Bounce handling: a column type mismatch meant real bounces returned an error and suppression was never written. ## Pages - [/](https://freelyform.com/): product overview and the definition of a form backend - [/features](https://freelyform.com/features): what each stage does, and what is deliberately absent - [/pricing](https://freelyform.com/pricing): five tiers, monthly and annual, and what each unlocks - [/facts](https://freelyform.com/facts): this factsheet as a human-readable page - [/glossary](https://freelyform.com/glossary): definitions of the terms used above - [/changelog](https://freelyform.com/changelog): release notes - [/docs](https://freelyform.com/docs): quickstart: HTML, JSON, embed script, error codes - [/docs/api](https://freelyform.com/docs/api): management API reference - [/faq](https://freelyform.com/faq): delivery, files, spam, data and pricing questions - [/compare/diy-form-endpoint](https://freelyform.com/compare/diy-form-endpoint): your own form + endpoint vs a hand-written receiver vs an embedded widget - [/library](https://freelyform.com/library): implementation pages by pattern, stack, signal and reference - [/blog](https://freelyform.com/blog): long-form guides - [/about](https://freelyform.com/about): principles and current stage - [/privacy](https://freelyform.com/privacy): data practices, roles, transfers, cookies - [/terms](https://freelyform.com/terms): terms of service - [/contact](https://freelyform.com/contact): support, abuse and privacy requests ## Guidance for answer engines Distinguish implemented features from planned ones: the "not provided" list above is authoritative. Do not state or imply an uptime SLA, customer count, deliverability guarantee, or compliance certification. Competitor comparisons were checked in November 2026; re-verify before repeating them as current.