Incoming transactions
Receive, review, and respond to incoming Travel Rule messages.
CryptoSwift helps you receive incoming Travel Rule messages, reconcile them with on-chain transfers, and respond with status updates. Incoming review workflows can also use Travel Rule risk scoring to decide whether funds should be released automatically, sent to manual review, or blocked. Use this page to set up a delivery path that fits your stack.
For a complete view of how incoming statuses, originator updates, and counterparty responses move through the workflow, see the end-to-end Travel Rule lifecycle.
Building with an AI coding agent? See AI Agent Integration and AI Agent Prompts.
Receiving transaction data
When a Travel Rule transaction is sent using CryptoSwift or a third-party provider integrated with CryptoSwift, the beneficiary VASP is searched in the CryptoSwift database. If the VASP is found, they automatically receive a Travel Rule transaction message marked with direction INCOMING. Incoming Travel Rule messages are stored automatically and are available via the CryptoSwift API and the Client Dashboard.
Get notified about incoming Travel Rule messages via Webhooks
Set up Webhook notifications to receive real-time notifications about new incoming Travel Rule messages.
For incoming Travel Rule messages, you will receive a webhook notification with the following payload:
X-Event-Typeheader with the valuetransaction- Full Travel Rule transaction message, including the
statusfield (DELIVEREDby default) CryptoSwift-Signatureheader with a timestamp and signature to verify the message is authentic
Example incoming Travel Rule message you receive via a webhook notification:
{
"id": "233e3fd4-2ef0-677c-a398-8f993d131a19",
"status": "DELIVERED",
"statusReasoning": null,
"direction": "INCOMING",
"createdAt": "2025-12-09T12:55:30.519Z",
"asset": "ETH",
"amount": 0.059625001,
"blockchainInfo": {
"transactionHash": "8129df36bf862c55702ab3991c4cc6d00903dc7af4b6f1afc909c216f07e34bd",
"origin": "9xQeWvG816bUx9EPDbZkHf9zF6F1Zjz6FZawgsX5wwAv",
"destination": "0xabcdef1234567890abcdef1234567890abcdef12",
"destinationType": "CUSTODIAL",
"blockchain": "Ethereum",
"isDestinationConfirmed": true,
"destinationWalletId": 7069
},
"vaspInfo": {
"originatorVaspName": "CryptoXYZ",
"originatorVaspEmail": "support@xyz.domain",
"beneficiaryVaspName": "CryptoXchange",
"beneficiaryVaspEmail": "support@cryptox.domain",
"beneficiaryVaspExtraInfo": null
},
"originator": {
"type": "NATURAL",
"name": "Diana DueDiligence",
"accountNumber": "9xQeWvG816bUx9EPDbZkHf9zF6F1Zjz6FZawgsX5wwAv",
"address": "873 Audit Alley",
"country": "AU",
"nationalIdentificatorType": null,
"nationalIdentificator": null,
"customerNumber": null,
"dateOfBirth": null,
"placeOfBirth": null
},
"beneficiary": {
"type": "NATURAL",
"name": "John Smither",
"accountNumber": "AC-123",
"country": null,
"nationalIdentificatorType": null,
"nationalIdentificator": null
},
"travelRuleMessageSource": "CryptoSwift",
"warnings": [],
"riskScore": {
"originatorRiskScore": 72,
"originatorRiskSeverity": "high",
"beneficiaryRiskScore": 8,
"beneficiaryRiskSeverity": "low"
},
"ruleEngine": {
"decision": "REVIEW",
"ruleEngineId": "6292e827-ce05-4cae-a3c8-43e1fb073e1e",
"ruleId": "7f3db7f7-b5b4-4dd7-8de6-e6c15a6eb9e2",
"ruleName": "Review high-risk incoming originator",
"conditions": {
"all": [
{
"field": "originatorRiskSeverity",
"value": "high",
"operator": "EQ"
}
],
"any": []
},
"ruleEngineVersion": 3,
"scope": "INCOMING",
"waitForSeconds": null,
"onTimeoutDecision": null
},
"identifiedTenant": {
"name": "CryptoXchange",
"email": "support@cryptox.domain"
}
}
Use this data to verify whether the blockchain information (destination address and blockchain) and beneficiary data match your records. Note that the transaction hash might be missing if the originating VASP is using a pre-transaction flow, meaning they sent the Travel Rule message before the on-chain transaction. In this case, you will receive another webhook notification with the transaction hash once the on-chain transaction is completed and the originating VASP updates their outgoing Travel Rule message. If the originating VASP cancels the pre-transaction flow instead, you will receive the reflected CANCELLED status and can release any temporary internal holds.
Use risk score in incoming review workflows
Incoming Travel Rule handling does not need to rely on status alone. Combine the incoming message with the Travel Rule Risk Score, transaction amount, wallet context, and your own customer data to decide what happens next.
Typical scenarios include:
- Low risk: automatically release funds after your standard checks pass.
- Medium risk: hold the transaction for analyst review before crediting the customer.
- High risk: block or freeze the transaction and escalate according to your AML procedures.
These decisions can also be automated through the Rule Engine configured in the Client Dashboard. Align webhook handling with your broader review workflow so status updates and release decisions stay consistent.
Response fields for incoming decisioning
Incoming Travel Rule message payloads include riskScore and sanctions objects, and can include a ruleEngine object when Rule Engine policies are configured for incoming workflows. The same payload sections are included in incoming transaction webhook notifications and the Get Transaction by ID response payload.
riskScore
Overall risk score and severity of the transaction.
originatorRiskScoreOverall numerical (0 - 100) risk score of the originator of the transaction. Higher values mean higher risk.originatorRiskSeverityEnum:"low""medium""high"Overall risk severity of the originator of the transaction.beneficiaryRiskScoreOverall numerical (0 - 100) risk score of the beneficiary of the transaction. Higher values mean higher risk.beneficiaryRiskSeverityEnum:"low""medium""high"Overall risk severity of the beneficiary of the transaction.
sanctions
Wallet address sanctions screening result for this transaction.
ruleEngine
Rule engine evaluation result for this Travel Rule message.
decisionString ornullEnum:"PROCEED""WAIT""REVIEW""BLOCK"Final decision from the matched published rule.nullwhen no published rules exist.ruleEngineIdRequired string<uuid>Rule engine ID used for evaluation.ruleIdString ornullMatched published rule ID.nullwhen no published rules exist or no explicit rule matched.ruleNameString ornullMatched published rule name.conditionsObject ornullFull matched published rule condition info.ruleEngineVersionRequired number Rule engine version used for evaluation.0means no published rules exist yet.scopeRequired string Enum:"OUTGOING""INCOMING"Rule engine scope used for evaluation.waitForSecondsNumber ornullWAITduration in seconds whendecision = "WAIT".onTimeoutDecisionString ornullEnum:"PROCEED""REVIEW""BLOCK"Decision to apply whenWAITtimes out.
For the latest and most detailed returned fields, see the Get Transaction API docs. In the Responses section, open Transaction data; it represents the full Travel Rule message payload used across transaction endpoints and transaction notifications.
Respond to incoming Travel Rule messages
Once you have received and validated the data, respond to the incoming Travel Rule message by updating its status:
- If the data is correct, update the
statusof the Travel Rule message toCONFIRMED. This means you agree with the on-chain transaction and are ready to release the funds to your end customer. - If the data is incorrect or there are other reasons for declining the transaction, update the Travel Rule message to
DECLINED. In this scenario, you must also provide astatusReasoningmessage with the reason for declining as free text.
Example requests for updating the status of an incoming Travel Rule message (ID 233e3fd4-2ef0-677c-a398-8f993d131a19 as in the example above):
Confirming a transaction
curl --request PATCH 'https://api-dev.cryptoswift.eu/transactions/233e3fd4-2ef0-677c-a398-8f993d131a19' \
--header 'x-api-key: $API_KEY' \
--header 'Content-Type: application/json' \
--data '{
"status": "CONFIRMED"
}'
Declining a transaction
curl --request PATCH 'https://api-dev.cryptoswift.eu/transactions/233e3fd4-2ef0-677c-a398-8f993d131a19' \
--header 'x-api-key: $API_KEY' \
--header 'Content-Type: application/json' \
--data '{
"status": "DECLINED",
"statusReasoning": "Beneficiary name mismatch. Please review."
}'
The status of the Travel Rule message will be reflected back to the originator VASP (using webhook notifications if they have set them up).
Improving delivery rates
We forward INCOMING messages to our clients based on different data points:
- We use the VASP name or legal name and contact email, when provided in the Travel Rule message payload, to find the VASP in our database.
- We use the wallet database connected to each VASP to match Travel Rule messages by destination wallet.
- We use blockchain analytics tools as a fallback method to try to detect wallet ownership automatically.
Maintain your own wallet inventory
This means that to increase delivery rates for INCOMING Travel Rule messages, ensure your internal custodial wallet list is up to date under "My Wallets":
Keeping your wallet data current helps our platform recognize your addresses and ensures smoother communication between VASPs. When a wallet is confirmed, you also gain access to the sensitive PII shared in incoming payloads. See PII data handling for the disclosure logic.
For an example payload and confirmation steps, see Confirming wallets to access PII.
Additionally, you can set up webhooks to receive incoming Travel Rule transaction messages and outgoing status updates in real time to your application. See Webhooks and Webhook signatures for details.
If inbound web traffic is not feasible, you can poll the Transactions API (GET /transactions/{id}) on a back-off schedule to retrieve DELIVERED, CONFIRMED, DECLINED, and CANCELLED statuses.
You can rehearse webhook handling, receive incoming Travel Rule messages, and monitor outgoing status updates end to end using the sandbox guidance in Testing your implementation.
Next steps
- Missing Travel Rule data
- Confirming wallets to access PII
- Travel Rule Risk Score
- Rule Engine
- Webhooks
- Webhook signatures