splitforms.com
All articles/ TUTORIALS10 MIN READPublished June 30, 2026

How to Send Form Data to an API (3 Methods, 2026 Guide)

Send HTML form data to any REST API in 2026 — native form action, fetch POST, and Axios. Copy-paste examples with error handling and validation.

✶ Written by
splitforms.com / blog

Founder of splitforms — the form backend API for developers. Writes about form UX, anti-spam, and shipping web apps without backend code.

Method 1: Native form action (no JavaScript)

The simplest approach. The browser handles everything — no JavaScript needed. Set the action attribute to your API endpoint and the method to POST.

<form action="https://splitforms.com/api/submit" method="POST">
  <input type="hidden" name="access_key" value="YOUR_ACCESS_KEY" />
  <input type="hidden" name="subject" value="New submission" />
  <input type="hidden" name="redirect" value="https://yoursite.com/thanks" />

  <label>
    Name
    <input name="name" required />
  </label>
  <label>
    Email
    <input name="email" type="email" required />
  </label>
  <label>
    Message
    <textarea name="message" required></textarea>
  </label>

  <input name="botcheck" type="checkbox" style="display:none" tabindex="-1" />
  <button type="submit">Send</button>
</form>

The browser encodes the form as application/x-www-form-urlencoded, sends a POST request to the endpoint, and follows the redirect response. This is the most reliable method — it works even if JavaScript fails to load.

Pros: Zero JavaScript, works everywhere, progressive enhancement friendly.

Cons: Full page reload on submit. No loading state, no inline success message without a redirect.

Method 2: fetch API with FormData (no page reload)

The modern approach. Intercept the form submit, send data viafetch, and handle the response without leaving the page.

<form id="contact-form">
  <input type="hidden" name="access_key" value="YOUR_ACCESS_KEY" />

  <label>Name <input name="name" required /></label>
  <label>Email <input name="email" type="email" required /></label>
  <label>Message <textarea name="message" required></textarea></label>

  <button type="submit">Send</button>
</form>

<script>
const form = document.getElementById('contact-form');

form.addEventListener('submit', async (e) => {
  e.preventDefault();

  const formData = new FormData(form);
  const button = form.querySelector('button[type="submit"]');
  button.disabled = true;
  button.textContent = 'Sending...';

  try {
    const response = await fetch('https://splitforms.com/api/submit', {
      method: 'POST',
      body: formData,
    });

    if (response.ok) {
      form.reset();
      alert('Thanks! We\'ll get back to you soon.');
    } else {
      alert('Something went wrong. Please try again.');
    }
  } catch (error) {
    alert('Network error. Please check your connection.');
  } finally {
    button.disabled = false;
    button.textContent = 'Send';
  }
});
</script>

This gives you a smooth single-page-app experience. The user never leaves the page, and you can show inline success/error states.

Pros: No page reload, loading state, inline feedback, works with any API.

Cons:Requires JavaScript. If JS is disabled, the form won't submit.

Method 3: Axios (for complex apps)

If you're already using Axios in your app, it provides automatic JSON transformation, request/response interceptors, and timeout handling.

import axios from 'axios';

async function submitForm(formData) {
  try {
    const response = await axios.post(
      'https://splitforms.com/api/submit',
      Object.fromEntries(formData),
      {
        headers: { 'Content-Type': 'application/json' },
        timeout: 10000,
      }
    );

    return { success: true, data: response.data };
  } catch (error) {
    if (error.code === 'ECONNABORTED') {
      return { success: false, error: 'Request timed out' };
    }
    return { success: false, error: error.message };
  }
}

Axios is overkill for a simple contact form but useful in larger apps where you've already standardized on it.

React / Next.js example

In a React component, use the fetch API with controlled inputs or FormData:

'use client';

import { useState } from 'react';

export function ContactForm() {
  const [status, setStatus] = useState('idle');

  async function handleSubmit(e: React.FormEvent<HTMLFormElement>) {
    e.preventDefault();
    setStatus('loading');

    const formData = new FormData(e.currentTarget);

    try {
      const res = await fetch('https://splitforms.com/api/submit', {
        method: 'POST',
        body: formData,
      });

      if (res.ok) {
        setStatus('success');
        (e.target as HTMLFormElement).reset();
      } else {
        setStatus('error');
      }
    } catch {
      setStatus('error');
    }
  }

  return (
    <form onSubmit={handleSubmit}>
      <input type="hidden" name="access_key" value="YOUR_ACCESS_KEY" />
      <input name="name" required />
      <input name="email" type="email" required />
      <textarea name="message" required />
      <button type="submit" disabled={status === 'loading'}>
        {status === 'loading' ? 'Sending...' : 'Send'}
      </button>
      {status === 'success' && <p>Thanks! We&apos;ll be in touch.</p>}
      {status === 'error' && <p>Something went wrong. Try again.</p>}
    </form>
  );
}

Validation before sending

Always validate on both client and server:

// Client-side: HTML5 validation (built-in)
<input name="email" type="email" required minlength="5" />

// Client-side: custom validation
form.addEventListener('submit', (e) => {
  const email = form.email.value;
  if (!email.includes('@')) {
    e.preventDefault();
    showError('Please enter a valid email address');
  }
});

// Server-side: the API validates again
// splitforms validates email format, checks for spam,
// and rejects empty required fields automatically.

Never trust client-side validation alone. The API must always re-validate.

Error handling checklist

  1. Loading state — disable the submit button during the request to prevent double-submits.
  2. Timeout — abort the request after 10 seconds using AbortController.
  3. Network errors — catch fetch rejection and show a user-friendly message.
  4. API errors — check response.ok and display the error message from the API.
  5. Fallback — if the API is down, store the submission in localStorage and retry.

Security considerations

  • HTTPS only. Never send form data over HTTP. splitforms enforces HTTPS.
  • Don't expose secrets. The access_key in your HTML is a public form key — it's designed to be visible. It only allows form submissions, not data retrieval.
  • Rate limiting. splitforms rate-limits by IP and access key. For your own API, add rate limiting.
  • Spam protection. Include the honeypot botcheck field. splitforms adds AI spam scoring on top.
  • CORS. splitforms sets permissive CORS headers. Your own API needs to configure them explicitly.

Frequently asked questions

How do I send HTML form data to a REST API?

Three methods: (1) Set the form's action attribute to the API URL and use the native form POST — simplest, but causes a page redirect. (2) Use the fetch API with FormData to POST without a page reload. (3) Use Axios for more advanced features like automatic JSON transformation and interceptors. For production forms, use a hosted backend like splitforms that handles validation, spam filtering, and email delivery.

Should I use FormData or JSON to send form data?

Use FormData for file uploads and when posting to endpoints that expect multipart/form-data. Use JSON (JSON.stringify) when posting to REST APIs that expect application/json. Both work with splitforms — the endpoint accepts both content types.

How do I handle errors when sending form data to an API?

Wrap your fetch call in try/catch, check response.ok, and display user-friendly error messages. For production forms, also implement a loading state (disable the submit button during request), a timeout (abort after 10 seconds), and a fallback (if the API is down, store locally and retry).

Can I send form data to an API without CORS issues?

If you're using a hosted backend like splitforms, CORS is handled automatically — the API sets permissive Access-Control-Allow-Origin headers. If you're calling your own API from a different domain, configure CORS headers on your server or proxy through a same-origin route handler.

What is the easiest way to send form data to an API?

The easiest method is to point your HTML form's action attribute directly at the API endpoint: <form action="https://splitforms.com/api/submit" method="POST">. No JavaScript required. The API receives the data, processes it, and redirects the user to your thank-you page.

Ship your form API today

A form API that just works.
splitforms gives you a production-ready API endpoint, spam filtering, email delivery, webhooks, and a dashboard — all free for 500 submissions/month. No credit card.
Get your API key free →

Keep reading

About the author
✻ ✻ ✻

Get your free contact form API key in 60 seconds.

500 free form submissions per month. No credit card. No SDK, no PHP, no plugin. Drop one POST endpoint in your form and submissions land in your dashboard and can notify your inbox on every plan.

Generate access key →Read the docs
founders pricing locked in · early access open