NisuformDocs

Submit endpoint

Full reference for POST /s/{key}, the one public endpoint every Nisuform form posts to, with request formats, responses and headers.

POST https://api.nisuform.com/s/{key}

This is the only endpoint your forms need. It is public, needs no API key and accepts requests from any website.

Path

ParameterDescription
keyThe form key. Letters, digits and hyphens, starting with a letter or digit, up to 64 characters. Not case sensitive.

Request body

Content typeUse it for
application/x-www-form-urlencodedPlain HTML forms. The browser's default.
multipart/form-dataHTML forms with enctype="multipart/form-data", FormData bodies and file uploads.
application/jsonfetch and server-side requests. The body must be a JSON object.

Any other content type, or JSON that can't be parsed, is rejected with 415 and unsupported_media_type.

Fields are name and value pairs:

  • Up to 50 fields. Extra fields are ignored.
  • Names up to 200 characters. A name ending in [] is saved without the brackets.
  • Values up to 10,000 characters. Longer values are cut.
  • Repeated names are joined into one comma-separated value, and so are JSON arrays.
  • Up to 200 KB per request, or 25 MB on Pro forms with file uploads turned on.

Names that start with an underscore, and the captcha token names, are special fields. They change how the submission is handled and are never stored.

Response format

The response depends on the request's Accept header:

Accept includes text/htmlResponse
Yes, like a normal browser form submitAn HTML page, or a 303 redirect
No, like fetch, cURL or a serverJSON

Send Accept: application/json from your code to always get JSON.

JSON responses

type SubmitSuccess = {
  ok: true
  submissionId?: string
  warning?: 'near_limit'
}

type SubmitFailure = {
  ok: false
  error: string
  message: string
}
StatusBodyWhen
200{ "ok": true, "submissionId": "..." }The submission was stored.
200{ "ok": true, "submissionId": "...", "warning": "near_limit" }Stored, and the team has used 95% of its monthly submissions.
200{ "ok": true }Dropped by the honeypot, the fill-time check or a block list. Nothing was stored.
4xx, 5xx{ "ok": false, "error": "...", "message": "..." }Rejected. See Errors.

Submissions that went to the spam folder answer like stored submissions, with a submissionId.

HTML responses

StatusPage
200The thank-you page, or your custom message on Pro.
303Redirect to your redirect URL or to _redirect, on Pro.
4xx, 5xxA page with the reason and a link back to the page the visitor came from.

Headers

HeaderSent
Access-Control-Allow-Origin: *On every response, so browsers can read it from any website.
Retry-AfterOn 429, with the number of seconds to wait.
LocationOn 303, with the redirect URL.
x-request-idOn every response. Include it when you contact support about a request.

OPTIONS requests get 204 with the CORS headers, so preflight requests from fetch succeed. Browsers may send the Content-Type and Accept request headers. The response headers above, other than Content-Type, are only readable outside the browser, like from a server or cURL.

Other methods

GET and other methods answer 405 with method_not_allowed. Browsers that open the endpoint see a short page explaining that it is a form endpoint.

Processing order

  1. Find the form by its key, or answer 404.
  2. Drop submissions from blocked IP addresses and countries.
  3. Check allowed websites, or answer 403.
  4. Check rate limits, or answer 429.
  5. Read and parse the body, or answer 413 or 415.
  6. Drop bots caught by the honeypot or the fill-time check.
  7. Reject empty submissions with 422, and invalid files with 400, 413 or 415.
  8. Reject submissions to closed forms with 423.
  9. Verify the Turnstile token, or answer 403.
  10. Mark link spam and duplicates as spam.
  11. Check the monthly limit, or answer 402.
  12. Validate answers against the form's fields, store the submission and its files, and queue notifications.

Examples

curl https://api.nisuform.com/s/YOUR_FORM_KEY \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -d '{"email":"jane@example.com","message":"Hello!"}'