Skip to main content

Creating a Validation Flow

To screen a professional or candidate, the first thing you need to do is create a screening flow. When creating a flow, you need to provide details about the professional and details about what you want to screen.

important

The system that connects through this API is strongly advised to support multiple screenings for a single professional. This is necessary in certain cases, for example when the screening expires or when the professional submits incorrect documents.

Request​

POST https://[api-url]/validation-flow
Authorization: Bearer yourapikeyhere
Authorization-Method: api-token
Content-Type: application/vnd.otentica.singlecheck.integrated.request+json

Request Body​

Complete Example​

{
"whitelabelStyleId": "nameOfYourCompanyStyle",
"language": "DUTCH",
"firstName": "Test",
"lastName": "Kees",
"email": "test@kees.com",
"phoneNumber": "0612345678",
"callbackUrl": "https://optional.callback/url",
"logoutRedirectUrl": "https://optional.logout.redirect/url",
"flowCompletionRedirectUrl": "https://optional.completion.redirect/url",
"personalizedMessage": "<p>Company is aangesloten bij Otentica voor het uitvoeren van het
pre-employment screening.</p><p><br></p><p>Otentica
is een platform waar diploma’s, certificaten, beroepskwalificaties en je identiteit worden
gecontroleerd door de bij Otentica aangesloten instanties. Om dit proces te bespoedigen vragen wij
je om de stappen zorgvuldig en zo compleet mogelijk te doorlopen.</p>",
"initialValues": null,
"requestedChecks": [
{
"checkName": "identity-data",
"importance": "SKIPPABLE"
},
{
"checkName": "correspondence-data",
"importance": "NOT_SKIPPABLE",
"configuration": {
"collectWebsiteUrl": false,
"collectLinkedInUrl": false
}
},
{
"checkName": "identity-document-v2",
"importance": "NOT_SKIPPABLE",
"configuration": {
"applicantLevelName": "id-and-liveness"
}
},
{
"checkName": "diploma-data",
"importance": "SKIPPABLE",
"configuration": {
"onlySkippableIfUnverifiedDiplomaAdded":true
}
},
{
"checkName":"unverified-diploma-data",
"importance":"SKIPPABLE"
},
{
"checkName": "unverified-certificate-data",
"importance": "NOT_SKIPPABLE",
"configuration": {
"requiredCertificates": [
{
"type": "wft",
"description": "Wft Basis",
"optional": true
}
]
}
},
{
"checkName": "healthcare-professional-data",
"importance": "SKIPPABLE"
},
{
"checkName": "youth-professional-data",
"importance": "SKIPPABLE"
},
{
"checkName": "company-data",
"importance": "SKIPPABLE",
"configuration": {
"checkLevel": "EXTENDED",
"enableCreditCheck": false,
"creditCheckMandatory": false
}
},
{
"checkName": "company-vat-data",
"importance": "SKIPPABLE"
},
{
"checkName": "integrity-data",
"importance": "NOT_SKIPPABLE",
"configuration": {
"position": "functie",
"specialCircumstances": "",
"screeningProfilePreset": "25",
"screeningProfiles": [],
"requestNewVog": true,
"allowExistingVog": false
}
},
{
"checkName": "bank-data",
"importance": "SKIPPABLE",
"configuration": {
"checkPersonalAccount": false,
"checkBusinessAccount": true
}
},
{
"checkName": "pep-check",
"importance": "SKIPPABLE"
},
{
"checkName": "sanctions-check",
"importance": "SKIPPABLE"
},
{
"checkName": "references",
"importance": "SKIPPABLE",
"configuration": {
"onlyAllowCompanyEmailAddresses": true,
"referencePeriod": "P3Y",
"referencePeriodOffset": "P1M",
"minNumberOfReferences": 2,
"maxNumberOfReferences": 10,
"questionNames": [
"workedForCompany-yesNo",
"position-yesNo",
"relation-freeText",
"agreements-yesNo",
"careful-yesNo",
"integrity-freeText",
"rehire-freeText"
]
}
}
]
}

Field Descriptions​

Basic Fields​

  • whitelabelStyleId (optional): ID of your custom style template
  • language: Either DUTCH or ENGLISH
  • firstName: Professional's first name
  • lastName: Professional's last name
  • email: Email address for invites and login codes
  • phoneNumber: Phone number for contact

URL Configuration​

  • callbackUrl (optional): URL for webhook notifications
  • logoutRedirectUrl (optional): URL to redirect after logout (used with authorized URLs)
  • flowCompletionRedirectUrl (optional): URL to redirect after flow completion

Message Customization​

  • personalizedMessage (optional): HTML message shown to the professional when they start the screening. Simple HTML is allowed; other HTML is filtered out.

Advanced Configuration​

  • initialValues (optional): Pre-validated data for specific checks. Only use after consulting with Otentica.
danger

When using initialValues, you must ensure that data supplied is correct, up-to-date, and validated. Incorrect data can lead to invalid validation results and may facilitate fraud. You take full responsibility for the consequences of incorrect or invalid data.

Requested Checks​

  • requestedChecks: Array of checks to include in the flow
    • checkName: Identifier of the check (see Available Checks)
    • importance: Either SKIPPABLE or NOT_SKIPPABLE
    • configuration (optional): Check-specific configuration

When you create a flow from a template, requestedChecks means something different — see Creating a Flow from a Template below.

Creating a Flow from a Template​

Instead of assembling requestedChecks yourself, you can create a flow from an existing template by passing templateId. The field is available on both content types: application/vnd.otentica.singlecheck.email.request+json and application/vnd.otentica.singlecheck.integrated.request+json.

The template must belong to the company that owns the API key. A template belonging to another company returns 403; a template that no longer exists returns 404.

When templateId is set, the back end:

  • expands the template's checks server-side, including their configuration and any pre-filled data, so you do not have to reproduce them;
  • copies the template's custom questions onto the new screening;
  • records the flow as having been created from that template.
requestedChecks changes meaning when templateId is set
Without templateIdWith templateId
requestedChecksThe complete list of checks. Must not be emptyOnly the exceptions to the template. May be empty ([]), meaning "use the template as-is"
removedChecksIgnoredNames of template checks to switch off for this candidate

Merge Rules​

  • An exception replaces the template's version of that check entirely. This is a check-level replacement, not a field-by-field merge — anything you omit from the exception is not inherited from the template.
  • An exception naming a check that is not in the template is appended as an extra check.
  • A check named in removedChecks is dropped from the template. If you name the same check in both requestedChecks and removedChecks, removedChecks wins and the check is dropped.
  • Order follows the template's check order, with any appended checks after it.

Example​

{
"firstName": "John",
"lastName": "Doe",
"email": "john.doe@example.com",
"language": "ENGLISH",
"templateId": 42,
"requestedChecks": [
{
"checkName": "diploma-data",
"importance": "NOT_SKIPPABLE"
}
],
"removedChecks": ["bank-data"]
}

This creates a screening from template 42, with diploma-data raised to NOT_SKIPPABLE for this candidate and bank-data switched off. Every other check comes from the template unchanged.

Custom Questions​

Custom questions cannot be sent inline in the flow creation payload. They are managed on a template and reach a screening through templateId. See Custom Questions for how the answers come back.

Response​

{
"checkToken": "abc123def456",
"readyForProfessional": false,
"flowId": 1234
}

Response Fields​

  • checkToken: Unique token to track this flow (save this!)
  • readyForProfessional: Whether the flow is ready to start
    • false: Wait for the READY callback before sending to professional
    • true: Professional can start immediately
  • flowId: Numeric ID of the same screening. This is what the ID-based endpoints take, such as the right-to-work reviewer endpoints and POST /validation-flow/check/{id}/archive

Professional Access URL​

Once the flow is ready, the professional can access it at:

  • Acceptance: https://demo.otentica.nl/validation/[checkToken]
  • Production: https://app.otentica.nl/validation/[checkToken]

Email Configuration​

By default, Otentica sends:

  • Invite emails to professionals
  • Reminder emails
  • Login codes

Contact Otentica support if you want to handle these emails yourself.

Example: Complete Flow Creation​

async function createValidationFlow() {
const flowData = {
whitelabelStyleId: "company-style",
language: "ENGLISH",
firstName: "John",
lastName: "Doe",
email: "john.doe@example.com",
phoneNumber: "+31612345678",
callbackUrl: "https://api.mycompany.com/webhooks/otentica",
personalizedMessage:
"<p>Welcome to our screening process. Please complete all required steps.</p>",
requestedChecks: [
{
checkName: "identity-data",
importance: "SKIPPABLE",
},
{
checkName: "correspondence-data",
importance: "NOT_SKIPPABLE",
},
{
checkName: "identity-document-v2",
importance: "NOT_SKIPPABLE",
configuration: {
applicantLevelName: "id-and-liveness",
},
},
{
checkName: "diploma-data",
importance: "SKIPPABLE",
configuration: {
onlySkippableIfUnverifiedDiplomaAdded: true,
},
},
],
};

const response = await fetch("https://api.otentica.nl/validation-flow", {
method: "POST",
headers: {
Authorization: `Bearer ${API_KEY}`,
"Authorization-Method": "api-token",
"Content-Type":
"application/vnd.otentica.singlecheck.integrated.request+json",
},
body: JSON.stringify(flowData),
});

const result = await response.json();

if (result.readyForProfessional) {
// Send screening URL to professional immediately
const screeningUrl = `https://app.otentica.nl/validation/${result.checkToken}`;
await sendInviteEmail(professionalEmail, screeningUrl);
} else {
// Wait for READY webhook before sending invite
await saveTokenForWebhook(result.checkToken);
}

return result.checkToken;
}

Check-Specific Configuration Reference​

correspondence-data​

ParameterTypeDefaultDescription
collectWebsiteUrlbooleanfalseAsk the candidate for their website URL
collectLinkedInUrlbooleanfalseAsk the candidate for their LinkedIn profile URL

Both URL fields support an explicit "I don't have this" state. When a candidate selects this option, the field is submitted as null with an explicit opt-out flag — it is not treated as missing data.

URLs must be fully qualified (e.g. https://www.example.com). LinkedIn URLs are validated to ensure they point to linkedin.com.

company-data​

ParameterTypeDefaultDescription
checkLevelstringBASICLevel of KvK data: BASIC, EXTENDED, or FULL
enableCreditCheckbooleanfalseEnable the credit check sub-check (requires EXTENDED or FULL)
creditCheckMandatorybooleanfalseWhen true, the candidate cannot proceed without completing the credit check

See Company & Financial Checks for the full list of credit check result fields.

pep-check and sanctions-check​

No additional configuration required. Both checks use the candidate's name and date of birth from the identity step.

See Background & Integrity Checks for result fields and match score details.

right-to-work-data​

ParameterTypeDefaultDescription
applicantLevelNamestring—Document capture level used for this check
requiredValiditystring—ISO-8601 period (e.g. P3M) the residence document must still be valid for
workCountrystringNLDISO 3166-1 alpha-3 code of the country the placement is worked in

See Right to Work for outcome codes, reason codes and the BSN privacy notes.

insolvency-data and guardianship-data​

No additional configuration required beyond the optional confirmSkip / confirmSkipMessage. Both use the candidate's name and date of birth from the identity step.

credit-registration-data​

ParameterTypeDefaultDescription
requireCertifiedOverviewbooleanfalseAccept only a certified (posted) credit overview
slaWorkingDaysinteger—Working days the candidate has to deliver a required certified overview
confirmAuthorizationDeclarationbooleanfalseRequire the candidate to accept the authorisation declaration before uploading

See Financial Integrity for result fields, the ASYNC_WAITING state and the privacy notes.