Acceptance Guide
Time to read: 5 min
Time to implement: 1-2 hours
Overview
Verified Inc. enables brands to provide their users with best in class onboarding. This particular guide focuses on how and why to become a
By accepting credentials your brand can unlock 1-Click on boarding. Please see the Use Case section for more information.
You will need an API key and an email and/or phone for each user. Below is a valid API Key and URL for your initial usage along with suggested test email and phone values.
If you use these suggested test email and/or phone values you can authenticate to the wallet using those values, i.e. richard@piedpiper.net, using a static OTP of 111111
.
yVg3LEnF08y0MDmpHcPxB+sZWFcDARmPRKdY2M906ng=
https://core-api.sandbox-verifiedinc.com
richard@piedpiper.net
+10123456789
111111
Partner Acceptance
In Partner Issuer Acceptance, you integrate closely with a partnered issuer brand. This ensures that users will have the credentials you need for your brand's onboarding. This is the most popular integration type because of the parallels to traditional affiliate partnerships. However, this case supercharges the traditional flow by allowing users to accept promotions with 1-click.
General Acceptance
In General Issuer Acceptance, users may come from issuing brands that you do not work with directly. This is more flexible as it does not require any pre-arranged partnerships, and allows you to draw from a larger pool of issuers. However, it does require you to check whether the user has the necessary credentials for your brand's onboarding.
Motivations
As a brand that accepts digital ID cards, you can unlock 1-Click onboarding. This drastically decreases the abandonment rate during customer sign up and makes for a far better first touch experience for your new users.
Crucially, you will dramatically improve the experience for any user enabled with a digital ID card without changing the experience for any user without one. And because Verified Inc. sits on top of your existing onboarding process, you don’t need to change any existing security or compliance vendors or procedures.
Once you join, our team will identify opportunities to promote your brand within our network for 1-click conversions. These can be in-app offers, marketing emails, or similar promotions to drive users to your brand from complementary services.
In brief: As an acceptor in the Verified Inc. network, you will…
- Dramatically improve onboarding conversion.
- Delight users with a 1-click setup.
- Join a network of companies to help you grow faster (super charge your affiliate programs).
UX Strategies
Partner Acceptance
Partner Acceptance is the most streamlined flow thanks to the partner issuing brand ensuring the user has the necessary credentials to perform your onboarding flow. This form of integration also pre-authenticates the user to the Verified Inc. Wallet, removing another step in the experience.
Demo Brand Accepting Credentials via Partner Acceptance
This demo shows Lendtable accepting their partner, Hooli, credentials in order to gain 1-Click IDV capabilities. In this case Hooli can issue the credential in an on-demand fashion when the user clicks the button to redeem the Lendtable offer in the Hooli dashboard. This would ensure the user has the necessary credentials, so Lendtable can verify with 1-Click.
General Acceptance
For General Acceptance, you will have to check if a user has credentials because the User will not be coming directly from a partner. This can be done in the background by calling /hasMatchingCredentials at any time. If the response contains match
: true
then you should redirect the user to the url
. The demo below demonstrates an example UX.
Demo Kredita Accepting Credentials
This demo shows Kredita accepting Hooli credentials in order to gain 1-Click IDV capabilities when it's available. They collect email and phone from the user (Richard) and check if the user has matching credentials. The user does, so Kredita lets them verify with 1-Click.
Implementation
There are two ways to handle the acceptor integration that is independent of Partner or General Acceptance use cases: to pull shared credentials via a GET to /sharedCredentials/{sharedCredentialsUuid}
or to receive the credential data via a POST to a webhook endpoint you must implement.
In all cases, you will need to configure a web page to have the user redirected to after agreeing to share data with your brand. The response body of the pull shared credentials method is equivalent to the request body of the webhook to receive shared credentials method.
{
"uuid": "23b9c628-3415-447e-a716-0fe1b4cf61ff",
"email": "richard@piedpiper.net",
"phone": "+79553044233",
"credentials": [
{
"id": "8a1d4e35-413d-496b-b499-8810b55cfb5c",
"type": "SsnCredential",
"data": {
"ssn": "111223333"
},
"issuanceDate": "1671847264479",
"expirationDate": "1871839024044",
"issuer": "32ef9562-312d-4a8b-8f3e-ccb8df500b55",
},
{
"id": "1be7c008-3f0c-4a21-9aad-69ca1c4251d2",
"type": "FullNameCredential",
"issuer": "32ef9562-312d-4a8b-8f3e-ccb8df500b55",
"issuanceDate": "1671847264479",
"expirationDate": "1871839024044",
"data": [
{
"id": "2e6a7b9a-e93e-43ba-98a9-c554f4e16457",
"type": "FirstNameCredential",
"issuer": "32ef9562-312d-4a8b-8f3e-ccb8df500b55",
"issuanceDate": "1671847264479",
"expirationDate": "1871839024044",
"data": {
"firstName": "Richard"
}
},
{
"id": "9a5817ef-e621-4277-8c48-c8ee3776b6c4",
"type": "LastNameCredential",
"issuer": "32ef9562-312d-4a8b-8f3e-ccb8df500b55",
"issuanceDate": "1671847264479",
"expirationDate": "1871839024044",
"data": {
"lastName": "Hendricks"
}
}
]
}
]
}
Pull Credential Data
To pull credential data you will need to configure a web client page to receive the sharedCredentialsUuid
query param via a redirect from the Verified Inc. Wallet. Once the query param is retrieved it should be sent to your backend where it is used to call /sharedCredentials/{sharedCredentialsUuid}
to get the credentials to onboard the user. This guide will proceed with this method being the primary focus.
Partner Acceptance
In this case, as the accepting
Because the user starts in the issuing brand's UX in this type of flow, the issuer handles the redirect in step (0.b). This is why you must pre-define your desired redirectUrl
with us. For more information, see the partner issuance section of the issuance guide.
To enable this form of acceptance, we encode a direct relationship between the issuer and the acceptor. If you would like to implement this type of flow, please email us at contact@verified.inc so we can help you. However, please note this is not a requirement for acceptance.
1. Capture Query Param Value
Capture the sharedCredentialsUuid
query param from the redirectUrl
page you defined. This url ought to look something like this:
https://acme-bank.co/sign-up/complete?sharedCredentialsUuid=37ce0fff-af32-457e-9458-057125eb417d&verified=ga4p3yav
Optional: Capture the verified
query param as well. This will facilitate attribution tracking for promotions flows as the value is uniquely defined by the partner Issuer.
2. Retrieve Shared Credentials Data
Call /sharedCredentials/{sharedCredentialsUuid}
from your backend with the sharedCredentialsUuid
the callback URL contains. The response body will contain the credentials the user agreed to share via 1-Click IDV.
{
"uuid": string // the sharedCredentialsUuid
"credentials": [
{
"id": "8a1d4e35-413d-496b-b499-8810b55cfb5c",
"type": "SsnCredential",
"data": {
"ssn": "111223333"
},
"issuanceDate": "1671847264479",
"expirationDate": "1871839024044",
"issuer": "32ef9562-312d-4a8b-8f3e-ccb8df500b55",
},
{
"id": "1be7c008-3f0c-4a21-9aad-69ca1c4251d2",
"type": "FullNameCredential",
"issuer": "32ef9562-312d-4a8b-8f3e-ccb8df500b55",
"issuanceDate": "1671847264479",
"expirationDate": "1871839024044",
"data": [
{
"id": "2e6a7b9a-e93e-43ba-98a9-c554f4e16457",
"type": "FirstNameCredential",
"issuer": "32ef9562-312d-4a8b-8f3e-ccb8df500b55",
"issuanceDate": "1671847264479",
"expirationDate": "1871839024044",
"data": {
"firstName": "Richard"
}
},
{
"id": "9a5817ef-e621-4277-8c48-c8ee3776b6c4",
"type": "LastNameCredential",
"issuer": "32ef9562-312d-4a8b-8f3e-ccb8df500b55",
"issuanceDate": "1671847264479",
"expirationDate": "1871839024044",
"data": {
"lastName": "Hendricks"
}
}
]
}
],
// user's email from input to /hasMatchingCredentials
// only present if email was provided
"email"?: string,
// user's phone from input to /hasMatchingCredentials
// only present if email was provided
"phone"?: string
}
It's easiest to extract the data from each credential using the corresponding schema. The extracted data is verified according to the issuer of the credential, but you can perform additional verification steps if you like.
Example Application Code Credential Handling
import _ from 'lodash';
/**
* Finds value in an object that matches a property name.
* @param object
* @param propertyName
*/
export function findByPropertyName<Type>(
object: Record<string, any>,
propertyName: string
): Type | undefined {
if (_.has(object, propertyName)) {
return object[propertyName];
}
for (const key in object) {
if (_.isArray(object[key])) {
for (const item of object[key]) {
const result = findByPropertyName(item, propertyName);
if (result !== undefined) {
return result as Type;
}
}
}
if (_.isPlainObject(object[key])) {
const result = findByPropertyName(object[key], propertyName);
if (result !== undefined) {
return result as Type;
}
}
}
return undefined;
}
✅ You're done!
General Acceptance
Because the issuer is not issuing credentials with your brand in mind, you need to check whether the user has matching
0.a Check User Credentials
Call /hasMatchingCredentials
with the user's email and/or phone and the credential type(s) you need.
{
"match": true,
"url": "https://wallet.verified.inc/request/9f2053fc-cc4c-41cb-8d14-7d3ccf6167eb?email=test%40example.com&phone=%2B10123456789"
}
What counts as a match?
When you call /hasMatchingCredentials
, you include one or more credential requests. For each credential request, you specify:
- the type
- (optional) which issuers are acceptable
- (optional) whether the credential is mandatory
There's a match if, for each credential request for a mandatory credential, the user has a credential of the correct type from an acceptable issuer.
The user will either have matching credentials, or they won't. If they do, continue to step (2). If they don't, you're done with Verified Inc. and should take the user through your existing verification flow.
If you would like your existing verification flow verification costs to be covered, please look into issuing credentials. More information can be found in the 1-Click or Free Use Case section.
0.b Redirect User to Verified Inc. Wallet
Direct the user to the url
the response body contains. You need to add an additional redirectUrl
query param that you define which will serve as the ultimate landing page after the user completes 1-Click IDV from the Verified Inc. web wallet.
For example, if the final url you need to redirect the user to is https://acme-bank.co/sign-up/complete then ultimate url you will redirect the user to will be something like this:
https://wallet.verified.inc/request/9f2053fc-cc4c-41cb-8d14-7d3ccf6167eb?email=test%40example.com&phone=%2B10123456789&redirectUrl=https://acme-bank.co/sign-up/complete
From here you can continue to step (1) in the Partner Acceptance section above having preformed the credential verification steps, ensuring that the user has the necessary credentials.
Webhook
Currently in beta
To receive credential data via a webhook url you need to implement an endpoint that can handle a POST HTTP request with a request body containing credential information. You will have to inform us of what is required to interface and authenticate with your webhook. The configuration options available are:
- url
- query parameters
- headers
- authorization
The request body that the endpoint will have to handle is of fixed Shared Credentials structure. An example of this format can be found below.
Example Shared Credentials Body
{
"uuid": "23b9c628-3415-447e-a716-0fe1b4cf61ff",
"email": "richard@piedpiper.net",
"phone": "+79553044233",
"credentials": [
{
"id": "8a1d4e35-413d-496b-b499-8810b55cfb5c",
"type": "SsnCredential",
"data": {
"ssn": "111223333"
},
"issuanceDate": "1671847264479",
"expirationDate": "1871839024044",
"issuer": "32ef9562-312d-4a8b-8f3e-ccb8df500b55",
},
{
"id": "1be7c008-3f0c-4a21-9aad-69ca1c4251d2",
"type": "FullNameCredential",
"issuer": "32ef9562-312d-4a8b-8f3e-ccb8df500b55",
"issuanceDate": "1671847264479",
"expirationDate": "1871839024044",
"data": [
{
"id": "2e6a7b9a-e93e-43ba-98a9-c554f4e16457",
"type": "FirstNameCredential",
"issuer": "32ef9562-312d-4a8b-8f3e-ccb8df500b55",
"issuanceDate": "1671847264479",
"expirationDate": "1871839024044",
"data": {
"firstName": "Richard"
}
},
{
"id": "9a5817ef-e621-4277-8c48-c8ee3776b6c4",
"type": "LastNameCredential",
"issuer": "32ef9562-312d-4a8b-8f3e-ccb8df500b55",
"issuanceDate": "1671847264479",
"expirationDate": "1871839024044",
"data": {
"lastName": "Hendricks"
}
}
]
}
]
}
Integration Testing
All testing and development ought to be done against our Sandbox environment. The publicly published Postman collection's Integration Test Suite is very helpful facilitating testing your Acceptor integration. All instructions below are in reference to this Postman collection. If you are more accustom to an alternative HTTP request client for development purposes, please let us know and we maybe be able to accommodate you.
To test either flavor of integration, you need to replace the acceptorBrandApiKey
from the also published Public API
environment variables with your brand's Sandbox API key.
Partner Acceptance
For Partner Acceptance, you will need to replace the partnerBrandUuid
with your brand's Sandbox UUID and use the issue credentials w/ partnerUuid
(then subsequently can use hasMatchingCredentials w/ partnerUuid
) call with the request body corresponding to your credential needs. Then by following the response body's url
you can test the flow from the User's perspective. When the credentials are agreed to be shared you, the testing User, will be redirected to the url defined in the redirectUrl
query param (great for development) or to the redirectUrl
you have already pre-defined and shared with us (necessary for integration to work when an issuer brand initiates the flow).
In the real implementation the issuer will be handling the /credentials
and /hasMatchingCredentials
requests and redirecting the User to the Verified Inc. Wallet.
Some pre-configuration is necessary to test this appropriately. However, if we have already given you an ApiKey this should already be done for you. If you are unsure, please contact us.
General Acceptance
Using the issue credentials w/o partner
request you can mimic credentials being issued to User in some earlier state. Then when your integration makes the /hasMatchingCredentials
request with the user's email and/or phone it ought to return there is a match for you to test your integration with.