Webhook Payload Reference
This reference documents the structure, field definitions, PII disclosure modes, and sample JSON payloads for Onbo webhook events (application.decision and application.reviewed).
Payload Structure
Every payload is built from a small number of top-level objects, each answering a different question about the application:
{
"event": { "…": "which event this is (webhooks only)" },
"applicationDetails": { "…": "which application it is about" },
"verificationResult": { "…": "what the automated checks concluded" },
"documents": { "…": "what was captured, by kind" },
"applicantData": { "…": "who the applicant is" },
"employeeI9Details": { "…": "I-9 specific fields (I-9 journeys only)" },
"reviewDetails": { "…": "what a human reviewer decided" }
}Only event and applicationDetails are always present. Every other object is omitted when the job produced nothing for it — an Onbo Plus application carries no employeeI9Details, and a job that was never reviewed carries no reviewDetails. Treat a missing key as “nothing to report”, never as an error.
Top-Level Event Object (event)
Present on webhook deliveries only. The Get Job Data API returns the same body without it, because a pull response describes no event.
| Field | Type | Description |
|---|---|---|
id | String | Unique event identifier. Remains constant across retries — use it for idempotency. |
type | String | Lifecycle event type: application.decision or application.reviewed. |
occurredAt | String | UTC ISO 8601 timestamp when the event occurred. |
payloadVersion | String | Version string of the payload contract (currently v1). |
piiMode | String | Personal data disclosure mode applied to this delivery (NONE, MASKED, or FULL). |
PII Disclosure Modes
Onbo allows organizations to configure how much personal data is delivered:
| PII Mode | Behavior |
|---|---|
NONE | Omits applicantData, documents, and verificationResult.identiFraud entirely, along with the personal fields inside employeeI9Details and reviewDetails. Decision outcomes, verification scores, and application metadata are still delivered. |
MASKED (Default) | Partial redaction of sensitive fields — see the mask formats below. |
FULL | Unmasked personal data. Note: an unmasked SSN additionally requires the explicit allow_full_ssn opt-in; FULL alone still masks it. |
Mask formats under MASKED
| Field | Rule | Example |
|---|---|---|
ssn | Last 4 digits | •••••6789 |
idNumber | Last 4 characters | ••••0000 |
phone | Last 4 digits | •••••••0142 |
dob, idDateOfBirth | Year kept, separators preserved | ••/••/1990 |
email | First character and full domain kept | t••••••••@example.com |
Under NONE, these fields are absent rather than masked.
Field Dictionary
1. Application Details (applicationDetails)
Always present. Identifies the application the event is about.
| Field | Type | Description |
|---|---|---|
applicationId | String | Unique application (job) identifier. |
externalId | String | Your own tracking identifier, supplied when the job was created. |
companyId | String | Organization ID owning the application. |
journey | String | The job type that produced this application, e.g. onbo_plus, employee_i9_onboarding. |
status | String | Current application state (e.g. Approved, approved, Review Identifraud, Declined). |
applicationCreatedAt | String | When the application was created. |
applicationUpdatedAt | String | When its state last changed. |
journey is the job type, for every flow — onbo_plus, employee_i9_onboarding, and so on. It is a stable discriminator: a given value always means the same kind of application.
status is carried verbatim and its casing varies by how the state was reached — a reviewer-set state arrives lowercase (approved), an automated one title-cased (Approved). Compare case-insensitively.
2. Verification Result (verificationResult)
What the automated checks concluded. Scores and decision codes describe the checks rather than the applicant, so this object is delivered at every PII mode — with the exception of identiFraud, which reports on the applicant and is withheld under NONE.
2.1 Deduplication (dedupResult)
| Field | Type | Description |
|---|---|---|
matchFound | Boolean | true if the applicant matched an existing record. |
matchCount | Number | How many records matched. Absent when no deduplication ran — absent and 0 are different claims. |
The matched records themselves are never delivered: they are other people’s identity data.
2.2 Document Validation (documentValidationResult)
One combined view of the face-match and liveness checks. Omitted entirely when neither check ran.
Onbo runs up to two face checks — an ID face match against the captured document, and a selfie live-check. This object merges them field by field, with the ID face match taking priority and the live-check supplying anything the ID check did not report. The two can disagree on a shared score, so this is one consolidated verdict rather than a per-vendor audit trail.
| Field | Type | Description |
|---|---|---|
isLive | Boolean | Whether a live face was detected. |
selfieLiveCheckStatus | String | Human-readable liveness status, e.g. Live Face Detected. |
faceVerificationResult | String | Face match verdict, e.g. Verified. |
faceVerificationScore | Number | Face match confidence, 0–100. |
realScore | Number | Liveness confidence, 0–1. |
verificationResult | String | Overall document verdict, e.g. Approved. |
verificationResultCode | String | Overall result code, e.g. 00. |
cellPhone / cellPhoneScore | Boolean / Number | Whether a phone screen was detected in frame, and its score. |
eyeCovering / eyeCoveringScore | Boolean / Number | Whether eyewear obstructed the face, and its score. |
faceMask / faceMaskScore | Boolean / Number | Whether a face covering was detected, and its score. |
headCovering / headCoveringScore | Boolean / Number | Whether a head covering was detected, and its score. |
advancedLiveness | Object | Deepfake detection verdict — status (e.g. AUTHENTIC) and score. |
idvFaceMatchDecision | Object | Per-check decision map — see below. |
The boolean flags are only present when a check actually reported them. An absent flag means “not assessed”, not false.
idvFaceMatchDecision maps each document inspection to its outcome. Keys are check names (Decision_FaceMatch, Decision_Expiration, Decision_Tamper, Decision_MRZ, …); each value is an object with result (e.g. OK) and stateCode (e.g. 00). The set of checks varies by document type and journey, so iterate the keys rather than expecting a fixed list.
2.3 Identity Fraud (identiFraud)
(Omitted under PII_MODE_NONE.)
Array of third-party identity-verification service results. Each entry carries serviceName and a profiles array; each profile carries the matched consumer record (name, address, idNumber, dateOfBirths) and a verificationResult with verified, a scores array of per-field match scores, and a data object holding the check-by-check breakdown (address, date of birth, phone, SSN validation, OFAC).
3. Documents (documents)
(Omitted under PII_MODE_NONE.)
Document slots grouped by what each document is, so you can find the identity document without knowing which of nine slot names a given journey happened to write. Each value is a Document URN (urn:documentsv1:<env>:<uuid>) used to fetch the binary via the Documents API.
A group with no captured documents is omitted entirely.
| Group | Slots |
|---|---|
id | idFront, idBack, idFrontListC, idBackListC, idFrontSecondListA, idBackSecondListA, videoIdImageFront, videoIdImageBack, videoData |
selfie | selfie, selfieImage, enrollmentSelfie, signatureSelfieImage |
signature | signatureImage, signatureVideo |
other | i9FormPDF, pdfReport |
"documents": {
"id": { "idFront": "urn:documentsv1:prod:…95" },
"selfie": { "selfie": "urn:documentsv1:prod:…fa" },
"signature": { "signatureImage": "urn:documentsv1:prod:…77" }
}Video captures group under id because a filmed identity document is the same evidence in another medium.
If your organization is configured for BASE64 document delivery, each slot carries base64 bytes instead of a URN — the slot is a string either way. Videos and the rendered I-9 PDF are always URNs regardless of that setting, as inlining them would not fit the delivery timeout.
i9FormPDF is the rendered Form I-9, on I-9 journeys; pdfReport is the generated summary report, on Onbo Plus. Both are rendered after the decision is reached, but they are delivered differently: the Onbo Plus decision event waits for pdfReport, so it is present on application.decision — except when the render failed, in which case the event is delivered without it rather than withheld. i9FormPDF is not waited for, so it is normally absent from application.decision and present on later events. Both stay URNs under BASE64 delivery, for the same reason videos do.
4. Applicant Data (applicantData)
(Omitted entirely under PII_MODE_NONE.)
Everything about the person, under one key for every journey — there is no separate customer/employee shape to branch on.
| Field | Type | Description |
|---|---|---|
personalData | Object | Name, date of birth, contact details, address, physical description, and the document’s own spellings of each — see below. |
addressDetails | Object | streetAddress, city, state, postalCode, country, countryCode. |
extractedIdData | Object | Fields read from the primary identity document. |
extractedSecondaryIdData | Object | The same shape, for the companion document of a two-part List A capture. |
attestationDetails | Object | citizenshipStatus and attestedAt. |
consents | Array | consentType (TERMS_AND_CONDITIONS, BIOMETRIC_PROCESSING, PRIVACY_POLICY), version, status (GIVEN), consentedAt. |
Personal data fields (personalData)
Read off the identity document and from what the applicant supplied. As with the extracted document fields, which of these appear depends on the document type and on what the capture could read — treat every field as optional.
| Field | Type | Description |
|---|---|---|
firstName | String | First name. |
middleName | String | Middle name. |
lastName | String | Last name. |
lastName2 | String | Second surname, on documents that print two. |
name | String | Full name. |
additionalNames | String | Any further names the document lists. |
dob | String | Date of birth. |
gender | String | Gender. |
uniqueNumber | String | An identifier the document assigns to the person. |
email | String | Contact email address. |
phone | String | Contact phone number. |
ssn | String | Social Security Number. |
address | String | Full address string. |
addressLine1 | String | Address line 1. |
addressLine2 | String | Address line 2. |
addressLine3 | String | Address line 3. |
city | String | City. |
state | String | State or province. |
parish | String | Parish, where the jurisdiction uses one. |
postalCode | String | Postal or ZIP code. |
country | String | Country. |
eyeColor | String | Eye colour printed on the document. |
hairColor | String | Hair colour printed on the document. |
height | String | Height printed on the document. |
weight | String | Weight printed on the document. |
nameNonEng | String | name in the document’s own script, when it is not Latin. |
firstNameNonEng | String | firstName in the document’s own script. |
middleNameNonEng | String | middleName in the document’s own script. |
lastNameNonEng | String | lastName in the document’s own script. |
additionalNamesNonEng | String | additionalNames in the document’s own script. |
addressNonEng | String | address in the document’s own script. |
addressLine1NonEng | String | addressLine1 in the document’s own script. |
addressLine2NonEng | String | addressLine2 in the document’s own script. |
name_doc | String | name exactly as printed, before normalisation. |
firstName_doc | String | firstName as printed. |
middleName_doc | String | middleName as printed. |
lastName_doc | String | lastName as printed. |
lastName2_doc | String | lastName2 as printed. |
dob_doc | String | dob as printed. |
linkUniqueId | String | Your own correlation identifier, echoed back. |
ssn, dob, dob_doc and uniqueNumber are masked under MASKED; see the mask formats above.
Extracted document fields (extractedIdData, extractedSecondaryIdData)
Fields read off the identity document by OCR, MRZ parsing and barcode decoding. Which fields appear depends on the document type and on what the capture could read — a passport yields MRZ fields and no driver-license fields, a US driver license yields the reverse. Treat every field here as optional.
| Field | Type | Description |
|---|---|---|
i9Document | String | Which I-9 list the document satisfies: ListA, ListB, or ListC. Present on I-9 journeys only; absent when no list applies. |
idType | String | Document code, e.g. PP (passport), DL (driver license). |
idState | String | Issuing state or province. |
idCountry | String | Document country of origin. |
idNumber | String | Primary document number. |
idNumber1 | String | Additional number, for documents that print more than one. |
idNumber2 | String | Additional number. |
idNumber3 | String | Additional number. |
idNumber4 | String | Additional number. |
idDateOfBirth | String | Date of birth printed on the document. |
idDateOfBirthFormatted | String | Date of birth, normalised. |
idExpirationDate | String | Expiration date. |
idExpirationDateFormatted | String | Expiration date, normalised. |
idIssueDate | String | Issue date. |
idIssueCountry | String | Country of issue. |
placeOfIssue | String | Issuing authority or place. |
mrzData | String | The raw machine-readable zone as read off the document. |
idNumberNonEng | String | idNumber in the document’s own script, when it is not Latin. |
idNumber2NonEng | String | idNumber2 in the document’s own script. |
idDateOfBirthNonEng | String | idDateOfBirth in the document’s own script. |
idExpirationDateNonEng | String | idExpirationDate in the document’s own script. |
idIssueDateNonEng | String | idIssueDate in the document’s own script. |
barcodeDataParsed | String | Decoded barcode contents, for documents carrying one (PDF417 on US driver licenses, for example). |
ageOver18 | String | Age check (Y / N). |
nationality | String | Nationality on the document. |
idNotExpired | String | Expiry check (Y / N). |
validIdNumber | String | Document number structure check (Y / N). |
negativeDBMatchFound | String | Whether the document matched a negative database (Y / N). |
mrzErrorMessage | String | Why MRZ parsing failed, when it did. Present only on failure. |
idNumber_doc | String | idNumber exactly as printed, before normalisation. |
idNumber1_doc | String | idNumber1 as printed. |
idNumber2_doc | String | idNumber2 as printed. |
idNumber3_doc | String | idNumber3 as printed. |
idNumber4_doc | String | idNumber4 as printed. |
idExpirationDate_doc | String | idExpirationDate as printed. |
idIssueDate_doc | String | idIssueDate as printed. |
profession | String | Profession or occupation. |
professionNonEng | String | profession in the document’s own script. |
employer | String | Employer named on the document. |
vehicleClass | String | Vehicle classes the holder may drive. Driving licences only. |
endorsement | String | Endorsements granted (motorcycle, hazmat, and so on). Driving licences only. |
licenseType | String | Licence category or type. Driving licences only. |
restriction | String | Restrictions imposed (corrective lenses, for example). Driving licences only. |
registrationDate | String | Registration date. Driving licences only. |
replacementDate | String | Replacement or reissue date. Driving licences only. |
maritalStatus | String | Marital status, where the document prints one. |
placeOfBirth | String | Place of birth on the document. |
The document’s own scans are not part of extractedIdData: idImageFront, idImageBack, idProcessImageFront and idProcessImageBack are never delivered here. The captured images are delivered as URNs under documents.id instead.
i9Document is derived from what was actually captured, so it is absent rather than guessed when the capture record is missing.
5. Employee I-9 Details (employeeI9Details)
Present on I-9 journeys only; omitted for applications that produce no I-9 data.
| Field | Type | PII | Description |
|---|---|---|---|
citizenshipStatus | String | Withheld under NONE | Self-attested status (citizen, noncitizen_national, lawful_permanent_resident, authorized_alien). |
firstDayOfEmployment | String | Always delivered | Employment start date. |
secondDocumentCapture | Boolean | Always delivered | true when a companion document was captured. Absent when it was not. |
documentsCaptured | Object | Always delivered | Which document was captured per list — {"listA": "U.S. Passport"}. Lists that captured nothing are omitted. |
employmentEligibilityDetails | Object | Withheld under NONE | completedReviews: employer Section 2 records, each with a phase and the employer’s form values. |
A document type label is not personal data, so documentsCaptured survives PII_MODE_NONE — you still learn which kind of document was presented without learning anything about the person.
6. Review Details (reviewDetails)
Delivered on application.reviewed only, and on a Get Job Data response for an application that was reviewed.
| Field | Type | PII | Description |
|---|---|---|---|
outcome | String | Always delivered | Review decision (approved, rejected, suspicious). |
completedReviews | Array | Withheld under NONE | Individual check outcomes: reviewType, result, completedAt. |
application.reviewed is not a thin delta — it carries the complete body, exactly as application.decision does, plus this object. Delivery is at-least-once with no ordering guarantee, so a reviewed event may be the only event you ever receive for an application and must stand on its own.
Sample Payload: application.decision
Onbo Plus, piiMode: MASKED.
{
"event": {
"id": "019fd6b7-3def-7ece-bd47-788508d3424d",
"type": "application.decision",
"occurredAt": "2026-03-15T14:32:00Z",
"payloadVersion": "v1",
"piiMode": "MASKED"
},
"applicationDetails": {
"applicationId": "019fa770-9ddd-85d5-51b6-ea77192d0b5b",
"externalId": "REQ-2026-0084417",
"companyId": "company-xyz-123",
"journey": "onbo_plus",
"status": "Approved",
"applicationCreatedAt": "2026-03-15T14:26:43Z",
"applicationUpdatedAt": "2026-03-15T14:32:00Z"
},
"verificationResult": {
"dedupResult": {
"matchFound": false,
"matchCount": 0
},
"documentValidationResult": {
"isLive": true,
"selfieLiveCheckStatus": "Live Face Detected",
"faceVerificationResult": "Verified",
"faceVerificationScore": 93.91,
"realScore": 0.921,
"verificationResult": "Approved",
"verificationResultCode": "00",
"advancedLiveness": {
"status": "AUTHENTIC",
"score": 0.15
},
"idvFaceMatchDecision": {
"Decision_FaceMatch": { "result": "OK", "stateCode": "00" },
"Decision_Expiration": { "result": "OK", "stateCode": "00" },
"Decision_Tamper": { "result": "OK", "stateCode": "00" }
}
}
},
"documents": {
"id": {
"idFront": "urn:documentsv1:prod:00000000-0000-0000-0000-0000000000f1"
},
"selfie": {
"selfie": "urn:documentsv1:prod:00000000-0000-0000-0000-0000000000f2"
}
},
"applicantData": {
"personalData": {
"name": "Jane Doe",
"firstName": "Jane",
"lastName": "Doe",
"email": "j•••@example.com",
"phone": "•••••••4567",
"dob": "••/••/1990",
"gender": "F",
"ssn": "•••••6789"
},
"addressDetails": {
"streetAddress": "100 Main Street",
"city": "Phoenix",
"state": "Arizona",
"postalCode": "85001",
"country": "UNITED STATES",
"countryCode": "US"
},
"extractedIdData": {
"idType": "PP",
"idNumber": "••••0000",
"idIssueDate": "19/04/2021",
"idExpirationDate": "18/04/2031",
"idIssueCountry": "USA",
"idDateOfBirth": "••/••/1990",
"ageOver18": "Y",
"idNotExpired": "Y",
"validIdNumber": "Y"
},
"consents": [
{
"consentType": "TERMS_AND_CONDITIONS",
"version": "v1",
"status": "GIVEN",
"consentedAt": "2026-03-15T14:28:11.198Z"
}
]
}
}Sample Payload: application.reviewed
Employee I-9, piiMode: MASKED. Note employeeI9Details and extractedIdData.i9Document.
{
"event": {
"id": "019fd7c8-4e1f-8edf-ce58-899619e4535e",
"type": "application.reviewed",
"occurredAt": "2026-03-15T15:10:00Z",
"payloadVersion": "v1",
"piiMode": "MASKED"
},
"applicationDetails": {
"applicationId": "01a065f2-86fb-a61c-8418-1c14d41f4a09",
"externalId": "REQ-2026-0084417",
"companyId": "company-xyz-123",
"journey": "employee_i9_onboarding",
"status": "Review Approved",
"applicationCreatedAt": "2026-03-15T14:26:29Z",
"applicationUpdatedAt": "2026-03-15T15:10:00Z"
},
"verificationResult": {
"dedupResult": {
"matchFound": false,
"matchCount": 0
},
"documentValidationResult": {
"isLive": true,
"selfieLiveCheckStatus": "Live Face Detected",
"faceVerificationResult": "Verified",
"faceVerificationScore": 86.09,
"realScore": 0.921,
"verificationResult": "Approved",
"verificationResultCode": "00",
"cellPhone": false,
"cellPhoneScore": 0,
"eyeCovering": false,
"eyeCoveringScore": 0,
"faceMask": false,
"faceMaskScore": 0.023,
"headCovering": false,
"headCoveringScore": 0,
"advancedLiveness": {
"status": "AUTHENTIC",
"score": 0.15
},
"idvFaceMatchDecision": {
"Decision_FaceMatch": { "result": "OK", "stateCode": "00" },
"Decision_ImageQuality": { "result": "OK", "stateCode": "00" },
"Decision_MRZ": { "result": "OK", "stateCode": "00" }
}
}
},
"documents": {
"id": {
"idFront": "urn:documentsv1:prod:00000000-0000-0000-0000-0000000000f1"
},
"selfie": {
"selfie": "urn:documentsv1:prod:00000000-0000-0000-0000-0000000000f2",
"selfieImage": "urn:documentsv1:prod:00000000-0000-0000-0000-0000000000f3"
},
"signature": {
"signatureImage": "urn:documentsv1:prod:00000000-0000-0000-0000-000000000001",
"signatureVideo": "urn:documentsv1:prod:00000000-0000-0000-0000-0000000000f4"
}
},
"applicantData": {
"personalData": {
"name": "TEST SAMPLE EMPLOYEE",
"firstName": "TEST",
"middleName": "SAMPLE",
"lastName": "EMPLOYEE",
"email": "t••••••••@example.com",
"phone": "•••••••0142",
"dob": "••/••/1990",
"gender": "M",
"ssn": "•••••3333"
},
"addressDetails": {
"streetAddress": "100 Sample Street",
"city": "Testtown",
"state": "Maharashtra",
"postalCode": "99999",
"country": "INDIA",
"countryCode": "IN"
},
"extractedIdData": {
"i9Document": "ListA",
"idType": "PP",
"idNumber": "••••0000",
"idIssueDate": "22/02/2024",
"idExpirationDate": "21/02/2034",
"idIssueCountry": "IND",
"idCountry": "IND",
"idDateOfBirth": "••/••/1990",
"nationality": "IND",
"placeOfBirth": "SHIRALAMAHARASHTRA",
"ageOver18": "Y",
"idNotExpired": "Y",
"validIdNumber": "Y"
},
"attestationDetails": {
"citizenshipStatus": "citizen"
},
"consents": [
{
"consentType": "TERMS_AND_CONDITIONS",
"version": "v1",
"status": "GIVEN",
"consentedAt": "2026-03-15T14:28:28.324Z"
},
{
"consentType": "BIOMETRIC_PROCESSING",
"version": "v1",
"status": "GIVEN",
"consentedAt": "2026-03-15T14:28:28.325Z"
}
]
},
"employeeI9Details": {
"citizenshipStatus": "citizen",
"firstDayOfEmployment": "03/09/2026",
"documentsCaptured": {
"listA": "U.S. Passport"
}
},
"reviewDetails": {
"outcome": "approved",
"completedReviews": [
{
"reviewType": "identifraud",
"result": "pass",
"completedAt": "2026-03-15T15:09:50Z"
}
]
}
}Sample Payload: PII_MODE_NONE
The same I-9 application delivered under NONE. applicantData and documents are absent entirely, and the personal fields inside employeeI9Details and reviewDetails are gone — while every verification outcome survives.
{
"event": {
"id": "019fd7c8-4e1f-8edf-ce58-899619e4535e",
"type": "application.reviewed",
"occurredAt": "2026-03-15T15:10:00Z",
"payloadVersion": "v1",
"piiMode": "NONE"
},
"applicationDetails": {
"applicationId": "01a065f2-86fb-a61c-8418-1c14d41f4a09",
"externalId": "REQ-2026-0084417",
"companyId": "company-xyz-123",
"journey": "employee_i9_onboarding",
"status": "Review Approved",
"applicationCreatedAt": "2026-03-15T14:26:29Z",
"applicationUpdatedAt": "2026-03-15T15:10:00Z"
},
"verificationResult": {
"dedupResult": {
"matchFound": false,
"matchCount": 0
},
"documentValidationResult": {
"isLive": true,
"selfieLiveCheckStatus": "Live Face Detected",
"faceVerificationResult": "Verified",
"faceVerificationScore": 86.09,
"realScore": 0.921,
"verificationResult": "Approved",
"verificationResultCode": "00",
"advancedLiveness": {
"status": "AUTHENTIC",
"score": 0.15
}
}
},
"employeeI9Details": {
"firstDayOfEmployment": "03/09/2026",
"documentsCaptured": {
"listA": "U.S. Passport"
}
},
"reviewDetails": {
"outcome": "approved"
}
}Parsing Guidance
- Read from the group, not the root. Application scalars live under
applicationDetails, personal data underapplicantData, check results underverificationResult. - Missing keys are normal. Every group is omitted when empty, and PII mode removes whole objects. Branch on presence, never assume a key exists.
- Compare
statuscase-insensitively — see the note underapplicationDetails. - Iterate
idvFaceMatchDecisionkeys rather than expecting a fixed set of checks. - An absent boolean is not
falseindocumentValidationResult— it means the check did not report.
See also
- Webhooks Overview — delivery, retries, and idempotency
- Verifying Signatures — HMAC verification
- Get Job Data API — the same body, pulled on demand