action and method, so it posts on its own until the script runs. The same request carries files, a spam blocker token and validation errors, and Axios or XMLHttpRequest can send it for code that uses them.
Prerequisites
Before you start, you need:- A formcarry account. Sign up is free.
- A form in the dashboard. Its endpoint is on the form’s Setup page. The examples use
https://formcarry.com/s/AbC123xyz; put yours in its place.
Fetch
To send a form withfetch, keep action and method="POST" on the form, post a FormData built from it on submit, and send Accept: application/json:
email field is the visitor’s address, so it becomes the reply to address of your notification email and the recipient of the auto response. A stored submission answers with code: 200. A refused one answers with the reason in message, see What every form needs.
Send Accept: application/json rather than leaving it out, otherwise the answer is the thank you page’s HTML and res.json() throws.
To refuse a second click before the answer arrives, disable the submit button and enable it again after:
429, so the button stays disabled until the answer is in. fetch rejects only when no answer came back; a refused submission resolves, with the reason in data.message.
To post an object instead, send it as JSON with Content-Type: application/json:
Files
To send files, add file inputs to the form from the first example and keep theFormData post:
multiple input sends every chosen file under its name.
For File objects from elsewhere, append each one under its own name:
Content-Type to the browser rather than setting it, otherwise the multipart boundary is missing and the upload fails.
For small files, stay with JSON and send each file as a data URL, one key per file, never an array:
Files are stored on paid plans only. Free plans store the rest of the submission without them.
Spam blocker
To add a challenge, load its script, put adiv with the widget class and your site key inside the form, and paste the secret key into the form’s settings under Form Security:
With reCAPTCHA v2:
FormData post above carries it.
With reCAPTCHA v3 there is no widget. Load the script with your site key, add a hidden input for the token, and ask for a token when the visitor submits:
403 for reCAPTCHA or 400 for the others:
localhost to the challenge’s allowed domains while you test.
Validation errors
A422 carries errors, one entry per failing field, each with a message. To mark each failing field invalid and let the browser report it:
Axios
The same post with Axios from its CDN script, withform and result from the first example:
Content-Type to Axios rather than setting it, otherwise the FormData upload loses its boundary. Axios rejects on any status outside 2xx, so formcarry’s answer to a refused submission is in err.response.data. A request that got no answer has no response, so check for it before reading it.
To post an object instead, pass it in place of the FormData; Axios sends it as JSON:
XMLHttpRequest
For code that cannot usefetch, the same post with XMLHttpRequest:
onload runs for 422 and 403 too, so read data.code. onerror runs only when no answer came back.
For a JSON body, set Content-Type and send a string:
What’s next
- Field validations: the rules you can set per field.
- Spam protection: the challenges, the filter and the honeypot.
- Email notifications: the auto response the visitor gets, keyed on
email.