Skip to content

Get real-time updates using webhooks

Set up webhooks on your CryptoSwift account

CryptoSwift uses webhooks to notify your application when events such as Incoming Travel Rule Transaction or Self-Hosted Wallet Verification occurs.

Webhooks are useful if you want to create a full integration between CryptoSwift and your own application and collect Incoming Travel Rule Transaction or Self-Hosted Wallets Verification messages.

Building with an AI coding agent? See AI Agent Integration and AI Agent Prompts.


How webhooks are used by CryptoSwift

Webhooks enable CryptoSwift to push real-time notifications to your application. CryptoSwift uses a JSON payload that is sent over HTTPS to notify your application. Those notifications can be used to execute actions in your backend systems.

Receiving webhook notifications

You can start receiving event notifications in your app using the steps in this section:

  1. Create a webhook endpoint in your application
  2. Register the webhook URL in CryptoSwift
  3. Handle requests from CryptoSwift
  4. Secure your webhook endpoint
Always double-check you are using the correct environment when integrating. Using the wrong base URL or API key will result in authentication errors.

1. Create a webhook

Create a webhook endpoint on your server that will accept incoming data. Make sure the URL is publicly accessible once deployed. If you want to limit access to your webhook endpoint, make sure to whitelist the CryptoSwift API IPs that will be calling it:

  • Dev: 34.88.32.82
  • Prod: 35.228.164.60

2. Register your webhook URL

Once the webhook endpoint has been created, register the webhook public URL for your CryptoSwift account using the API or Client Dashboard (under Settings).

You can use the tenant/me PATCH endpoint and provide {"webhookUrl": "..."} object in the request body.

Notabene network webhooks

If you also want to receive Travel Rule messages from the Notabene network, configure Notabene to forward notifications to the tenant-specific URL shown in Client Dashboard → Settings → External integrations:

  • Create a free Notabene account.
  • Set the Notification Webhook URL in Notabene to the tenant-specific URL from the CryptoSwift dashboard.

3. Handle requests from CryptoSwift

CryptoSwift uses a JSON payload to notify your application.

There are multiple event types CryptoSwift can forward to your application which you can distinguish by checking the X-Event-Type header:

Event TypeHeaderDescription
Travel Rule TransactiontransactionFor Travel Rule Transaction messages (new incoming transactions or status updates to existing outgoing transactions), the full Travel Rule message is forwarded to your application. See the Travel Rule data model for more details.
Self-hosted wallet verificationwallet-verificationFor widget and API-driven verification updates. See the wallet verification widget and wallet verification API guides for payload details.

Travel Rule messages

CryptoSwift sends a transaction event in two main situations:

  • Incoming messages: expect a webhook when another VASP sends your tenant a Travel Rule message. The payload has direction: "INCOMING" and normally starts with status: "DELIVERED". Further notifications can arrive when the originator adds or changes data. For example, adding the transactionHash after a pre-transaction message, or cancelling the message.
  • Outgoing updates: after you create an outgoing message, expect webhooks when its delivery or counterparty response changes. Common updates include delivery to the beneficiary VASP and the beneficiary confirming or declining the message. Beneficiary identification, risk analysis, and other processing can also add or update transaction data.

Each notification contains the full current Travel Rule message, not only the fields that changed. Reconcile it by id and use direction to route it to your incoming or outgoing workflow. In particular, inspect:

  • status and statusReasoning for the current lifecycle state and any explanation
  • blockchainInfo for the transaction hash, network, and wallet addresses
  • vaspInfo, originator, and beneficiary for counterparty or party-data changes
  • riskScore, including sanctions results, plus warnings and ruleEngine when present

Some personal data can be omitted from incoming messages until the destination wallet is confirmed. For the disclosure rules, see PII data handling.

Example outgoing status-update payload:

{
  "id": "233e3fd4-2ef0-477c-a398-8f993d131a19",
  "status": "CONFIRMED",
  "statusReasoning": null,
  "direction": "OUTGOING",
  "createdAt": "2026-07-31T09:42:18.519Z",
  "asset": "ETH",
  "amount": 0.059625001,
  "amountUsd": 223.41,
  "amountEur": 193.64,
  "metadata": "withdrawal-8472",
  "blockchainInfo": {
    "transactionHash": "8129df36bf862c55702ab3991c4cc6d00903dc7af4b6f1afc909c216f07e34bd",
    "origin": "0x1234567890abcdef1234567890abcdef12345678",
    "destination": "0xabcdef1234567890abcdef1234567890abcdef12",
    "destinationType": "CUSTODIAL",
    "blockchain": "Ethereum",
    "isDestinationConfirmed": true,
    "destinationWalletId": 7069
  },
  "vaspInfo": {
    "originatorVaspName": "Originator VASP",
    "originatorVaspEmail": "support@originator.example",
    "beneficiaryVaspName": "Beneficiary VASP",
    "beneficiaryVaspEmail": "support@beneficiary.example",
    "beneficiaryVaspExtraInfo": null
  },
  "originator": {
    "type": "NATURAL",
    "name": "Diana DueDiligence",
    "accountNumber": "customer-123",
    "address": "873 Audit Alley",
    "country": "AU",
    "nationalIdentificatorType": null,
    "nationalIdentificator": null,
    "customerNumber": "customer-123",
    "dateOfBirth": null,
    "placeOfBirth": null
  },
  "beneficiary": {
    "type": "NATURAL",
    "name": "John Smither",
    "accountNumber": "AC-123",
    "country": "EE",
    "nationalIdentificatorType": null,
    "nationalIdentificator": null
  },
  "travelRuleMessageSource": "CryptoSwift",
  "riskScore": {
    "originatorRiskScore": 18,
    "originatorRiskSeverity": "low",
    "beneficiaryRiskScore": 12,
    "beneficiaryRiskSeverity": "low",
    "sanctions": {
      "originatorWallet": {
        "isSanctioned": false,
        "details": []
      },
      "beneficiaryWallet": {
        "isSanctioned": false,
        "details": []
      }
    }
  },
  "ruleEngine": {
    "decision": "PROCEED",
    "ruleEngineId": "6292e827-ce05-4cae-a3c8-43e1fb073e1e",
    "ruleId": "7f3db7f7-b5b4-4dd7-8de6-e6c15a6eb9e2",
    "ruleName": "Proceed with low-risk outgoing transfer",
    "conditions": {
      "all": [
        {
          "field": "beneficiaryRiskSeverity",
          "operator": "EQ",
          "value": "low"
        }
      ],
      "any": []
    },
    "ruleEngineVersion": 3,
    "scope": "OUTGOING",
    "waitForSeconds": null,
    "onTimeoutDecision": null
  }
}

Fields that are not available or do not apply can be null or omitted. Treat webhook deliveries as notifications: process them idempotently and retrieve the latest transaction with GET /transactions/{id} before making an irreversible decision.

Self-hosted wallet verifications

CryptoSwift sends a wallet-verification event when a wallet verification is updated or processed, whether the flow was started through the widget or the API. Notifications can follow proof submission, asynchronous Satoshi Test monitoring, or a manual status update.

Use id to reconcile the notification with your request. Inspect status and statusReasoning for the result, flow and metadata for routing, and the proof-specific, risk, warning, or reuse fields when present. Handle PENDING, VERIFIED, ACTION_REQUIRED, FAILED, DECLINED, and DELETED as current states rather than assuming every notification is a successful completion. The full payload and a current example are documented in Receive Notification via Webhook.

For both event types, verify the signature, parse the JSON body, queue any longer-running processing, and return a 2xx response.

4. Secure your webhook endpoint

Use webhook signatures to verify that it was indeed CryptoSwift that generated a webhook request and that it didn't come from a server acting like CryptoSwift. This is an optional but recommended step in order to guarantee a secure integration.

The custom CryptoSwift-Signature header is sent with each webhook notification. See webhook signatures to find out how to set up and validate webhook signatures.

Next steps