API Reference
See also our Postman docs.
Authentication
Every request detailed below requires an Verified Inc. API key as an Authorization
header value.
To test in our sandbox environment, you can use our test brand and user:
Test Brand API Credentials
yVg3LEnF08y0MDmpHcPxB+sZWFcDARmPRKdY2M906ng=
https://core-api.sandbox-verifiedinc.com
To get an API key for your own brand, email us at Support@Verified.Inc.
Test User Login Credentials
+10123456789
richard@piedpiper.net
111111
These are Hooli and Richard Hendricks — yes, the ones from Silicon Valley! 😂
API keys are sensitive, so please only use them in a secure backend service environment. This means that ideally your clients will communicate with your own backend service, which will then call the Verified Inc. API. Your clients should never have direct access to your Verified Inc. API key.
Environments
We have two environments. Please do all integration against the sandbox environment.
Environment | Base URL | Wallet URL |
---|---|---|
Sandbox | https://core-api.sandbox-verifiedinc.com | https://wallet.sandbox-verifiedinc.com |
Production | https://core-api.verified.inc | https://wallet.verified.inc |
The sandbox domain is sandbox-verifiedinc.com
but the production domain is verified.inc
. This is purely because .inc
domains are quite expensive!
Development
While developing your integration you can use a dummy user account if you would like.
email: richard@piedpiper.net || richard.hendricks@verified.inc
phone: +10123456789 || +550123456789
By using these test identifiers you can authenticate to the wallet using a static OTP value of 111111
, allowing you to test the full flow of the integration more easily. We recommend using a proper test email or phone to recieve actual verification messages during the final stages of development.
Credentials issued to the test user will be deleted every day at 05:00 UTC.
Core Functionality
The core functionality of our API allows your brand to participate in the Verified Network through 1-Click Signup. For more advanced use cases like Issue to Earn, please refer to our advanced API section.
1-Click
Begin a 1-Click Signup flow, so a
A user is an individual in the Verified Inc. network. Each user has at least one phone or emails, aka userIdentifiers associated with them. They can have multiple of either.+ More...user can easily share their verifiedExample: Richard is a user in your account system and potentially of the Verified Inc. network. He has two email addresses and one phone with him. Credentials can be issued to or requested of him using any of these identifiers.Components: Referenced in API endpoints `/hasMatchingCredentials` and `/issueCredentials`. User data is associated by using these user identifiers that you already keep on your users.A credential is a collection of data about a person. It's issued by a company and can be requested by other network participants, gated by the user's consent.+ More...credentials.Example: ACME Lending issues a KYC verification credential to Richard (an ACME user). This includes Richard's contact information and account numbers, as well as a level of confidence in the accuracy of the data.Components: A company issues credentials following the steps in the Issuance Guide.
Method: POST
Path: /1-click
You need to provide:
- User's phone
- (Optional) User's email.
- (Optional) Verification option(s). Controls the SMS verification messaging.
- (Optional) Content object of request page options. To allow for minor messaging adjustments to the Wallet request page from which the user provides consent to share data.
- (Optional) Credential request(s). (if you would like to deviate from the default credential requests).
- (Optional) Redirect URL. If you would like to redirect the user to a different URL than the one provided in your settings.
- (Optional) isHosted. If you would like to do the non-hosted integration .
- (Optional) User's birthDate. Only required if you are using the non-hosted integration.
A credential requests encodes which CredentialRequest
objects.
{
type: string, // the type of credential data being requested
issuers: string[], // list of acceptable brandIds; if empty, all issuer brands are valid
required?: boolean, // @deprecated - Use mandatory field instead. If the credential is required
mandatory?: 'yes' | 'no' | 'if_available' // if the credential is required, not required, or required if available.
description?: string // a description field that is shown to the user; can be used to explain why the information is being requested
allowUserInput?: boolean // when true, the user will be shown an input to add their own information if they choose.
children?: CredentialRequest[] // list of sub-credentials relevant to the parent credential (e.g. FullNameCredential(FirstNameCredential, MiddleNameCredential LastNameCredential)
}
The endpoint comes with a default credential requests configuration shown below which should be suffice for most customers.
Default 1-Click Credential Requests
[
{
"type": "FullNameCredential",
"children": [
{
"type": "FirstNameCredential"
},
{
"type": "MiddleNameCredential"
},
{
"type": "LastNameCredential"
}
],
"allowUserInput": true
},
{
"type": "EmailCredential",
"allowUserInput": true
},
{
"type": "PhoneCredential"
},
{
"type": "AddressCredential",
"children": [
{
"type": "Line1Credential"
},
{
"type": "Line2Credential"
},
{
"type": "CityCredential"
},
{
"type": "StateCredential"
},
{
"type": "CountryCredential"
},
{
"type": "ZipCodeCredential"
}
],
"allowUserInput": true
},
{
"type": "BirthDateCredential",
"allowUserInput": true
},
{
"type": "SsnCredential",
"allowUserInput": true
}
]
This endpoint performs a similar role to /hasMatchingCredentials but with a few key differences:
- Can only be used with a user's phone number
- Triggers an SMS verification message to the user that Verified Inc. sends
- Much greater chance of success getting user data than the standard acceptance flow because data is pulled on demand
The same API key necessary to call /1-click grants you, and only, you access to the encrypted credential data documented in Get Shared Credentials. Please keep this key secure.
Request Body
{
phone: string, // user's phone number in E.164 format
email?: string, // user's email address; optional
verificationOptions?: 'only_link' | 'only_code' | 'both_link_and_code' // Optional: controls the SMS verification messaging. Default is 'only_code'.
content?: {
title?: 'Signup' | 'Verify' | 'Apply', // Optional: title of the request page. Default is 'Signup'
description?: string, // Optional: description displayed under the consent page header. Default is 'Make sure everything is correct:'
}
credentialRequests?: CredentialRequest[], // Optional: a list of one or more CredentialRequest objects. Encodes which credentials are being asked for
redirectUrl?: string, // Optional: redirect url to redirect user to after the user has completed the 1-click flow. Default is the redirect url provided in your settings.
isHosted?: boolean, // Optional: if you would like to do the non-hosted integration. Default is true.
birthDate?: string // Optional: user's birth date in YYYY-MM-DD format. Required if you are using the non-hosted integration.
}
Response Body
{
"url": string // Verified Inc. Web Wallet url to redirect user to for credential request handling. It will redirect back to your client. Only present if match is true.
"match": boolean // indicates whether we can provide the user with a 1-Click Signup flow
"smsBody": string // the SMS body that we recommend sending to the user; You will only have to handle sending the SMS in Production.
}
The url
from the response ought to then be enriched with a redirectUrl
query param that will take the next step in your target service's user onboarding webpage. More information on this can be found in 1-Click Signup.
Trusted 1-Click
The "trusted" 1-click sign-up flow is very similar to the standard 1-click sign-up flow, but allows for the user to skip the phone OTP step with us. The "trusted" nomenclature comes from Verified Inc. having to perform additional integration checks prior to enabling this feature for your brand.
Method: POST
Path: /1-click/trusted
You need to provide:
- User's phone
- User's birth date.
- (Optional) User's email.
- (Optional) Credential request(s). If you would like to update from the default credential requests.
A credential requests encodes which CredentialRequest
objects.
{
type: string, // the type of credential data being requested
issuers: string[], // list of acceptable brandIds; if empty, all issuer brands are valid
required?: boolean, // @deprecated - Use mandatory field instead. If the credential is required
mandatory?: 'yes' | 'no' | 'if_available' // if the credential is required, not required, or required if available.
description?: string // a description field that is shown to the user; can be used to explain why the information is being requested
allowUserInput?: boolean // when true, the user will be shown an input to add their own information if they choose.
children?: CredentialRequest[] // list of sub-credentials relevant to the parent credential (e.g. FullNameCredential(FirstNameCredential, MiddleNameCredential LastNameCredential)
}
The endpoint comes with a default credential requests configuration shown below which should be suffice for most customers.
Default 1-Click Credential Requests
[
{
"type": "FullNameCredential",
"children": [
{
"type": "FirstNameCredential"
},
{
"type": "MiddleNameCredential"
},
{
"type": "LastNameCredential"
}
],
"allowUserInput": true
},
{
"type": "EmailCredential",
"allowUserInput": true
},
{
"type": "PhoneCredential"
},
{
"type": "AddressCredential",
"children": [
{
"type": "Line1Credential"
},
{
"type": "Line2Credential"
},
{
"type": "CityCredential"
},
{
"type": "StateCredential"
},
{
"type": "CountryCredential"
},
{
"type": "ZipCodeCredential"
}
],
"allowUserInput": true
},
{
"type": "BirthDateCredential",
"allowUserInput": true
},
{
"type": "SsnCredential",
"allowUserInput": true
}
]
This endpoint performs a similar role to /1-click but with a few key differences:
- You must handle user's phone verification within the same session of calling this endpoint
- The user's A credential is a collection of data about a person. It's issued by a company and can be requested by other network participants, gated by the user's consent.+ More...credentials are returned synchronously in the response bodyExample: ACME Lending issues a KYC verification credential to Richard (an ACME user). This includes Richard's contact information and account numbers, as well as a level of confidence in the accuracy of the data.Components: A company issues credentials following the steps in the Issuance Guide.
Request Body
{
phone: string, // user's phone number in E.164 format
birthDate: string // user's birth date in YYYY-MM-DD format. Required if you are using the non-hosted integration.
email?: string, // Optional; user's email address;
credentialRequests?: CredentialRequest[], // Optional: a list of one or more CredentialRequest objects. Encodes which credentials are being asked for
}
Response Body
{
"uuid": string // the 1-click uuid that can be used to update the user's credentials if they edit them post retrieval in your sign up form
"identifiers": {
[identifierType: string]: string
},
"credentials": {
[shortenedCredentialType: string]: string
},
"metadata": {
"identifiers": {
[identifierType: string]: {
[metadataType: string]: string
}
},
"credentials": {
[shortenedCredentialType: string]: {
[metadataType: string]: string
}
}
}
}
The 1-click/trusted
response is identical to the Get 1-Click
Credentials response, but with the addition of the uuid
attribute. This uuid
can be used to update the user's credentials if they edit them post-retrieval in your sign-up form. You are inventive in calling the update endpoint for the benefit of issue to earn.
Get 1-Click Credentials
Get the
A credential is a collection of data about a person. It's issued by a company and can be requested by other network participants, gated by the user's consent.+ More...credentials of a user who has completed a 1-Click Signup flow.Example: ACME Lending issues a KYC verification credential to Richard (an ACME user). This includes Richard's contact information and account numbers, as well as a level of confidence in the accuracy of the data.Components: A company issues credentials following the steps in the Issuance Guide.
Method: GET
Path: /1-click/{uuid}
When a 1ClickUuid
as a query parameter.
This endpoint allows you to retrieve the
You need to provide:
- the
1ClickUuid
that was returned in the query param after redirecting the user to theredirectUrl
attribute from the/1-click
response
Your brand's access to 1-Click credentials is deleted after 5 minutes of the initial credential data retrieval.
If in the 1-Click Response, the credentials
attribute is not present, then means the user opted out of sharing their credentials.
But you can still use the 1ClickUuid
to check if the user verified their phone number or email address.
Definitions
- An identifier is a phone number or email address the user uses to verify for 1-Click Signup.
identifierType
is the type of identifier (phone
oremail
).
- A credential is a piece of data the user shares (e.g. birth date or SSN).
-
A credential type is a string indicating the type of a credential (e.g.
SsnCredential
orFirstNameCredential
). It's formatted inPascalCase
and always includes the wordCredential
at the end. -
shortenedCredentialType
is the shortened credential type incamelCase
. The shortened credential type is just the type without the wordCredential
(e.g.birthDate
orssn
). For subcredentials of a composite credential, it includes the shortened credential type of its parent credential(s) (e.g.fullName.firstName
).Accepted Values
Currently, accepted values for
shortenedCredentialType
are:email
fullName.firstName
fullName.middleName
fullName.lastName
birthDate
address.line1
address.line2
address.city
address.state
address.zipCode
address.country
ssn
-
- Data in this context means identity information about a user (e.g. their name, contact information, etc.)
- Metadata in this context means any additional data that's not identity information about a user (e.g. the verification method for their identity information).
-
metadataType
is the type of metadata.Accepted Values
Currently, possible values for
metadataType
are:id
: unique identifier for a credential- UUID
- Applies only to credentials
verificationMethod
: how an identifier or credential was verified- enum:
"phone_carrier"
,"otp"
,"self_attested"
, ornull
- Applies to both identifiers and credentials
- enum:
status
: status of a credential- enum:
"valid"
or"revoked"
- Applies only to credentials
- enum:
issuerUuid
: brand that issued a credential- UUID
- Applies only to credentials
issuanceDate
: date a credential was issued- Unix timestamp
- Applies only to credentials
expirationDate
: date a credential expires- Unix timestamp
- Applies only to credentials
-
Response Body
{
"identifiers": {
[identifierType: string]: string
},
"credentials": {
[shortenedCredentialType: string]: string
},
"metadata": {
"identifiers": {
[identifierType: string]: {
[metadataType: string]: string
}
},
"credentials": {
[shortenedCredentialType: string]: {
[metadataType: string]: string
}
}
}
}
One particularly valuable piece of metadata is verificationMethod
, which describes how the credential (piece of user data) was verified. It can take the following values:
"phone_carrier"
: verified via phone carrier records"otp"
: verified via an OTP (one time passcode)"self_attested"
: attested by the user themselves (not verified)null
We support a few different formats for user data, for example the default format for the dateBirth
credential is a unixTimestamp, but you can also request it different formats (e.g. MM/DD/YYYY
or YYYY-MM-DD
), or for the state
credential, you can request it as a 2-letter abbreviation (e.g. CA
) or as the full state name (e.g. California
).
Accepted Formats
Currently, accepted formats for user data are:
dateBirth
: unixTimestamp, or any combination ofy
(year),M
(month),d
(day),/
(slash), and-
(dash)state
: 2-letter abbreviation, full state namecountry
: 2-letter abbreviation, full country nameaddress
: instead getting a object with all keys, you can get a string with any combination, (e.g.line1, city, state-country
)fullName
: instead getting a object with all keys, you can get a string with any combination, (e.g.firstName, lastName
)
Update 1-Click Credentials
This endpoint is to be used for updating the 1-click credentials passed to your brand in the 1-click non-hosted and 1-click trusted flows.
Method: POST
Path: /1-click/{uuid}/credentials
You need to provide:
- The 1-click uuid
- The credential values in same format they were provided. See example below.
{
"fullName": {
"firstName": "Leonardo",
"lastName": "Messi"
},
"ssn": "111111110",
"email": "leonardo@verified.inc"
}
This is an optional endpoint only relevant for the 1-click non-hosted and trusted variants. Because we send the user's data directly to your application, without the user using our web Wallet (which is part of the hosted variant), the user never gets a chance to update any of the data that's autofilled for them. If you allow them to editing and/or enrich their data on your side, within a UI/UX that you manage and implement, you can use this endpoint to pass that information back to us (and earn revenue share as a result).
If this endpoint is optional, why use it?
If you to call this endpoint after the user has made edits to their data on your side, you will earn a share of the revenue generated when the user uses that data elsewhere.revenue streams.
Request Body
{
"uuid": string // the 1-click uuid from the POST /1-click/trusted response
"credentials": {
[shortenedCredentialType: string]: string
}
}
The response body will contain credentials conforming to credential schemas. Please see the Postman docs for examples of this response body.
Response Body
[
{
type: string, // credential type
verificationMethod: string // verification method
data: CredentialsList | {
[credentialKey: string]: string // credential data
},
}
]
The response body is currently in a more verbose format than that of the response for GET /sharedCredentials
or POST /1-click
(both trusted and non-hosted). However, in practice, the details of the response body are non-consequential for you as long as a 201 HTTP status code is received.
Advanced Functionality
The 1-Click Signup functionality that is covered in the core API section are higher level abstractions for these advanced endpoints. Thus, it is unlikely you will need to use these for most flows. However, for completeness please refer to this section for the advanced use cases documentation which covers endpoints mostly related to pure Issue to Earn integrations.
Check User Credentials
Check if a user has matching
A credential is a collection of data about a person. It's issued by a company and can be requested by other network participants, gated by the user's consent.+ More...credentials. If so, aExample: ACME Lending issues a KYC verification credential to Richard (an ACME user). This includes Richard's contact information and account numbers, as well as a level of confidence in the accuracy of the data.Components: A company issues credentials following the steps in the Issuance Guide.A request (or credential request) is a request for a credentials to be shared by a user. It's created when a company successfully checks if a user has matching credentials, via /hasMatchingCredentials. Only if the user has the ability to response with the matching credentials is a request created.+ More...request is created to get theExample: Hooli FinTech checks if Richard has a SSN and LastName credential issued by ACME Lending. Because he does, a request is created for those credentials specifically from ACME Lending. Hooli presents this request to Richard by directing him to the `url` received in the `/hasMatchingCredentials` response body.Components: A company creates a user specific request by using /hasMatchingCredentials.. If it is case the user does not have the desired credentials then a request is not created. If it is the case the user does, a request is created and is returned in the form of a `url` attribute in response to the client.A user is an individual in the Verified Inc. network. Each user has at least one phone or emails, aka userIdentifiers associated with them. They can have multiple of either.+ More...user's consent to share the data.Example: Richard is a user in your account system and potentially of the Verified Inc. network. He has two email addresses and one phone with him. Credentials can be issued to or requested of him using any of these identifiers.Components: Referenced in API endpoints `/hasMatchingCredentials` and `/issueCredentials`. User data is associated by using these user identifiers that you already keep on your users.
Method: POST
Path: /hasMatchingCredentials
You need to provide:
- User's email or phone
- (Optional) Credential request(s). Required if Partner UUID is not provided.
- (Optional) Partner UUID.
- (Optional) List of the sub-credentials that make up the credential. If not provided, all sub-credentials will be returned.
A credential requests encodes which CredentialRequest
objects.
{
type: string, // the type of credential data being requested
issuers: string[], // list of acceptable brandIds; if empty, all issuer brands are valid
required?: boolean, // @deprecated - Use mandatory field instead. If the credential is required
mandatory?: 'yes' | 'no' | 'if_available' // if the credential is required, not required, or required if available.
description?: string // a description field that is shown to the user; can be used to explain why the information is being requested
allowUserInput?: boolean // when true, the user will be shown an input to add their own information if they choose.
children?: CredentialRequest[] // list of sub-credentials relevant to the parent credential (e.g. FullNameCredential(FirstNameCredential, MiddleNameCredential LastNameCredential)
}
If you list multiple issuers, the user can include a credential issued by any one of those listed. If issuers
is left empty the user can include a credential with matching type issued by any issuer.
The Credential
If mandatory field are missing, then the credential will be treated as optional.
The Credential children
attribute. This attribute is used to specify the sub-credentials that make up the credential. If not provided, all sub-credentials will be returned.
(eg: If you request a AddressCredential
and you only want the city
and state
sub-credentials, you can specify that in the children
attribute.)
The same ApiKey necessary to call /hasMatchingCredentials grants you and only you access to the encrypted credential data documented in Get Shared Credentials. Please keep this key secure.
Request Body
{
email?: string, // user's email address; optional if phone is provided
phone?: string, // user's phone number; optional if email is provided
credentialRequests: CredentialRequest[], // a list of one or more CredentialRequest objects. Encodes which credentials are being asked for; not used if partnerUuid is provided
partnerUuid?: string, // partner's uuid; optional
description?: string // A description displayed in the consent page header. If no description is provided, a default value will be displayed.
}
Response Body
{
"match": boolean, // indicates whether the user has matching credentials
"url": string // Verified Inc. Web Wallet url to redirect user to for credential request handling. It will redirect back to your client. Only present if match is true.
}
The url
from the response ought to then be enriched with a redirectUrl
query param that will take the next step in your target service's user onboarding webpage.
For example, if you want to check if a user has credentials of type SsnCredential
, FullNameCredential
and AddressCredential
issued by any issuer you would send the following request:
Request Body
{
"email": "richard@piedpiper.net",
"credentialRequests": [
{
"type": "SsnCredential",
"issuers": [],
"mandatory": "yes"
},
{
"type": "FullNameCredential",
"issuers": [],
"mandatory": "yes"
},
{
"type": "PhoneCredential",
"issuers": [],
"mandatory": "if_available",
"allowUserInput": true
},
{
"type": "AddressCredential",
"issuers": [],
"children": [
{
"type": "CityCredential",
"issuers": [],
"mandatory": "if_available"
},
{
"type": "StateCredential",
"issuers": [],
"mandatory": "yes"
},
{
"type": "CountryCredential",
"issuers": [],
"mandatory": "yes"
},
{
"type": "ZipCodeCredential",
"issuers": []
}
]
}
]
}
Let's break this down to understand what is happening here:
SsnCredential
is a "single attribute atomic credential" and therefore does not have any sub-credentials. Because it is marked asmandatory
, it only matches if the user has a credential.
{
"type": "SsnCredential",
"issuers": [],
"mandatory": "yes"
}
FullNameCredential
is a "composite credential" and therefore has 2 sub-credentials¹:FirstNameCredential
,LastNameCredential
. Because it is marked asmandatory
, and it has nochildren
attribute, it only matches if the user has a credential with all sub-credentials.
{
"type": "FullNameCredential",
"issuers": [],
"mandatory": "yes"
}
PhoneCredential
is a "single attribute atomic credential" and therefore does not have any sub-credentials. Because we set aallowUserInput
attribute oftrue
, the user will be given an opportunity to enter a new value if they choose to. Note that this have not relation withmandatory
field, it just accepts and validates the user input data."
{
"type": "PhoneCredential",
"issuers": [],
"mandatory": "if_available",
"allowUserInput": true
}
-
The
AddressCredential
credential is made up of 6 sub-credentials:Line1Credential
,Line2Credential
,CityCredential
,StateCredential
,CountryCredential
andZipCodeCredential
.But because we specified a
children
attribute, we are only asking for theCityCredential
,StateCredential
,CountryCredential
andZipCodeCredential
sub-credentials. SoLine1Credential
andLine2Credential
are ignored.AddressCredential{
"type": "AddressCredential",
"issuers": [],
"children": [
{
"type": "CityCredential",
"issuers": [],
"mandatory": "if_available"
},
{
"type": "StateCredential",
"issuers": [],
"mandatory": "yes"
},
{
"type": "CountryCredential",
"issuers": [],
"mandatory": "yes"
},
{
"type": "ZipCodeCredential",
"issuers": []
}
]
}
The user will be asked to share the CityCredential
if available (this means if the user has a credential of type CityCredential
it will be mandatory, but if the user does not have a credential of type CityCredential
the user will still be able to share the AddressCredential
credential).
StateCredential
and CountryCredential
are mandatory and therefore the user must have a credential of each type to match.
ZipCodeCredential
is optional and therefore the user may or may not have a credential of type to match.
Get Shared Credentials
Get verified
A credential is a collection of data about a person. It's issued by a company and can be requested by other network participants, gated by the user's consent.+ More...credential data shared by aExample: ACME Lending issues a KYC verification credential to Richard (an ACME user). This includes Richard's contact information and account numbers, as well as a level of confidence in the accuracy of the data.Components: A company issues credentials following the steps in the Issuance Guide.A user is an individual in the Verified Inc. network. Each user has at least one phone or emails, aka userIdentifiers associated with them. They can have multiple of either.+ More...user.Example: Richard is a user in your account system and potentially of the Verified Inc. network. He has two email addresses and one phone with him. Credentials can be issued to or requested of him using any of these identifiers.Components: Referenced in API endpoints `/hasMatchingCredentials` and `/issueCredentials`. User data is associated by using these user identifiers that you already keep on your users.
Method: GET
Path: /sharedCredentials/{sharedCredentialsUuid}
When a sharedCredentialsUuid
as a query parameter.
This endpoint allows you to retrieve the shared /hasMatchingCredentials
endpoint.
You need to provide:
- the
sharedCredentialsUuid
that was returned in the query param after redirecting the user to theredirectUrl
attribute from the/hasMatchingCredentials
response
Your brand's access to shared credentials is deleted after 5 minutes of the initial credential data retrieval.
The response body consists of Credential objects with the plaintext user data.
{
"id": string, // credential id
"type": string, // credential type
"issuer": string, // credential issuer brandId
"issuanceDate": number, // when credential was created as a milliseconds since epoch unix timestamp
"expirationDate"?: number, // when credentials expires as a milliseconds since epoch unix timestamp
"data": Map<string, any> | Credential[] // credential data map/array that matches the credential type's JSON Schema definition
}
Response Body
{
"uuid": string, // the uuid from the query parameter of the redirect back to your client; identifies the collection of credentials shared by the user
"credentials": Credential[], // a list of one or more Credential objects
"email"?: string, // the user's email from the input to /hasMatchingCredentials; only present if email was provided
"phone"?: string // the user's phone from the input to /hasMatchingCredentials; only present if phone was provided
}
To facilitate extracting the credential data we recommend leveraging the Schema Resolver to get the schema of the credential types. Because Credential schemas are immutable they can then be cached and referenced when retrieving the credential data.
Issue Credentials
Issue
A credential is a collection of data about a person. It's issued by a company and can be requested by other network participants, gated by the user's consent.+ More...credentials to aExample: ACME Lending issues a KYC verification credential to Richard (an ACME user). This includes Richard's contact information and account numbers, as well as a level of confidence in the accuracy of the data.Components: A company issues credentials following the steps in the Issuance Guide.A user is an individual in the Verified Inc. network. Each user has at least one phone or emails, aka userIdentifiers associated with them. They can have multiple of either.+ More...user.Example: Richard is a user in your account system and potentially of the Verified Inc. network. He has two email addresses and one phone with him. Credentials can be issued to or requested of him using any of these identifiers.Components: Referenced in API endpoints `/hasMatchingCredentials` and `/issueCredentials`. User data is associated by using these user identifiers that you already keep on your users.
Method: POST
Path: /credentials
You need to provide:
- Credentials data array
- Either a phone and/or email attribute
- (Optional) Partner UUID.
- (Optional) Tracking Identifier for credential usage attribute.
Data about the user, must comply with our credential schema definitions.
An example Credentials object is below:
{
"type": string, // credential type
"data": Map<string, any> | Credentials[], // credential data map/array that matches the credential type's JSON Schema definition
"id"?: string, // credential id - uuid formatted; optional. If not provided, a random uuid will be generated
"expirationDate?": number // when the credential expires as a milliseconds since unix epoch; optional
}
While not required, we recommend providing a unique id
following uuid
format for each credential. This allows for idempotent credential issuance - meaning if a duplicate id
value is seen another credential will not be created. Expect a HTTP status code of 409
if this is the case. If you do not provide an id
, a random uuid will be generated for you.
An expiration date is not the only control on whether a credential is valid. You can also change the credential's status at any time, for example to revoke it. See Patch Credentials.
Credential data is stored securely via a data privacy vault that encrypts and tokenizes the data. The data is only retrieved and decrypted for the brand that the
Composite credentials are credentials that are made up of other credentials. For example, a FullNameCredential
is made up of FirstNameCredential
, MiddleNameCredential
(optional), and LastNameCredential
. When issuing a composite credential, you must provide the child credentials as well.
Example
{
"type": "FullNameCredential",
// based on the properties attribute of the schema
// note that the data is an array of objects, not a single object
"data": [
{
"type": "FirstNameCredential",
"data": {
"firstName": "Richard"
}
},
{
"type": "LastNameCredential",
"data": {
"lastName": "Hendricks"
}
}
]
}
See Data Schemas for more information.
Request Body
{
"credentials": Credentials[], // a list of one or more Credentials objects
"email"?: string, // user's email address; optional if phone is provided
"phone"?: string // user's phone number in E.164 format; optional if email is provided
"trackingId"?: string // user tracking identifier
}
Response Body
{
"email": string, // user's email address if provided
"phone": phone, // user's phone number if provided
"trackingId"?: string // user tracking identifier if provided
"credentials": [{
"id": string, // credential id
"type": string, // credential type
"data": Map<string, any> | Credentials[], // credential data map/array that matches your provided data and the credential type's JSON Schema definition
"issuanceDate": string, // when credential was created as a milliseconds since epoch unix timestamp
"expirationDate?": string, // when the credential expires as a milliseconds since unix epoch; optional
"status": 'valid' | 'revoked' // an enum to denote whether the credential is valid (all credentials are valid when first issued) — note that this is independent of the expirationDate
}],
"url"?: string // Only present if partnerUuid was provided and conditions are met. See the Issuance Guide for more information.
}
The issued credential contains an id
that you should store. You'll need this, for example, if you ever want to revoke the credential. We recommend storing the entire credential, indexed on the credential id
. However, it is also an acceptable to store credential id
s associated with a user and use the Get Credential or Get All User Credentials endpoint to retrieve the full credential.
Patch Credential
Patch a previously issued
A credential is a collection of data about a person. It's issued by a company and can be requested by other network participants, gated by the user's consent.+ More...credential.Example: ACME Lending issues a KYC verification credential to Richard (an ACME user). This includes Richard's contact information and account numbers, as well as a level of confidence in the accuracy of the data.Components: A company issues credentials following the steps in the Issuance Guide.
Method: PATCH
Path: /credentials/{id}
You can optionally provide any of the following in the request body:
- (Optional) new credential data
- (Optional) new credential expiration date
- (Optional) new credential status
Credential data must comply with our credential schema definitions.
If a credential is expired but the status is 'valid' it is an unusable credential. Likewise, if the credential as not expired but the status is 'revoked', it is also not usable credential.
Credential data is stored securely via a data privacy vault that encrypts and tokenizes the data. The data is only retrieved and decrypted for the brand that the
Request Body
{
"data": Map<string, any> | Credentials[], // credential data map/array that matches the credential type's JSON schema definition
"expirationDate?": number // when the credentials expires as a milliseconds since epoch unix timestamp; optional
"status": 'valid' | 'revoked' // an enum to denote whether the credential is valid (all credentials are valid when first issued) — note that this is independent of the expirationDate
}
Response Body
{
"id": string, // credential id
"type": string, // credential type
"data": Map<string, any> | Credentials[], // credential data map/array that matches your provided data and the credential type's JSON Schema definition
"issuanceDate": string, // when credential was created as a milliseconds since epoch unix timestamp
"expirationDate?": number, // when the credential expires as a milliseconds since epoch unix timestamp; optional
"status": 'valid' | 'revoked' // an enum to denote whether the credential is valid (all credentials are valid when first issued) — note that this is independent of the expirationDate.
}
The resultant credential id
remains the same, so after a 200 HTTP response code is received, nothing further needs to be updated on your end.
Patch All User Credentials
Patch all previously issued by your brand to a user.
Method: PATCH
Path: /userCredentials/{userIdentifier}
A
The only credential value that can by updated in this manner is status
. A credential status must be in the request body.
This endpoint all modifies credentials issued to the user by your brand.
Request Body
{
"status": 'valid' | 'revoked' // an enum to denote whether the credential is valid (all credentials are valid when first issued) — note that this is independent of the expirationDate
}
Response Body
{
"credentials": {
"id": string, // credential id
"type": string, // credential type
"data": Map<string, any> | Credentials[], // credential data map/array that matches your provided data and the credential type's JSON Schema definition
"issuanceDate": string, // when credential was created as a milliseconds since epoch unix timestamp
"expirationDate?": number, // when the credential expires as a milliseconds since epoch unix timestamp; optional
"status": 'valid' | 'revoked' // an enum to denote whether the credential is valid (all credentials are valid when first issued) — note that this is independent of the expirationDate.
}[]
}
The response body contains a list of all credentials that were modified on the credentials
key.
Get Credential
Get a previously issued
A credential is a collection of data about a person. It's issued by a company and can be requested by other network participants, gated by the user's consent.+ More...credential.Example: ACME Lending issues a KYC verification credential to Richard (an ACME user). This includes Richard's contact information and account numbers, as well as a level of confidence in the accuracy of the data.Components: A company issues credentials following the steps in the Issuance Guide.
Method: GET
Path: /credentials/{id}
This endpoint returns a credential (issued by your brand) via the credential id
.
Response Body
{
"id": string, // credential id
"type": string, // credential type
"data": Map<string, any> | Credentials[], // credential data map/array that matches your provided data and the credential type's JSON Schema definition
"issuanceDate": string, // when credential was created as a milliseconds since epoch unix timestamp
"expirationDate?": number, // when the credential expires as a milliseconds since epoch unix timestamp; optional
"status": 'valid' | 'revoked' // an enum to denote whether the credential is valid (all credentials are valid when first issued) — note that this is independent of the expirationDate.
}
Get All User Credentials
Get all previously issued by your brand to a user.
Method: GET
Path: /userCredentials/{userIdentifier}
A
This endpoint all modifies credentials issued to the user by your brand.
It should be clear that this endpoint should not be used in place of /hasMatchingCredentials
, which can check user credentials across many issuers but does not return the credentials' values.
This endpoint is simply a nice to have for an issuer to see all credentials they have issued to a user.
Response Body
{
"credentials": {
"id": string, // credential id
"type": string, // credential type
"data": Map<string, any> | Credentials[], // credential data map/array that matches your provided data and the credential type's JSON Schema definition
"issuanceDate": string, // when credential was created as a milliseconds since epoch unix timestamp
"expirationDate?": number, // when the credential expires as a milliseconds since epoch unix timestamp; optional
"status": 'valid' | 'revoked' // an enum to denote whether the credential is valid (all credentials are valid when first issued) — note that this is independent of the expirationDate.
}[]
}
The response body contains a list of all credentials on the credentials
key.
Get Partner Credential Requests
Get the partner's pre-defined
A request (or credential request) is a request for a credentials to be shared by a user. It's created when a company successfully checks if a user has matching credentials, via /hasMatchingCredentials. Only if the user has the ability to response with the matching credentials is a request created.+ More...credential requests.Example: Hooli FinTech checks if Richard has a SSN and LastName credential issued by ACME Lending. Because he does, a request is created for those credentials specifically from ACME Lending. Hooli presents this request to Richard by directing him to the `url` received in the `/hasMatchingCredentials` response body.Components: A company creates a user specific request by using /hasMatchingCredentials.. If it is case the user does not have the desired credentials then a request is not created. If it is the case the user does, a request is created and is returned in the form of a `url` attribute in response to the client.
Method: GET
Path: /credentialRequests/{partnerUuid}
This endpoint returns a list of credential requests that the partner has defined for their brand.
Response Body
{
"credentialRequests": CredentialRequest[]
}
{
type: string, // the type of credential data being requested
issuers: string[], // list of acceptable brandIds; if empty, all issuer brands are valid
required?: boolean, // @deprecated - Use mandatory field instead. If the credential is required
mandatory?: 'yes' | 'no' | 'if_available' // if the credential is required, not required, or required if available.
description?: string // a description field that is shown to the user; can be used to explain why the information is being requested
allowUserInput?: boolean // when true, the user will be shown an input to add their own information if they choose.
children?: CredentialRequest[] // list of sub-credentials relevant to the parent credential (e.g. FullNameCredential(FirstNameCredential, MiddleNameCredential LastNameCredential)
}
This endpoint is helpful when developing the partner issuance flow.