NueForm

Webhook Payloads

Complete reference for NueForm webhook payload schemas, including the form.submitted event structure, answer formats by question type, and quiz results.

Every NueForm webhook request sends a JSON payload in the request body. This page documents the complete payload schema for each event type.

Common Structure

All webhook payloads share these top-level fields:

FieldTypeDescription
eventstringThe event type (e.g., form.submitted)
formIdstringThe unique ID of the form
formTitlestringThe title of the form at the time of submission
responseIdstringThe unique ID of the response
answersarrayArray of answer objects
respondentobject or nullIdentity of the logged-in respondent, when the form required login. null for anonymous submissions. See Respondent Identity.
submittedAtstringISO 8601 timestamp of when the event was dispatched

form.submitted Payload

This is the payload sent when a respondent submits a complete form response.

Full Example

json
{
  "event": "form.submitted",
  "formId": "507f1f77bcf86cd799439011",
  "formTitle": "Customer Feedback Survey",
  "responseId": "507f1f77bcf86cd799439022",
  "answers": [
    {
      "questionId": "507f1f77bcf86cd799439033",
      "value": "Jane Doe",
      "label": "What's your name?",
      "type": "short_text"
    },
    {
      "questionId": "507f1f77bcf86cd799439044",
      "value": "jane@example.com",
      "label": "What's your email address?",
      "type": "email"
    },
    {
      "questionId": "507f1f77bcf86cd799439055",
      "value": 4,
      "label": "How would you rate your experience?",
      "type": "rating"
    },
    {
      "questionId": "507f1f77bcf86cd799439066",
      "value": "The onboarding flow was smooth and intuitive.",
      "label": "What did you like most?",
      "type": "long_text"
    },
    {
      "questionId": "507f1f77bcf86cd799439077",
      "value": ["c3a1e5f2-8b4d-4f6a-9e21-7d0b3c8a5f14", "9b7e2d41-5c3f-4a8e-b6d0-1f2a4c6e8b93"],
      "label": "Which features do you use?",
      "type": "multiple_choice"
    },
    {
      "questionId": "507f1f77bcf86cd799439088",
      "value": true,
      "label": "Would you recommend us?",
      "type": "yes_no"
    }
  ],
  "respondent": {
    "id": "507f1f77bcf86cd799439016",
    "name": "Jane Smith",
    "email": "jane@example.com",
    "auth_method": "sso"
  },
  "submittedAt": "2025-03-15T14:32:07.123Z"
}

Field Reference

Top-Level Fields

event --- string

Always "form.submitted" for this event type.

formId --- string

The MongoDB ObjectId of the form. This is a 24-character hexadecimal string.

formTitle --- string

The human-readable title of the form at the time the webhook fires. Note that if you rename the form later, previously delivered webhooks will still contain the old title.

responseId --- string

The MongoDB ObjectId of the stored response. You can use this to fetch the full response via the Responses API or as an idempotency key to deduplicate webhook deliveries.

submittedAt --- string

ISO 8601 timestamp indicating when the webhook was dispatched. This is generated at dispatch time and will be very close to (but not necessarily identical to) the response's submittedAt field in the database.

respondent --- object or null

Identity of the logged-in user who submitted the response, surfaced only when the form required login (requireLogin: true). null for all anonymous submissions. See Respondent Identity below for the full schema and behaviour.

Answer Objects

Each entry in the answers array represents a single question's response:

FieldTypeDescription
questionIdstringThe MongoDB ObjectId of the question
valueanyThe respondent's answer (format varies by question type)
labelstringWeb submissions only. The question's title as plain text, in the language the respondent answered in.
typestringWeb submissions only. The question type, such as short_text or matrix.
subLabelsobjectWeb submissions only, for a question with sub-fields, such as Contact Info, Address or a Question Group. Maps each sub-field's ID to its label.
valueLabelsobjectWeb and phone-call submissions, for a question whose choices, rows or columns come from a variable. value then holds item values, and this map gives the label of each chosen value. On a Matrix the keys are row:<value> and column:<value>. Answers to fixed lists don't carry it.

Answers from phone calls carry questionId, value and, for a list taken from a variable, valueLabels. Web answers can also carry viewedAt and answeredAt — when the question was shown and answered, as ISO 8601 timestamps from the respondent's device. More fields may be added over time, so ignore any you don't use.

A web answer to a list loaded from a variable looks like this:

json
{
  "questionId": "507f1f77bcf86cd799439099",
  "value": "siamese",
  "label": "Which breed is your cat?",
  "type": "dropdown",
  "valueLabels": { "siamese": "Siamese" }
}

The same answer given on a phone call arrives without label and type.

Answer Values by Question Type

The value field in each answer object varies depending on the question type. Here is the format for each type:

Text Inputs

Question TypeValue TypeExample
short_textstring"Jane Doe"
long_textstring"I really enjoyed the product..."
emailstring"jane@example.com"
phonestring"+1 (555) 123-4567"
numbernumber42
urlstring"https://example.com"

Choice Questions

Question TypeValue TypeExample
multiple_choice (single)string"c3a1e5f2-8b4d-4f6a-9e21-7d0b3c8a5f14"
multiple_choice (multi)array<string>["c3a1e5f2-8b4d-4f6a-9e21-7d0b3c8a5f14", "__other__:Word of mouth"]
dropdown (single)string"e0c4a7d9-2f16-4b3e-8a57-c19d6f2b4e80"
dropdown (multi)array<string>["e0c4a7d9-2f16-4b3e-8a57-c19d6f2b4e80", "5d8f1b36-a9e2-4c07-b3d4-6e1a9f7c2b58"]
yes_nobooleantrue

value holds choice IDs, not labels: the id of each chosen entry in the question's choices. The builder creates these IDs as UUIDs. The API and the MCP server also accept a choice without an id, such as { "label": "Search engine" }; in a web answer, value then holds that choice's label instead of an ID. multiple_choice and dropdown send a single string, or an array of strings when allowMultiple is true. Image choices (layout: "blocks") are multiple_choice questions too.

If the respondent picks Other, the entry is __other__: followed by the text they typed, as in the example above. A phone call stores an Other answer as the caller's own words, without the prefix.

Webhooks don't send the labels of a fixed list. To show them, match each ID against the question's choices, which Get Form returns; for a choice without an id, value already holds its label. When the choices come from a variable, value holds item values and the answer's valueLabels gives their labels — see Answer Objects.

Rating Questions

Question TypeValue TypeExampleRange
ratingnumber41 to steps (default 5)
opinion_scalenumber7min to max
npsnumber90 to 10

Date and Time

Question TypeValue TypeExample
datestring"2025-03-15"

The date string format matches the dateFormat property configured on the question (defaults to YYYY-MM-DD).

Question TypeValue TypeExample
legalbooleantrue
statementstring"" (always empty --- statements collect no data)

Ranking

Question TypeValue TypeExample
rankingarray<string>["5d8f1b36-a9e2-4c07-b3d4-6e1a9f7c2b58", "c3a1e5f2-8b4d-4f6a-9e21-7d0b3c8a5f14", "71a4c9e0-3b5d-4f82-9c16-d2e8a0b7f345"]

The array holds choice IDs in the respondent's order, from first to last; in a web answer, a choice saved without an id appears as its label instead. Match the IDs to their labels as for Choice Questions.

Matrix

Question TypeValue TypeExample
matrixobject{ "Speed": "Satisfied", "Price": "Neutral" }

For a Matrix with fixed rows and columns, the object maps each row label to the selected column label. When its rows or columns come from a variable, it maps row values to column values, and the labels the respondent saw are in the answer's valueLabels, under row:<value> and column:<value> keys.

File Upload

Question TypeValue TypeExample
file_uploadstring"https://storage.nueform.io/uploads/abc123.pdf"

The value is the URL of the uploaded file in NueForm's storage.

Signature and Drawing

Question TypeValue TypeExample
signaturestring"data:image/png;base64,iVBOR..."
drawingstring"data:image/png;base64,iVBOR..."

Both return a base64-encoded PNG data URI of the captured image.

Recording

Question TypeValue TypeExample
recordingstring"https://storage.nueform.io/recordings/abc123.webm"

The value is the URL of the uploaded recording file.

Composite Questions

Composite question types (contact_info, address, question_group, multi_question_page) produce one answer entry, under the composite question's own questionId. Its value is an object keyed by sub-field ID. Contact Info and Address use built-in IDs such as first_name and zip_code; a Question Group or Multi-Question Page uses the ID of each question inside it. Each sub-field's value has the format of its own question type. Web answers also carry subLabels, which maps each sub-field ID to its label.

For example, a contact_info question produces:

json
{
  "questionId": "507f1f77bcf86cd7994390aa",
  "value": {
    "first_name": "Jane",
    "last_name": "Doe",
    "phone_number": "+1 555-0100",
    "email": "jane@example.com",
    "company": "Acme Inc."
  },
  "label": "How can we reach you?",
  "type": "contact_info",
  "subLabels": {
    "first_name": "First Name",
    "last_name": "Last Name",
    "phone_number": "Phone Number",
    "email": "Email",
    "company": "Company"
  }
}

The same answer given on a phone call has the same value, without label, type and subLabels.

Respondent Identity

When a form is configured with requireLogin: true, every accepted submission is tied to a signed-in user. Webhook payloads expose that identity to form owners through the respondent field. For all other submissions the field is null.

Schema

json
{
  "respondent": {
    "id": "507f1f77bcf86cd799439016",
    "name": "Jane Smith",
    "email": "jane@example.com",
    "auth_method": "sso"
  }
}
FieldTypeDescription
idstringThe respondent's user ID.
namestringDisplay name on the respondent's account.
emailstringEmail address on the respondent's account.
auth_methodstringEither "sso" or "login". "sso" indicates the respondent is a member of the form's team via Single Sign-On; "login" indicates any other supported authentication method.

When respondent is populated

respondent is populated only when:

  1. The form has requireLogin set to true, and
  2. The submitter signed in because the form required it before submitting.

When requireSsoLogin is also true, only users who are members of the form's team via SSO can reach the submit step, so every populated respondent will have auth_method: "sso".

When respondent is null

The field is always present in the JSON for predictable downstream parsing, and is null whenever any of these is true:

  • The form did not require login (requireLogin was false).
  • The submitter was anonymous.
  • The response was saved via the post-submit consent flow (the "claim this response" prompt). Consent-saved responses never appear in webhook payloads with identity attached — they are stored only in the user's "My Responses" view and are not exposed to webhook receivers.

Webhook payloads only expose identity for respondents who logged in because the form required it. Identities collected via post-submit consent are intentionally withheld from webhooks to honor the boundary between a respondent's privacy and an owner's insight.

Quiz Results

For forms running in a quiz mode (knowledge_quiz, lead_qualification, or match_quiz), the stored response includes a quizResults object. While this object is not directly included in the webhook payload, you can retrieve it via the Responses API using the responseId from the webhook.

The quizResults object has the following structure:

json
{
  "formMode": "knowledge_quiz",
  "score": 7,
  "correctAnswers": 7,
  "totalScorableQuestions": 10,
  "maxScore": 10,
  "matchedEndingId": "507f1f77bcf86cd799439099"
}
FieldTypeDescription
formModestringThe quiz mode: knowledge_quiz, lead_qualification, or match_quiz
scorenumberThe respondent's total score
correctAnswersnumberNumber of questions answered correctly (knowledge quiz only; 0 for other modes)
totalScorableQuestionsnumberTotal number of questions that contribute to the score
maxScorenumberThe maximum achievable score
matchedEndingIdstring or undefinedThe ID of the end screen shown to the respondent based on their score
endingTalliesobject or undefinedMatch quiz only: maps each end screen ID to its tally count

Metadata

The stored response may also include a metadata object containing hidden fields passed via URL parameters. This is available via the Responses API but is not included in the webhook payload.

json
{
  "hiddenFields": {
    "utm_source": "google",
    "utm_campaign": "spring_sale",
    "user_id": "ext_12345"
  }
}

To access metadata for a webhook-delivered response, fetch it using the responseId:

bash
curl https://app.nueform.io/api/v1/forms/FORM_ID/responses/RESPONSE_ID \
  -H "Authorization: Bearer nf_your_api_key"

HTTP Headers

Every webhook request includes these HTTP headers:

HeaderValue
Content-Typeapplication/json
X-NueForm-SignatureHMAC-SHA256 hex digest of the raw request body

See Verification for how to validate the signature.

Payload Size

Webhook payloads are typically small (under 10 KB). The size depends primarily on the number of questions and the length of text answers. File upload answers contain URLs (not file contents), so they do not significantly increase payload size.

Next Steps

  • Verification --- Validate webhook signatures
  • Testing --- Test webhook payloads locally
  • Events --- Event types and delivery guarantees
Last updated: October 8, 2026