Skip to content

Travel Rule Network Messaging Overview

Send partner-originated Travel Rule messages into CryptoSwift using Partner API messaging endpoints.

This page covers the Partner -> CryptoSwift direction: the partner network sends a Travel Rule message into CryptoSwift using the standardized Partner API. Partner network calls use the X-Partner-Api-Key header and dedicated /partners endpoints.

Workflow

StepEndpointPurpose
1. Resolve the beneficiary VASPGET /partners/vasps or GET /partners/vasps/by-walletSelect a verified VASP directly from the directory, or find one by wallet address, blockchain, and asset.
2. Deliver a Travel Rule messagePOST /partners/transactionsSend transaction metadata and encrypted IVMS101 payload to CryptoSwift for the selected verified VASP.
3. Update a Travel Rule messagePATCH /partners/transactions/{id}Add transaction hash or other message data that was missing when the Partner transaction was first delivered.

Partner Travel Rule messaging can be used in both pre-transaction and post-transaction flows.

Post-Transaction Flow

In a post-transaction flow, the on-chain transaction already exists when the Travel Rule message is sent. The partner usually only needs to call Deliver a Travel Rule message once with the transaction metadata, encrypted IVMS101 payload, and transaction hash.

Pre-Transaction Flow

In a pre-transaction flow, the partner can send the Travel Rule message before the on-chain transaction hash is available. Status updates from the receiving VASP on the CryptoSwift network, such as CONFIRMED or DECLINED, arrive asynchronously through Partner webhooks. If the transaction is then executed based on the beneficiary VASP response, the partner can call Update a Travel Rule Message to add the on-chain transaction hash.

Prerequisites

Before sending Travel Rule messages into CryptoSwift, make sure CryptoSwift has access to the originating VASP data from your network. This allows CryptoSwift to attach the required sender VASP details to incoming messages and validate the VASP identifier supplied in each Partner transaction request.

CryptoSwift also needs the partner network's VASP list with public keys so CryptoSwift can send Travel Rule messages back to your network and encrypt payloads for the correct receiving VASP. You can make this VASP directory and key material available through an API, an automated distribution pipeline, or a separate operational handoff agreed with CryptoSwift.

1. Resolve the Beneficiary VASP

Choose the lookup pattern that fits your integration. If your product already lets a user select the counterparty VASP by name, fetch the verified entity directory and send the message to the selected VASP. If your flow starts with wallet details, search for the verified VASP by wallet address instead.

Option A: List Verified Entities

Use GET /partners/vasps before creating a transaction so your network can resolve verified VASPs and retrieve the public key needed for encryption.

curl --location 'https://api-dev.cryptoswift.eu/partners/vasps' \
  --header 'X-Partner-Api-Key: <partner-api-key>'

Response:

[
  {
    "id": "14f4fb9d-4c69-5843-8b18-dbb77540182b",
    "name": "Acme Exchange",
    "legalName": "Acme Digital Assets LLC",
    "type": "VASP",
    "isVerified": true,
    "inNetwork": true,
    "updatedAt": "2026-06-02T10:00:00.000Z",
    "isRiskAssessed": true,
    "description": "Verified CryptoSwift network entity",
    "isMicaCompliant": true,
    "countries": [
      "US"
    ],
    "url": "https://acme.exchange",
    "publicKey": "<beneficiary VASP public key base64>"
  }
]

Use the entity id as beneficiaryVaspId and use publicKey as the receiver public key for the IVMS101 encryption handshake.

Option B: Search for a Verified Entity by Wallet Address

Use GET /partners/vasps/by-wallet when you have the beneficiary wallet details and want CryptoSwift to identify the verified VASP tied to that address.

Required query parameters:

ParameterTypeDescription
addressstringWallet address of the entity to find.
blockchainstringBlockchain name, for example Ethereum.
assetstringAsset symbol, for example ETH.
curl --location 'https://api-dev.cryptoswift.eu/partners/vasps/by-wallet?address=0x1234567890abcdef1234567890abcdef12345678&blockchain=Ethereum&asset=ETH' \
  --header 'X-Partner-Api-Key: <partner-api-key>'

Successful response:

{
  "id": "14f4fb9d-4c69-5843-8b18-dbb77540182b",
  "name": "Acme Exchange",
  "legalName": "Acme Digital Assets LLC",
  "type": "VASP",
  "isVerified": true,
  "inNetwork": true,
  "updatedAt": "2026-06-02T10:00:00.000Z",
  "isRiskAssessed": true,
  "description": "Verified CryptoSwift network entity",
  "isMicaCompliant": true,
  "countries": [
    "US"
  ],
  "url": "https://acme.exchange",
  "publicKey": "<beneficiary VASP public key base64>"
}

If the wallet is not tied to a verified VASP in CryptoSwift, the endpoint returns 404.

2. Deliver Travel Rule Messages

Use POST /partners/transactions to deliver a Partner -> CryptoSwift Travel Rule message for a verified beneficiary VASP. The request contains non-PII transaction metadata at the root level and the encrypted IVMS101 payload in the root-level ivms101 field.

Required fields:

FieldTypeDescription
assetstringAsset symbol used for the transaction.
amountnumberAmount of asset transferred.
blockchainInfoobjectBlockchain transaction details. destination is required inside this object.
ivms101stringEncrypted IVMS101 data.
originatorVaspIdstringOriginator VASP ID on the partner side.
originatorVaspPubKeystringOriginator VASP public key on the partner side.
beneficiaryVaspIdstringBeneficiary VASP ID on the CryptoSwift side.
{
  "asset": "BTC",
  "amount": 0.1,
  "blockchainInfo": {
    "transactionHash": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16",
    "origin": "origin-wallet-address",
    "destination": "destination-wallet-address",
    "destinationType": "CUSTODIAL",
    "blockchain": "Bitcoin"
  },
  "ivms101": "<base64 encrypted payload>",
  "originatorVaspId": "<originator VASP id>",
  "originatorVaspPubKey": "<originator VASP public key base64>",
  "beneficiaryVaspId": "<CryptoSwift beneficiary VASP id>",
  "createdAt": "2026-05-14T12:00:00.000Z"
}

createdAt is optional and is set automatically when omitted. originatorVaspPubKey must match the private key used to encrypt the IVMS101 payload.

Build and Encrypt the IVMS101 Payload

Before calling POST /partners/transactions, first create the plaintext IVMS101 payload with the required Originator and Beneficiary personal data. The plaintext object that gets encrypted must be wrapped inside an ivms101 root object:

{
  "ivms101": {
    "Originator": {
      "...": "..."
    },
    "Beneficiary": {
      "...": "..."
    }
  }
}

Encrypt this whole wrapper object, not only the inner Originator and Beneficiary values. The encrypted output is then base64 encoded and sent as the top-level ivms101 string in the Travel Rule message request.

Conceptually, before encryption, the transaction payload would look like this:

{
  "asset": "BTC",
  "amount": 0.1,
  "blockchainInfo": {
    "transactionHash": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16",
    "origin": "origin-wallet-address",
    "destination": "destination-wallet-address",
    "destinationType": "CUSTODIAL",
    "blockchain": "Bitcoin"
  },
  "ivms101": {
    "ivms101": {
      "Originator": {
        "...": "..."
      },
      "Beneficiary": {
        "...": "..."
      }
    }
  },
  "originatorVaspId": "<originator VASP id>",
  "originatorVaspPubKey": "<originator VASP public key base64>",
  "beneficiaryVaspId": "<CryptoSwift beneficiary VASP id>"
}

In the actual API request, the top-level ivms101 field must contain the encrypted base64 string instead of the plaintext object.

For the official IVMS101 data model and field definitions, see the interVASP IVMS101 documentation.

Example: Natural Persons

{
  "ivms101": {
    "Originator": {
      "originatorPersons": [
        {
          "naturalPerson": {
            "name": {
              "nameIdentifier": [
                {
                  "primaryIdentifier": "Coleman",
                  "secondaryIdentifier": "Thomas",
                  "nameIdentifierType": "LEGL"
                }
              ]
            },
            "dateAndPlaceOfBirth": {
              "dateOfBirth": "1964-05-13",
              "placeOfBirth": "US"
            },
            "customerIdentification": "AB9876521",
            "countryOfResidence": "US"
          }
        }
      ],
      "accountNumber": [
        "0x3e069aeac00a0b098fcf1310eea3ea9a940325d3"
      ]
    },
    "Beneficiary": {
      "beneficiaryPersons": [
        {
          "naturalPerson": {
            "name": {
              "nameIdentifier": [
                {
                  "primaryIdentifier": "Coins",
                  "secondaryIdentifier": "Linda",
                  "nameIdentifierType": "LEGL"
                }
              ]
            },
            "dateAndPlaceOfBirth": {
              "dateOfBirth": "1998-11-01",
              "placeOfBirth": "DE"
            },
            "customerIdentification": "DE52327832",
            "countryOfResidence": "DE"
          }
        }
      ],
      "accountNumber": [
        "0x05ff6964D21e5dAE3b1010D5AE0465b3c450F381"
      ]
    }
  }
}

Example: Legal Persons

{
  "ivms101": {
    "Originator": {
      "originatorPersons": [
        {
          "legalPerson": {
            "name": {
              "nameIdentifier": [
                {
                  "legalPersonName": "Coleman Digital Assets Inc.",
                  "legalPersonNameIdentifierType": "LEGL"
                }
              ]
            },
            "nationalIdentification": {
              "nationalIdentifier": "5493001KJTIIGC8Y1R12",
              "nationalIdentifierType": "LEIX"
            },
            "customerIdentification": "AB9876521",
            "countryOfRegistration": "US"
          }
        },
        {
          "naturalPerson": {
            "name": {
              "nameIdentifier": [
                {
                  "primaryIdentifier": "Coleman",
                  "secondaryIdentifier": "Thomas",
                  "nameIdentifierType": "LEGL"
                }
              ]
            }
          }
        }
      ],
      "accountNumber": [
        "0x3e069aeac00a0b098fcf1310eea3ea9a940325d3"
      ]
    },
    "Beneficiary": {
      "beneficiaryPersons": [
        {
          "legalPerson": {
            "name": {
              "nameIdentifier": [
                {
                  "legalPersonName": "Coins Treasury GmbH",
                  "legalPersonNameIdentifierType": "LEGL"
                }
              ]
            },
            "nationalIdentification": {
              "nationalIdentifier": "529900T8BM49AURSDO55",
              "nationalIdentifierType": "LEIX"
            },
            "customerIdentification": "DE52327832",
            "countryOfRegistration": "DE"
          }
        },
        {
          "naturalPerson": {
            "name": {
              "nameIdentifier": [
                {
                  "primaryIdentifier": "Coins",
                  "secondaryIdentifier": "Linda",
                  "nameIdentifierType": "LEGL"
                }
              ]
            }
          }
        }
      ],
      "accountNumber": [
        "0x05ff6964D21e5dAE3b1010D5AE0465b3c450F381"
      ]
    }
  }
}
Legal person payloads require a natural person

When the Originator or Beneficiary is a legal person, include a related natural person as well. This is usually the person initiating or receiving the transaction on behalf of the company, or a company representative such as a director or CEO, depending on the use case.

Because the originating and beneficiary VASPs are known to both networks and their public keys are shared separately, you do not need to include OriginatorVASP or BeneficiaryVASP objects inside the wrapped IVMS101 plaintext. You can include those objects optionally when your internal data model requires them, but CryptoSwift does not require them for this Partner API flow.

Encrypt the IVMS101 Payload

After creating the wrapped plaintext IVMS101 object, encrypt it before placing it into the Travel Rule message request.

Keys required:

KeyFormatPurpose
Originator VASP private keyBase64 encoded Ed25519 seed, 32 bytes after base64 decoding.Used to encrypt the IVMS101 payload.
Originator VASP public keyBase64 encoded Ed25519 public key.Sent as originatorVaspPubKey in the transaction request.
Beneficiary VASP CryptoSwift public keyRetrieved from CryptoSwift through the verified entity lookup endpoint.Used as the receiver public key for encryption.

Encrypt the wrapped IVMS101 payload using the originator VASP private key and the beneficiary VASP public key. Base64 encode the encrypted result and place it directly into the Travel Rule message payload as ivms101.

For implementation details, key conversion, nonce handling, and a Node.js/TypeScript helper, see the Message Encryption Protocol.

curl --location --request POST 'https://api-dev.cryptoswift.eu/partners/transactions' \
  --header 'X-Partner-Api-Key: <partner-api-key>' \
  --header 'Content-Type: application/json' \
  --data-raw '{
    "asset": "BTC",
    "amount": 0.1,
    "blockchainInfo": {
      "transactionHash": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16",
      "origin": "origin-wallet-address",
      "destination": "destination-wallet-address",
      "destinationType": "CUSTODIAL",
      "blockchain": "Bitcoin"
    },
    "ivms101": "<base64 encrypted payload>",
    "originatorVaspId": "<originator VASP id>",
    "originatorVaspPubKey": "<originator VASP public key base64>",
    "beneficiaryVaspId": "<CryptoSwift beneficiary VASP id>"
  }'

Response:

{
  "id": "86cc6fd8-caac-4b13-bb84-5d58e5d6d0cc",
  "status": "DELIVERED",
  "asset": "BTC",
  "amount": 0.1,
  "blockchainInfo": {
    "transactionHash": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16",
    "origin": "origin-wallet-address",
    "destination": "destination-wallet-address",
    "destinationType": "CUSTODIAL",
    "blockchain": "Bitcoin"
  },
  "ivms101": "<base64 encrypted payload>",
  "originatorVaspId": "<originator VASP id>",
  "originatorVaspPubKey": "<originator VASP public key base64>",
  "beneficiaryVaspId": "<CryptoSwift beneficiary VASP id>",
  "createdAt": "2026-05-14T12:00:00.000Z"
}

3. Update a Travel Rule Message

Use PATCH /partners/transactions/{id} to update an existing Partner transaction from the partner side. This is commonly used when the blockchain transaction hash becomes available after the Travel Rule message was delivered, or when other request data was missing or needs correction.

For blockchainInfo, the destination address cannot be modified through this endpoint.

curl --location --request PATCH 'https://api-dev.cryptoswift.eu/partners/transactions/<transaction-id>' \
  --header 'X-Partner-Api-Key: <partner-api-key>' \
  --header 'Content-Type: application/json' \
  --data-raw '{
    "beneficiaryVaspId": "<CryptoSwift beneficiary VASP id>",
    "ivms101": "<updated base64 encrypted payload>",
    "originatorVaspId": "<originator VASP id>",
    "originatorVaspPubKey": "<originator VASP public key base64>",
    "blockchainInfo": {
      "transactionHash": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16",
      "origin": "origin-wallet-address",
      "destinationType": "CUSTODIAL",
      "blockchain": "Bitcoin"
    }
  }'

CryptoSwift returns 404 if the referenced transaction or involved VASPs do not exist, and 400 when required payload fields are missing for decrypting IVMS101 data.