Basic HTML contact form
Works from static HTML and returns the hosted success page unless a valid redirect is supplied.
<form action="https://api.formsfort.com/submit" method="POST">
<input type="hidden" name="access_key" value="YOUR_ACCESS_KEY" />
<input type="text" name="name" required />
<input type="email" name="email" required />
<textarea name="message" required></textarea>
<input type="checkbox" name="botcheck" style="display:none" />
<button type="submit">Send</button>
</form>
Advanced all options
Combines the Web3Forms-compatible reserved fields supported by the baseline API.
<form action="https://api.formsfort.com/submit" method="POST" enctype="multipart/form-data">
<input type="hidden" name="access_key" value="YOUR_ACCESS_KEY" />
<input type="hidden" name="subject" value="New Submission" />
<input type="hidden" name="from_name" value="Website Contact" />
<input type="hidden" name="replyto" value="[email protected]" />
<input type="hidden" name="ccemail" value="[email protected]; [email protected]" />
<input type="hidden" name="webhook" value="https://example.com/webhook" />
<input type="hidden" name="redirect" value="https://example.com/thanks" />
<input type="checkbox" name="botcheck" style="display:none" />
<input type="hidden" name="recaptcha_response" id="recaptchaResponse" />
<input type="file" name="attachment" />
<input type="email" name="email" required />
<textarea name="message" required></textarea>
<button type="submit">Send</button>
</form>
Ajax JavaScript form
JavaScript submissions receive JSON with the request id, queued delivery id, and echoed submitted fields.
const response = await fetch("https://api.formsfort.com/submit", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Accept": "application/json"
},
body: JSON.stringify({
access_key: "YOUR_ACCESS_KEY",
name: "Ada",
email: "[email protected]",
message: "Hello"
})
});
const result = await response.json();
Multi-column contact form
Layout is pure frontend markup; the API receives the same named fields.
<form class="contact-grid" action="https://api.formsfort.com/submit" method="POST">
<input type="hidden" name="access_key" value="YOUR_ACCESS_KEY" />
<input name="first_name" placeholder="First name" required />
<input name="last_name" placeholder="Last name" required />
<input name="email" type="email" placeholder="Email" required />
<input name="phone" placeholder="Phone" />
<textarea name="message" class="full" required></textarea>
<button class="full" type="submit">Send</button>
</form>
JavaScript validation
Validate before calling the public endpoint, then render the API message.
const form = document.querySelector("form");
const status = document.querySelector("[data-status]");
form.addEventListener("submit", async (event) => {
event.preventDefault();
if (!form.reportValidity()) return;
const response = await fetch("https://api.formsfort.com/submit", {
method: "POST",
body: new FormData(form)
});
const result = await response.json();
status.textContent = result.message;
});
Contact form with dark mode
Visual theme changes do not affect the submission contract.
<form class="dark-contact" action="https://api.formsfort.com/submit" method="POST">
<input type="hidden" name="access_key" value="YOUR_ACCESS_KEY" />
<input name="name" required />
<input name="email" type="email" required />
<textarea name="message" required></textarea>
<button type="submit">Send</button>
</form>
<style>
.dark-contact {
background: #111816;
color: #e7f4ed;
padding: 24px;
}
</style>
Raw contact form
Use this minimal version when a builder or CMS strips extra attributes.
<form action="https://api.formsfort.com/submit" method="POST">
<input name="access_key" value="YOUR_ACCESS_KEY" />
<input name="name" />
<input name="email" />
<textarea name="message"></textarea>
<button>Submit</button>
</form>
hCaptcha, reCAPTCHA, and Turnstile tokens
Enable the provider in the dashboard, then submit the provider token with the matching reserved field name.
<!-- hCaptcha -->
<input type="hidden" name="h-captcha-response" value="TOKEN" />
<!-- Google reCAPTCHA v3 -->
<input type="hidden" name="recaptcha_response" value="TOKEN" />
<!-- Cloudflare Turnstile -->
<input type="hidden" name="cf-turnstile-response" value="TOKEN" />
File upload form
Paid/manual forms can accept multipart attachments after upload settings and scanning are configured.
<form action="https://api.formsfort.com/submit" method="POST" enctype="multipart/form-data">
<input type="hidden" name="access_key" value="YOUR_ACCESS_KEY" />
<input name="email" type="email" required />
<input type="file" name="attachment" accept="application/pdf,image/*" />
<button type="submit">Send</button>
</form>
Advanced file uploader
The helper script reserves object-storage uploads and submits clean storage keys without forwarding them as custom data.
<form action="https://api.formsfort.com/submit" method="POST">
<input type="hidden" name="access_key" value="YOUR_ACCESS_KEY" />
<input
type="file"
name="resume"
data-advanced="true"
data-max-files="3"
data-max-file-size="3MB"
multiple />
<button type="submit">Send</button>
</form>
<script src="https://api.formsfort.com/client/script.js" async defer></script>
Multiple checkbox values
Repeated field names are accepted and delivered as comma-separated values.
<label><input type="checkbox" name="interest" value="Product" /> Product</label>
<label><input type="checkbox" name="interest" value="Sales" /> Sales</label>
<label><input type="checkbox" name="interest" value="Support" /> Support</label>
Custom redirect
Non-JavaScript form posts may redirect to a same-host HTTPS page after delivery is queued. Cross-domain redirects require a paid/manual entitlement.
<input type="hidden" name="redirect" value="https://example.com/thanks" />
CC recipients
Paid/manual entitlements can copy extra recipients on the queued notification email.
<input type="hidden" name="ccemail" value="[email protected]; [email protected]" />
Webhook forwarding
Paid/manual entitlements can queue a JSON webhook delivery alongside email forwarding.
<input type="hidden" name="webhook" value="https://example.com/webhook" />
Recipient verification
Generated access keys stay blocked until the recipient verifies ownership of the inbox.
POST /v1/forms/{formId}/recipient-verifications
POST /v1/forms/{formId}/verify-recipient