Travel Rule recipes
These playbooks walk through real-world Travel Rule scenarios end-to-end. From data collection in your product to the final API calls. Using CryptoSwift you can implement both post- and pre-transaction Travel Rule flows, though we generally recommend starting with the post-transaction pattern for its lower operational overhead. Each recipe links back to the detailed references so your team can move quickly without guessing what to do next.
When implementing the Travel Rule you typically need to cover these domains:
- Outgoing transactions (withdrawals)
- Incoming transactions (deposits)
- Self-hosted wallet verification (where relevant for your business)
From a technical standpoint also plan for:
- Managing your custodial wallet list on the CryptoSwift platform
- Setting up webhook notifications for lifecycle events
Once these building blocks are in place you have everything required to stay compliant with the Travel Rule.
Outgoing transactions: collecting and delivering Travel Rule data
Post-transaction flow
When an end customer requests an outgoing crypto transfer you already have rich KYC data in your customer database that you can use to fill in the originator data. As an additional step you need to ask them for the beneficiary name. Submit the Travel Rule transaction message with this data concurrently with the blockchain transfer.
Workflow
- Capture the withdrawal request (amount, asset, destination address) in your product UI.
- Fetch the customer profile from your KYC system to map originator fields (name, address, account identifiers, etc.).
- Collect the beneficiary name from the user in the withdrawal form.
- Call the CryptoSwift Transactions API to create the Travel Rule message and send it to the beneficiary VASP.
curl --request POST 'https://api.cryptoswift.eu/transactions' \ --header 'x-api-key: $API_KEY' \ --header 'Content-Type: application/json' \ --data '{ "asset": "USDC", "amount": "250.00", "blockchainInfo": { "blockchain": "Ethereum", "transactionHash": "0x7d...c93", "origin": "0xCustomerWallet", "destination": "0xBeneficiaryWallet", "destinationType": "CUSTODIAL" }, "originator": { "type": "NATURAL", "name": "Jamie Rivera", "address": "Alexanderplatz 25, Berlin", "country": "DE", "accountNumber": "cust-45781" }, "beneficiary": { "type": "NATURAL", "name": "Leonie Schulz", "accountNumber": "swift-88452" }, "vaspInfo": { "beneficiaryVaspName": "SwiftExchange", "beneficiaryVaspEmail": "compliance@swiftexchange.eu" } }'
- Store the transaction UUID from the response to reconcile settlements and later updates.
Compare payload fields with the reference example in Send and receive data → Creating a new transaction and the post-transaction workflow guide.
Pre-transaction flow
You may decide to wait for a response from the counterparty before sending the on-chain transaction. This pre-transaction flow mainly differs because:
- The Travel Rule message is created and delivered before you broadcast the on-chain transaction.
- The initial payload omits the transaction hash, which you append later with
PATCH /transactions/{id}
once the transfer settles.
Implementation outline:
- Submit the
CREATE
request without a transaction hash so the beneficiary VASP can review the intent. - Monitor for
DELIVERED
orCONFIRMED
statuses via webhooks or periodic polling. - Decide whether to proceed immediately, wait for confirmation, or fall back to the post-transaction workflow based on risk.
- After broadcasting, update the record with the blockchain hash and any additional status details.
Because automatic confirmation rates remain low today, build a fallback that escalates to manual outreach when the timer expires. A hybrid approach waits for DELIVERED
—it proves the counterparty received the payload even if they have not confirmed it yet. See the detailed pre-transaction workflow guide for payload examples and operational checklists.
Incoming transactions: operational checklist
Incoming flows combine webhook handling, wallet management, and conditional AML decisions. With webhook delivery in place, keep the following building blocks ready.
1. Maintain your custodial wallet inventory
A complete wallet registry ensures we can route Travel Rule messages automatically.
curl --request POST 'https://api.cryptoswift.eu/wallets' \ --header 'x-api-key: $API_KEY' \ --header 'Content-Type: application/json' \ --data '{ "address": "0xCustodialVault01", "asset": "USDC", "blockchain": "Ethereum", "metadata": "Operations hot wallet" }'
- Repeat for each custodial wallet you manage, or bulk-import via
POST /wallets/upload-csv
. - When we detect a new custodial wallet automatically, confirm ownership in the dashboard or with
PATCH /wallets/{id}
so that associated PII becomes visible. See PII Data Handling for the confirmation effects. - The metadata field is a free text field that you can use to connect the wallet to your internal identifiers, add tags, etc.
2. Decide when to release funds or trigger a claim
When a Travel Rule message is missing or incomplete for an incoming crypto transaction, pick one of the following based on your AML policy:
- Release funds immediately once on-chain confirmations arrive for low-risk transactions.
- Create a claim so the originator VASP can supply the missing data. Use the Claims API when the transaction exceeds internal risk thresholds.
curl --request POST 'https://api.cryptoswift.eu/claims' \ --header 'x-api-key: $API_KEY' \ --header 'Content-Type: application/json' \ --data '{ "asset": "BTC", "blockchainInfo": { "blockchain": "Bitcoin", "transactionHash": "f4184fc5964...", "origin": "bc1qh...", "destination": "bc1qy..." }, "vaspInfo": { "originatorVaspName": "InternationalExchange" } }'
- Document the condition matrix (amount thresholds, origin risk scores) inside your transaction monitoring system. The Claims article provides guidance on tailoring claim logic.
3. Backfill when counterparties cannot push Travel Rule data
You can still satisfy record-keeping requirements even if the originator VASP fails to deliver a message:
- Optional: Ask the receiving customer for the originator name or any available data before releasing funds.
- Store the information with an
INCOMING
Travel Rule message using the standard Transactions API by setting"direction": "INCOMING"
.
curl --request POST 'https://api.cryptoswift.eu/transactions' \ --header 'x-api-key: $API_KEY' \ --header 'Content-Type: application/json' \ --data '{ "direction": "INCOMING", "asset": "ETH", "amount": "1.45", "blockchainInfo": { "blockchain": "Ethereum", "transactionHash": "0x1cf...3aa", "origin": "0xOriginator", "destination": "0xCustodyVault" }, "beneficiary": { "type": "NATURAL", "name": "Local Customer", "accountNumber": "wallet-0912" }, "originator": { "type": "NATURAL", "name": "Disclosed by customer" } }'
- You can store also partial data without the beneficiary section.
- Continue updating the record with
PATCH /transactions/{id}
if additional data arrives later.
Deposits and withdrawals involving self-hosted wallets
Before releasing or accepting funds linked to self-hosted wallets, verify ownership to reduce counterparty risk. Check your regulatory obligations for exact requirements, including any thresholds that mandate self-hosted wallet verification.
Implementation options
- Embed the self-hosted wallet verification widget in your withdrawal flow so customers can prove ownership as part of your UX.
- Or trigger verification via API-first flows (signature proof, Satoshi test, visual proof) described in Self-hosted wallet verification API integration.
Kick off widget verification for a pending withdrawal: See example here See example here.
When using our Widget, you can customise the look and feel (font, colors, logo) of the Widget UI using the Client Dashboard and/or API.
Webhook notifications
Stand up a single HTTPS endpoint to capture all Travel Rule lifecycle updates delivered by CryptoSwift. The same endpoint receives both native network messages and from external sources that have been configured (eg Notabene).
- Accept
POST
requests and persist the payload before returning a response. - Allow-list CryptoSwift delivery IPs if your firewall blocks unknown sources.
- To additionally receive messages from Notabene network you must:
- Create a free Notabene account.
- Set the Notification Webhook URL in Notabene to the tenant-specific URL available in Client Dashboard → Settings → External integrations.
Incoming Travel Rule messages
- Notifications arrive with
direction: "INCOMING"
and the full Travel Rule payload for your review. - Validate the beneficiary data against your internal records, run risk checks, and then update the transaction status with the CryptoSwift API so the originator can see the outcome.
curl --request PATCH 'https://api.cryptoswift.eu/transactions/{transactionId}' \ --header 'x-api-key: $API_KEY' \ --header 'Content-Type: application/json' \ --data '{ "status": "CONFIRMED" }'
- If the transaction must be declined, provide additional context for the originator.
curl --request PATCH 'https://api.cryptoswift.eu/transactions/{transactionId}' \ --header 'x-api-key: $API_KEY' \ --header 'Content-Type: application/json' \ --data '{ "status": "DECLINED", "statusReasoning": "Beneficiary name mismatch. Please review." }'
Outgoing transaction status updates
- Expect follow-up webhook calls whenever an outgoing transaction changes state (for example, when a beneficiary VASP confirms or declines it).
- No API action is usually required, but make sure the events reach operations or compliance teams so they can follow up on declines or additional data requests quickly.
Self-hosted wallet verification results
- The same webhook endpoint receives status updates from the self-hosted wallet verification workflows (widget or API-based).
- Use the notification payload to tie the verification result back to the pending withdrawal or deposit request, then continue the flow. See Self-hosted wallet verification for detailed verification mechanics.
See the Webhooks section for more details about setting up Webhooks.
Next steps
- Webhooks – Configure event delivery for the flows you implement.
- Webhook signatures – Verify inbound requests before processing them.
- Travel Rule data model – Confirm the fields required across each scenario.
- Get started – Revisit the integration roadmap and next milestones.