Implementation steps
This series of guides explains how to use the FrankieOne API to perform many different types of functions. It includes descriptions, code samples and things to consider during implementation It is important to remember the following:
- The Individuals API is separate and can not be used in conjunction with any other API.
- All sample requests require authorization as defined in the Getting Started section.
Individual Verification
The following examples show how to use the FrankieOne API to perform functions related to an individual.
Create an individual entity
To create an individual entity eligible for verification, make a request to the POST /v2/individuals
API endpoint.
- To add a name to an individual, use the
name
object in the request body.
"name": {
"givenName": "Johnny",
"middleName": "Tan",
"familyName": "Doe",
"displayName": "Johnny Tan Doe"
}
- To add a date of birth to an individual, use the
dateOfBirth
object in the request body.
...
"dateOfBirth": {
"year": "1990",
"month": "05",
"day": "15"
},
...
- To add an address to an individual, use the addresses array in the request body.
- To add multiple addresses, add a separate address to the addresses array.
...
"addresses":
[
{
"type": "RESIDENTIAL",
"streetName": "King",
"streetNumber": "123",
"streetType": "Street",
"neighborhood": "Melbourne CBD",
"locality": "Melbourne",
"subdivision": "VIC",
"country": "AUS",
"postalCode": "3000",
"status": "CURRENT"
}
]
...
- To acknowledge consent for an individual, use the consents array in the request body.
...
"consents":
[
{
"type": "GENERAL"
},
{
"type": "CREDITHEADER"
},
{
"type": "DOCS"
},
]
}
...
Sample request
curl --location 'http://api.{{env}}.frankie.one/v2/individuals' \
--header 'api_key: {{your_apiKey}}' \
--header 'X-Frankie-CustomerID: {{your_CustomerID}}' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--data-raw '{
"individual": {
"name":
{
"givenName": "Johnny",
"middleName": "Tan",
"familyName": "Doe",
"displayName": "Johnny Tan Doe"
},
"dateOfBirth":
{
"year": "1990",
"month": "05",
"day": "15"
},
"addresses":
[
{
"type": "RESIDENTIAL",
"streetName": "King",
"streetNumber": "123",
"streetType": "Street",
"neighborhood": "Melbourne CBD",
"locality": "Melbourne",
"subdivision": "VIC",
"country": "AUS",
"postalCode": "3000",
"status": "CURRENT"
}
],
"consents":
[
{
"type": "GENERAL"
},
{
"type": "CREDITHEADER"
},
{
"type": "DOCS"
}
]
}
}'
Sample response
Collect the
entityId
in the response as it will be used in subsequent API calls for this individual.
Status: 201 Created
{
"individual": {
"entityId": "{entityId}",
"entityType": "INDIVIDUAL",
"createdAt": "2024-01-31T23:21:57.296Z",
"schemaVersion": 2,
"addresses": [
{
"addressId": "{addressId}",
"type": "RESIDENTIAL",
"streetName": "King",
"streetNumber": "123",
"streetType": "Street",
"neighborhood": "Melbourne CBD",
"locality": "Melbourne",
"subdivision": "VIC",
"country": "AUS",
"postalCode": "3000",
"status": "CURRENT"
}
],
"name": {
"nameId": "{nameId}",
"givenName": "Johnny",
"middleName": "Tan",
"familyName": "Doe",
"displayName": "Johnny Tan Doe"
},
"dateOfBirth": {
"dateOfBirthId": "{dateOfBirthId}"
"normalized": "1990-03-31",
"year": "1990",
"month": "03",
"day": "27",
"type": "GREGORIAN"
},
"consents":
[
{
"type": "GENERAL"
},
{
"type": "CREDITHEADER"
},
{
"type": "DOCS"
},
]
}
},
"requestId": "{requestId}"
}
Note: Service Profiles have been intentionally omitted for brevity
Addresses
Don't forget the Address ID.
When updating an address, don’t forget to include the
addressId
field. This would have been in the response message when you first added the address.You can always get the
addressId
(and all other IDs) if you call theGET /v2/{entityType}/{entityId}
API call.
Don't forget the Country
This field is mandatory and must be one of the ISO-3166-alpha-3 codes.
See here: List of ISO 3166 country codes
Address Types
Addresses have a number of available type options. Whilst this is an optional field, it is good practice to include the type to assist with processing and checking. It is recommended that these following types be used:
**RESIDENTIAL **
- This will be the primary address used when trying to determine the country of residence and primary current address. IfRESIDENTIAL
has been used for this, note that this will be deprecated and removed in the next major version of the API.**POSTAL **
- This is a mailing address. It is also used as the current residential address if noRESIDENTIAL
type is found.
Street Address and the use of the streetName
field
streetName
fieldIt can be hard to break down an address and so we’ve made the streetName
field quite flexible.
Whilst it is best to break the address into its constituent parts, you can combine streetNumber
, streetName
and streetType
into the streetName
field if required.
It's better to break down the address fields.
Whilst combining the fields is readily supported, best matching results are found when you break the address down into as many fields as you can.
Structured Addresses
It is always best to use the structured address and map in 1-1 the following fields.
Field name | Description | Type |
---|---|---|
type | The type of address, for example residential , postal | String (enum) |
typeDescription | The description of the address. Used for reference only. | string |
unitNumber | Unit | Apartment | Flat | Suite | others number. | string |
streetNumber | The number on the street. Generally a number, but can also be alphanumeric ( for example, 3A). | string |
streetName | The name of the street. | string |
streetType | The street type - for example, Road, St, Ave, Circuit, and others. | string |
buildingName | The name of the building, apartment block, condo, and others | string |
locality | (formerly town) The locality, town, village, suburb, or city | string |
district | (formerly region) The district, region, county, province, or cantonment of the address | string |
neighborhood | The neighborhood or suburb in the town or city. Note: Only use neighborhood if locality is already captured as part of the address and an additional location is required. Otherwise just use locality. | string |
subdivision | The administrative area, state, or subdivision. Note: Abbreviations (“VIC”) and full names (“Victoria”) are acceptable. | string |
country | The ISO-3166-1 alpha 3 country code of the address. | string |
postalCode | The postal code or zip code of the address. | string |
careOf | Individual or business name at this address if not the same as the name of the entity to which this address belongs. | string |
longForm | The full address details. It is preferable that the address is broken down into its constituent parts however where that is not possible, a longForm can be used. Note: longForm address matching generally produces weaker results due to the complexity involved in breaking down, interpreting and mapping an entire address from a single string. | string |
status | Determines the status of this address in relation to the entity using it. Example: Current or Future Note: “Current” addresses will be treated as primary addresses for verification purposes. | string (enum) |
validTo | When will this entity no longer be using this address? Used for reference only. | date |
validFrom | When did the entity first start using this address? Used for reference only. | date |
Example 1: Full Address Entered as Separate Fields (preferable)
...
"addresses":
[
{
"type": "RESIDENTIAL",
"streetName": "King",
"streetNumber": "123",
"streetType": "Street",
"locality": "Melbourne",
"subdivision": "VIC",
"country": "AUS",
"postalCode": "3000",
"status": "CURRENT"
}
]
...
Example 2: Full Address Entered as Long Form
...
"addresses":
[
{
"type": "RESIDENTIAL",
"longForm": "123 King Street, Melbourne 3000, Victoria, Australia",
"status": "CURRENT"
}
]
...
Consent
Before proceeding with data verification checks, obtaining consent is essential and varies based on the verification type. While general consent encompasses standard verifications against government databases, it may not include credit checks and document validations. Consult with your AML team and the FrankieOne team to determine what consent flags you need to supply.
Consent | Description |
---|---|
GENERAL | This indicates that the entity has given consent for their name, address, or DoB to be checked against our various databases and external services. |
DOCS | This indicates that the entity has given consent to have their identity documents checked against official sources. |
CREDITHEADER | This indicates that the entity has given permission to have their details checked against a credit bureau service. If this check fails, you must inform the user that the check failed and put them in touch with the bureau directly so that they may update their details as necessary. This is not normally available by default, so please see your account manager about making this service available. |
UNDER18 | This indicates that the entity is under the age of 18 and a parent or guardian has provided consent. This is a special case of the consent.general flag (see above). consent.docs would still be required to check their passports or drivers license. |
PAYROLL | This consent is used to allow access to verifying an identity using payroll data. |
INSURANCE | This consent is used to allow access to verifying an identity using workcover data. |
SUPERANNUATION | This consent is used to allow access to verifying an identity using superannuation data. |
Retrieve an individual entity
The individual entity can be retrieved at any time by making a request to the GET /v2/individuals/{entityId}
API endpoint.
Update an individual entity
The individual entity can be updated at any time by making a request to the PATCH /v2/individuals/{entityId} API
endpoint.
To update a specific element of an individual entity, be sure to provide the relevant information you wish to update along with the ID of the object. This does not the case with primary entity elements (name
, dateOfBirth
, placeOfBirth
)
Example 1: update a name
"name":
{
"givenName": "James",
"familyName": "Done"
}
Example 2: update an address
"addresses":
[
{
"addressId": "{addressId}",
"status": "CURRENT"
}
]
Example 3: update alternateDatesOfBirth
"alternateDatesOfBirth":
{
"dateOfBirthId": "{dateOfBirthId}",
"year": "1992",
"month": "12",
"day": "05"
}
Adding entity elements
To add a new object to an existing entity, simply add the new object without an ID.
Example 1: adding an address
"addresses":
[
{
"type": "RESIDENTIAL",
"streetNumber": "123",
"streetName": "King",
"streetType": "Street",
"locality": "Melbourne",
"postalCode": "3000",
"subdivision": "NSW",
"country": "AUS",
"status": "CURRENT"
}
]
Adding consents
Consents will not be duplicated so new consent types will simply be added if not already applied.
Example 2: adding consents
"consents":
[
{
"type": "CREDITHEADER"
}
]
Deleting entity elements
Individual entity objects can be deleted at any time by making a request to the DELETE /v2/individuals/{entityId}/{objectType}/{objectId}
API endpoint.
Example 1: deleting a phoneNumber
DELETE /v2/individuals/{entityId}/phonenumbers/{objectId}
Example 2: deleting a emailAddress
DELETE /v2/individuals/{entityId}/emailaddresses/{objectId}
Deleting documents
Individual document objects can be deleted at any time by making a request to the DELETE /v2/individuals/{entityId}/documents/{documentId}
API endpoint.
DELETE /v2/individuals/{entityId}/documents/{documentId}
Deleting document attachments
Individual document attachment objects can be deleted at any time by making a request to the DELETE /v2/individuals/{entityId}/documents/{documentId}/attachments/{attachmentId}
API endpoint.
DELETE /v2/individuals/{entityId}/documents/{documentId}/attachments/{attachmentId}
Withdrawing consent
Individual consent of a certain type can be withdrawn at any time by making a request to the DELETE /v2/individuals/{entityId}/consents/{consentType}
API endpoint.
DELETE /v2/individuals/{entityId}/consents/CREDITHEADER
Delete an individual entity
The individual entity can be deleted at any time by making a request to the DELETE /v2/individuals/{entityId}
API endpoint.
Individual entities that are deleted can not be recovered by FrankieOne.
Please ensure you only delete entities that are no longer needed for any purpose, including audit or compliance.
Execute a workflow
To start onboarding an individual and running checks on them, you’ll need to call the "execute workflow" API endpoint. Upon execution, the workflow will return a result.
curl --location --request POST
'https://api.{{env}}.frankie.one/v2/individuals/{entityId}/serviceprofiles/kyc/workflows/{workflowName}/execute' \
--header 'api_key: {{your_apiKey}}' \
--header 'X-Frankie-CustomerID: {{your_CustomerID}}' \
--header 'X-Frankie-CustomerChildID: {{your_CustomerChildID}}' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
Retrieve a workflow execution result
The workflow execution result can be retrieved at any time post execution by making a request to the GET /v2/individuals/{entityId}/serviceprofiles/{serviceName}/workflows/{workflowName}/executions/{workflowExecutionId}
API endpoint.
Retrieve a history of workflow execution result
The individual entity can be updated at any time by making a request to the PATCH /v2/individuals/{entityId}
API endpoint.
Interpreting Workflow Results
After a workflow has been executed, various elements require examination to determine the final outcome.
Legend:
- ‼️ - Results that deem whether the entity has passed or failed or the workflow failed to execute to completion.
- ⚠ - Context on why the entity may have passed or failed.
- ℹ️ - Information-only, no contribution to whether the entity has passed or failed.
Field name | Description | Importance |
---|---|---|
status | The ultimate assessment of whether the individual passed all workflow requirements lies in the status , which provides a conclusive recommendation based on the checks run. It accounts for whether all verification checks were successful or if there were failures.The status also captures manual intervention such as any action of overriding the result directly outside the context of a workflow. • UNCHECKED - Workflow has not yet been executed or the workflow result was not updated successfully as part of the workflow execution.• IN_PROGRESS - Workflow is currently running and awaiting completion.• PASS - Workflow completed successfully and the entity passed all checks required. Alternatively, the status was applied manually proceeding workflow execution.• FAIL - Workflow completed successfully, however the entity did not pass all checks required. Alternatively, the status was applied manually proceeding workflow execution.Note: the **statusOverrideAt** field can be used to determine if the status was manually overridden. | ‼️ |
statusOverrideAt | The UTC time of when the status was manually overridden outside the workflow execution. | ℹ️ |
statusOverrideRequestId | The unique requestId of the request that manually overrode the status outside the workflow execution. | ℹ️ |
statusOverrideBy | The X-Frankie-Username header value in the request that manually overrode the status outside of the workflow execution. | ℹ️ |
result | The result is the original workflow outcome that was determined at the completion of the workflow. In the case of manual override, this will differ from the status .• UNCHECKED - Workflow has not yet been executed or the workflow result was not updated successfully as part of the workflow execution.• IN_PROGRESS - Workflow is currently running and awaiting completion.• PASS - Workflow completed successfully and the entity passed all checks required.• FAIL - Workflow completed successfully, however the entity did not pass all checks required. | ⚠ |
workflowExecutionState | The workflowExecutionState is an indicator of whether the workflow was able to execute to completeness. The workflowExecutionState should always be in a state of “COMPLETED” otherwise it is telling that the workflow execution did not finish executing and that the result should be taken with that context in mind. | ‼️ |
workflowStepResults | The workflowStepResults is a detailed list of all the steps that were executed as part of the workflow and their individual outcomes. | ⚠ |
riskAssessment | The riskAssessment is a summary of all the risk factors that were encountered during the execution of the workflow and the accumulated risk level of the entity as a result of those factors. | ⚠ |
issues | issues is a summary of all the issues that were encountered during the execution of the workflow that may have affected the outcome such as errors, insufficient data, or simply a failed verification.Typically issues will only be present if any checks have failed. | ⚠ |
workflowExecutionId | The unique identifier of the workflow execution. Generated on triggering the workflow execution. | ℹ️ |
serviceProfileId | The unique identifier of the service profile in which the workflow was executed. Set based on the serviceName in the path of the workflow execution request API. | ℹ️ |
workflowId | The ID of the workflow that was executed. Set based on the workflowName in the path of the workflow execution request API. | ℹ️ |
workflowName | The name of the workflow that was executed. Set based on the workflowName in the path of the workflow execution request API. | ℹ️ |
steps | The steps that were executed as part of this workflow execution: order - order in which the steps were executed passed - steps that passed or were successful in execution failed - steps that failed or were unsuccessful in execution incomplete - steps that did not execute or did not execute to completion notApplicable - steps that did not run because they were deemed unnecessary | ℹ️ |
entityType | The type of entity in which the workflow was executed. INDIVIDUAL or ORGANIZATION . | ℹ️ |
errors | Any errors that were encountered as part of the workflow execution | ⚠ |
requestId | The requestId is the unique identifier of the request that triggered this workflow execution. | ℹ️ |
entityId | The entityId of the individual/organization in which the workflow was executed. | ℹ️ |
startedAt | startedAt refers to when the workflow started executing. | ℹ️ |
endedAt | endedAt refers to when the workflow finished executing. | ℹ️ |
createdAt | createdAt refers to when the process result was created. | ℹ️ |
updatedAt | updatedAt refers to when the process result was last updated. | ℹ️ |
updatedBy | updatedBy refers to who last updated the workflow execution. This will be the value of the X-Frankie-Username header of the request that executed the workflow or overrode the workflow result. | ℹ️ |
schemaVersion | Refers to the version of the schema returned. Will always be 2 in the FrankieOne v2.x API. | ℹ️ |
notes | Any additional notes that were captured during the process. | ℹ️ |
Know Your Customer (KYC) Database Verification
Example 1: Pass
"workflowResult": {
"createdAt": "2024-07-08T06:37:22.520433Z",
"endedAt": "2024-07-08T06:37:27.697016Z",
"entityType": "INDIVIDUAL",
"issues": [...],
"workflowExecutionId": "{workflowExecutionId}",
"requestId": "{requestId}",
"entityId": "{entityId}",
"startedAt": "2024-01-15T02:18:11.365Z",
"endedAt": "2024-01-15T02:18:11.365Z",
"workflowId": "{workflowId}",
"workflowName": "onboarding",
"steps": "[KYC]",
"result": "PASS",
"status": "PASS",
"workflowExecutionState": "COMPLETED",
"schemaVersion": 2,
"serviceProfileId": "{serviceProfileId}",
"updatedAt": "2024-07-08T06:37:27.769601Z",
"updatedBy": "system:frankieone",
"riskAssessment": [...],
"workflowStepResults": [...]
},
"requestId": "{requestId}"
Example 2: Fail
"workflowResult": {
"createdAt": "2024-07-08T06:37:22.520433Z",
"endedAt": "2024-07-08T06:37:27.697016Z",
"entityType": "INDIVIDUAL",
"issues": [...],
"workflowExecutionId": "{workflowExecutionId}",
"requestId": "{requestId}",
"entityId": "{entityId}",
"startedAt": "2024-01-15T02:18:11.365Z",
"endedAt": "2024-01-15T02:18:11.365Z",
"workflowId": "{workflowId}",
"workflowName": "onboarding",
"steps": "[KYC]",
"result": "FAIL",
"status": "FAIL",
"workflowExecutionState": "COMPLETED",
"schemaVersion": 2,
"serviceProfileId": "{serviceProfileId}",
"updatedAt": "2024-07-08T06:37:27.769601Z",
"updatedBy": "system:frankieone",
"riskAssessment": [...],
"workflowStepResults": [...]
},
"requestId": "{requestId}"
Example 3: Workflow failed but status was overridden to be passed
"workflowResult": {
"createdAt": "2024-07-08T06:37:22.520433Z",
"endedAt": "2024-07-08T06:37:27.697016Z",
"entityType": "INDIVIDUAL",
"issues": [...],
"workflowExecutionId": "{workflowExecutionId}",
"requestId": "{requestId}",
"entityId": "{entityId}",
"startedAt": "2024-01-15T02:18:11.365Z",
"endedAt": "2024-01-15T02:18:11.365Z",
"workflowId": "{workflowId}",
"workflowName": "onboarding",
"steps": "[KYC]",
"result": "FAIL",
"status": "PASS",
"workflowExecutionState": "COMPLETED",
"schemaVersion": 2,
"serviceProfileId": "{serviceProfileId}",
"updatedAt": "2024-07-08T06:37:27.769601Z",
"updatedBy": "system:frankieone",
"riskAssessment": [...],
"workflowStepResults": [...]
},
"requestId": "{requestId}"
Interpreting Workflow Step Results
Workflow outcomes will encompass a variety of individual step outcomes, each autonomously documenting the findings of their specific verification processes. Steps such as data verification/Know Your Customer (KYC) checks, Anti-Money Laundering (AML) screenings, Identity Verification (IDV), and risk evaluations are integral components of a workflow. To streamline reporting, step outcomes are consolidated according to their category, ensuring that identical steps are aggregated and presented as a unified outcome. For instance, KYC procedures may be executed repeatedly using a diversified set of service providers and configurations; however, a singular step outcome will be generated, encapsulating the entirety of the assessments conducted.
Each step is defined in a consistent format, with significant variations stemming from the stepData
and processResults
only. These elements are distinct to each step type, providing tailored insights specific to the step’s function.
Know Your Customer (KYC) Database Verification
The KYC workflow step takes into account all the processed data and indicates the outcome in the result
field.
UNCHECKED
- KYC was not attempted due to a failure in a previous stepMISSING_DATA
- KYC was not attempted as not enough data was availableMATCH
- KYC was attempted successfully, the entity was verified against the required number of data sourcesNO_MATCH
- KYC was attempted, however the entity was not verified against any data sourcesPARTIAL
- KYC was attempted, however the entity was not verified against the required number of data sources if more than 1 was requiredERROR
- KYC was attempted, however an error was encountered during the process. See errors for more information.
{
"workflowResult": {
"workflowStepResults": [
{
"endedAt": "2024-05-14T04:04:12.66319Z",
"objectId": "{objectId}",
"objectType": "INDIVIDUAL",
"processResults": [...],
"requestId": "{requestId}",
"result": "MATCH",
"serviceProviders": [...],
"startedAt": "2024-05-14T04:04:11.849152Z",
"stepData": {...},
"stepName": "kyc",
"stepResultId": "{stepResultId}",
"workflowExecutionId": "{workflowExecutionId}"
},
]
}
}
Service Provider Result
The KYC workflow step indicates the service provider overall outcome as the
serviceProviders.result
{ "workflowResult": { "workflowStepResults": [ { "endedAt": "2024-05-14T04:04:12.66319Z", "objectId": "{objectId}", "objectType": "INDIVIDUAL", "processResults": [...], "requestId": "{requestId}", "result": "MATCH", "serviceProviders": [ { "endedAt": "2024-05-14T04:04:12.663187286Z", "provider": "dvs", "result": "MATCH", "startedAt": "2024-05-14T04:04:11.849152Z" } ], "startedAt": "2024-05-14T04:04:11.849152Z", "stepData": {...}, "stepName": "kyc", "stepResultId": "{stepResultId}", "workflowExecutionId": "{workflowExecutionId}" }, ] } }
Step Summary: Data Source Match Details
To gain insight into which personal information matched against specific sources, please refer to the matchedRules
. Commonly, you’ll find a singular ruleMatches
entry detailing the outcome of a particular rule established in the workflow. For example, a rule might stipulate that both a name and either a date of birth or address be verified against two independent data sources. matchTypes
will reveal the exact element verified, while matchSources
will specify the data sources used for confirmation. Any data sources consulted but yielding no matches will be listed as nonMatchSources
.
After a KYC step has been executed, various elements require examination to determine the final outcome.
Legend:
- ‼️ - Results that deem whether the entity has passed or failed or the workflow failed to execute to completion.
- ⚠ - Context on why the entity may have passed or failed.
- ℹ️ - Information-only, no contribution to whether the entity has passed or failed.
Matched and Unmatched Rules
The matchedRules
and unmatchedRules
that exist within the KYC workflow step summary are identical in structure and differ only in whether the ruleset was matched against successfully (matchedRules
) or not (unmatchedRules
).
Field name | Description | Importance |
---|---|---|
matchedRules | List of all the KYC rulesets that matched and the summary of those matches. See Matched and Unmatched Rules. | ⚠ |
unmatchedRules | List of all the KYC rulesets that did not match and the summary of those matches. See Matched and Unmatched Rules. | ⚠ |
Rulesets
The requirements rulesets are defined within the KYC workflow step configuration and are used to determine whether the number of data source matches have been met for each entity element (for example, name, date of birth, address and others) for the verification to be considered a match.
Field name | Description | Importance |
---|---|---|
ruleName | Name of the ruleset Default: default | ℹ️ |
ruleOrder | Order in which we attempted to match the results against the requirements defined in the ruleset. Example: 1 | ℹ️ |
ruleMatches | List of matches that made up this ruleset. See Rule Matches. | ⚠ |
Ruleset Match Details
The specific matching details of each rule that was matched or not matched.
Field name | Description | Importance |
---|---|---|
matchTypes | The match types that this overall count and results refer to | ⚠ |
matchCount | Number of matches found for this ruleset | ⚠ |
matchCountRequired | Number of matches required for this ruleset to be satisfied | ⚠ |
hasAllRequiredSourcesMatched | Determines whether a match has been found for all required data sources defined in the ruleset. Note: Optional. This is only evaluated if 1 or more data sources have been set as mandatory within the KYC workflow step configuration. | ⚠ |
requiredSourcesMatched | List of the required sources that the entity has been matched against. Note: Optional. This is only evaluated if 1 or more data sources have been set as mandatory within the KYC workflow step configuration. | ⚠ |
requiredSourcesNotMatched | List of the required sources that the entity has not been matched against. Note: Optional. This is only evaluated if 1 or more data sources have been set as mandatory within the KYC workflow step configuration. | ⚠ |
isVerified | Determines whether the matches required have been satisfied, indicating a successful matched ruleset. Based on whether matchCount >= matchCountRequired true/false | ‼️ |
Ruleset Matched Types
The specific matching details of each element (for example, name
, dateOfBirth
, and others) that was matched or not matched.
Field name | Description | Importance |
---|---|---|
objectId | The unique identifier of the object (for example: name, address, date of birth) that was verified | ℹ️ |
objectType | The type of the object that was verified (for example: name, address, date of birth) | ℹ️ |
matchCount | Number of matches found for this object type | ⚠ |
matchSources | List of all the data sources that the entity was matched against. Example: “au-elec-roll” | ⚠ |
nonMatchSources | List of all the data sources that the entity was not matched against. Example: “au-elec-roll” | ⚠ |
isChecked | Determines whether an attempt was made to verify the entity’s personal information as identified by the objectId and objectType (for example: name, date of birth, address) | ⚠ |
isVerified | Determines whether the entity’s personal information as identified by the objectId and objectType (for example: name, date of birth, address) was able to be verified by at least 1 data source. | ‼️ |
Example 1: Successful KYC Database Verification
Let’s break down the following match result:
name
,dob
andaddress
were checked as they are listed undermatchTypes
- Based on the
matchCount
we can determine how many data sources we were able to match against for each element:name
matched against the Australian Electoral Roll (“au-elec-roll”) and Equifax Public Credit Data Header (“au-efax-cdh-pub”)address
matched against the Australian Electoral Roll (“au-elec-roll”) onlydateOfBirth
matched against the Equifax Public Credit Data Header (“au-efax-cdh-pub”)
matchCount
equals thematchCountRequired
which means we were able to find enough matches for a positive resultrequiredSourcesMatched
indicates that the Australian Electoral Roll (“au-elec-roll”) was a source that was required to be matched against, which it was (name, address)isVerified
indicates that the match requirements were satisfied based on the rule criteria
"summary": {
"matchedRules": [
{
"ruleName": "SafeHarbour2x2",
"ruleOrder": 1,
"ruleMatches": [
{
"matchTypes": {
"name": {
"objectId": "{objectId}",
"matchCount": 2,
"matchSources": ["au-elec-roll", "au-efax-cdh-pub"],
"nonMatchSources": ["au-efax-cdh-consumer"],
"isChecked": true,
"isVerified": true
},
"address": {
"objectId": "{objectId}",
"matchCount": 1,
"matchSources": ["au-elec-roll"],
"nonMatchSources": ["au-efax-cdh-pub", "au-efax-cdh-consumer"],
"isChecked": true,
"isVerified": true
},
"dateOfBirth": {
"objectId": "{objectId}",
"matchCount": 1,
"matchSources": [""au-efax-cdh-pub""],
"nonMatchSources": ["au-elec-roll", "au-efax-cdh-consumer"],
"isChecked": true,
"isVerified": true
}
},
"matchCount": 2,
"matchCountRequired": 2,
"hasAllRequiredSourcesMatched": true,
"requiredSourcesMatched": ["au-elec-roll"],
"isVerified": true
}
]
}
],
...
Example 2: Unsuccessful KYC Database Verification
Similarly to the matchedRules
, the unmatchedRules
contains a singular ruleMatches
entry detailing the outcome of a particular rule established in the workflow that has not been met.
Let’s break down the following non matched result:
name
,dob
andaddress
were checked as they are listed undermatchTypes
- Based on the
matchCount
we can see nomatchSources
present which tells us that there were no matches. - The
nonMatchSources
lists the sources that were checked against but without a successful match resultname
did not match against the Australian Electoral Roll (“au-elec-roll”) and Equifax Public Credit Data Header (“au-efax-cdh-pub”) or Equifax Consumer Credit Data Header (“au-efax-cdh-consumer”)address
did not match against the Australian Electoral Roll (“au-elec-roll”) and Equifax Public Credit Data Header (“au-efax-cdh-pub”) or Equifax Consumer Credit Data Header (“au-efax-cdh-consumer”)dateOfBirth
did not match against the Australian Electoral Roll (“au-elec-roll”) and Equifax Public Credit Data Header (“au-efax-cdh-pub”) or Equifax Consumer Credit Data Header (“au-efax-cdh-consumer”)
matchCount
does not equal thematchCountRequired
which means we were not able to find enough matches for a positive resultrequiredSourcesMatched
indicates that the Australian Electoral Roll (“au-elec-roll”) was also a source that was required to be matched against, which was notisVerified
indicates that the match requirements were not satisfied based on the rule criteria
"summary": {
"unmatchedRules": [
{
"ruleName": "SafeHarbour2x2",
"ruleOrder": 1,
"ruleMatches": [
{
"matchTypes": {
"name": {
"matchCount": 0,
"nonMatchSources": ["au-elec-roll", "au-efax-cdh-pub", "au-efax-cdh-consumer"],
"isChecked": true,
"isVerified": false
},
"address": {
"matchCount": 0,
"nonMatchSources": ["au-elec-roll", "au-efax-cdh-pub", "au-efax-cdh-consumer"],
"isChecked": true,
"isVerified": false
},
"dateOfBirth": {
"matchCount": 0,
"nonMatchSources": ["au-elec-roll", "au-efax-cdh-pub" "au-efax-cdh-consumer"],
"isChecked": true,
"isVerified": false
}
},
"matchCount": 0,
"matchCountRequired": 2,
"hasAllRequiredSourcesMatched": false,
"requiredSourcesNotMatched": ["au-elec-roll"],
"isVerified": false
}
]
}
]
Process Results: Data Source Match Details
KYC match details are represented as processResults
existing under the workflow step results for steps that require verification or some sort of checks to be run and differ based on the context of what the check is trying to accomplish. For checks against external data sources, the processResults
will aim to capture what exactly has matched against what source. Steps typically return an array of all the individual process results that were used in determining that step’s result
.
After a KYC step has been executed, various elements require examination to determine the final outcome.
Legend:
- ‼️ - Results that deem whether the entity has passed or failed or the workflow failed to execute to completion.
- ⚠ - Context on why the entity may have passed or failed.
- ℹ️ - Information-only, no contribution to whether the entity has passed or failed.
Field name | Description | Importance |
---|---|---|
processResultId | The processResultId represents the unique identifier of the process result | ℹ️ |
class | The class reflects the type of process result (for example: KYC, AML) | ℹ️ |
result | The result is the overall outcome of the process (for example: MATCH, NO_MATCH, PARTIAL) | ‼️ |
state | The state reflects whether the process was completed successfully or whether an error of some kind was encountered during the process | ⚠ |
stepName | The stepName indicates the workflow step that triggered the process and thus generated the process result | ℹ️ |
stepType | The stepType indicates whether there was a subtype for the step. Generally used in non-KYC step process results. | ℹ️ |
groupId | The groupId is generated in order to tie related process results together. In the context of KYC, a single groupId will be generated and added to each process result per data source that is checked. | ℹ️ |
systemStatus | The systemStatus indicates that the result is valid and was used in determining the overall step result (typically only VALID results will be returned unless specifically requested). | ⚠ |
manualStatus | The manualStatus indicates whether the result has been manually classified by an operator outside of FrankieOne (for example: via API or Portal). This is set most commonly in AML classifications where an operator has registered whether a potential match is a true positive or false positive. | ⚠ |
providerResult | • The providerResult.confidence refers to the confidence rating that was returned by the provider. Defaults to 0/100 if confidence is not explicit. • providerResult.name refers to the name of the provider• Any unique identifier on the data provider side will be returned as providerResult.reference The providerResult.source indicates the raw source that was checked againstThe providerResult.sourceNormalized indicates the normalized source that was checked against.Note: Same sources checked by different providers will have the same sourceNormalized value but different source values. | ⚠ |
riskFactors | Any risk factors returned by the service provider will be present as riskFactors and potentially utilized in FrankieOne’s own risk engine, depending on your risk configuration. | ⚠ |
objectId | The objectId indicates the exact element that was checked. | ℹ️ |
objectType | The objectType indicates the specific type of element that was checked. | ℹ️ |
entityId | The entityId of the individual that was checked | ℹ️ |
createdAt | createdAt refers to when the process result was created. | ℹ️ |
updatedAt | updatedAt refers to when the process result was last updated. | ℹ️ |
updatedBy | updatedBy refers to who last updated the process result. Generally this will be FrankieOne unless a manual override was triggered. | ℹ️ |
schemaVersion | Refers to the version of the schema returned. Will always be 2 in the FrankieOne v2.x API. | ℹ️ |
requestId | The unique identifier of the request that generated this process result | ℹ️ |
notes | Any additional notes that were captured during the process. May contain extra information about how the result was determined. | ⚠ |
errors | Any errors that were encountered as part of the process. | ⚠ |
Example: 1: KYC Data Source Match Details
Process Result Objects (PROs) encapsulate the outcomes of specific processes (check, comparison, verification etc.). They play a crucial role in evaluating the overall outcome of relevant workflow steps.
Let’s break down the following KYC process result:
- The
class
is “KYC” which indicates the process is in relation to a KYC database verification check. - The address of the entity has been successfully verified against the Australian Electoral Roll:
- Based on the
objectType
we can see that the specific element checked was an “ADDRESS” - The
providerResult
array contains the details of the service provider that the entity was checked against:- The service provider is the Document Verification Service as indicated by the
name
field (“dvs”) - The specific data source that was checked is the Australian Electoral Roll as indicated by the source (“au-elec-roll”) and
sourceNormalized
(“au-elec-roll”) fields
- The service provider is the Document Verification Service as indicated by the
- The result is “MATCH” indicating that the address was successfully matched.
- Based on the
- The check was completed successfully (
state
is “COMPLETED”) and has not yet been invalidated in any way (systemStatus
is “VALID”), therefore it is safe to determine that the process ran to completion and was indeed used in determining the successfulresult
. - There has been no manual status applied to the process (due to the absence of a
manualStatus
field)
"processResults": [
{
"class": "KYC",
"createdAt": "2024-07-11T23:57:08.197185Z",
"entityId": "{entityId}",
"groupId": "{groupId}",
"notes": {...},
"objectId": "{objectId}",
"objectType": "ADDRESS",
"processResultId": "{processResultId}",
"providerResult": {
"confidence": "100",
"name": "dvs",
"reference": "{referenceId",
"source": "au-elec-roll",
"sourceNormalized": "au-elec-roll"
},
"supplementaryData": {
"matchStrengths": {
"fullAddress": 100,
"streetNumber": 100,
"streetName": 100
"streetType": 100,
"locality": 100,
"district": 100,
"subdivision": 100,
"postalCode": 100,
"country": 100,
},
"fuzziness": {
"normalized": 0,
"actual": 0
},
"wasNameMatchStrongEnough": true
},
"requestId": "{requestId}",
"result": "MATCH",
"schemaVersion": 2,
"state": "COMPLETED",
"stepName": "KYC",
"systemStatus": "VALID",
"updatedAt": "2024-07-11T23:57:08.197185Z"
}
Example: 2: KYC Data Source Non-Match Details
Similar to Process Results (PROs) for KYC database verification matches, process results that result in no match will be generated during step execution and will provide insights into why the data source could NOT be matched.
Let’s break down the following KYC process result:
- The
class
is “KYC” which indicates the process is in relation to a KYC database verification check. - The address of the entity has been checked but was not verified against the Australian Electoral Roll:
- Based on the
objectType
we can see that the specific element checked was an “NAME” - The
providerResult
array contains the details of the service provider that the entity was checked against:- The service provider is the Document Verification Service as indicated by the
name
field (“dvs”) - The specific data source that was checked is the Australian Electoral Roll as indicated by the source (“au-elec-roll”) and
sourceNormalized
(“au-elec-roll”) fields
- The service provider is the Document Verification Service as indicated by the
- The
result
is “MATCH” indicating that the address was successfully matched.
- Based on the
- The
matchStrengths
withinsupplementaryData
shows that no part of the name matched at all. - The fuzziness within
supplementaryData
shows that an exact match (normalized
as “0”) was required, potentially restricting any passable partial matching (“Sarah”, “Sara”). - The check was completed successfully (state is “COMPLETED”) and has not yet been invalidated in any way (systemStatus is “VALID”), therefore it is safe to determine that the process ran to completion and was indeed used in determining the successful
result
. - There has been no manual status applied to the process (due to the absence of a
manualStatus
field).
"processResults": [
{
"class": "KYC",
"createdAt": "2024-07-11T23:57:08.197185Z",
"entityId": "{entityId}",
"groupId": "{groupId}",
"notes": {...},
"objectId": "{objectId}",
"objectType": "NAME",
"processResultId": "{processResultId}",
"providerResult": {
"confidence": "0",
"name": "dvs",
"reference": "{referenceId}",
"source": "au-elec-roll",
"sourceNormalized": "au-elec-roll"
},
"supplementaryData": {
"matchStrengths": {
"fullname": 0,
"familyName": 0,
"givenName": 0,
"otherNames": 0,
"firstInitialFamilyName": 0
},
"fuzziness": {
"normalized": 0,
"actual": 0
}
}
"requestId": "{requestId}",
"result": "NO_MATCH",
"schemaVersion": 2,
"state": "COMPLETED",
"stepName": "KYC",
"systemStatus": "VALID",
"updatedAt": "2024-07-11T23:57:08.197185Z"
}
Anti-Money Laundering (AML) Screening
AML screening results are reflected in the result
field, which clearly indicates the step’s outcome. This field summarizes the step’s result, taking into account all the processed data. For instance, if an individual’s details such as name show up on any AML screening lists like PEP or Sanctions lists, the result will be HIT
. If not, the result will be CLEAR
.
{
"workflowResult": {
"workflowStepResults": [
{
"endedAt": "2024-05-14T04:04:12.66319Z",
"objectId": "{objectId}",
"objectType": "INDIVIDUAL",
"processResults": [...],
"requestId": "{requestId}",
"result": "CLEAR",
"serviceProviders": [
{
"endedAt": "2024-05-14T04:04:12.663187286Z",
"provider": "complyadvantage",
"result": "CLEAR",
"startedAt": "2024-05-14T04:04:11.849152Z"
}
],
"startedAt": "2024-05-14T04:04:11.849152Z",
"stepData": {...},
"stepName": "aml",
"stepResultId": "{stepResultId}",
"workflowExecutionId": "{workflowExecutionId}"
},
]
}
}
processResults
and summary has been omitted for brevity
Process Results: AML Match Results
processResults
exist under the workflow step results for steps that require verification or some sort of checks to be run and differ based on the context of what the check is trying to accomplish. For checks against external data sources, the processResults
will aim to capture what exactly has matched against what source. Steps typically return an array of all the individual process results that were used in determining that step’s result
.
Take for instance the following example:
"processResults": [
{
"class": "AML",
"createdAt": "2024-05-14T04:04:12.566065Z",
"entityId": "{entityId}",
"notes": {...},
"objectId": "{objectId}",
"objectType": "name",
"processResultId": "{processResultId}",
"providerResult": {
"confidence": "100",
"name": "complyadvantage",
"reference": "{referenceId}",
"riskScore": 0
},
"result": "HIT",
"state": "COMPLETED",
"stepName": "pep",
"supplementaryData": {...},
"systemStatus": "VALID",
"updatedAt": "2024-05-14T04:04:12.566065Z"
}
Supplementary Workflow Steps
Start Step
The start step indicates a successful commencement of the workflow. An effective measure to ascertain if the workflow initiated without complications is to check if the execution result includes a start step with a “COMPLETE” result
. Typically, no processResults
are anticipated for this step.
{
"requestId": "{requestId}",
"individual": {...},
"workflowResult": {
"workflowStepResults": [
{
"endedAt": "2024-07-22T05:46:07.722933Z",
"objectId": "{objectId}",
"objectType": "INDIVIDUAL",
"requestId": "{requestId}",
"result": "COMPLETE",
"risk": {
"contributedScore": 150,
"factors": [
{
"factor": "entity_type",
"score": 0,
"value": "Individual"
},
{
"factor": "country",
"score": 50,
"value": "Lithuania"
},
{
"factor": "entity_age",
"score": 100,
"value": "Under 18"
}
],
"level": "HIGH",
"overallScore": 150
},
"schemaVersion": 2,
"startedAt": "2024-07-22T05:46:09.013204Z",
"stepName": "START",
"stepResultId": "{stepResultId}",
"updatedBy": "01J3CFKFJE1HJACPRFZ7F47N5K",
"workflowExecutionId": "{workflowExecutionId}"
}
]
}
}
Finish Step
The finish step indicates whether the workflow completed successfully. This means that all results have been collected and stored, ready for further investigation. To check if the workflow finished without issues, look for a “COMPLETE” result
. Keep in mind that this only confirms the workflow’s completion, not the success of individual checks or the absence of errors. Typically, no processResults
are generated in this step.
{
"requestId": "{requestId}",
"individual": {...},
"workflowResult": {
"workflowStepResults": [
{
"endedAt": "2024-07-22T05:46:26.547446Z",
"objectId": "{objectId}",
"objectType": "INDIVIDUAL",
"requestId": "{requestId}",
"result": "COMPLETE",
"schemaVersion": 2,
"startedAt": "2024-07-22T05:46:26.511309Z",
"stepName": "FINISH",
"stepResultId": "{stepResultId}",
"updatedBy": "system:frankieone",
"workflowExecutionId": "{workflowExecutionId}"
}
]
}
}
Decision Step
The decision step within the workflow serves as a critical juncture that determines the workflow’s status—be it PASS, FAIL, or REVIEW. This determination hinges on the specific actions taken during the workflow. For instance, if all preceding steps have been executed flawlessly and all checks were cleared, the workflow is typically set to be “PASS”. Conversely, if there’s a hiccup in any step, such as an issue with individual verification, the workflow is likely to be marked as “FAIL”. It’s important to note that the statuses set can be modified within the workflow builder.
{
"workflowStepResults": [
{
"endedAt": "2024-07-22T05:46:25.826735Z",
"objectId": "{objectId}",
"objectType": "INDIVIDUAL",
"processResults": [],
"requestId": "{requestId}",
"result": "COMPLETE",
"schemaVersion": 2,
"startedAt": "2024-07-22T05:46:25.76572Z",
"stepName": "DECISION",
"stepResultId": "{stepResultId}",
"summary": {
"stepName": "DECISION",
"workflowExecutionResult": "PASS"
},
"updatedBy": "system:frankieone",
"workflowExecutionId": "{stepResultId}"
}
]
}
Risk Step
The risk step in the workflow is a mandatory checkpoint for risk assessment. It doesn't result in a pass or fail status. Instead, it's simply marked as "COMPLETED" once a risk evaluation has been conducted. This step ensures that risks are always considered in the process, without directly affecting the workflow's status. While the risk assessment itself doesn't change the workflow, the information gathered may be useful for later steps.
"workflowStepResults": [
{
"endedAt": "2024-07-22T05:46:24.998288Z",
"objectId": "{objectId}",
"objectType": "INDIVIDUAL",
"requestId": "{requestId}",
"result": "COMPLETE",
"schemaVersion": 2,
"startedAt": "2024-07-22T05:46:24.963811Z",
"stepName": "RISK",
"stepResultId": "{stepResultId}",
"updatedBy": "system:frankieone",
"workflowExecutionId": "{workflowExecutionId}"
}
]
}
Classifying AML Match Results
After investigating the supplementaryData
for any AML screening match details, you’ll need to make a decision on whether the person you are evaluating matches the person that we found during screening (true positive) or not (false positive).
To confirm whether an AML screening hit is true positive, false positive or unknown, you’ll need to update the manualStatus
of the process result. The manualStatus
is used to store any manually determined statuses on a result as not to override the initial result gathered as part of the workflow execution.
Example 1: Classify Single Match as True Positive
curl --location --request POST
'https://api.{{env}}.frankie.one/v2/individuals/{entityId}/results/{processResultId}' \
--header 'api_key: {{your_apiKey}}' \
--header 'X-Frankie-CustomerID: {{your_CustomerID}}' \
--header 'X-Frankie-CustomerChildID: {{your_CustomerChildID}}' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--data-raw '{
"processResults": [
"{processResultId}"
],
"manualStatus": "TRUE_POSITIVE"
}'
Example 2: Classify Multiple Matches as False Positive
curl --location --request POST
'https://api.{{env}}.frankie.one/v2/individuals/{entityId}/results/aml' \
--header 'api_key: {{your_apiKey}}' \
--header 'X-Frankie-CustomerID: {{your_CustomerID}}' \
--header 'X-Frankie-CustomerChildID: {{your_CustomerChildID}}' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--data-raw '{
"processResults": [
"processResultId", "processResultId"
],
"manualStatus": "FALSE_POSITIVE"
}'
Updated 4 days ago