Onboard an individual
How to onboard a user using Pre-Built UIs or the API
TAB-Pre-Built UIs
Onboard a user using Pre-Built UIs
Embedded flows allow you to verify users from within your application. You can securely create Counterparties without touching sensitive information. You will spend less time on development. Alternatively, you can send data via API to have full control over the onboarding experience.
1. Retrieve API Key
Go to your API Keys page. There you will find your Organization ID and API keys. Your default Sandbox or Production keys have the appropriate permissions. Otherwise, create or modify an API key to have manage permissions for Compliance, Counterparties, and External Accounts.
2. Create User Onboarding
Create a User Onboarding. If you would like to use the default flows for KYC and KYB, pass in default-individual
or default-business
for the flow alias. You can also customize what checks are run- learn more here.
You can also optionally prefill fields in the user onboarding flow using the data parameter. Individuals can still edit the fields. Please pay close attention to the format and names of the attributes, as other data will be ignored.
If you have previously verified the email address or phone number of users, you can optionally pass them. This data will be compared against what the user enters and is a signal for the KYC checks. Phone numbers should include the country code (e.g. +1
for US-based phone numbers) and be formatted without spaces (e.g. +11234567890
).
curl --request POST \
-u ORGANIZATION_ID:API_KEY \
--url https://app.moderntreasury.com/api/user_onboardings \
-H 'Content-Type: application/json' \
-d '{
"flow_alias": "default-individual"
}'
curl --request POST \
-u ORGANIZATION_ID:API_KEY \
--url https://app.moderntreasury.com/api/user_onboardings \
-H 'Content-Type: application/json' \
-d '{
"flow_alias": "default-individual",
"data": {
"first_name": "Harry",
"last_name": "Potter",
"date_of_birth": "1980-07-31",
"phone_number": "+11111111111",
"email": "[email protected]",
"address": {
"line1": "4 Privet Drive",
"line2": "",
"locality": "San Francisco",
"region": "CA",
"postal_code": "94108",
"country": "US"
},
"taxpayer_identifier": "123456789",
"external_account": {
"account_details": [
{
"account_number": "123456789",
"account_number_type": "other"
}
],
"routing_details": [
{
"routing_number": "121141822",
"routing_number_type": "aba"
}
],
"account_type": "checking"
}
}
}'
curl --request POST \
-u ORGANIZATION_ID:API_KEY \
--url https://app.moderntreasury.com/api/user_onboardings \
-H 'Content-Type: application/json' \
-d '{
"flow_alias": "default-individual",
"verified_email": "[email protected]",
"verified_phone": "+11111111111"
}'
This API request will return a User Onboarding object.
{
"id": "dacabe14-4b1b-4219-8226-02b3d247477d",
"object": "user_onboarding",
"live_mode": true,
"metadata": {},
"flow-alias": "default-individual",
"status": "processing",
"counterparty_id": null,
"external_account_id": null,
"decision_id": null,
"created_at": "2022-05-24T02:45:08Z",
"updated_at": "2022-05-24T02:45:08Z"
}
Be careful not to share your API key with your frontend, as it is private. Create User Onboarding objects in your backend only.
3. Embed Flow
Integrate Modern Treasury’s user onboarding flow by inserting a code snippet into your application. You can use a React component (see our user-onboarding-react Github repo for detailed instructions), or you can use pure Javascript.
To initiate the flow, supply the ID (from the User Onboarding object created in the last step (dacabe14-4b1b-4219-8226-02b3d247477d
).
You can also optionally supply custom callback methods that fire on specific events.
import { MTUserOnboarding } from "@modern-treasury/user-onboarding-react";
const options = {
userOnboardingId: "dacabe14-4b1b-4219-8226-02b3d247477d",
onSuccess: () => {
console.log("MT User Onboarding is a Success!");
},
onCancel: () => {
console.log("MT User Onboarding has been Canceled!");
},
onError: () => {
console.log("MT User Onboarding has an Error!");
},
style: {
backgroundColor: "green",
boarder: "none",
color: "white",
width: "200px",
height: "75px",
children: "Open User Onboarding",
className: "MT-Onboarding",
padding: "15px 32px",
textAlign: "center",
textDecoration: "none",
display: "inline-block",
fontSize: "16px",
},
};
function App() {
return (
<div className="App">
<MTUserOnboarding {...options}>
Open User Onboarding
</MTUserOnboarding>
</div>
);
}
import { useMTUserOnboarding } from "@modern-treasury/user-onboarding-react";
// Pass in optional options as shown below
const options = {
...
}
const [ready, error, open] = useMTUserOnboarding(options);
return (
<button
onClick={() => open("dacabe14-4b1b-4219-8226-02b3d247477d")}
disabled={!ready}
>
Open MT-Onboarding
</button>
);
<!DOCTYPE html>
<html lang="en">
<head>
<script src="https://cdn.moderntreasury.com/compliance/v1/mt-onboarding.js"></script>
<script type="application/ecmascript">
function openIframe() {
const onSuccess = function (event) {
// handle success event (e.g. move user to the next step of your flow following KYC)
};
const onError = function (event) {
// handle error event (e.g. open the iframe again)
};
const onCancel = function (event) {
// handle cancel event (e.g. email the user later to try and reactivate them)
// note: this event will not be triggered if the user closes their browser.
};
const userOnboardingId = document.getElementById('userOnboardingId').value;
window.onboardingInstance = MTOnboarding.open({
userOnboardingId: userOnboardingId, // required
onSuccess: onSuccess, // optional
onError: onError, // optional
onClose: onCancel, // optional
});
}
</script>
</head>
<body>
<label for="userOnboardingId">User Onboarding ID:</label>
<input type="text" value="dacabe14-4b1b-4219-8226-02b3d247477d" name="userOnboardingId" id="userOnboardingId">
<br/>
<button onclick="openIframe()">
Open
</button>
</body>
</html>
There are three callbacks.
Callback | Description |
---|---|
onSuccess | Runs if the user completes the onboarding flow, regardless of the eventual outcome of the verification. |
onCancel | Runs if the user closes the iframe before the user completes the onboarding flow. |
onError | Runs if there is an error in the onboarding flow. |
For each event, a message will be sent. For error events, this message will look like { event: "error", error: "REASON_FOR_ERROR" }
. Below are potential reasons for an error.
Error Message | Reason |
---|---|
user_onboarding_expired | The userOnboardingId has expired (it is valid for 24 hours). |
user_onboarding_api_key_invalid | The API key used for creating the user onboarding was deactivated. |
user_onboarding_completed | User onboarding already completed. |
user_onboarding_not_found | User onboarding with given ID was not found. |
internal_server_error | An unexpected error occurred. |
When the user successfully completes the onboarding flow, checks will be kicked off automatically.
Authenticating the user before sending them to Modern Treasury Compliance, and limiting the number of submission attempts, help prevent fraudsters from abusing your verification flow.
4. Monitor User Onboarding
Based on the compliance score, a User Onboarding will be automatically approved
, automatically denied
, or have a Case opened for manual review.
If a User Onboarding is approved
, a Counterparty and External Account will be created. If a User Onboarding is denied
, a Counterparty will not be created. The id
of the Counterparty and External Accounts will be included in the webhooks and User Onboarding object.
Webhooks are used to provide status updates on User Onboardings.
{
"event": "approved",
"data": {
"id": "dacabe14-4b1b-4219-8226-02b3d247477d",
"object": "user_onboarding",
"live_mode": true,
"metadata": {},
"party_type": "individual",
"status": "approved",
"counterparty_id": "72d63b95-910f-41ae-a13c-5a9465c891a1",
"external_account_id": "4c95964e-c9d4-4102-9183-2c8ae39e2c1d",
"decision_id": "08d9b87d-67a2-4234-a6d0-e8fec11ebb4f",
"created_at": "2022-05-16T05:14:02Z",
"updated_at": "2022-05-16T05:14:02Z"
}
}
Additional information about the User Onboarding can be found in the related Decision object. You can alternatively monitor this object for status on User Onboardings.
Check out this guide to learn more about testing Customer Onboarding in the Sandbox.
TAB-API
Onboard a user using the API
With the API integration, you have full control over the user onboarding experience. Implement your own frontend to collect the data and send Modern Treasury the data for verification. Alternatively, you can embed a pre-built flow to quickly add this capability to your application.
1. Retrieve your API Key
Go to your API Keys page. There you will find your Organization ID and API keys. Your default Sandbox or Production keys have the appropriate permissions. Otherwise, create or modify an API key to have manage permissions for Compliance, Counterparties, and External Accounts.
2. Create a User Onboarding
Create a User Onboarding. Provide information via the data field and set the status field to processing
.
For KYC, the flow alias should be default-individual
. For KYB, the flow alias should be default-business
. You can also customize what checks are run- learn more on the Customize User Onboarding Checks page.
Optionally, you can provide:
- Verified email and verified phone: You can enter an email address or phone number that you have verified previously with the user. Phone numbers should include the country code (e.g. +1 for US-based phone numbers) and be formatted without spaces (e.g. +11234567890). This data will be compared against what the user enters and is a signal for the KYC checks.
- Session key: If you integrate the Device and Behavior SDK, pass in a session key for matching data collected from the SDK with this customer onboarding.
curl --request POST \
-u ORGANIZATION_ID:API_KEY \
--url https://app.moderntreasury.com/api/user_onboardings \
-H 'Content-Type: application/json' \
-d '{
"status":"processing",
"flow_alias": "default-individual",
"data": {
"first_name": "Harry",
"last_name": "Potter",
"date_of_birth": "1980-07-31",
"phone_number": "+11111111111",
"email": "[email protected]",
"address": {
"line1": "4 Privet Drive",
"line2": "",
"locality": "San Francisco",
"region": "CA",
"postal_code": "94108",
"country": "US"
},
"taxpayer_identifier": "123456789",
"external_account": {
"account_details": [
{
"account_number": "123456789",
"account_number_type": "other"
}
],
"routing_details": [
{
"routing_number": "121141822",
"routing_number_type": "aba"
}
],
"account_type": "checking"
}
}
}'
curl --request POST \
-u ORGANIZATION_ID:API_KEY \
--url https://app.moderntreasury.com/api/user_onboardings \
-H 'Content-Type: application/json' \
-d '{
"status":"processing",
"flow_alias": "default-individual",
"verified_email": "[email protected]",
"verified_phone": "+11111111111",
"data": {
"first_name": "Harry",
"last_name": "Potter",
"date_of_birth": "1990-01-02",
"phone_number": "+11111111111",
"email": "[email protected]",
"address": {
"line1": "Hogsmeade Ave",
"line2": "",
"locality": "San Francisco",
"region": "CA",
"postal_code": "94108",
"country": "USA"
},
"taxpayer_identifier": "123456789",
"external_account": {
"account_details": [
{
"account_number": "1111111111",
"account_number_type": "other"
}
],
"routing_details": [
{
"routing_number": "021000021",
"routing_number_type": "aba"
}
],
"account_type": "checking"
}
}
}'
curl --request POST \
-u ORGANIZATION_ID:API_KEY \
--url https://app.moderntreasury.com/api/user_onboardings \
-H 'Content-Type: application/json' \
-d '{
"status":"processing",
"flow_alias": "default-individual",
"session_key": "5195ac52-afb7-4425-bd8b-8234263f2139",
"data": {
"first_name": "Harry",
"last_name": "Potter",
"date_of_birth": "1990-01-02",
"phone_number": "+11111111111",
"email": "[email protected]",
"address": {
"line1": "Hogsmeade Ave",
"line2": "",
"locality": "San Francisco",
"region": "CA",
"postal_code": "94108",
"country": "USA"
},
"taxpayer_identifier": "123456789",
"external_account": {
"account_details": [
{
"account_number": "1111111111",
"account_number_type": "other"
}
],
"routing_details": [
{
"routing_number": "021000021",
"routing_number_type": "aba"
}
],
"account_type": "checking"
}
}
}'
This API request will return a User Onboarding object.
{
"id": "dacabe14-4b1b-4219-8226-02b3d247477d",
"object": "user_onboarding",
"live_mode": true,
"metadata": {},
"party_type": "individual",
"status": "processing",
"counterparty_id": null,
"external_account_id": null,
"compliance_rule_metadata": null,
"decision_id": null,
"created_at": "2023-03-20T22:02:03Z",
"updated_at": "2023-03-20T22:02:03Z"
}
The checks will be kicked off automatically.
3. Monitor User Onboarding
Based on the compliance score, a User Onboarding will be automatically approved
, automatically denied
, or have a Case opened for manual review.
If a User Onboarding is approved
, a Counterparty and External Account will be created. If a User Onboarding is denied
, a Counterparty will not be created. The id
of the Counterparty and External Accounts will be included in the webhooks and User Onboarding object.
Webhooks are used to provide status updates on User Onboardings.
{
"event": "approved",
"data": {
"id": "dacabe14-4b1b-4219-8226-02b3d247477d",
"object": "user_onboarding",
"live_mode": true,
"metadata": {},
"party_type": "individual",
"status": "approved",
"counterparty_id": "72d63b95-910f-41ae-a13c-5a9465c891a1",
"external_account_id": "4c95964e-c9d4-4102-9183-2c8ae39e2c1d",
"decision_id": "08d9b87d-67a2-4234-a6d0-e8fec11ebb4f",
"created_at": "2022-05-16T05:14:02Z",
"updated_at": "2022-05-16T05:14:02Z"
}
}
Additional information about the User Onboarding can be found in the related Decision object. You can alternatively monitor this object for status on User Onboardings.
Check out this guide to learn more about testing Customer Onboarding in the Sandbox.
Updated 10 months ago