Ingest endpoint
One URL accepts every submission, and answers in four different ways.
Your markup only has to know one URL. What it accepts, what it answers, and what changes the answer.
Open the pageLibrary · 9 entries
One endpoint, three body formats, a short list of limits, and a named error for every rejection. If a behaviour is not written down here, we have not promised it.
A contract you cannot finish reading is not a contract. This section exists so that the other three sections can spend their words on judgement instead of repeating syntax. If you only need to know what to send and what comes back, you can stop here.
Two conventions run through every page. First, anything a browser cannot do by itself is marked as optional. Second, every value that can fail is paired with the exact string it fails with, because "something went wrong" is not a debugging aid.
These pages describe the current early-access build. When a limit or a code changes, the reviewed date on the page changes with it. The dashboard and this reference are meant to agree; when they disagree, the dashboard is what actually ran.
Ingest endpoint
Your markup only has to know one URL. What it accepts, what it answers, and what changes the answer.
Open the pageRequest formats
Urlencoded needs no JavaScript, JSON keeps types, multipart is the only way to attach a file. Pick by what you cannot give up.
Open the pageLimits
Twenty requests a minute per form per IP, 64 KB bodies, 100 fields, five files of 25 MB. Nothing is truncated; everything is refused by name.
Open the pageStatus codes
Six status codes, a dozen stable error strings, and what each one should make your page say.
Open the pageWebhook signature
x-freelyform-signature carries t= and v1=. The signed string is the timestamp, a dot, then the raw body — verify before you parse.
Open the pageEmbed script
One script tag turns a plain form post into an inline result message. It never renders the form, never styles it, and never sends files.
Open the pageManagement API
Ingest is public and protected by rules. Everything that can read or change your data is bearer-keyed, account-scoped, and returns 401 without a key.
Open the pageIdempotency
One key per submit intent. Reusing it returns the record you already made instead of making another.
Open the pagePartial submissions
Save what has been typed, hand back a link, finish later from any device. The link is a capability, so treat it as one.
Open the pageMachine-readable summary
The FreelyForm ingest contract is a single endpoint, POST /f/FORM_ID, that accepts urlencoded, JSON, or multipart bodies and answers with JSON, an HTML success page, a 303 redirect, or a named error. Limits, status codes, the webhook signature header, the optional embed script, and the bearer-keyed management API are documented here as implemented behaviour rather than intentions.
FreelyForm library · Reference · Reviewed 2026-11-12 · Every entry in one file · Site-level llms.txt
Create a form, verify your inbox, and point your existing HTML at the endpoint. No server, no SDK, no rewrite.
POST https://freelyform.com/f/FORM_ID