Reference

API reference

Everything you need to integrate with the submission endpoint. There's exactly one URL and three methods.

Endpoint

POST/f/:formId

Submit a form. Form ID is the public 8-char key (or custom slug) shown in your dashboard.

GET/f/:formId

In a browser, renders the hosted form page (when one exists) or a friendly “API-only” notice. From a non-browser client, returns 405.

OPTIONS/f/:formId

CORS preflight. Returns 204 with permissive CORS headers.

Accepted content types

  • application/x-www-form-urlencoded — standard HTML form POSTs.
  • multipart/form-data — HTML form POSTs that include file inputs.
  • application/json — programmatic submissions from fetch / clients.

Response shape

We return JSON when the request's Accept header asks for it (or when there's no text/html in the Accept). Browser navigations get a redirect or a styled HTML response instead.

Successful JSON response (200 OK):

json
{ "ok": true, "message": "Submission received" }

Error JSON response (4xx or 5xx):

json
{ "error": "Form not found or inactive." }

Status codes

StatusMeaningWhen
200OKSubmission accepted and queued for delivery.
302FoundBrowser submitted the form and _redirect / _next is set.
400Bad RequestSubmission is empty after stripping control fields.
404Not FoundForm ID doesn't exist or has been deactivated.
405Method Not AllowedMethod other than POST/OPTIONS without a hosted form.
410GoneOwner account is scheduled for deletion.
429Too Many RequestsRate limit hit (per-IP, per-form, or per-account-month). Retry-After header tells you when.
500Server ErrorUnexpected error. Submission was not stored.

Headers we set

FieldTypeDescription
Access-Control-Allow-Origin*Submit from any origin without proxying.
Access-Control-Allow-MethodsPOST, OPTIONSEchoed on preflight responses.
Access-Control-Allow-HeadersContent-TypeAll clients need.
Retry-AftersecondsReturned with 429 responses.

cURL example

bash
curl -X POST https://formto.email/f/YOUR_FORM_ID \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{
    "name": "Ada Lovelace",
    "email": "ada@example.com",
    "message": "Hello!",
    "_subject": "New homepage lead"
  }'
No API keys
The endpoint is intentionally public. Your form ID is the only piece of information needed to submit. Pair it with the honeypot, rate limits, and (if needed) per-form deactivation from your dashboard instead of treating the URL as a secret.