Submit Inbound Notification
Submit verification responses from employers, schools, and third-party services
Submit Inbound Notification
Use this endpoint to submit verification responses from external parties. The system processes responses through various channels (email, forms, fax, and generic JSON) and automatically extracts verification details using AI.Authentication
Bearer Token Required - Include your JWT token in the Authorization header.Quick Examples
Request Parameters
Optional Fields
msg_<timestamp>_<random>. You can also provide it in messageData.id - the system will use the top-level messageId if present, otherwise messageData.id, otherwise auto-generate.messageId as the threadId. You can also
provide it in messageData.threadId - the system will use the top-level threadId if present, otherwise
messageData.threadId, otherwise use the messageId.Optional Fields
STANDARD) Available Values:
STANDARD, EMAIL, EFORM, MICROSOFT_GRAPH, FAX_WEBHOOK, VOICE_TRANSCRIPT, TICKETING, JITBIT, JSON Channel Types:
STANDARD- Default whenchannelis omittedEMAIL- Email responsesEFORM- Electronic formsMICROSOFT_GRAPH- Office 365FAX_WEBHOOK- Fax responsesVOICE_TRANSCRIPT- Phone/voice transcription responsesTICKETING/JITBIT- Ticketing systemsJSON- Generic structured JSON payloads from upstream systems
Attachments
Attachments are supported for PDF files. PDFs are automatically processed to extract text content, which is then used during message classification and verification data extraction. Supported Format:- PDF files (
application/pdf) - Fully supported with text extraction - Other file types may be included but will not be processed
- PDFs are processed using document extraction tools
- Extracted text is included in the message analysis
- Processing errors are logged but do not block message processing
Response
Fields:
type- Classification type (see Classification Types below)confidence- Score from 0 to 1 indicating classification confidence
-reasoning- Explanation of the classification decision
extractedData. This temporary
backward-compatible shape applies to every channel. Each object includes
backward-compatible flat provided* / verified* values (including applicant names and providedReasonLeft) and the canonical fields comparison map. See the
EmploymentVerification object for field definitions.employmentVerification, omitted from extractedData. This is the single
highest-confidence provider education-history object for every channel. Each object includes backward-compatible flat
provided* / verified* values and the canonical fields comparison map. See the EducationVerification
object for field definitions.employmentVerification and educationVerification temporarily return one object for backward compatibility. A future
version will return sorted arrays after consumers migrate to the array contract.JSON.
Does not include duplicate employmentVerification / educationVerification objects when those are returned at the response
root.searchId, outcome, and channelClassification Types
The classificationtype field is one of the INTENT enum values assigned by the inbound processing pipeline:
VERIFICATION- Verification confirmed with detailsINFO_REQUEST- Employer/school needs more information, or a general information requestINFO_PROVIDED- Applicant provided information that may need follow-upNEXT_CONTACT- Indicates a different contact at the entity should be reached nextWRONG_ENTITY- Message indicates the wrong organization/entity was contactedRECORD_NOT_FOUND- No employment/education record foundAUTHORIZATION_FORM_REQUEST- Authorization form is needed before the entity will respondNO_ACTION_REQUIRED- Message requires no further actionUNKNOWN- Could not determine intentOTHER- Other classification that doesn’t fit the above
THIRD_PARTY is a deprecated legacy value — the classifier remaps it to WRONG_ENTITY internally, so it will never appear in a response’s classification.type.Examples
Employment Verification
employmentVerification object with per-field comparison in fields
(not nested in extractedData). Example from an EMAIL channel response for Pablo’s Pizza / John Smith:
Education Form Submission
Generic JSON Submission
Usechannel: "JSON" when an upstream system sends structured third-party verification data instead of an email, fax, or ticket transcript. Place the provider payload in messageData.data.
JSON channel requirements:
Supported JSON payload shapes
The API detects employment or education history records from common vendor response layouts. You do not need to normalize the payload to a single schema — pass the vendor object inmessageData.data.
Employment searches — records are enumerated from:
Employment JSON example
extractedData contains the best-match
scalars and operational flags, while root-level employmentVerification contains the single highest-confidence provider history
object.
Education JSON example
channel: "JSON" submissions return the same synchronous processing envelope as other channels: messageId, success,
classification, extractedData, the applicable root-level employmentVerification / educationVerification object, metadata,
and processedAt. The verification object is the highest-confidence provider history row. The employment example selects the row
with confidence 0.94 for search EXT-DEV-1781042158637-1. The raw
provider payload is not echoed in the synchronous response or webhook payloads. For the full verification.completed JSON closeout
shape, see Webhook events — Employment Verification (JSON
channel).
Comparison fields: selected JSON record
JSON channel responses expose comparison output at two levels:Field comparison metadata (fields.*.comparison)
Normalized verification objects (for example employmentVerification.fields on downstream webhooks) attach per-field comparison metadata. similarity is not a universal score — deterministic exact string matches use similarity: 1, and probabilistic / organization-name comparisons use their evaluated score. Date and number fields never include similarity; deterministic matches and mismatches on those types use distance instead.
distance: 0, no similarity):
similarity present):
Downstream webhook delivery
In addition to the synchronous response body, successful JSON submissions emit extraction and the selected normalized verification object asynchronously. Primary delivery paths:verification.notificationwithnotificationType: "INBOUND_RECEIVED_DETAIL"— best-match scalars (and optionalapplicantMismatch/_requiresManualReviewflags) atdata.metadata.extractedData; the highest-confidence record with per-field comparison at root-leveldata.employmentVerificationordata.educationVerification(not nested inextractedData).applicantMismatchesandapplicantDiscrepanciesare not included.verification.action_requiredwithreasonCode: "HUMAN_ESCALATION"or"OTHER"— when manual review is required for non-verified or JSON-channel holds;extractedDataunderdata.metadata.extractedDatawithout duplicate verification data. JSON-channel only (channel: "JSON",status: "QA Review"): root-leveldata.message(human-readable review summary for client UI) plus the highest-confidencedata.employmentVerificationordata.educationVerificationobject. EMAIL/FAX/VOICE action-required webhooks omitmessage. Verified EMAIL/FAX/VOICE with field mismatches typically close viaverification.completedandverificationResult.discrepancy: trueinstead.- Activity metadata — root-level
employmentVerification/educationVerificationplus strippedextractedData(same split as webhooks), alongsidemessageId,threadId,contactType, andmessageContext verification.completed— root-leveldata.employmentVerification(ordata.educationVerification) as the single highest-confidence object for JSON.data.verificationResult.extractedDatakeeps scalar extraction and comparison metadata without duplicate verification data.verificationResult.discrepancyis the operational closeout flag and may befalsewhen the selected row only has non-criticalfields.*.status: "match_with_discrepancy"entries.
INBOUND_RECEIVED_DETAIL webhook envelope for search 86bc0a43-6a10-4f85-a093-e4244ed78107 / EXT-DEV-1781042158637-1 (Pablo’s Pizza / John Smith). metadata.extractedData is identical wherever that object appears; the selected verification object sits at the payload root.
employmentVerification / educationVerification is the highest-confidence object. Field-level comparison for that selected row appears on data.employmentVerification.fields / data.educationVerification.fields. applicantMismatches and applicantDiscrepancies are not included in webhook or inbound notification payloads — use fields.* instead. When a critical mismatch triggers escalation, metadata.extractedData may include applicantMismatch: true and _requiresManualReview: true without field-level objects. When the search closes without escalation, verification.completed may set verificationResult.discrepancy: false even though employmentVerification.fields.position.status is match_with_discrepancy — see Webhook events.
Auto-Generated IDs
When messageId or threadId are not provided, the system automatically generates them:Error Responses
200 (the controller forces @HttpCode(HttpStatus.OK)), even when processing fails. Failures are represented in the response body, not the HTTP status — check the success and failureReasons fields on every response.400 Bad Request shape as every other endpoint — there is no 422 status configured for this API. messageId is optional and can never trigger a “should not be empty” failure; messageData.timestamp is the field actually marked as required.
JSON channels also require messageData.from and messageData.to; the controller checks this explicitly and returns a single-string 400 message (not the array shape) naming the missing fields.
How It Works
The inbound notification processing follows these steps:- Submit - You send verification response via API
- ID Generation - If
messageIdorthreadIdare not provided, they are auto-generated - Validate - System validates required fields and checks for malicious content. For
JSONchannel, validates thatmetadata.searchRefIdand a non-emptymessageData.datapayload are present. For other channels, validatesmessageData.fromandmessageData.to. - Match - Links message to active verification search:
JSONchannel: Matches exclusively onmetadata.searchRefId(external search ID or internal reference). Does not scan the payload body for reference numbers.- Other channels: Extracts 7–8 digit reference numbers from subject, body, attachments, or uses
metadata.searchRefId/threadIdwhen provided.
- Process Attachments - PDF attachments are processed to extract text content (if present; skipped for
JSONchannel) - Analyze Contact - Determines sender type (APPLICANT, ENTITY, or UNKNOWN). JSON channel requests are treated as ENTITY responses.
- Classify & Extract - AI-powered classification extracts verification details:
JSONchannel: Extracts directly from structured provider payload; selects the best-matching employment or education record when multiple are present.- Other channels: Analyzes the message content to extract structured verification data.
- Extracts structured outcome (VERIFIED, NO_RECORD, THIRD_PARTY, INFO_REQUESTED, etc.)
- Parses verification data (dates, positions, confirmation status)
- Cross-check Provided Data - Compares extracted applicant, employment, or education details against the order data on file. Tenant comparison settings (see tenant
config.comparisonConfig) tune behavior: calendar-day windows per date field (startDate,endDate,graduationDate), semantic equivalence thresholds for applicant name, job title, degree, major, and location proximity, and salary tolerances. For employment salary, when both the order value (providedSalaryin search metadata) and the extracted salary parse, the API normalizes common compensation text (for example annual, hourly, monthly, weekly, andk/msuffixes) to an estimated annual USD amount and treats a mismatch only if the gap exceeds both the configured absolute-dollar threshold and the relative (percent) threshold; otherwise it falls back to the same normalized string comparison used for other plain-text fields. Mismatch reasons for dates and salaries include the compared raw values (and annualized figures for salary) to aid review. - Persist Results - Saves processing results, classification, and extracted data
- Update Search - Updates search status if terminal outcome (VERIFIED, NO_RECORD, THIRD_PARTY, WRONG_ORG)
- Schedule Follow-up - If non-terminal outcome (INFO_REQUESTED, INSUFFICIENT), schedules next outbound attempt
- Notify - Sends webhook if verification reaches terminal state
Common Use Cases
Best Practices
Message IDs:- Use unique identifiers (UUIDs recommended) if available
- Never reuse message IDs
- Optional: Omit the field entirely if you don’t have one - the system will auto-generate it
- If provided, ensure it’s unique across all messages
- Keep consistent for related messages in the same conversation thread
- Helps track conversation history across multiple exchanges
- Optional: Omit the field entirely if you don’t have one - the system will use the messageId as the threadId
- Use the same threadId for all messages in the same conversation
- Always use ISO 8601 format
- Example:
2026-01-15T10:30:00.000Z
- Include all verification details in the
body.textfield - Include reference number: The message must contain a 7-8 digit reference number to match the message to the correct verification search. The system looks for patterns like:
- “Reference: 12345678”
- “Ref. 12345678”
- “Ticket # 12345678”
- “Case # 12345678”
- Or standalone 7-8 digit numbers
- Mention attachments sent via separate channels if needed
JSON channel): - Set
channelto"JSON"and place the vendor response inmessageData.data - Always include
metadata.searchRefId— this is the only search-matching mechanism for JSON requests. Use the search’s external ID (e.g.EXT-DEV-1781042158637-1) or internal reference number - Set
metadata.providerto identify the upstream system for audit and traceability - Pass the vendor payload as-is; normalization to a single schema is not required
- When the provider returns multiple employment or education records, include all of them — the API selects the record that best matches the applicant and submitted search data
- For every channel, HTTP 200 includes a response body; check
successand processfailureReasonswhen present - Successful responses include best-match scalars in
extractedDataand the highest-confidence normalized provider record in the applicable root-level verification object - Implement retry with exponential backoff for server errors
Troubleshooting
“metadata.searchRefId is required for JSON channel requests”- Include
metadata.searchRefIdon everychannel: "JSON"request - The value must be a non-empty string
- Ensure
messageData.datais a non-empty object containing at least one enumerable employment or education record - Do not send only
{ "text": "..." }or{ "html": "..." }keys without structured verification data
- Verify
metadata.searchRefIdmatches the search’sexternalSearchIdor internal reference - Ensure the search is still active (not completed or cancelled)
- Check that the search has the INBOUND objective enabled
- Verify the message contains a valid 7-8 digit reference number in one of the supported formats:
- “Reference: 12345678”
- “Ref. 12345678”
- “Ticket # 12345678”
- “Case # 12345678”
- Or a standalone 7-8 digit number
- Ensure the reference number matches an active verification search
- Ensure search is still active (not completed or cancelled)
- Check that the search has the INBOUND objective enabled
- Check sender email matches expected contact (if applicable)
- Non-JSON channels require both
messageData.fromandmessageData.to - These fields are optional only when
channelis"JSON"
- All required fields must be present for the channel type
- Check timestamp is valid ISO 8601
- Review error messages in response
- Verify data types match requirements
- Ensure all required fields are present
Next Steps
Authorizations
Bearer authentication header of the form Bearer <token>, where <token> is your auth token.
Body
Message data
Message ID to process (auto-generated if not provided)
Thread ID (auto-generated if not provided)
Channel type
MICROSOFT_GRAPH, FAX_WEBHOOK, STANDARD, EMAIL, TICKETING, JITBIT, EFORM Additional metadata. Can include pre-extracted data from upstream systems: - provider: Source system identifier (e.g., 'SNH AI ', 'JITBIT') - searchRefId: Reference ID for the search - activityId: Activity ID from upstream system - link: URL to original ticket/message - intention: Pre-classified intent (VERIFICATION, INFO_REQUEST, THIRD_PARTY, etc.) - confidence: Confidence level from upstream (0-1). Defaults to 0.95 if not provided. - structuredData: Pre-extracted verification data with verifiedInfo and verificationResult
Response
The response is of type object.

