Formspark
Formspark is a form backend. An HTML form posts to https://submit-form.com/FORM_ID, and Formspark stores the submission, emails the form's notification recipients, and runs the form's integrations. The site brings its own HTML and CSS.
There are two surfaces:
https://submit-form.com/FORM_IDreceives submissions from browsers. It needs no credentials.https://api.formspark.io/public/v1creates and manages forms and reads submissions. It needs an API token.
Get a form id
A form id comes from the user. They create a form in the dashboard at https://dashboard.formspark.io and copy its action URL, or code with an API token creates one with POST /forms. Do not invent an id. Until there is one, use https://submit-form.com/echo, which echoes the submitted payload back.
Submit from an HTML form
<form action="https://submit-form.com/FORM_ID" method="POST">
<input type="email" name="email" required />
<textarea name="message" required></textarea>
<button type="submit">Send</button>
</form>- Give every input, select and textarea a
name, or its value is not sent. - Formspark does no server-side validation. Validate in the browser with
required,minlength,maxlength,patternand input types. - Formspark does not accept files. Upload them to a storage provider and submit the resulting URL as a text field.
- After a browser form post, Formspark redirects the visitor to its feedback page, or to
_redirectwhen the form sets one.
Submit with JavaScript
Send JSON with both Content-Type: application/json and Accept: application/json. Without that Accept header, Formspark treats the request as a browser form post and answers with a redirect.
const response = await fetch("https://submit-form.com/FORM_ID", {
method: "POST",
headers: {
"Content-Type": "application/json",
Accept: "application/json",
},
body: JSON.stringify({ email, message }),
});
if (!response.ok) throw new Error(await response.text());An accepted submission answers 200 with the submitted fields as JSON. A rejected one answers with a status and a short plain-text message: 400 for a file or for JSON that is not an object or array, 402 when the workspace is out of submissions, 403 when spam protection rejects it, and 404 when the form id matches no form. An empty POST is accepted and stores nothing.
Control fields
Fields whose name starts with an underscore control the submission and are not stored with it. In JSON, nest them as objects, such as {"_email": {"subject": "New message"}}.
_redirectsends the visitor to a URL afterwards, and_errorto another one when something fails._appendset tofalsestops the fields being appended to the redirect URL._email.subject,_email.fromand_email.replytoshape the notification email. A field namedemail,mailor_replytoalso sets its reply-to address._languagepicks the language of the feedback page and the autoresponder._feedback.*fields customize the feedback page._honeypotand_gotchaare spam traps: hide the field with CSS, and a submission that fills it is rejected as spam.
Botpoison, reCAPTCHA, hCaptcha and Turnstile are configured per form in the dashboard, and their widgets go on the page. See the spam protection page.
Use the API
The API works on upgraded workspaces. GET /me and GET /workspaces work on any plan, and other calls on a free workspace answer 403 with the code upgrade_required. The user creates a token at https://dashboard.formspark.io/account/api-tokens with the least scopes the task needs: workspaces:read|write, forms:read|write, submissions:read|write. Read the token from the environment, never from source code.
curl https://api.formspark.io/public/v1/me \
-H "Authorization: Bearer $FORMSPARK_TOKEN"
curl -X POST https://api.formspark.io/public/v1/forms \
-H "Authorization: Bearer $FORMSPARK_TOKEN" \
-H "Content-Type: application/json" \
-d '{"workspaceId":"WORKSPACE_ID","name":"Contact","notificationEmails":["you@example.com"]}'
curl "https://api.formspark.io/public/v1/forms/FORM_ID/submissions?limit=50" \
-H "Authorization: Bearer $FORMSPARK_TOKEN"- The response to
POST /formsholds the form'sid, which the HTML form posts to. PATCHapplies the fields sent and keeps the rest. Sendnullto clear a field, except a boolean, which takestrueorfalse.- Lists are cursor paginated. While
hasMoreistrue, passnextCursorback asstartingAfter. Treat cursors as opaque. - Errors are
application/problem+json. Branch oncode, not ondetail. GETis safe to retry. Check whether aPOSTlanded before retrying it, since a repeatedPOSTcreates a second form or workspace.- The OpenAPI 3.1 description is at https://api.formspark.io/public/v1/openapi.json.
Documentation
Each page below is Markdown. Read the one that matches the task before writing code.
- Installation
- AJAX submissions
- Spam protection
- Redirection
- Notification email
- Common issues
- Limits and plans
- API overview
- API tokens
- API reference
- Pagination
- Errors
Framework examples follow the same pattern, such as https://documentation.formspark.io/examples/react.md or https://documentation.formspark.io/examples/nextjs.md. The page index is at https://documentation.formspark.io/llms.txt, and every page in one file is at https://documentation.formspark.io/llms-full.txt.