Dotfile provide a Case management system where you can organize your KYC/KYB processes. Open case, add new entities in a case, approve or reject the case.
Cases can be seen has folders where you would store all the entities and checks related to a same underlying customer or KYC/KYB process.
Case can be created:
- via the Console, when a User creates a new Case
- via the API, creating a case
Case lifecycle
- Open: Entities in the case are under investigation, we collect document, process data, ask questions to them and review all information
- Approved: Everything is approved, we have process and review all checks are approved. The case (customer) is verified and ready to access your service
- Rejected: Some checks are rejected and the case (customer) is identify as not compliant and cannot access your service
- Closed: Entities in the case are not under investigation anymore. Checks and entities will be kept in the event the case is reopened
Case review
To approve or reject a case via the API, you can create a case review:
status
:"approved"
,"rejected"
or"closed"
comment
: Optional comment to explain and document the decision. This comment may be required depending on your workspace setting.next_review_at
: Optional date to override the date that would be set from your workspace setting and the case risk level at this time ornull
to not schedule a periodic review for this case.
The review information of the case is then available when retrieving a case and in all case webhook events.
Lean more about the Case approval flow in the product doc
Case Flags
A Case can have different flags that describe a specific state of the case.
-
contact_has_actions
When an contact action is required -
reviewer_has_actions
When a reviewer action is required -
flags
: An array containing an ordered set of:all_checks_approved
When there is no actions left from any users and all checks are approved.for_review
Review is ready for the reviewer, no actions left from the contact.for_first_collect
When contact has actions for the first time and need to upload documents or verify it’s identity.for_recollection
Recollection is ready for the contact because all checks have been reviewed and there are some recollection needed (checks rejected or expired), no actions left from the reviewer.first_collect_completed
When an initial collection is done.
Case ID and External ID
For each case, we provide an auto-generated UUID (v4) but you can add your own external ID when creating a case.
You can find these IDs on the Case header in the console:
External ID must be unique.
Two cases cannot share the same External ID.
If you need to set custom data on a case, please refer to Custom data
Custom Properties
You can define Custom Properties on Case, Company or Individual entities in your Dotfile workspace settings.
Custom Properties will ensure you submit quality value with constraint depending on the type you chose:
- Choices
- Countries
- Date
- Numeric
- Phone number
- Text
- URL
- Yes/No
You will be able to set custom property values on entities via create (POST) and update (PATCH) endpoints. In the payload, custom_properties
is a key-value object where the key is the Custom Property key
you can find on your workspace settings and the value must respect the constraint of the property type.
{
"name": "Some example case",
"status": "open",
"custom_properties": {
"ubo_us_citizen": true,
"main_activity_country": ["FR"]
}
}
You can set null
to reset the value.
Choices
A valid array of option key
of the Custom Property.
Settings: Allow Multiple
true
→ can have more than one elementfalse
→ can have only one element
{
"custom_properties": {
"office_location": ["emea"]
}
}
Countries
A valid array of ISO 3166-1 alpha-2 country code (eg FR
).
Settings: Allow Multiple
true
→ can have more than one elementfalse
→ can have only one element
{
"custom_properties": {
"main_activity_country": ["FR", "GB"]
}
}
Date
Date in format ISO 8601 (yyyy-MM-dd
eg 2023-01-31
)
{
"custom_properties": {
"last_audit": "2022-02-03"
}
}
Email
A valid email string with a maximum of 250 characters.
{
"custom_properties": {
"default_email": "[email protected]"
}
}
Numeric
A numeric value that can be formatted as a number, percentage or currency with a currency code and with a maximum and minimum .
{
"custom_properties": {
"yearly_turnover": "20000",
}
}
Phone number
A valid (E164) phone number string
{
"custom_properties": {
"default_phone_number": "+33654489875"
}
}
Text
A valid string with a maximum of 250-1500 characters.
Settings: isMultiLine
- single line (
isMultiLine=false
) maximum of 250 characters - multi line (
isMultiLine=true
) maximum of 1500 characters
{
"custom_properties": {
"source_of_funds": "income"
}
}
URL
A valid (RFC 3986) URL string
{
"custom_properties": {
"external_link": "https://dotfile.com"
}
}
Yes/No
A boolean (true
/false
).
{
"custom_properties": {
"ubo_us_citizen": true
}
}
Metadata
You can set key-value data to a case in the metadata
property when creating or updating the case. The main use-case is to stored some specific data that could be reuse in your system.
This data is stored as a key-value object where the value are only string
:
{
"metadata": {
"custom_key": "true",
"my_data": "this is important",
"count": "42"
}
}
When updating a case, the metadata in input will override the whole existing metadata object (no merge between existing and new key or value). You can also pass metadata: null
to remove all metadata.
Case metadata are always attach to the case object even on context of webhook payload.
Risk
Via API, you can push automatic risk on case using the API endpoint Creates an automatic Risk.
Via the Console, you can set manual risk on case.
If you set manual risk on a case, new automatic risk that are pushed on case will be saved but will not be set as the current risk. You need to “enable (back) the automatic risk” on the Console to set it as current.
Risk object
level
: correspond to the risk level, can benot_defined
low
medium
high
prohibited
.score
: is a number that is the total score calculated for this risk.components
: is an object of numbers that contains the details of the score. It helps to understand the risk score and level.flags
: is an object of boolean that contains the details of flags for this risk. It helps to understand the risk level.
Example of automatic risk: :
{
"level": "medium",
"score": 10067,
"components": {
"customer_score": 1400,
"product_score": 3000,
"delivery_channel_score": 2000,
"transaction_score": 1667,
"geography_score": 2000
},
"flags": {
"prohibited_country_ubo": true,
"complex_company_alert": false
}
}
If you push the exact same risk than the latest automatic risk, it will not be saved and we will return the latest automatic risk instead (no error from the API).
Case relation
If you need to investigate complex company structure in a case, you can define relation between companies and individuals. This is display as a graph in the Console App.
You can have two types of companies in a case:
- Main company: this is the unique company at the core of the investigation, you are looking for the UBO of this company
- Affiliated companies: intermediate companies that could be between the main company and beneficial owners
You can also have individuals that are the Beneficial Owners of the main company or others individuals interesting to investigate (such as Legal representatives or minor shareholders).
Relation object
The relations
property on company or individual object is an array of relation
like this:
to_company_id
: describe a relation to the company idfrom_individual_id
orfrom_company_id
: entity the relation comes fromownership_percentage
: number (0-100) of the ownership percentagevoting_rights_percentage
: number (0-100) of the voting rights percentageroles
: array of roles (shareholder
,legal_representative
)position
: string of the position to company
Create relation
Via entity (individual, company) creation
For company POST /companies
and individual POST /individuals
, at the property relations
, you can pass a relation
object to link the new entity.
You could omit the
to_company_id
or therelations
property and it will implicitly create a relation to the main company.
Example: Payload to create an individual related to an affiliated company
{
"case_id": "{{case_id}}",
"is_business_contact": true,
"is_beneficial_owner": true,
"first_name": "Tony",
"last_name": "Stark",
"maiden_name": null,
"email": "[email protected]",
"ownership_percentage": 33.33,
"voting_rights_percentage": 33.33,
"relations": [
{
"to_company_id": "{{affiliated_company_id}}",
"roles": [
"shareholder"
],
"position": "CEO",
"ownership_percentage": 33.33,
"voting_rights_percentage": 33.33
}
]
}
Create/Update/delete relations for existing entities
You could also manage relation via the dedicated CUD endpoints:
You need to specify the to_company_id
(if omitted it links to the main company) and the from_individual_id
or from_company_id
to create the relation.
If you want to change the to_company_id
or from_individual_id
or from_company_id
, you need to create the new relation and delete the old one. The graph cannot have orphan entities so be sure to create relation first.
Total and Direct percentage
There are two percentage properties:
ownership_percentage
voting_rights_percentage
You can find them at two levels:
- On the individual object, there are the Total interest in the main company
- On relation object, there are the Direct interest in the
to_company_id
referenced in the relation
We also compute total percentage according to all direct percentage define on relations.