NisuformDocs

API overview

Create forms, change their settings and work with submissions from your own code with the Nisuform REST API and an API key.

The Nisuform API lets your code do what you do on a form's pages in the dashboard: create and configure forms, page through submissions, mark them read, starred or spam, delete them, download their files and export them as CSV.

You don't need the API to collect submissions. Forms post to the submit endpoint, which is public and needs no key. Use the API when a script, a server or an automation needs to manage forms or read what came in.

https://api.nisuform.com/v1

Quick start

Create an API key

In the dashboard, open Account from the menu under your picture, go to API keys and choose Create key. Copy the key. It starts with nfa_ and is only shown once. See API keys.

Check that it works

curl https://api.nisuform.com/v1/me \
  -H "Authorization: Bearer $NISUFORM_API_KEY"

The response shows your account and the team the key works in.

List your forms and their submissions

curl https://api.nisuform.com/v1/forms \
  -H "Authorization: Bearer $NISUFORM_API_KEY"

curl "https://api.nisuform.com/v1/forms/FORM_ID/submissions?filter=unread" \
  -H "Authorization: Bearer $NISUFORM_API_KEY"

Authentication

Send the key in the Authorization header of every request:

Authorization: Bearer nfa_...

A missing, unknown or revoked key gets 401. API keys are secrets: call the API from a server, a script or an automation tool, never from code that runs in a visitor's browser. The API doesn't accept browser requests from other websites.

Teams

Every key belongs to one team, picked when you create it. Everything the key does happens in that team:

  • GET /v1/forms lists that team's forms, and new forms are created there.
  • Forms in your other teams answer 404, as if they didn't exist.
  • Plan limits and Pro features follow that team's plan.

Switching teams in the dashboard doesn't change which team a key works in.

Endpoints

API keys can use these endpoints:

MethodPathDoes
GET/v1/meGet your account and the key's team
GET/v1/formsList forms
POST/v1/formsCreate a form
GET/v1/forms/{id}Get a form
PATCH/v1/forms/{id}Update a form
DELETE/v1/forms/{id}Delete a form and its submissions
POST/v1/forms/{id}/duplicateCopy a form
POST/v1/forms/{id}/rotate-keyGive a form a new key
POST/v1/forms/{id}/test-submissionsSend a test submission
GET/v1/forms/{formId}/submissionsList submissions
GET/v1/forms/{formId}/submissions/{id}Get a submission
PATCH/v1/forms/{formId}/submissionsMark submissions read, starred or spam
DELETE/v1/forms/{formId}/submissionsDelete submissions
GET/v1/forms/{formId}/submissions/{id}/files/{index}Get a download link for an uploaded file
GET/v1/forms/{formId}/export.csvExport submissions as CSV

Everything else stays in the dashboard: teams and members, billing, integrations, analytics, your profile and API keys themselves. API keys get 403 there.

Requests and responses

  • Send request bodies as JSON with Content-Type: application/json. GET requests take query parameters.
  • Responses are JSON, except the CSV export.
  • IDs are UUIDs. Times are ISO 8601 strings in UTC, like 2026-09-29T10:00:00.000Z.
  • Every response has an x-request-id header. Include it when you contact support about a request.
  • New fields can be added to responses at any time, so ignore fields your code doesn't know.

Errors

Errors answer with a 4xx or 5xx status and a JSON body:

{
  "defined": true,
  "code": "NOT_FOUND",
  "status": 404,
  "message": "Form not found"
}

Branch on code. message is written for people and can change.

StatusCodeWhen
400BAD_REQUESTThe input is invalid. data.issues lists each problem with its path and message.
401UNAUTHORIZEDThe key is missing, unknown or revoked.
402PAYMENT_REQUIREDThe change needs the Pro plan, or the team reached its form limit.
403FORBIDDENAPI keys can't use this endpoint.
404NOT_FOUNDThe form or submission doesn't exist, or it is in another team.
429TOO_MANY_REQUESTSThe key sent too many requests. Wait for the seconds in Retry-After.
500INTERNAL_SERVER_ERRORSomething went wrong on our side. Retry later.

A validation error looks like this:

{
  "defined": true,
  "code": "BAD_REQUEST",
  "status": 400,
  "message": "Input validation failed",
  "data": {
    "issues": [{ "path": ["name"], "message": "Too small: expected string to have >=1 characters" }]
  }
}

Rate limits

Each key can send 120 requests a minute. Past that, requests get 429 with a Retry-After header until the minute is over. To pull many submissions, ask for up to 100 per page or use the CSV export.

Rate limits on the submit endpoint are separate. See Limits.

Get new submissions as they arrive

The API is the right tool for reading and managing submissions on demand. To react to each new submission, use a webhook on Pro instead of asking the API every few seconds.