Integrate · Last updated April 23, 2026
JavaScript / Fetch integration
For single-page apps, custom loading states, or any case where you do not want a full page reload, POST to the same endpoint from JavaScript. The response is JSON — see Response format for the exact shape.
Fetch example
Send a JSON body with fetch. This works from any modern browser, server, or edge runtime.
JavaScriptsubmit-form.js
const formData = {
name: 'John Doe',
email: 'john@example.com',
message: 'Hello!',
};
fetch('https://saveform.io/api/submit/YOUR_FORM_ID', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(formData),
})
.then((response) => response.json())
.then((data) => console.log('Success:', data))
.catch((error) => console.error('Error:', error));React example
A typical controlled form in React, posting JSON and surfacing the result inline.
TSXContactForm.tsx
import { useState } from 'react';
export function ContactForm() {
const [status, setStatus] = useState<'idle' | 'sending' | 'ok' | 'err'>('idle');
async function onSubmit(e: React.FormEvent<HTMLFormElement>) {
e.preventDefault();
setStatus('sending');
const data = Object.fromEntries(new FormData(e.currentTarget));
const res = await fetch('https://saveform.io/api/submit/YOUR_FORM_ID', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data),
});
setStatus(res.ok ? 'ok' : 'err');
}
return (
<form onSubmit={onSubmit}>
<input name="name" required />
<input name="email" type="email" required />
<textarea name="message" required />
<button disabled={status === 'sending'}>Send</button>
{status === 'ok' && <p>Thanks — got it.</p>}
{status === 'err' && <p>Something went wrong.</p>}
</form>
);
}