Skip to main content

VerificationQuestion Schema

Use verification questions to collect employer or institution responses beyond core verification fields (dates, title, degree, and similar). Define custom questions when you create an order; responses are returned on terminal webhooks after the verifier completes the form. Attach questions on each search via searchTypes[].verificationQuestions. See SearchTypeDto.

Download this guide

Prerequisites

  1. Authentication — Bearer token required. See Authentication.
  2. Create order — Questions are sent in the Create order body under each searchTypes[] entry.
  3. Supported search typesEMPLOYMENT and EDUCATION only.
Standard employment and education form fields are always prepended automatically. Custom questions follow in the order you send them.

Integration flow

Integration flow: client creates order with verificationQuestions, API sends form to verifier, verifier returns completed form, API delivers verification.completed webhook with responses

Click the diagram to view full screen

  1. Define custom questions on each relevant searchTypes[] entry at order creation.
  2. The platform sends a form (PDF and/or online questionnaire link), including custom questions and standard questions.
  3. Responses are extracted from the returned form or eform payload.
  4. On verification.completed, answers appear in data.verificationQuestions (and data.questionnaire). Incomplete or invalid required answers escalate via verification.action_required instead — those paths do not also send verification.completed.
Questions are defined at order creation only. You cannot add or change questions after the order is submitted.

Supported Fields (request)

Send these fields when creating an order. Do not send fieldKey, origin, or conditionMet — the platform assigns those.

Validation limits

Invalid payloads return 400 Bad Request. See Error handling.

Question types

Type-specific rules

For single_select and multi_select, matching is case-sensitive against options[].value. Align webhook parsing with those values.
minSelections / maxSelections bounds are enforced whenever the question is present on the returned form — independent of required. If you set minSelections: 1 on an optional (required: false) multi_select question, a verifier who leaves it at zero selections still triggers VERIFICATION_DATA_INVALID (see Incomplete or invalid answers) on PDF/fax/voice inbound paths. To make a multi_select question truly skippable, omit minSelections (or set it only when the question is also required: true).
There is no first-class “unable to answer” path for required free_text or numeric questions. When verifiers may not know the answer, prefer a select type with an Unknown / N/A option.

Conditional questions

Optional condition attaches a one-level dependency on an earlier question: Allowed parent types: yes_no, single_select, checkbox, numeric, rating_scale (not free_text or multi_select). Nesting: One level only — a parent that itself has a condition is rejected. Semantics after extraction:
  • Parent matches → conditionMet: true; required applies if set.
  • Parent does not match → conditionMet: false; child selectedAnswer is cleared to null. Excess answers still allow completion when other required fields are satisfied.

Ordering and schema version

  • Display order = array order of verificationQuestions in the request.
  • The resolved form is standard questions first, then custom questions in request order.
  • Questionnaire instances use schemaVersion "1".

Response fields (webhook)

Each question in webhook payloads includes the request fields plus:

Where responses appear

Prefer indexing by fieldKey for standard questions and by questionId (or fieldKey) for custom questions. Always branch on type before reading selectedAnswermulti_select returns a string[], every other type returns a string or null.

Channel selection and escalations

Outbound does not branch on whether custom questions are required. Email and fax send a verification PDF in parallel when those channels are enabled. The email body includes the questionnaire URL when the search has a non-empty questionnaireUrl.

Incomplete or invalid answers

On PDF / fax / voice inbound paths (not host-validated eform): These paths emit verification.action_required with reasonCode: HUMAN_ESCALATION and do not emit verification.completed. Online eform completeness for required questions depends on the eform host. Preferred structured payload shape:

Standard questions

The platform always prepends standard questions for the search type. Standard questionId values live in a reserved range (700001+ employment, 700101+ education). Collision is keyed by (questionId, fieldKey) against the active standard set:
  • Exact questionId + fieldKey match → idempotent skip (custom copy ignored)
  • Same questionId, different fieldKey400 Bad Request
  • Same fieldKey, different questionId400 Bad Request
Retired standard IDs (for example former 700003 employment status, 700007 salary, 700101 graduated, 700107 gpa) are reusable as custom IDs. Standard question definitions cannot be overridden.

Employment (searchType: "EMPLOYMENT")

All employment standard questions are optional (required: false).

Education (searchType: "EDUCATION")

All education standard questions are optional (required: false) with allowComment: false.

Internal QuestionnaireInstance

The platform stores questions as a QuestionnaireInstance:
On verification.completed, both are present when a questionnaire is pinned:
  • data.verificationQuestions — the questions array (convenient flat access)
  • data.questionnaire — the full instance (schemaVersion, searchType, questions)

Examples

Custom questions on order creation

Include a questionnaireUrl when you have required custom questions and a usable email contact — that routes the verifier to your eform instead of a verification PDF.
In the example above, condition.dependsOn: 700001 targets the standard employment eligible_for_rehire question. 100008 depends on a custom yes_no parent (100004).

Minimal optional questions (no eform required)

When every custom question is optional, channel selection stays on the standard parallel PDF path. You can omit questionnaireUrl:

Webhook response (verification.completed)

Answers arrive on the completed webhook. data.verificationQuestions is the flat array; data.questionnaire wraps the same questions with schema metadata. Core verification results (verificationResult, employmentVerification / educationVerification) are unchanged — questions are additive.
In a live payload, questionnaire.questions is the same array as data.verificationQuestions (shown abbreviated as [] above to keep the example readable).

Parsing answers in your handler

Escalation: missing required answer

Escalation: invalid answer marks

Escalation: voice-only contact

Route these escalations the same way as other HUMAN_ESCALATION events — alert ops, show escalationSubtype in review UI, and use partial metadata.verificationQuestions when present. See Webhook events.

Implementation notes

  • Stable IDs — Reuse the same questionId across orders for correlation. Custom fieldKey is derived from the prompt; changing the prompt changes fieldKey.
  • Pre-fill — Set selectedAnswer / comment at order creation when known. The verifier may still change values on the form.
  • Parsing — Index by fieldKey for standard questions and by questionId or fieldKey for custom. Use origin to distinguish them. Treat multi_select answers as arrays.
  • No custom questions — Standard questions still appear on the form and in webhooks (data.verificationQuestions / data.questionnaire).
  • Escape hatches — For required free_text / numeric there is no built-in “unable to answer” path. Prefer single_select / multi_select with an Unknown / N/A option when verifiers may not know the answer.
  • Eform preferred payload — When hosting your own questionnaire, post structured answers keyed by fieldKey (see Incomplete or invalid answers).
  • Delivery — Question answers ride the same webhook delivery path as other terminal events (HMAC signature, retries, idempotency via X-Event-Id). See Webhook integration.

Common integration pitfalls

FAQ

Are standard questions always included? Yes. Standard employment/education questions are always prepended — even when you send zero custom questions. Custom questions follow in request order. Can I update questions after creating an order? No. Define all questions in the initial Create order request. Questions are immutable after submit. Does multi_select break existing consumers? Only for that type: selectedAnswer is a string[]. Other types remain strings (or null). Update consumers that assume every answer is a string. When do I get data.questionnaire vs only data.verificationQuestions? Both are present together whenever a questionnaire is pinned on the search (EMPLOYMENT and EDUCATION searches). Use whichever shape is more convenient; the question objects are identical. Do questionnaire escalations also send verification.completed? No. Gate escalations (MISSING_REQUIRED_INFORMATION, VERIFICATION_DATA_INVALID) and VOICE_ONLY_NOT_SUPPORTED emit verification.action_required only.