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
| Parameter | Description |
|---|---|
key | The form key. Letters, digits and hyphens, starting with a letter or digit, up to 64 characters. Not case sensitive. |
Request body
| Content type | Use it for |
|---|---|
application/x-www-form-urlencoded | Plain HTML forms. The browser's default. |
multipart/form-data | HTML forms with enctype="multipart/form-data", FormData bodies and file uploads. |
application/json | fetch 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/html | Response |
|---|---|
| Yes, like a normal browser form submit | An HTML page, or a 303 redirect |
No, like fetch, cURL or a server | JSON |
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
}| Status | Body | When |
|---|---|---|
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
| Status | Page |
|---|---|
200 | The thank-you page, or your custom message on Pro. |
303 | Redirect to your redirect URL or to _redirect, on Pro. |
4xx, 5xx | A page with the reason and a link back to the page the visitor came from. |
Headers
| Header | Sent |
|---|---|
Access-Control-Allow-Origin: * | On every response, so browsers can read it from any website. |
Retry-After | On 429, with the number of seconds to wait. |
Location | On 303, with the redirect URL. |
x-request-id | On 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
- Find the form by its key, or answer
404. - Drop submissions from blocked IP addresses and countries.
- Check allowed websites, or answer
403. - Check rate limits, or answer
429. - Read and parse the body, or answer
413or415. - Drop bots caught by the honeypot or the fill-time check.
- Reject empty submissions with
422, and invalid files with400,413or415. - Reject submissions to closed forms with
423. - Verify the Turnstile token, or answer
403. - Mark link spam and duplicates as spam.
- Check the monthly limit, or answer
402. - 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!"}'