JavaScript fetch
Send Submissions from your front-end code and read the JSON answer.
Any framework can send a Submission with fetch. You keep full control of the
form, its validation and what the visitor sees afterwards.
Send JSON
A request with a JSON body, or with Accept: application/json, gets JSON back
instead of a redirect. The body has to be a JSON object. Its values can be
strings, numbers, booleans, arrays or nested objects.
Send a form element
To send a <form> as it is, pass a FormData and ask for JSON:
FormData is sent as multipart, so this also works for forms with file
inputs (see file uploads). Leave the Content-Type
header out: the browser adds it, with the boundary.
Read the answer
A stored Submission answers 201:
Spam gets exactly the same answer, so a bot can't tell it was caught.
An error answers with a status code and a code you can branch on:
Always check result.ok rather than the HTTP status alone: a failed request
still has a JSON body in this shape.
Gotchas
- Send
Accept: application/json. Without it, a urlencoded or multipart post gets the303redirect, andfetchfollows it and hands you the thank-you page. - Send a
Content-Typefor a string body.fetchdefaults totext/plain, which the endpoint refuses with400 invalid_body. - The endpoint checks, in this order: the Form exists and is on, the Plan's monthly limit, the Submit Key, Allowed Origins, rate limits, the body, Turnstile, then the honeypot and timing. The first failure is the answer you get.
CORS
The endpoint answers CORS requests, preflight included, from any origin. Once
a Form has Allowed Origins, only
those origins can post to it from a browser. Allowed methods are POST and
OPTIONS, and the only request header you can add is Content-Type. A
browser can't send a Submit Key or X-Visitor-IP, which
suits a key that has to stay secret.