Skip to content

Embed on your site

Point plain HTML, fetch or React forms at your Nisuform endpoint. Works with JSON, urlencoded and multipart payloads.

Plain HTML

The simplest integration. Set action and method, no JavaScript needed:

<form action="https://api.nisuform.dev/s/YOUR_KEY" method="POST">
  <input type="text" name="name" required>
  <input type="email" name="email" required>
  <textarea name="message"></textarea>
  <input type="text" name="_gotcha" style="display:none" tabindex="-1" autocomplete="off">
  <button type="submit">Send</button>
</form>

Browser submissions redirect to your thank-you page, or to your custom redirectUrl on Pro.

Fetch

For single-page apps, POST JSON or FormData and read the JSON response:

const res = await fetch('https://api.nisuform.dev/s/YOUR_KEY', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ name, email, message }),
})

const out = await res.json()
if (!out.ok) {
  // out.error is a stable code, see the table below
}

A successful submission returns { "ok": true, "submissionId": "..." }.

React

async function handleSubmit(e) {
  e.preventDefault()
  const data = Object.fromEntries(new FormData(e.currentTarget))
  const res = await fetch('https://api.nisuform.dev/s/YOUR_KEY', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(data),
  })
  const out = await res.json()
  if (out.ok) setStatus('sent')
}

Payload rules

  • Content types: application/json, application/x-www-form-urlencoded and multipart/form-data
  • Up to 50 fields per submission, 10,000 characters per value
  • Body size cap: 200 KB
  • Fields named with a leading underscore are ignored, so _gotcha and friends never reach your inbox
  • CORS is open: submit from any site
  • File uploads are skipped for now; file inputs arrive without their contents

Error codes

Failed submissions return { "ok": false, "error": "code" } with a matching status:

CodeStatusMeaning
unsupported_media_type400Content type not supported
invalid_key404Unknown access key, check the Setup tab
quota_exceeded402Monthly submission limit reached
payload_too_large413Body over 200 KB
form_paused423Form is paused
rate_limited429Too fast, honor Retry-After

NoteSpam that is dropped silently still returns { "ok": true }. This is deliberate: bots learn nothing and real users never see a false rejection.