Send outbound Travel Rule message

Learn how to submit compliant and secure outbound messages.

An outbound Travel Rule transaction is the process of data exchange between VASPs that precedes sending virtual assets (VA) from one entity to another. To make a VA transfer on behalf of the originator, first you need to create an outbound Travel Rule message for each corresponding blockchain transaction.

How processing of outbound Travel Rule messages works

Before creating a blockchain transaction, you need to send an outbound Travel Rule message and complete data exchange with the beneficiary VASP. This process includes the following steps:

  1. You need to install the rules that initiate the Travel Rule checks and let you act on the results.
  2. Then you must send Sumsub a Travel Rule message with all its data, including:
    • Information about the originator and the originating VASP.
    • Information about the expected beneficiary and, if known, the beneficiary VASP.
  3. Once you have sent all the data and set the rules, Sumsub performs beneficiary VASP attribution to identify the beneficiary VASP:
  4. You can track the data transfer status in the Transactions and Travel Rule -> Transactions section to see the status of your Travel Rule message. At this stage, you can get one of the following statuses:
    • If the system did not find the beneficiary VASP, you will see the counterpartyVaspNotFound status.
    • If the beneficiary VASP does not support the Sumsub protocols, you will see the counterpartyVaspNotReachable status.
  5. If the beneficiary VASP is identified, Sumsub asks them for the confirmation of the Travel Rule message details.
    Beneficiary VASP needs to confirm that the beneficiary wallet address belongs to them in order to protect personal information from being shared with unauthorised entities. After that, we ask to confirm relevant Personally Identifiable Information (PII):
    • If the beneficiary VASP did not respond within the expected timeframe, you will see the expired status.
    • If the beneficiary VASP confirms that the wallet address does not belong to them, you will see the counterpartyUnconfirmedOwnership status.
    • If the beneficiary VASP reports a mismatch in the data, you will see the counterpartyMismatchedData status.
  6. Based on the rules you installed and the beneficiary VASP response, the outbound message gets the Approved, Rejected, or Put on hold status.
  7. Sumsub sends a webhook indicating the message status to your compliance team.

Send outbound Travel Rule message

The following is a sequence of steps to be taken to send an outbound Travel Rule message.

Step 1: Enable required rules

To apply the Travel Rule solution to the outbound messages, do the following:

  1. In the Dashboard, open the Rules Library.
  2. Select the Travel Rule bundle and install the rules.

We recommend installing all the rules available in the bundle, as it is the quickest and easiest way to cover all of the check steps.

📘

Note

The rules you install remain in Test mode until you activate them.

You can also activate a rule bundle specific to your jurisdiction (EU, UK, Singapore, etc).

Step 2: Set up timeout timers

You can specify the time period during which you want to receive the Travel Rule message data from the beneficiary VASP. You can also set up conditions on how to process messages that are not accompanied with any Travel Rule data after the selected period of time:

  1. In the Dashboard, open the Transactions and Travel Rule section, go to Settings, and choose Confirmation Timeout.
  2. To set up the desired conditions for a message, select the threshold and how to treat the data.
  3. To apply the set parameters, click Save.

Step 3: Generate app token

Once you have installed and enabled the rules, you will need to generate an app token to sign your API calls. For more information on how to generate a token, refer to this article.

Step 4: Send Travel Rule message

After completing the setup of the desired conditions and signing your API calls, you will be able to send a Travel Rule message.

To send the Travel Rule message, you can use any of the following API methods:

See the following examples:

curl -X POST \
  'https://api.sumsub.com/resources/applicants/67a0ec0b9aa0951851d627ef/kyt/txns/-/data' \
  -H 'Content-Type: application/x-ndjson' \
  -d $'{
	"txnId": "b4xdq4qjh5qpo06r8cpunc",
	"type": "travelRule",
	"applicant": {
	  "type": "individual",
	  "nameType": "birthName",
	  "dob": "1992-05-08",
	  "placeOfBirth": "Paris, France",
	  "address": {
		"country": "FRA",
		"town": "Paris",
		"postCode": "75001",
		"street": "Rue de Rivoli",
		"subStreet": "1"
	  },
	  "idDoc": {
		"number": "1234567",
		"country": "FRA",
		"idDocType": "PASSPORT",
		"registrationAuthority": "Ille-de-France 01"
	  },
	  "residenceCountry": "FRA",
	  "paymentMethod": {
		"type": "account",
		"accountId": "1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa"
	  },
	  "institutionInfo": {},
	  "firstName": "",
	  "lastName": ""
	},
	"counterparty": {
	  "externalUserId": "rwopmrnkuaob6d9ettn8",
	  "firstName": "Jack",
	  "lastName": "Posek",
	  "nameType": "birthName",
	  "type": "individual",
	  "dob": "1991-04-07",
	  "placeOfBirth": "Berlin, Germany",
	  "address": {
		"country": "DEU",
		"town": "Berlin",
		"postCode": "10115",
		"street": "Chauseestr.",
		"subStreet": "60"
	  },
	  "idDoc": {
		"number": "65434543",
		"country": "DEU",
		"idDocType": "PASSPORT",
		"registrationAuthority": "BerlinMitte"
	  },
	  "residenceCountry": "DEU",
	  "paymentMethod": {
		"type": "",
		"accountId": "bcаfdhgj86pxvf5nk45353xecdrw6nrx3zzy9xl7q",
		"memo": "3213"
	  },
	  "institutionInfo": {
		"internalId": "645a5a60294c3b043c84594f"
	  }
	},
	"info": {
	  "direction": "out",
	  "amount": 0.01,
	  "currencyCode": "BTC",
	  "type": ""
	},
	"props": {
	  "customProperty": "Custom value that can be used in rules"
	},
	"txnDate": "2025-01-30 11:41:55+0000"
  }'
curl -X POST \
  'https://api.sumsub.com/resources/kyt/misc/txns/import' \
  -H 'Content-Type: application/x-ndjson' \
  -d $'{
	"txnId": "b4xdq4qjh5qpo06r8cpunc",
	"type": "travelRule",
	"applicant": {
	  "type": "individual",
	  "nameType": "birthName",
	  "dob": "1992-05-08",
	  "placeOfBirth": "Paris, France",
	  "idDoc": {
		"number": "1234567",
		"country": "FRA",
		"idDocType": "PASSPORT",
		"registrationAuthority": "Ille-de-France 01"
	  },
	  "residenceCountry": "FRA",
	  "paymentMethod": {
		"accountId": "1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa"
	  },
	  "institutionInfo": {},
	  "firstName": "",
	  "lastName": ""
	},
	"counterparty": {
	  "externalUserId": "rwopmrnkuaob6d9ettn8",
	  "firstName": "Jack",
	  "lastName": "Posek",
	  "nameType": "birthName",
	  "type": "individual",
	  "dob": "1991-04-07",
	  "placeOfBirth": "Berlin, Germany",
	  "idDoc": {
		"number": "65434543",
		"country": "DEU",
		"idDocType": "PASSPORT",
		"registrationAuthority": "BerlinMitte"
	  },
	  "residenceCountry": "DEU",
	  "paymentMethod": {
		"accountId": "bcаfdhgj86pxvf5nk45353xecdrw6nrx3zzy9xl7q",
		"memo": "3213"
	  },
	  "institutionInfo": {
		"internalId": "645a5a60294c3b043c84594f"
	  }
	},
	"info": {
	  "direction": "out",
	  "amount": 0.01,
	  "currencyCode": "BTC",
	  "type": ""
	},
	"txnDate": "2025-01-30 11:41:55+0000"
  }\n{
	"txnId": "b4xdq6544qjh5qpo06r8cpunc",
	"type": "travelRule",
	"applicant": {
	  "type": "individual",
	  "nameType": "birthName",
	  "dob": "1992-05-08",
	  "placeOfBirth": "Paris, France",
	  "idDoc": {
		"number": "1234567",
		"country": "FRA",
		"idDocType": "PASSPORT",
		"registrationAuthority": "Ille-de-France 01"
	  },
	  "residenceCountry": "FRA",
	  "paymentMethod": {
		"accountId": "1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa"
	  },
	  "institutionInfo": {},
	  "firstName": "",
	  "lastName": ""
	},
	"counterparty": {
	  "externalUserId": "rwopmrnkuaob6d9ettn8",
	  "firstName": "Jack",
	  "lastName": "Posek",
	  "nameType": "birthName",
	  "type": "individual",
	  "dob": "1991-04-07",
	  "placeOfBirth": "Berlin, Germany",
	  "idDoc": {
		"number": "65434543",
		"country": "DEU",
		"idDocType": "PASSPORT",
		"registrationAuthority": "BerlinMitte"
	  },
	  "residenceCountry": "DEU",
	  "paymentMethod": {
		"accountId": "bcаfdhgj86pxvf5nk45353xecdrw6nrx3zzy9xl7q",
		"memo": "3213"
	  },
	  "institutionInfo": {
		"internalId": "645a5a60294c3b043c84594f"
	  }
	},
	"info": {
	  "direction": "out",
	  "amount": 0.03,
	  "currencyCode": "BTC",
	  "type": ""
	},
	"txnDate": "2025-01-30 12:41:55+0000"
  }'

Step 5: Receive webhook

Once you have sent a Travel Rule message, you will receive one of the following webhooks:

These webhooks indicate the status of the message after checking the transfer against the installed rules.

If the beneficiary VASP has confirmed the Travel Rule message, your message will get the approved status, and you will receive the applicantKytTxnApproved webhook. In this case, proceed to the next step.

{
  "applicantId": "634829375766b80001a40152",
  "applicantType": "individual",
  "correlationId": "f24f6616020245053139a6537303a251",
  "sandboxMode": false,
  "externalUserId": "customExternalUserId",
  "type": "applicantKytTxnApproved",
  "reviewResult": {
    "reviewAnswer": "GREEN"
  },
  "reviewStatus": "completed",
  "createdAt": "2025-01-30 11:41:55+0000",
  "createdAtMs": "2025-01-30 11:41:55+0000",
  "clientId": "coolClientId",
  "kytTxnId": "64a7dc05fbf57c624afcb72d",
  "kytDataTxnId": "b4xdq4qjh5qpo06r8cpunc",
  "kytTxnType": "travelRule"
}

If you receive the applicantKytOnHold webhook, your message has been suspended and queued for manual review by the dedicated compliance officer:

{
  "applicantId": "634829375766b80001a40152",
  "applicantType": "individual",
  "correlationId": "98d4dac61c977c1b3f81d6ab78d29c3c",
  "sandboxMode": false,
  "externalUserId": "customExternalUserId",
  "type": "applicantKytOnHold",
  "reviewStatus": "onHold",
  "createdAt": "2025-01-30 11:41:55+0000",
  "createdAtMs": "2025-01-30 11:41:55+0000",
  "clientId": "coolClientId",
  "kytTxnId": "64a7dc05fbf57c624afcb72d",
  "kytDataTxnId": "b4xdq4qjh5qpo06r8cpunc",
  "kytTxnType": "travelRule"
}

If your message has not been confirmed, it gets the rejected status, and you will receive the applicantKytTxnRejected webhook:

{
  "applicantId": "634829375766b80001a40152",
  "applicantType": "individual",
  "correlationId": "0f5a7c828bab750775564534fc0470a8",
  "sandboxMode": false,
  "externalUserId": "customExternalUserId",
  "type": "applicantKytTxnRejected",
  "reviewResult": {
    "reviewAnswer": "RED",
    "reviewRejectType": "FINAL"
  },
  "reviewStatus": "completed",
  "createdAt": "2025-01-30 11:41:55+0000",
  "createdAtMs": "2025-01-30 11:41:55+0000",
  "clientId": "coolClientId",
  "kytTxnId": "64a7dc05fbf57c624afcb72d",
  "kytDataTxnId": "b4xdq4qjh5qpo06r8cpunc",
  "kytTxnType": "travelRule"
}

Step 6: Update blockchain transaction details

To complete the Travel Rule process, submit your transaction to the blockchain. After the blockchain confirmation, retrieve the blockchain hash and use it to update the Travel Rule message via this API method.

An example of a request to update the message:

curl -X PATCH \
     'https://api.sumsub.com/resources/kyt/txns/66cd891eefa135789ce5264f/data/info' \
     -H 'content-type: application/json' \
     -d '{ "paymentTxnId": "3213654zdrgsetrr51435ergh453t5z43rb" }'

After the data exchange, the Travel Rule message will get the completed status. Once you have updated the blockchain transaction ID, you will see the finished data exchange status, indicating the closing of the blockchain transaction.