Skip to main content
Search

Callback - PII Verification

When your counterparty initiated a Pre-transaction Travel Rule or a Post-transaction Travel Rule request, and they designate your VASP as the Travel Rule Receiver VASP, you will receive this callback with callbackType=4 to validate the PII correctness based on your in-house KYC data.

For further details of the request structure, see: RegularizeCallbackVerifyAddressRequest.

TypePre-transaction Travel RulePost-transaction Travel Rule
Your Role in Travel RuleTravel Rule Receiver VASPTravel Rule Receiver VASP
Your Counterparty in Travel RuleTravel Rule Initiator VASPTravel Rule Initiator VASP
Your Role in TransferBeneficiary VASPOriginator VASP
Your Counterparty Role in TransferOriginator VASPBeneficiary VASP
Your ResponsibilityConfirm correctness of Beneficiary PersonConfirm correctness of Originator Person

Request

You can expect to receive below request From GTR:

{
"requestId": "IGicRINHYF4N",
"invokeVaspCode": "[Invoker VASP Code]",
"originatorVasp": "[Originator VASP Code]",
"beneficiaryVasp": "[Beneficiary VASP Code]",
"callbackType": 4,
"callbackData": {
"requestId": "IGicRINHYF4N",
"txId": "1fcd10006f252d2cca3a4803d0dcb84b0ee10ef73d1055f0fe23ce4ead0f6e75", // In pre-transaction travel rule, txId will be null
"amount": "1000",
"fiatPrice": "6.66",
"fiatName": "USDT",
"network": "ETH",
"ticker": "USDT",
"tag": "",
"address": "1GURHee2JsCkdpxVisjbjAeNhbDbGub8R4",
"secretType": 1,
"originatorVasp": "[Originator VASP Code]", // save it, don't use it
"beneficiaryVasp": "[Beneficiary VASP Code]", // save it, don't use it
"initiatorVasp": "[Initiator VASP Code]",
"receiverVasp": "[Receiver VASP Code / Your VASP Code]",
"verificationDirection": 1, // 1: RECEIVER TO SENDER (Post-transaction Travel Rule, YOU are Originator), 2: SENDER TO RECEIVER (Pre-transaction Travel Rule, You are Beneficiary)
"piiSecuredInfo": {
"initiatorKeyInfo": {
"publicKey": "[COUNTER_PARTY_VASP_PUBLIC_KEY]"
},
"receiverKeyInfo": {
"publicKey": "[YOUR_PUBLIC_KEY]"
},
"piiSecretFormatType": "FULL_JSON_OBJECT_ENCRYPT",
"piiSpecVersion": "ivms101-2020",
"secretAlgorithm": "ed25519_curve25519",
"securedPayload": "[Encrypted PII, clear-text is forbidden]"
}
}
}

PII Matching Process

Once you receive above request, you can start your PII matching process by following below steps.

1. Identify the algorithm and decrypt

  • Decrypt the PII payload from piiSecuredInfo.securedPayload by using piiSecuredInfo.initiatorPublicKey and your Self-hosted Private Key.
  • piiSecuredInfo.secretAlgorithm tells the exact encryption algorithm, if your VASP supports multiple algorithms.
  • Decrypted PII is usually in JSON format.
  • All encryption algorithms are listing in Secret Algorithm in GTR.

✍️ If you operate as a Travel Rule Service Provider(TRSP) just as GTR, you shouldn't and you can't decrypt PII payload on behalf of your VASP clients.

Your VASP client should always self-custody their Private Key and do the decryption by themselves.

2. Identify the PII Version and deserialize it to structure

  • Parse decrypted PII into PII Data Structure
  • piiSecuredInfo.piiSpecVersion tells the exact PII specification version , if your system supports multiple PII specifications.
  • All PII specification version are listing in List of PII Spec Version.

3. Compare the Required PII / Supported PII Fields

  • Compare all the required PII and supported PII fields to the decrypted payload.
  • Add PII field matching result to the verifyFields of response body.
  • the type should refer to the PII Verify Fields, and using the VerifyFields ID as the value of type, and the status: 1: matched, 2: mismatch, 3: not support.
  • In the pre-transaction travel rule: beneficiary VASP perspective, it could be possible that you need to collect the originator info as required, but you cannot verify it. Fields in this kind of situation should use: 4: INFO_INSUFFICIENT or 5: INFO_EXISTS to reply.
  • Just to verify all the fields that you can verify, DO NOT use initiatorExpectedVerifyFields.
  • For the matching method, please refer to the: PII Verify Fields and PII Verify Methods
Field NameVerifyFields IDRequiredSupported Verify
Beneficiary Legal Person Name111001YesYes
Beneficiary Country of Registration111022NoYes
Beneficiary Natural Person National ID110045NoNo
Originator Country of Registration101022YesNo
Originator Natural Person Address - Address Lines100031YesNo
"verifyFields": [
{
"message": "matched (success)",
"status": 1, // (SUCCESS)
"type": "111001" // Beneficiary Legal Person Name
},
{
"message": "mismatch (failed)",
"status": 2, // (FAILED)
"type": "111022" // Beneficiary Country of Registration
},
{
"message": "not support",
"status": 3, // (NOT SUPPORT)
"type": "110045" // Beneficiary Natural Person National ID
},
{
"message": "info missing",
"status": 4, // <-- you need originator info but insufficient (FAILED)
"type": "100031" // Originator Natural Person Address - Address Lines
},
{
"message": "info exists (success)",
"status": 5, // <-- you need originator info and it provided (SUCCESS)
"type": "101022" // Originator Country of Registration
}
]

4. Decide the final result

Final result of PII Verification is decided by you based on your compliance requirement.

For example:

Field NameVerifyFields IDYour Compliance RequiredYou Support Validation
Beneficiary Legal Person Name111001YesYes
Beneficiary Country of Registration111022YesYes
Beneficiary Natural Person National ID110045NoNo
Originator Country of Registration101022YesNo
Originator Natural Person Address - Address Lines100031YesNo

✍️ You should focus on the Your Compliance Required fields so you can give the final result based on the matching status of these fields.

5. Understand the direction

IVMS Payload contains the PII info of both Originator Person and Beneficiary Person. To decide which person's PII is the one you should validate, you can use the verificationDirection in the request body:

  • if verificationDirection = 2: this is a Pre-transaction Travel Rule situation. So, you, as the Travel Rule Receiver VASP, also serves as a Beneficiary VASP. You should validate the Beneficiary person in the IVMS payload with your in-house KYC data of your customers.
  • if verificationDirection = 1: this is a Post-transaction Travel Rule situation. So, you, as the Travel Rule Receiver VASP, also serves as an Originator VASP. You should validate the Originator person in the IVMS payload with your in-house KYC data of your customers.

6. Put your company info into PII and encrypt again

  • You're required to fill in your company info into OriginatorVASP or BeneficiaryVASP of IVMS payload and encrypt again.
  • Encrypt PII payload data by your self-hosted Private Key and the piiSecuredInfo.initiatorPublicKey.
  • Put the encrypted data into securedPayload of the response.
  • You should also fill in the secretAlgorithm and piiSpecVersion which is same as the request body.

If verificationDirection=1, it means you should fill your VASP's entity info to OriginatorVASP structure.

{
"ivms101": {
... keep original data ...
"OriginatingVASP": {
"originatingVASP": {
// required
"legalPerson": {
// required, nameIdentifier*, localNameIdentifier, phoneticNameIdentifier
"name": {
"nameIdentifier": [
{
"legalPersonName": "Originator VASP Company Name - VVVV Inc.",
"legalPersonNameIdentifierType": "LEGL" // Usually Fixed as LEGL // for legal person: LEGL, SHRT, TRAD
}
]
},
// required, For Company Legal Person use RAID and fill your company ID in nationalIdentifier
"nationalIdentification": {
// nationalIdentifierType: ISO20022, ARNU, CCPT, RAID, DRLC, FIIN, TXID, SOCS, IDCD, LEIX, MISC,
"nationalIdentifierType": "RAID",
// registrationAuthority: GLEIF code (i.e: 香港公司註冊處核發 Hong Kong Company Registry Approved, For more please check: https://www.gleif.org/en/about-lei/code-lists/gleif-registration-authorities-list)
"registrationAuthority": "RA000388",
// countryOfIssue: ISO 3166-1 alpha-2 codes
"countryOfIssue": "HK",
// nationalIdentifier: (i.e: Your Company ID from authority)
"nationalIdentifier": "38429049028390482"
},
// required
"geographicAddress": [
{
// required
"country": "HK", // ISO 3166-1 alpha-2 codes
"townName": "Hong Kong",
"addressType": "GEOG", // HOME, BIZZ, GEOG
"addressLine": ["Please fill your address here"],

// optional:
"department": "OfficeOfTheCEO",
"subDepartment": "InternalAudit8562",
"streetName": "SiliconAlley65",
"buildingNumber": "J4H6",
"buildingName": "VirtualTower200",
"floor": "Floor94",
"postBox": "CB842",
"room": "BionicRoom38",
"postCode": "TT7643",
"townLocationName": "E-Sector",
"districtName": "BlockchainDistrict",
"countrySubDivision": "E-Province"
}
],
// required
"countryOfRegistration": "HK"
}
}
},

If verificationDirection=2, it means you should fill your VASP's entity info into BeneficiaryVASP part.

{
"ivms101": {
... keep original data ...
"BeneficiaryVASP": {
"beneficiaryVASP": {
// required
"legalPerson": {
// required, nameIdentifier*, localNameIdentifier, phoneticNameIdentifier
"name": {
"nameIdentifier": [
{
"legalPersonName": "Beneficiary VASP Company Name - VVVV Inc.",
"legalPersonNameIdentifierType": "LEGL" // Usually Fixed as LEGL // for legal person: LEGL, SHRT, TRAD
}
]
},
// required, For Company Legal Person use RAID and fill your company ID in nationalIdentifier
"nationalIdentification": {
// nationalIdentifierType: ISO20022, ARNU, CCPT, RAID, DRLC, FIIN, TXID, SOCS, IDCD, LEIX, MISC,
"nationalIdentifierType": "RAID",
// registrationAuthority: GLEIF code (i.e: 香港公司註冊處核發 Hong Kong Company Registry Approved, For more please check: https://www.gleif.org/en/about-lei/code-lists/gleif-registration-authorities-list)
"registrationAuthority": "RA000388",
// countryOfIssue: ISO 3166-1 alpha-2 codes
"countryOfIssue": "HK",
// nationalIdentifier: (i.e: Your Company ID from authority)
"nationalIdentifier": "38429049028390482"
},
// required
"geographicAddress": [
{
// required
"country": "HK", // ISO 3166-1 alpha-2 codes
"townName": "Hong Kong",
"addressType": "GEOG", // HOME, BIZZ, GEOG
"addressLine": ["Please fill your address here"],

// optional:
"department": "OfficeOfTheCEO",
"subDepartment": "InternalAudit8562",
"streetName": "SiliconAlley65",
"buildingNumber": "J4H6",
"buildingName": "VirtualTower200",
"floor": "Floor94",
"postBox": "CB842",
"room": "BionicRoom38",
"postCode": "TT7643",
"townLocationName": "E-Sector",
"districtName": "BlockchainDistrict",
"countrySubDivision": "E-Province"
}
],
// required
"countryOfRegistration": "HK"
}
}
},

7. Preflight Check Status

  • Only when your VASP serves as the Beneficiary VASP, you can tell the originator whether you will decide to receive the funds by filling the field preflightCheckStatus.
  • If you are the Originator VASP, you could just simply reply preflightCheckStatus as NONE.
  • For preflightCheckStatus, it can be one of:
    • NONE
    • NOT_SUPPORT
    • SKIPPED
    • ACCEPTED
    • PENDING
    • REJECTED
{
...
"preflightCheckStatus": "ACCEPTED",
"preflightCheckMessage": "will accept",
}

Response

Once you go through above PII Matching steps, GTR expect to receive your response as below. GTR will treat this callback request as Timeout if no response from your server in 2 seconds.

{
"data": {
"verifyFields": [
{
"message": "matched (success)",
"status": 1,
"type": "111001"
},
{
"message": "mismatch (failed)",
"status": 2,
"type": "111022"
},
{
"message": "not support",
"status": 3,
"type": "110045"
},
{
"message": "info missing",
"status": 4, // <-- you need originator info but insufficient (FAILED)
"type": "100031" // Originator Natural Person Address - Address Lines
},
{
"message": "info exists (success)",
"status": 5,
"type": "101022"
}
],
"piiSecuredInfo": {
"initiatorKeyInfo": {
"publicKey": "[COUNTER_PARTY_VASP_PUBLIC_KEY]"
},
"receiverKeyInfo": {
"publicKey": "[YOUR_PUBLIC_KEY]"
},
"piiSecretFormatType": "FULL_JSON_OBJECT_ENCRYPT",
"piiSpecVersion": "ivms101-2020",
"secretAlgorithm": "ed25519_curve25519",
"securedPayload": "[Encrypted PII, clear-text is forbidden]"
}
},
"preflightCheckStatus": "ACCEPTED",
"preflightCheckMessage": "will accept",
"verifyMessage": "Verification Success" or "Verification Failed",
"verifyStatus": 100000 or 200003
}

Response A: Pass

{
"data": {
// ...same as above
},
"verifyMessage": "Verification Success",
"verifyStatus": 100000
}

Response B: Fail

If one of required field failed, mismatch or info missing, then result as:

{
"data": {
// ...same as above
},
"verifyMessage": "Verification Failed",
"verifyStatus": 200003
}