EaserixDocs
Forms

Endpoint reference

The Forms ingest endpoint contract — accepted content types, field handling, responses, redirects, errors, CORS, and rate limits.

View as Markdown
Answer

Send an HTTP POST to https://f.easerix.com/[form-id] with form-encoded, multipart, or JSON data — no authentication. JSON clients get back {"ok": true, "id": "..."}; plain HTML posts get a 302 redirect when the form is configured for one. Requests are rate-limited to 60 per minute per form and IP.

The endpoint

Every form has one public URL, shown on its page in the app:

https://f.easerix.com/<form-id>
MethodBehavior
POSTSubmit the form — the contract below
OPTIONSCORS preflight — 204 with the form's CORS headers
GETA friendly JSON hint that the endpoint accepts POST

No API key, no auth header — the form id in the URL is the only credential. A paused or deleted form responds 404 to POST, indistinguishable from a form that never existed.

Accepted content types

Content-TypeNotes
application/x-www-form-urlencodedWhat a plain HTML <form method="POST"> sends — works with zero JavaScript
multipart/form-dataAccepted; file contents are not stored — filenames are joined into a _files field
application/jsonA flat JSON object; body capped at 1 MiB

Field handling

  • Every value is stored as a string. JSON numbers, booleans, and null are stringified (null becomes an empty string); nested objects and arrays are stored as compact JSON text.
  • If the same field name is sent more than once (form-encoded/multipart), the last value wins.
  • URL query parameters are not stored as fields — only the request body is.
  • Name your email field email: it becomes the notification's Reply-To and the autoresponder recipient.

Reserved field names

FieldMeaning
_gotcha, _honeyHoneypot traps — a non-empty value flags the submission as spam; always stripped before storage
cf-turnstile-responseCloudflare Turnstile token (the widget adds it automatically); may also be sent as an X-Turnstile-Token header; stripped before storage
_filesWritten by the server when a multipart submission includes files — don't send it yourself

There is no per-request redirect field (no _next or similar) — the post-submit redirect is configured per form in the app (see below).

Success responses

The endpoint decides between a JSON response and a redirect based on how you called it. A request counts as a JSON client if any of these is true:

  • the query string has ?ajax=1,
  • the Accept header contains application/json,
  • the request body is application/json.
CallerResponse
JSON client200 with {"ok": true, "id": "<submission-id>"}
HTML post, form set to Redirect with a URL302Location is the form's configured redirect URL
HTML post otherwise200 with {"ok": true}

Spam-flagged submissions return the same success response as clean ones — deliberately, so bots can't detect the filters.

Error responses

All errors are JSON with a single error field.

StatusBodyWhen
400{"error": "could not parse submission"}Body didn't parse as the declared content type
403{"error": "origin not allowed"}Browser Origin not on the form's allowed-origins list
404{"error": "form not found"}Unknown form id — or a paused form (indistinguishable)
429{"error": "rate limit exceeded"}More than 60 requests/minute for this form from your IP
500{"error": "could not save submission"}Server-side storage failure

CORS

By default any origin may POST to a form; browser requests get a matching Access-Control-Allow-Origin. To lock a form to your own sites, list them under Settings → Allowed origins in the app (exact origin match, e.g. https://mysite.com) — other origins then get 403. Requests without an Origin header (curl, server-to-server) are always allowed. OPTIONS preflight is handled, allowing POST and the Content-Type header.

Rate limits

60 requests per minute per form + client IP. Exceeding it returns 429; wait and retry.

Submit with JavaScript

const res = await fetch("https://f.easerix.com/YOUR_FORM_ID", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Accept": "application/json",
  },
  body: JSON.stringify({
    email: "[email protected]",
    message: "Hello from my site",
  }),
});

const data = await res.json(); // { ok: true, id: "..." }
if (!res.ok) {
  console.error(data.error);
}

The same snippet, pre-filled with your form's endpoint, is on the form's page in the app under Integrate → fetch().

Frequently asked questions

Do I need an API key to submit?

No. The ingest endpoint is public by design — the form id is the only credential. (The management API at /v1/... is a different, authenticated surface.)

Can I make a plain HTML form show JSON instead of redirecting?

Yes — append ?ajax=1 to the endpoint URL in your form's action, or send an Accept: application/json header. The query parameter is not stored as a submission field.

How do redirects after submit work?

Set Settings → Success behavior to Redirect and provide the URL in the app. Plain HTML posts then get a 302 to it. JSON clients never get redirected — they always receive the JSON body.

Last updated on

On this page