Headless Forms

Create a backend-only Makeform form, then POST submissions to its HTTPS endpoint from your own website, app, or server. Responses land in your Makeform inbox and can run the form's enabled notifications and integrations.

Private preview — Headless creation is currently available only to selected creators. Free includes 1 enabled endpoint and 50 Headless submissions per month. Pro and Business include unlimited enabled endpoints and Headless submissions. Respondent auto-reply is paid-only.

Headless-native forms do not have a hosted /f/... page. The endpoint is their public collection surface.

Quick start

  1. From Create form, choose Headless endpoint. Name it and add the website domain that will submit.
  2. Makeform creates a Headless-native form and endpoint. You'll get a URL like:
https://www.makeform.ai/api/headless/f/hf_xxxxxxxxxxxxxxxx
  1. Confirm every browser origin you use (for example, https://example.com and https://www.example.com) or generate an API key for server-side use.
  2. Keep the endpoint enabled and point your client at it:

Plain HTML

<form action="https://www.makeform.ai/api/headless/f/hf_XXXX" method="POST"> <input type="text" name="name" required /> <input type="email" name="email" required /> <input type="text" name="_gotcha" style="display:none" tabindex="-1" /> <input type="hidden" name="_redirect" value="https://example.com/thanks" /> <button type="submit">Send</button> </form>

JavaScript (fetch)

await fetch('https://www.makeform.ai/api/headless/f/hf_XXXX', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ name: 'Ada', email: 'ada@example.com' }), })

Server-side (cURL + API key)

curl -X POST https://www.makeform.ai/api/headless/f/hf_XXXX \ -H "Authorization: Bearer mfh_live_..." \ -H "Content-Type: application/json" \ -d '{"name":"Ada","email":"ada@example.com"}'

Authentication

Every request must satisfy one of two modes:

ModeHowUse for
BrowserThe request's exact Origin (scheme + host + optional port) matches an Allowed Origin (CORS enforced)Forms on your own website
API keyAuthorization: Bearer <key> or X-Makeform-Headless-Key: <key> headerServers, scripts, mobile apps

API keys are shown once at creation and can be rotated or revoked at any time from the Headless settings. Rotating immediately invalidates the previous key.

Request format

Send application/json or application/x-www-form-urlencoded (what a plain HTML form sends). multipart/form-data is not supported — don't set enctype on your form. Field names must match your form's field names.

Reserved fields (never stored as answers):

FieldPurpose
_gotchaHoneypot. Render it hidden and empty — any value silently drops the submission as spam
_redirectURL to redirect the browser to after success (303). Must be on one of your Allowed Origins
_session_idOptional session id for linking partial submissions
cf-turnstile-response (or _turnstile)Cloudflare Turnstile token, when Turnstile is enabled

Validation

Submissions are validated against your published form:

  • Strict mode (default): unknown fields are rejected; required fields and types are enforced. Best when you control the client.
  • Loose mode: unknown fields are accepted, stored, and learned into the Headless-native form schema. Primitive arrays are learned as multi-value fields; complex values are safely normalized before storage. Useful when the payload evolves, but review learned fields before switching to strict mode.

Validation failures return 400 with a machine-readable errors object naming each offending field.

Spam protection

  • Honeypot (default): include the hidden _gotcha field; bots that fill it are silently dropped (the request still returns success, so bots learn nothing).
  • Cloudflare Turnstile (optional): add your Turnstile site key + secret in Headless settings, then include the widget's cf-turnstile-response token in browser submissions. API-key (server) requests skip Turnstile.
  • Rate limits apply to every endpoint.

Responses

StatusMeaning
200{ "ok": true } — submission stored
303Success with _redirect — browser is redirected
400Validation failed — body includes errors, or the form is not published
401 / 403Missing/invalid API key, or origin not allowed
404Endpoint doesn't exist or is disabled
429Rate limited — or the Free plan's 50 submissions/month reached (the error message says which)

Limits

FreePro / Business
Enabled endpoints1Unlimited
Submissions / month50Unlimited
Rate limitsStandardStandard

The monthly quota counts completed Headless submissions across personal forms and forms owned by your teams during the UTC calendar month. When a Free account hits it, requests return 429 until the month rolls over or the billing owner upgrades.

FAQ

Do integrations fire for Headless submissions? Enabled integrations and owner notifications run through the normal submission service. Owner notification is enabled by default at creation and can be opted out. Respondent auto-reply is available on Pro and Business. Headless entries are tagged with their source in your inbox.

Can I use one endpoint for several websites? Yes — add each site's origin to Allowed Origins.

File uploads? Not yet supported over the headless endpoint — use a hosted or embedded form for file fields.

CORS errors in the browser? The exact origin (scheme + host + port) must be listed in Allowed Origins. https://www.example.com and https://example.com are different origins.

The endpoint returns 404 even though the URL looks correct? The endpoint may be disabled, deleted, owned by an account outside the current preview, or attached to a suspended/deleted form. A disabled endpoint deliberately looks missing.

The endpoint returns 401 or 403 from a server? Do not send a browser Origin header from server code. Send a current mfh_live_... key in either supported authentication header, and rotate the key if it may have leaked.

Can I submit multipart data? No. Send JSON or URL-encoded fields. File uploads, multipart/form-data, and file-field payloads are not supported.