Skip to main content
Search

One Step Travel Rule Verification

This POST /api/verify/v2/one_step API provides a unified way for Travel Rule Initiator VASP to initiate a Travel Rule request in 2 situations: Pre-transaction Travel Rule and Post-transaction Travel Rule.

For further details of this endpoint, see API Reference: /api/verify/v2/one_step

TypeDescription & ResponsibilityYour Role
Pre-transaction Travel Rule- The transaction has not yet been submitted to the blockchain.
- This is usually part of a Withdrawal process.
- Your VASP is responsible for preparing and sending the PII payload to the Beneficiary VASP before you execute this transfer on the blockchain.
Originator VASP
Post-transaction Travel Rule- The transaction has already been recorded on the blockchain.
- This is usually part of a Deposit process.
- Your VASP is responsible for preparing and sending the PII payload to the Originator VASP after you receive this transfer from blockchain.
Beneficiary VASP

In different situations, your Travel Rule requests will go through different verification steps (Stage).

TypeVerification Steps (Stage)
Pre-transaction Travel Rule1. Address Verification
2. PII Verification
Post-transaction Travel Rule1. TX ID Verification
2. PII Verification

✍️ Your PII payload will be put on hold until your counterparty reply PASS to the 1st verification step. If they respond FAIL, your encrypted PII payload will not be sent to them.

To know which stage the failure you receive comes from, please refer to Verify Status.

Initiate Pre-transaction Travel Rule with One-Step

✍️ Before crypto assets transferred onto blockchain, this API should be invoked as part of your withdrawal process.

Request & Response

curl --silent --location --request POST "/api/verify/v2/one_step" \
--cert-type P12 --cert ./certificate.p12:'[MY_PASSWORD_OF_CERT]' \
--header 'Content-Type: application/json' \
--header "Authorization: Bearer [YOUR LOGIN TOKEN]" \
--header "Connection: keep-alive" \
--data-raw "{
\"requestId\": \"[REQUEST ID]\",
\"network\": \"[NETWORK NAME]\",
\"address\": \"[Beneficiary Address]\",
\"tag\": \"[TAG]\",
\"txId\": null, // In pre-transaction travel rule, this will be null
\"verifyDirection\": 2, // 2: Sender-to-receiver (Pre-transaction Travel Rule)
\"targetVaspCode\": \"[TARGET_VASP_CODE]\",
\"ticker\": \"[TICKER NAME]\",
\"amount\": \"[CRYPTO TRANSFER AMOUNT: 0, 0.3, 1200000]\",
\"fiatName\": \"[FIAT NAME: USD/USDT/EUR/GBP...]\",
\"fiatPrice\": \"[FIAT RATIO PRICE]\",
\"sourceVaspCode\": \"[IF YOU ON-BEHALF SOMEONE INIT THIS REQUEST, PLEASE FILL IT THEM ID (Normally you don't need it, leave it blank if you're not vendor company)]\",
\"expectVerifyFields\": [\"110026\",\"110025\",\"110045\"],
\"piiSecuredInfo\": {
\"initiatorKeyInfo\": {
\"publicKey\": \"[MY_PUBLIC_KEY]\"
},
\"piiSecretFormatType\": \"[TARGET_PII_SECRET_FORMAT_TYPE]\",
\"piiSpecVersion\": \"[TARGET_PII_SPEC_VERSION]\",
\"receiverKeyInfo\": {
\"publicKey\": \"[THEIR_PUBLIC_KEY]\"
},
\"secretAlgorithm\": \"[TARGET_ALGORITHM]\",
\"securedPayload\": \"[PII (encrypted)]\"
}
}"

Details of these parameters (same as Post-transaction travel rule):

  • verifyDirection: specify it as 2 in the Pre-transaction Travel Rule. However in Post-transaction Travel Rule, set it as 1.
  • amount: the amount of crypto currency, for example: 0.01 (for BTC), should not be empty, at least to be: 0, (Reference: Longest AVAX should be decimal(28,18) / numeric(28,18))
  • ticker: the name(symbol) of crypto currency, the list could refer to: List of ticker
  • network: the network name or chain symbol, the list could refer to: List of network
  • address: the address of the beneficiary
  • tag: beneficiary address tag (memo). the tag is optional, if the network chain requires the tag like (XRP, XLM, TRX), then this is necessary.
  • piiSecuredInfo: the PII information to be sent
    • piiSecretFormatType: support for FULL_JSON_OBJECT_ENCRYPT, JSON_FIELD_ENCRYPT or JSON_FIELD_HASH, if you're not using any library provided by GTR, please consider to use FULL_JSON_OBJECT_ENCRYPT as default encryption method.
    • initiatorKeyInfo: only bring your public key information here, do not bring any private key or sensitive information. according to the algorithm to select corresponding public key.
    • receiverKeyInfo: the counter-party VASP's public key that selected in the previous api: vaspDetail.
    • secretAlgorithm: the encryption algorithm, support for ED25519_CURVE25519 and more, please refer to: Secret Algorithm in GTR
    • piiSpecVersion: the version of the PII specification, please refer to: List of PII Specification Version
    • secretPayload: the encrypted PII information, the format is base64 encoded string. (If the library already encrypted, don't do it again), current max of length is 60000 bytes.
    • In Post-transaction travel rule, you should put your VASP's company info in IVMS BeneficiaryVASP and put your user to Beneficiary. In Pre-transaction travel rule, you should put your company info to OriginatingVASP and put your user to Originator in the IVMS.
  • requestId: the unique identifier for the transaction request, should generate from your service, the format is recommend to be "[YOUR_EXCHANGE_NAME]-[UUID_v4]", and this requestId will also pass to the counter-party VASP's system as well
  • fiatName: the name of fiat currency, it's ok to use different currency like: EUR/USD/HKD...etc, could also using USDT stable coin, whatever the fiatPrice or amount is zero or not, should set the field name default to USD.
  • fiatPrice: the price of the crypto currency in fiat currency, for example: 10000 (for 10000 USD), should not be empty, at least to be: 0
  • txId: the transaction id of the crypto asset transfer, In the pre-transaction travel rule, this should be null and updated later via Notify TXID. In the post-transaction travel rule, this should be necessary.
  • expectVerifyFields: the fields that you want to verify and get the result from response (or callback), the list of fields id can refer to: PII Verify Fields

You can expect to receive a response like:

{
"data": {
"targetVaspCode": "[TARGET_VASP_CODE]",
"requestId": "[REQUEST ID]",
"verifyFields": [
{
"message": "matched",
"status": 1, // matched
"type": "111006" // Beneficiary Natural Person Name
},
{
"message": "date of birth mismatch",
"status": 2, // not matched
"type": "111025" // Beneficiary Natural Person Date of birth
},
{
"message": "not support",
"status": 3, // not Support
"type": "110029" // Beneficiary Natural Person Name
},
{
"message": "place of birth missing",
"status": 4, // info missing
"type": "100024" // Originator Natural Person place of birth
},
{
"message": "date of birth exists",
"status": 5, // info exists
"type": "100025" // Originator Natural Person Date of birth
}
],
"piiSecuredInfo": {
"initiatorKeyInfo": {
"publicKey": "[MY_PUBLIC_KEY]"
},
"piiSecretFormatType": "[TARGET_PII_SECRET_FORMAT_TYPE]",
"piiSpecVersion": "[TARGET_PII_SPEC_VERSION]",
"receiverKeyInfo": {
"publicKey": "[THEIR_PUBLIC_KEY]"
},
"secretAlgorithm": "[TARGET_ALGORITHM]",
"securedPayload": "[PII From Beneficiary]"
}
},
"verifyMessage": "Verification Success",
"verifyStatus": 100000,
"verifyStage": "PII_VERIFICATION"
}

ExpectVerifyFields & VerifyFields

You should always set the expectVerifyFields in the request body based on your VASP's compliance requirement, as an Originator VASP.

For example, as an Originator VASP, if your compliance requirement is to verify the beneficiary's PII as:

Field NameVerifyFields IDRequired
Beneficiary Legal Person Name111001Yes
Beneficiary Country of Registration111022Yes
Beneficiary Natural Person National ID110045No

Then you should set the expectVerifyFields in the request body as:

{
"expectVerifyFields": [
"111001", // Beneficiary Legal Person Name
"111022", // Beneficiary Country of Registration
"110045" // Beneficiary Natural Person National ID
]
}

For the full list of Verify Fields, you can refer to: PII Verify Fields

In the response body, matching result from your counterparty will return to you via the verifyFields:

{
...
"verifyFields": [
{
"message": "matched",
"status": 1, // matched
"type": "111006" // Beneficiary Natural Person Name
},
{
"message": "date of birth mismatch",
"status": 2, // not matched
"type": "111025" // Beneficiary Natural Person Date of birth
},
{
"message": "not support",
"status": 3, // not Support
"type": "110029" // Beneficiary Natural Person Name
},
{
"message": "place of birth missing",
"status": 4, // info missing
"type": "100024" // Originator Natural Person place of birth
},
{
"message": "date of birth exists",
"status": 5, // info exists
"type": "100025" // Originator Natural Person Date of birth
}
]
...
}

For each verifyFields.status

Status Enum CodeStatus EnumDescription
0SKIPYou specified this field to be verified viaexpectVerifyFields, but your counterparty skipped it for some reason.

In simple words, you can treat this as a Skip.
1MATCH / PASSYou specified this field to be verified via expectVerifyFields and your counterparty confirmed the verification result is a true match.

In simple words, you can treat this as a Success.
2MISMATCHYou specified this field to be verified viaexpectVerifyFields and your counterparty confirmed the verification result is a mismatch.

In simple words, you can treat this as a Failed.
3NOT_SUPPORTYou specified this field to be verified viaexpectVerifyFields but your counterparty neither expects this field nor supports to validate it.

In simple words, you can treat this as a Skip.
4INFO_MISSINGYou didn't include this field but your counterparty expects to receive it.

In simple words, you can treat it as a Warning.
5INFO_EXISTSYou specified this field to be verified viaexpectVerifyFields but your counterparty can only confirm they received it as non-empty however they can't further validate it.

In simple words, you can treat this as a Success.

The verifyFields in the response may return more fields than what expectVerifyFields included in the request body and this is because your counterparty VASP may have to follow different regulatory advise in their jurisdiction.

✍️ You can focus on the matching result of the fields you specified in the expectVerifyFields and ignore the others. This should help you to meet your minimum compliance requirement.

For example, you may receive verifyFields like:

...
[
{
"message": "matched",
"status": 1, // matched
"type": "111006" // Beneficiary Natural Person Name
},
{
"message": "date of birth mismatched",
"status": 2, // not matched
"type": "111025" // Beneficiary Natural Person Date of birth
},
{
"message": "not support",
"status": 3, // NOT SUPPORT
"type": "110029" // Beneficiary Natural Person Name
},
{
"message": "place of birth info missing",
"status": 4, // info missing
"type": "100024" // Originator Natural Person place of birth
},
{
"message": "date of birth exists",
"status": 5, // info exists
"type": "100025" // Originator Natural Person Date of birth
}
]
...
Field NameVerifyFields IDStatusRequired From You?Required From Your VASP?
Beneficiary Natural Person Name111006MATCHED: 1YesYes
Beneficiary Natural Person Date of birth111025MISMATCH: 2YesNo
Beneficiary Natural Person Name110029NOT_SUPPORT: 3NoNo
Originator Natural Person place of birth100024INFO_MISSING: 4NoYes
Originator Natural Person Date of birth100024INFO_EXISTS: 5NoYes

As GTR suggested, you can digest verifyFields and only check the matching results of fields you specified in the expectVerifyFields. Then, you can make your own final decision to continue your user's withdrawal process or reject it.

const originatorRequiredFieldIds = ["111006", "111025"]

let decideToTransfer = true
for(let fieldId of originatorRequiredFieldIds) {
let found = false;
for(let fieldResult of response.verifyFields) {
if(fieldResult.type == fieldId) {
found = true
switch(fieldResult.status) {
case 2: // mismatch
decideToTransfer = false
break;
}
break;
}
}
// not found in field results
if(!found) {
decideToTransfer = false
}
}

Initiate Post-transaction Travel Rule with One-Step

✍️ After crypto assets received from blockchain, this API could be invoked as part of your deposit process.

Request & Response

curl --silent --location --request POST "/api/verify/v2/one_step" \
--cert-type P12 --cert ./certificate.p12:'[MY_PASSWORD_OF_CERT]' \
--header 'Content-Type: application/json' \
--header "Authorization: Bearer [YOUR LOGIN TOKEN]" \
--header "Connection: keep-alive" \
--data-raw "{
\"requestId\": \"[REQUEST ID]\",
\"network\": \"[NETWORK NAME]\",
\"address\": \"[Beneficiary Address (TO ADDRESS): *Check note 1]\",
\"tag\": \"[TAG]\",
\"txId\": \"[REQUIRED]\", // In case of Post-transaction travel rule, this is required. Sample TXID: 0x570ea1e8026c7defa2d00bfabba73a8d3d51b23
\"verifyDirection\": 1, // 1: Receiver-to-sender (Post-transaction Travel Rule)
\"targetVaspCode\": \"[TARGET_VASP_CODE]\",
\"ticker\": \"[TICKER NAME]\",
\"amount\": \"[CRYPTO TRANSFER AMOUNT]\",
\"fiatName\": \"[FIAT NAME: USD/USDT/EUR/GBP...]\",
\"fiatPrice\": \"[FIAT RATIO PRICE]\",
\"sourceVaspCode\": \"[IF YOU ON-BEHALF SOMEONE INIT THIS REQUEST, PLEASE FILL IT THEM ID (Normally you don't need it, leave it blank if you're not vendor company)]\",
\"expectVerifyFields\": [\"100026\",\"100025\",\"100045\"],
\"piiSecuredInfo\": {
\"initiatorKeyInfo\": {
\"publicKey\": \"[MY_PUBLIC_KEY]\"
},
\"piiSecretFormatType\": \"[TARGET_PII_SECRET_FORMAT_TYPE]\",
\"piiSpecVersion\": \"[TARGET_PII_SPEC_VERSION]\",
\"receiverKeyInfo\": {
\"publicKey\": \"[THEIR_PUBLIC_KEY]\"
},
\"secretAlgorithm\": \"[TARGET_ALGORITHM]\",
\"securedPayload\": \"[PII (encrypted)]\"
}
}"

Details of these parameters are mostly same as Pre-transaction Travel Rule except:

  • verifyDirection: specify it as 1 in the Post-transaction Travel Rule.
  • address: this is your user's address (Beneficiary/ TO ADDRESS)
  • txId: specify the transaction id that you received from blockchain. In the post-transaction travel rule, this should be mandatory.

You will get following response:

{
"data": {
"targetVaspCode": "[TARGET_VASP_CODE]",
"requestId": "[REQUEST ID]",
"verifyFields": [
{
"message": "matched",
"status": 1, // matched
"type": "101006" // Originator Natural Person Name
},
{
"message": "date of birth matched",
"status": 2, // not matched
"type": "101024" // Originator Natural Person Date of birth
}
],
"piiSecuredInfo": {
"initiatorKeyInfo": {
"publicKey": "[MY_PUBLIC_KEY]"
},
"piiSecretFormatType": "[TARGET_PII_SECRET_FORMAT_TYPE]",
"piiSpecVersion": "[TARGET_PII_SPEC_VERSION]",
"receiverKeyInfo": {
"publicKey": "[THEIR_PUBLIC_KEY]"
},
"secretAlgorithm": "[TARGET_ALGORITHM]",
"securedPayload": "[PII From Beneficiary]"
}
},
"verifyMessage": "Verification Success",
"verifyStatus": 100000,
"verifyStage": "PII_VERIFICATION"
}

Travel Rule Request Pending

After you initiate the one-step request, you may receive a response with status verifyStatus:100002 at once. This means your request enters into a Travel Rule Pending Flow.

{
"verifyMessage": "Verification Success",
"verifyStatus": 100002,
"verifyStage": "ADDRESS_VERIFICATION"
}

💡 As of Nov 2025, Pending Flow is not widely adopted among GTR's API-automated clients. Most of GTR's members will reply verification result as Pass or Fail immediately.

For different Travel Rule scenario and different verifyStage:

ScenarioDescription
Pre-transaction Travel Rule- If you received ADDRESS_VERIFICATION, it means PII_VERIFICATION is not done yet by your counterparty VASP.
- If you received PII_VERIFICATION, it means ADDRESS_VERIFICATION has been completed by your counterparty VASP.
Post-transaction Travel Rule- If you received TRANSACTION_VERIFICATION, it means PII_VERIFICATION is not done yet by your counterparty VASP.
- If you received PII_VERIFICATION means TRANSACTION_VERIFICATION has been completed by your counterparty VASP.

If your request enters into a Travel Rule Pending Flow, GTR will call back to your service for any verification result within 72 hours. If time is up, GTR will still update you with an expired status.

For any Pending Flow Travel Rule requests, your Compliance team should make decision whether executing this asset transfer onto blockchain or not. However, GTR also have some implementation recommendations.

ScenarioGTR Recommendations
Pre-transaction Travel Rule [Withdrawal Process]GTR recommends you don't execute asset transfer onto blockchain if ADDRESS_VERIFICATION is failed or still pending. only if PII_VERIFICATION success or failed (depends if your compliance allow to make transfer without verification result) to send the assets.
Post-transaction Travel Rule [Deposit Process]We will recommend to have questionnaire and let the user select the brand to get vaspCode and do Post-transaction Travel Rule to verify the originator, it will hold the deposit. If you don't want to hold it, then another way is to let your user declare the questionnaire and save to your service.

Verify Status

  • 100000: Success
  • 100002: Pending
  • 200001: Address Not Found
  • 200007: TX ID Not Found
  • 200003: PII Verify Failed

* For 100002: Pending, there's only specific VASP that have pending flow will cause this result, if you're not support for pending flow to get address and PII verify results asynchronously, please treat as failed and remove from your list.

Other status codes:

  • 100001: Common Fail
  • 200002: Cannot Decrypt
  • 200006: Cannot Encrypt
  • 100006: GTR Server Failed
  • 100007: Originator Server Failed
  • 100008: Beneficiary Server Failed

* For the error handling details, please check Errors Handling & Retry.

Please note that the verifyStatus in the PII verification scenario will generally be represented by the following codes, and the codes can be conduct into the two different stage, first to verify address or TX ID, and then do the PII verification, it is sequential behaviour, if the first stage result failed, then will not go to the second stage.

First stage: Address or TX ID Verification

If you received the response with the following code, that means the first stage is not success.

  • 200001: Address Not Found
  • 200007: TX ID Not Found

Second stage: PII Verification

If you received the response with the following code, that means the first stage is success.

  • 100000: Success
  • 200003: Verify Failed

GTR Recommendation: Response Handling Process