Headless authentication
Use Headless authentication to accept submissions from your website or call an endpoint from your server. Each endpoint has its own allowed origins and backend key.
Beta
This feature is available to all accounts. Its request and response format can change without a new API version. Do not depend on it for anything you cannot update quickly.
Choose how to authenticate
| Caller | What to send |
|---|---|
| Browser | The page’s Origin must exactly match an allowed origin for the endpoint. |
| Server | Send a backend key and omit the Origin header. |
Use the endpoint ID in the submit URL, not the form ID. If a request includes an Origin, Makeform treats it as a browser request, even if the request also includes a key. The key is ignored. A disallowed origin gets 403 with error Origin is not allowed. A request with no Origin and no valid key gets 401 with error Missing or invalid API key and code auth.
Configure allowed origins
Add the origins that can submit from a browser in the endpoint’s settings. Matching uses the exact scheme://host[:port]; the host is lowercased and a trailing slash is dropped. An empty allowed origins list permits no browser origins.
In the dashboard, entering a domain expands it to both the https:// and https://www. origins. Entering localhost:3000 expands it to both http://localhost:3000 and https://localhost:3000. Paths are dropped.
With MCP, set update_headless_endpoint.allowed_origins to the complete replacement string array. An empty array ([]) makes the endpoint key-only. An endpoint needs at least one allowed origin or a backend key before it can be enabled. You can create an endpoint in the dashboard under Create → Headless.
Use a backend key
A Headless key starts with mfh_live_ and has at least 32 URL-safe characters after the prefix. Send it as a Bearer token or with the X-Makeform-Headless-Key header.
curl -X POST https://submit.makeform.ai/f/ENDPOINT_ID \
-H "Authorization: Bearer mfh_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: order-1234-attempt" \
-d '{"name":"Ada","email":"[email protected]"}'Each endpoint has one key. The key is shown once when created, in the dashboard or with the MCP tool create_headless_api_key. It is scoped to that endpoint, is not a management credential, and differs from mf_live_ API keys. Rotating it immediately invalidates the old key; you can also revoke it.
To create or replace a key with MCP, the endpoint must already exist. Call create_headless_api_key with form_id first. Then call it with form_id, confirm_create: true, and the returned key_token. The token expires after 10 minutes. The second call returns the full key once.
Browser requests and CORS
CORS allows POST and OPTIONS requests with the Content-Type, X-Makeform-Session, and Idempotency-Key headers. Preflight requests return 204; the preflight max age is 86400 seconds. A disallowed origin gets Access-Control-Allow-Origin: null; a request with no Origin gets Access-Control-Allow-Origin: *.
Browsers cannot send backend keys cross-origin: Authorization is not an allowed CORS header. Make browser submissions from an origin listed in the endpoint settings.
If Turnstile is enabled for an endpoint, browser requests must include the token as cf-turnstile-response or _turnstile. A missing or failed token returns 400 with code captcha. Requests using a backend key skip Turnstile.
If respondent email verification is required, submissions using a backend key fail with 403, code email_verification, and verificationCode: "EMAIL_VERIFICATION_REQUIRED". Verification requires browser-origin requests.
Partial saves require an allowed browser Origin; backend-key authentication cannot be used for them. Partial saves are for Page forms only. A Headless-only form returns 403 with code unsupported.