# Create address Source: https://docs.wavynode.com/api-reference/endpoint/create-address POST /projects/{projectId}/addresses Creates a new relevant address to listen for compliance events and alerts for a given project. Requires Developer role. Once registered, Wavy Node monitors this address and sends notifications to your webhook when it interacts with risky or blacklisted wallets. # Create API key Source: https://docs.wavynode.com/api-reference/endpoint/create-api-key POST /projects/{projectId}/keys Creates a new API key for a given project. # Create investigation Source: https://docs.wavynode.com/api-reference/endpoint/create-investigation POST /projects/{projectId}/investigations Creates a new investigation for a wallet address. Optionally triggers an incremental layer-by-layer analysis. Creates an investigation record and, if no prior analysis exists for the wallet, triggers a background risk analysis via the tracker service. ## Standard vs incremental analysis By default, the analysis runs in **standard mode**: the API polls the tracker until the full result is ready, then stores it. The response includes the complete transaction graph. When you pass `"incremental": true`, the tracker performs a **layer-by-layer BFS analysis**. Each depth layer is persisted independently so you can poll for partial results while the analysis is still running. ```bash theme={null} curl -X POST https://api.wavynode.com/v1/projects/{projectId}/investigations \ -H "x-api-key: ApiKey wavy_..." \ -H "Content-Type: application/json" \ -d '{ "name": "Binance Hot Wallet", "wallet": "0x28C6c06298d514Db089934071355E5743bf21d60", "chainId": "1" }' ``` ```bash theme={null} curl -X POST https://api.wavynode.com/v1/projects/{projectId}/investigations \ -H "x-api-key: ApiKey wavy_..." \ -H "Content-Type: application/json" \ -d '{ "name": "Binance Hot Wallet", "wallet": "0x28C6c06298d514Db089934071355E5743bf21d60", "chainId": "1", "incremental": true }' ``` ## Request body | Field | Type | Required | Description | | ------------- | ------- | -------- | ------------------------------------------------------------------------ | | `name` | string | yes | Human-readable name for the investigation | | `wallet` | string | yes | Blockchain address to investigate | | `chainId` | string | no | Chain ID (defaults to `"1"` — Ethereum mainnet) | | `incremental` | boolean | no | When `true`, runs a layer-by-layer incremental analysis. Default `false` | ## Response ```json theme={null} { "success": true, "data": { "id": "7d457074-055a-477e-a1a3-ae2ac446ba1b", "project_id": 1, "analysis_id": "eff04343-ce57-48c7-b478-f58531b1611f", "analysis_status": "pending", "name": "Binance Hot Wallet", "wallet": "0x28C6c06298d514Db089934071355E5743bf21d60", "status": "active", "nodes": [ { "id": "0x28c6c06298d514db089934071355e5743bf21d60", "type": "wallet", "data": { "address": "0x28C6...", "label": "Root", "balance": 0 }, "position": { "x": 0, "y": 0 } } ], "edges": [], "tracked_transactions": [], "created_at": "2026-04-29T16:17:14.000Z", "updated_at": "2026-04-29T16:17:14.000Z" } } ``` The `analysis_id` may be empty initially if the analysis record is still being created in the background. Poll the investigation endpoint to get the updated `analysis_id`. ## Polling for incremental results When `incremental: true`, use these endpoints to track progress and fetch layer results as they complete: 1. **Poll progress** — `GET /v1/analysis/{analysisId}/progress` 2. **Fetch layer** — `GET /v1/analysis/{analysisId}/layers/{layer}` See [Get analysis progress](/api-reference/endpoint/get-analysis-progress) and [Get layer result](/api-reference/endpoint/get-analysis-layer) for details. Poll the current layer progress and provisional risk score. Fetch the cumulative graph and patterns for a specific depth layer. # Delete address Source: https://docs.wavynode.com/api-reference/endpoint/delete-address DELETE /projects/{projectId}/addresses/{addressId} Removes a relevant address from the project's monitored address list. # Delete API key Source: https://docs.wavynode.com/api-reference/endpoint/delete-api-key DELETE /projects/{projectId}/keys/{keyId} Deletes an API key for a given project. # Delete investigation Source: https://docs.wavynode.com/api-reference/endpoint/delete-investigation DELETE /projects/{projectId}/investigations/{id} Deletes an investigation. Analysis and graph data are preserved for audit. # Get layer result Source: https://docs.wavynode.com/api-reference/endpoint/get-analysis-layer Returns the incremental analysis result for a specific BFS depth layer, including the cumulative graph and detected patterns. Each layer represents one level of depth in the BFS (breadth-first search) graph traversal. Layer 0 is the root address, layer 1 includes its direct counterparties, layer 2 their counterparties, and so on. ## Request ```bash theme={null} curl https://api.wavynode.com/v1/analysis/{analysisId}/layers/{layer} \ -H "x-api-key: ApiKey wavy_..." ``` ### Path parameters | Parameter | Type | Description | | ------------ | ------------- | ---------------------------------------- | | `analysisId` | string (uuid) | The analysis ID from the tracker service | | `layer` | integer | The BFS depth level to fetch (0-based) | ## Response — completed layer ```json theme={null} { "success": true, "data": { "analysisId": "2912b99e-ddb7-41bf-af29-fa0136361bf7", "layer": 1, "status": "completed", "riskScore": 46, "isProvisional": true, "totalLayers": 7, "detectedPatterns": [ { "patternType": "high_value_transfers", "confidence": 0.85, "severity": "medium", "description": "Multiple high-value transfers detected" } ], "newPatterns": [ { "patternType": "high_value_transfers", "confidence": 0.85, "severity": "medium", "description": "Multiple high-value transfers detected" } ], "removedPatterns": [], "cumulativeGraph": { "rootAddress": "0x47ac0fb4f2d84898e4d9e7b4dab3c24507a6d503", "nodes": { "0x47ac...": { "address": "0x47ac...", "type": "eoa" } }, "edges": [{ "from": "0x47ac...", "to": "0xabcd...", "value": "1000000000" }], "metadata": { "totalNodes": 15, "totalEdges": 42 } }, "newNodes": { "0xabcd...": { "address": "0xabcd...", "type": "eoa" } }, "newEdges": [{ "from": "0x47ac...", "to": "0xabcd...", "value": "1000000000" }], "layerMetadata": { "processingTimeMs": 2340, "nodeCount": 15, "edgeCount": 42, "newNodeCount": 12, "newEdgeCount": 38, "errorCount": 0, "patternDetectionTimeMs": 180, "timestamp": "2026-04-29T16:22:32.000Z" } } } ``` ## Response — pending layer If the requested layer hasn't been processed yet: ```json theme={null} { "success": true, "data": { "analysisId": "2912b99e-ddb7-41bf-af29-fa0136361bf7", "layer": 5, "status": "pending", "totalLayers": 7 } } ``` ### Response fields | Field | Type | Description | | ------------------ | ------- | -------------------------------------------------------------- | | `analysisId` | string | The analysis identifier | | `layer` | integer | The BFS depth level | | `status` | string | `completed`, `pending`, or `failed` | | `riskScore` | number | Provisional risk score at this depth (0–100) | | `isProvisional` | boolean | `true` for all layers except the final one | | `totalLayers` | integer | Maximum depth (for progress calculation) | | `detectedPatterns` | array | All patterns detected in the cumulative graph up to this layer | | `newPatterns` | array | Patterns first detected at this layer | | `removedPatterns` | array | Patterns from the previous layer no longer detected | | `cumulativeGraph` | object | Full transaction graph from root to this depth | | `newNodes` | object | Nodes added at this layer | | `newEdges` | array | Edges added at this layer | | `layerMetadata` | object | Processing statistics for this layer | The `layer` parameter is **0-based**. Layer 0 is the root address analysis. If `maxDepth` is 7, valid layers are 0 through 6. ## Caching Completed layers are immutable. The API returns `Cache-Control: public, max-age=3600` for completed layers, so clients can safely cache them. Pending layers return `Cache-Control: no-cache`. ## Pattern diffing Each layer includes `newPatterns` and `removedPatterns` relative to the previous layer. This enables incremental UI updates — you can highlight newly detected patterns without re-processing the entire list. | Layer | Detected | New | Removed | Interpretation | | ----- | -------- | --- | ------- | ------------------------------------------------ | | 0 | 0 | 0 | 0 | Root address only, no patterns yet | | 1 | 1 | 1 | 0 | First pattern detected at depth 1 | | 2 | 2 | 1 | 0 | Additional pattern found at depth 2 | | 3 | 1 | 0 | 1 | One pattern no longer detected with more context | # Get analysis progress Source: https://docs.wavynode.com/api-reference/endpoint/get-analysis-progress Returns the current progress of an analysis, including completed layers and provisional risk score. Useful for showing a progress indicator while an incremental analysis is running. Returns how many BFS layers have completed out of the maximum depth, along with the latest provisional risk score. ## Request ```bash theme={null} curl https://api.wavynode.com/v1/analysis/{analysisId}/progress \ -H "x-api-key: ApiKey wavy_..." ``` ### Path parameters | Parameter | Type | Description | | ------------ | ------------- | ----------------------------------------------------------------------------------------------------- | | `analysisId` | string (uuid) | The analysis ID returned by the tracker service. Available in the investigation's `analysis_id` field | ## Response ```json theme={null} { "success": true, "data": { "analysisId": "2912b99e-ddb7-41bf-af29-fa0136361bf7", "status": "running", "completedLayers": 3, "maxDepth": 7, "incremental": true, "riskScore": 46, "patternsDetected": 1, "startedAt": "2026-04-29T16:22:26.949Z" } } ``` ### Response fields | Field | Type | Description | | ------------------ | ------- | --------------------------------------------------------------- | | `analysisId` | string | The analysis identifier | | `status` | string | Current status: `pending`, `running`, `completed`, or `failed` | | `completedLayers` | integer | Number of BFS depth layers that have finished processing | | `maxDepth` | integer | Total number of layers the analysis will process | | `incremental` | boolean | Whether this is an incremental (layer-by-layer) analysis | | `riskScore` | number | Latest provisional risk score (0–100). Updates after each layer | | `patternsDetected` | integer | Number of suspicious patterns detected so far | | `startedAt` | string | ISO 8601 timestamp of when the analysis started | The `riskScore` is **provisional** while the analysis is running. It may increase or decrease as deeper layers reveal more transaction patterns. The final score is set when `status` becomes `completed`. ## Polling strategy Poll this endpoint every **2 seconds** while `status` is `running`. When `completedLayers` increments, fetch the new layer via [Get layer result](/api-reference/endpoint/get-analysis-layer). Stop polling when `status` is `completed` or `failed`. ```javascript theme={null} const POLL_INTERVAL = 2000; let lastLayer = -1; const poll = setInterval(async () => { const res = await fetch(`/v1/analysis/${analysisId}/progress`, { headers }); const { data } = await res.json(); if (data.completedLayers > lastLayer) { // Fetch the new layer const layer = await fetch(`/v1/analysis/${analysisId}/layers/${data.completedLayers - 1}`, { headers }); lastLayer = data.completedLayers; } if (data.status === 'completed' || data.status === 'failed') { clearInterval(poll); } }, POLL_INTERVAL); ``` # Get chain details Source: https://docs.wavynode.com/api-reference/endpoint/get-chain GET /chains/{chainId} Retrieves detailed information about a specific blockchain network, including market data and network statistics. # Get investigation Source: https://docs.wavynode.com/api-reference/endpoint/get-investigation GET /projects/{projectId}/investigations/{id} Retrieves a specific investigation with its transaction graph nodes and edges. # Get report download URL Source: https://docs.wavynode.com/api-reference/endpoint/get-report-download GET /reports/{reportId} Retrieves a signed URL to download a specific compliance report. The signed URL is temporary. Use it immediately to download the report file. # Scan risk Source: https://docs.wavynode.com/api-reference/endpoint/get-scan-risk-results GET /projects/{projectId}/addresses/scan-risk Retrieves risk analysis results for one or more blockchain addresses. Requires Developer role. Use this endpoint to retrieve previously analyzed risk results without triggering a new scan. Results are cached and updated periodically. For an overview of how risk scores work, see [Risk scores](/concepts/risk). For detailed information about detected patterns and response examples, see [Risk analysis](/concepts/risk-analysis). Addresses with `riskLevel: "critical"` should be reported to the regulator per applicable regulations. See [Regulations](/concepts/regulations) for details. ## Related resources Learn how Wavy Node calculates risk scores and recommended actions by risk level. Technical reference with pattern weights, severity levels, and detailed examples. Manage relevant on-chain addresses for compliance monitoring. # Get wallet balance Source: https://docs.wavynode.com/api-reference/endpoint/get-wallet-balance GET /wallets/{wallet}/balance Retrieves the total balance of a wallet address in USD, along with individual asset breakdowns. # Get wallet report Source: https://docs.wavynode.com/api-reference/endpoint/get-wallet-report GET /wallets/{wallet}/report Generates an AI-written report about the compliance status and activity of a specific wallet address. # Get wallet status Source: https://docs.wavynode.com/api-reference/endpoint/get-wallet-status GET /wallets/{wallet}/status Retrieves the compliance status of a specific wallet address, including risk tags and recent activity. # List addresses Source: https://docs.wavynode.com/api-reference/endpoint/list-addresses GET /projects/{projectId}/addresses Retrieves all the relevant on-chain addresses configured for a specific project. # List API keys Source: https://docs.wavynode.com/api-reference/endpoint/list-api-keys GET /projects/{projectId}/keys Retrieves all the API keys for a given project. # List all chains Source: https://docs.wavynode.com/api-reference/endpoint/list-chains GET /chains Retrieves all the blockchain networks supported by Wavy Node. # List investigations Source: https://docs.wavynode.com/api-reference/endpoint/list-investigations GET /projects/{projectId}/investigations Retrieves all investigations for a project, including risk scores from linked analyses. # List compliance reports Source: https://docs.wavynode.com/api-reference/endpoint/list-reports GET /reports Retrieves compliance reports filtered by project, period, and country. Reports are auto-generated documents required by regulators. ## Supported countries | Code | Country | | ---- | ----------- | | `MX` | México | | `CO` | Colombia | | `SV` | El Salvador | | `GT` | Guatemala | ## Query parameters | Parameter | Type | Required | Description | | ------------- | ------- | -------- | ----------------------------- | | `projectId` | integer | yes | Your project ID | | `period` | string | yes | Period in `YYYY-MM` format | | `countryCode` | string | yes | One of `MX`, `CO`, `SV`, `GT` | | `limit` | integer | no | Max results (default: 10) | | `offset` | integer | no | Pagination offset | | `search` | string | no | Filter by report name | Reports are generated automatically based on your project's transaction activity and the regulatory requirements of each jurisdiction. # Update investigation Source: https://docs.wavynode.com/api-reference/endpoint/update-investigation PATCH /projects/{projectId}/investigations/{id} Updates an investigation's name, status, or tracked transactions. # Introduction Source: https://docs.wavynode.com/api-reference/introduction Compliance, fraud prevention, and risk analysis API for payment providers and crypto exchanges in Latin America. The Wavy Node API lets you analyze blockchain addresses, monitor wallets, and manage compliance workflows for your projects. ## Base URL ``` https://api.wavynode.com/v1 ``` ## Authentication All endpoints require your API key in the `x-api-key` HTTP header. The value must include the `ApiKey` prefix: ```bash highlight={1} theme={null} curl -H "x-api-key: ApiKey wavy_your_api_key_here" \ https://api.wavynode.com/v1/chains ``` Get your API key from the [Wavy Node dashboard](https://wavynode.com/dashboard). Always include the `ApiKey` prefix before your key. The correct format is: ```highlight={1} theme={null} x-api-key: ApiKey wavy_... ``` Sending only the key without the prefix (e.g., `x-api-key: wavy_...`) will result in an authentication error. Some API routes require you to provide the `projectId` in the URL. You can find your project's `projectId` in the dashboard under **Project Settings**. ## Response format All responses use JSON with a consistent structure: | Field | Type | Required | Description | | --------- | ------- | -------- | ----------------------------------- | | `success` | boolean | yes | Whether the request was successful | | `data` | any | no | Response payload | | `message` | string | no | Additional context or error message | ### Error example ```json theme={null} { "success": false, "error": "invalid_request", "message": "The api key is invalid" } ``` ## Available endpoints Get information about supported blockchain networks. Check wallet status, balance, and generate AI reports. Analyze blockchain addresses for risk and suspicious patterns. Create investigations with standard or incremental layer-by-layer analysis. Track incremental analysis progress and fetch per-layer results. Auto-generated regulatory compliance reports (MX, CO, SV, GT). Manage relevant on-chain addresses for compliance monitoring. Manage API keys for your projects programmatically. # Regulations Source: https://docs.wavynode.com/concepts/regulations Regulatory framework covered by Wavy Node. Wavy Node evaluates each transaction against the applicable regulatory frameworks in the corresponding jurisdiction. # Mexico 🇲🇽 ### LFPIORPI *Ley Federal para la Prevención e Identificación de Operaciones con Recursos de Procedencia Ilícita.* Under Mexican regulations, Virtual Asset Service Providers (VASPs) are classified as “Vulnerable Activity,” regulated by the "LFPIORPI (Art. 17, Section XVI): > The regular and professional offering of virtual asset exchange by entities other than Financial Institutions carried out through electronic, digital, or similar platforms that manage or operate by facilitating or performing purchase or sale transactions of such assets owned by their customers or provide means for the custody, storage, or transfer of virtual assets other than those recognized by the Bank of Mexico under the Law Regulating Financial Technology Institutions, including transactions carried out with Mexican citizens from another jurisdiction. Our software covers AML for Vulnerable Activities, risk matrices, establishes reporting thresholds (UMAs), and notifications to the SAT (SPPLD). Want to know if your company needs to be regulated under this jurisdiction? Schedule a call with our team. # International standards 🌎 ### FATF Wavy Node implements the Financial Action Task Force recommendations: * Recommendation 15: New technologies (virtual assets) * Recommendation 16: Travel Rule ### Travel Rule For virtual asset transfers exceeding USD \$1,000, Wavy Node verifies that the required originator and beneficiary information is included: * Originator name * Originator account or wallet number * Originator address or national ID * Beneficiary account or wallet number * Beneficiary name (Coming soon) Coming soon: support for Colombia, El Salvador, Guatemala, Chile, Argentina, Brazil, USA, European Union. # Risk scores Source: https://docs.wavynode.com/concepts/risk How Wavy Node calculates risk scores for blockchain addresses using contextual and deterministic analysis. Wavy Node assigns a risk score from 0 to 100 to each analyzed blockchain address. The scoring system is contextual (considers the type of address) and fully deterministic (same inputs always produce the same outputs). ## Risk scale | Range | Level | Recommended action | | ------ | -------- | ------------------------------------ | | 0 | Verified | Verified legitimate entity | | 1-19 | Minimal | No action needed | | 20-39 | Low | Passive monitoring | | 40-59 | Medium | Investigation recommended | | 60-79 | High | Priority investigation | | 80-100 | Critical | Immediate action / regulatory report | ## How the score is calculated The risk score combines three factors: The system analyzes the transaction graph to detect suspicious patterns like mixing, peel chains, structuring, and more. Each pattern has a weight and confidence score that contribute to the final risk score. The system considers what type of address is being analyzed. A registered exchange with high transaction volume is treated differently than an unknown wallet with the same patterns. Detection thresholds adjust based on the wallet's transaction volume to reduce false positives for high-activity addresses. ## Address categories The score varies depending on the type of address being analyzed. | Address type | No patterns | Minor patterns | Critical patterns | Discount | | -------------------- | ----------- | -------------- | ----------------- | -------- | | Registered exchanges | 0 | 0-20 | 20-40 | 80% | | Public figures | 5-10 | 30-60 | 60-100 | None | | Verified protocols | 5-10 | 30-60 | 60-100 | None | | Foundations / DAOs | 5-10 | 30-60 | 60-100 | None | | Labeled addresses | 5 | 5-20 | 20-40 | None | | Smart contracts | 5 | 15-35 | 35-65 | None | | Unknown | 10 | 30-60 | 60-100 | None | Only registered exchanges receive a discount (80%). Other known categories are recognized for metadata purposes but their patterns are evaluated at full weight. ## Actions by risk level | Level | Monitoring | Investigation | Report | Block | | ----------------- | ---------- | ------------- | -------- | -------- | | Minimal (0-19) | Standard | No | No | No | | Low (20-39) | Increased | Optional | No | No | | Medium (40-59) | Intensive | Yes | Evaluate | No | | High (60-79) | Continuous | Urgent | Yes | Evaluate | | Critical (80-100) | Real-time | Immediate | Required | Yes | ## Suspicious activity flag The `suspiciousActivity` field is set to `true` when any of the following conditions are met: * Risk score is 70 or higher * Any pattern with `critical` severity is detected * Three or more patterns with `high` severity are detected The risk scoring system is essential for compliance with regulations such as FATF recommendations, Travel Rule, Mexico's Fintech Law, and LFPIORPI. See the full technical reference with pattern weights, severity levels, confidence thresholds, and detailed examples. # Risk analysis Source: https://docs.wavynode.com/concepts/risk-analysis Detected patterns, volume scaling, and response examples from the Wavy Node risk scoring system. This page covers the patterns Wavy Node detects and how to interpret the results you receive from the [Scan Risk](/api-reference/endpoint/get-scan-risk-results) endpoint. For an overview of how risk scores work, see [Risk scores](/concepts/risk). ## Detected patterns The analysis engine identifies the following risk patterns in the transaction graph: | Pattern | Severity | Description | | ---------------------- | -------- | ------------------------------------------------------ | | `mixing` | Critical | Use of mixing services to hide fund origins | | `peel_chain` | High | Transaction chains to fragment and obscure funds | | `structuring` | High | Splitting amounts to avoid reporting thresholds | | `round_tripping` | Medium | Funds returning to origin after multiple hops | | `mass_wallet_creation` | Medium | Coordinated creation of multiple wallets | | `wash_trading` | Medium | Artificial transactions to simulate volume | | `exchange_hopping` | Low | Rapid movement between exchanges to break traceability | ## Volume scaling Detection thresholds adjust based on the wallet's transaction volume to reduce false positives for high-activity addresses. | Transactions | Scaling factor | | ---------------- | -------------- | | Under 1,000 | 1.0x | | 1,000 - 10,000 | 1.5x | | 10,000 - 50,000 | 2.0x | | 50,000 - 100,000 | 2.5x | | Over 100,000 | 3.0x | ## Response examples ```json theme={null} { "address": "0x1234...", "riskScore": 10, "riskLevel": "minimal", "suspiciousActivity": false, "patterns": [] } ``` No detected patterns. Standard monitoring applies. ```json theme={null} { "address": "0x3f5ce5fbfe3e9af3971dd833d26ba9b5c936f0be", "riskScore": 0, "riskLevel": "minimal", "suspiciousActivity": false, "patterns": [], "metadata": { "isRegisteredExchange": true, "exchangeName": "Binance" } } ``` Registered exchanges receive an 80% discount on their risk score. ```json theme={null} { "address": "0xabcd...", "riskScore": 78, "riskLevel": "high", "suspiciousActivity": true, "patterns": [ { "type": "mixing", "confidence": 0.85, "severity": "critical" }, { "type": "peel_chain", "confidence": 0.70, "severity": "high" } ] } ``` Mixing combined with peel chain. Requires immediate investigation. ```json theme={null} { "address": "0xmixer...", "riskScore": 92, "riskLevel": "critical", "suspiciousActivity": true, "patterns": [ { "type": "mixing", "confidence": 0.95, "severity": "critical" }, { "type": "structuring", "confidence": 0.88, "severity": "high" }, { "type": "round_tripping", "confidence": 0.82, "severity": "medium" } ] } ``` Multiple laundering techniques detected. Urgent escalation and regulatory report required. # Supported Source: https://docs.wavynode.com/concepts/supported Blockchain networks and tokens monitored by Wavy Node. Wavy Node monitors multiple EVM-compatible chains and Stellar. You can also query available chains via the [List Chains](/api-reference/endpoint/list-chains) endpoint. ## Chains | Chain | ID | Currency | Type | Explorer | | ---------------- | ------- | -------- | ------- | ---------------------------------------------------------- | | Ethereum Mainnet | `1` | ETH | EVM | [etherscan.io](https://etherscan.io) | | Optimism | `10` | ETH | EVM | [optimistic.etherscan.io](https://optimistic.etherscan.io) | | Polygon | `137` | POL | EVM | [polygonscan.com](https://polygonscan.com) | | Lisk | `1135` | ETH | EVM | [blockscout.lisk.com](https://blockscout.lisk.com) | | Stellar | `1234` | XLM | Stellar | [stellarchain.io](https://stellarchain.io) | | Story Mainnet | `1514` | IP | EVM | [storyscan.io](https://www.storyscan.io) | | Mantle | `5000` | MNT | EVM | [mantlescan.xyz](https://mantlescan.xyz) | | Base | `8453` | ETH | EVM | [basescan.org](https://basescan.org) | | Arbitrum | `42161` | ETH | EVM | [arbiscan.io](https://arbiscan.io) | | Celo Mainnet | `42220` | CELO | EVM | [celoscan.io](https://celoscan.io) | | Avalanche | `43114` | AVAX | EVM | [snowscan.xyz](https://snowscan.xyz) | Mantle is currently inactive. Contact us if you need monitoring on this chain. ## Tokens by chain | Token | Symbol | Contract | | ------------------ | ------ | -------------------------------------------- | | USD Coin | USDC | `0xaf88d065e77c8cC2239327C5EDb3A432268e5831` | | USD Coin (Bridged) | USDC.e | `0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8` | | Tether USD | USDT | `0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9` | | Dai Stablecoin | DAI | `0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1` | | Wrapped Ether | WETH | `0x82aF49447D8a07e3bd95BD0d56f35241523fBab1` | | Wrapped BTC | WBTC | `0x2f2a2543B76A4166549F7aaB2e75Bef0aefC5B0f` | | PayPal USD | PYUSD | `0x46850aD61C2B7d64d08c9C754F45254596696984` | | Token | Symbol | Contract | | ----------- | ------ | -------------------------------------------- | | USD Coin | USDC | `0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48` | | Tether USD | USDT | `0xdAC17F958D2ee523a2206206994597C13D831ec7` | | DAI | DAI | `0x6B175474E89094C44Da98b954EedeAC495271d0F` | | Wrapped BTC | WBTC | `0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599` | | PayPal USD | PYUSD | `0x6c3ea9036406852006290770BEdFcAbA0e23A0e8` | | Token | Symbol | Contract | | -------------- | ------ | -------------------------------------------- | | USD Coin | USDC | `0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359` | | Tether USD | USDT | `0xc2132D05D31c914a87C6611C10748AEb04B58e8F` | | Dai Stablecoin | DAI | `0x8f3Cf7ad23Cd3CaDbD9735AFf958023239c6A063` | | Wrapped Ether | WETH | `0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619` | | Wrapped SOL | WSOL | `0xd93f7E271cB87c23AaA73edC008A79646d1F9912` | | PayPal USD | PYUSD | `0x99aF3EeA856556646C98c8B9b2548Fe815240750` | | Token | Symbol | Contract | | ------------- | ------ | -------------------------------------------- | | USD Coin | USDC | `0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913` | | Tether USD | USDT | `0xfde4C96c8593536E31F229EA8f37b2ADa2699bb2` | | DAI | DAI | `0x50c5725949A6F0c72E6C4a641F24049A917DB0Cb` | | USDS | USDS | `0x820C137fa70C8691f0e44Dc420a5e53c168921Dc` | | Wrapped Ether | WETH | `0x4200000000000000000000000000000000000006` | | Wrapped BTC | WBTC | `0x1ceA84203673764244E05693e42E6Ace62bE9BA5` | | Solana | SOL | `0x311935Cd80B76769bF2ecC9D8Ab7635b2139cf82` | | Token | Symbol | Contract | | ------------------- | ------ | -------------------------------------------- | | USD Coin | USDC | `0xcebA9300f2b948710d2653dD7B07f33A8B32118C` | | Tether USD | USDT | `0x48065fbBE25f71C9282ddf5e1cD6D6A887483D5e` | | Celo Colombian Peso | cCOP | `0x8A567e2aE79CA692Bd748aB832081C45de4041eA` | | Wrapped Ether | WETH | `0xD221812de1BD094f35587EE8E174B07B6167D9Af` | | Wrapped BTC | WBTC | `0x8aC2901Dd8A1F17a1A4768A6bA4C3751e3995B2D` | | Token | Symbol | Contract | | -------------- | ------ | -------------------------------------------- | | USD Coin | USDC | `0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E` | | Tether USD | USDT | `0x9702230A8Ea53601f5cD2dc00fDBc13d4dF4A8c7` | | Dai Stablecoin | DAI.e | `0xd586E7F844cEa2F87f50152665BCbc2C279D8d70` | | Wrapped Ether | WETH.e | `0x49D5c2BdFfac6CE2BFdB6640F4F80f226bc10bAB` | | Wrapped BTC | WBTC | `0x0555E30da8f98308EdB960aa94C0Db47230d2B9c` | | Token | Symbol | Contract | | ------------- | ------ | -------------------------------------------- | | Bridged USDC | USDC.e | `0xF242275d3a6527d877f2c927a82D9b057609cc71` | | Tether USD | USDT | `0x05D032ac25d322df992303dCa074EE7392C117b9` | | Wrapped Ether | WETH | `0x4200000000000000000000000000000000000006` | | Lisk | LSK | `0xac485391EB2d7D88253a7F1eF18C37f4242D1A24` | | Wrapped BTC | WBTC | `0x03C7054BCB39f7b2e5B2c7AcB37583e32D70Cfa3` | | Token | Symbol | Contract | | -------------- | ------ | -------------------------------------------- | | USD Coin | USDC | `0x09Bc4E0D864854c6aFB6eB9A9cdF58aC190D0dF9` | | Tether USD | USDT | `0x201EBa5CC46D216Ce6DC03F6a759e8E766e956aE` | | Wrapped Ether | WETH | `0xdEAddEaDdeadDEadDEADDEAddEADDEAddead1111` | | Wrapped Mantle | WMNT | `0x78c1b0C915c4FAA5FffA6CAbf0219DA63d7f4cb8` | | Token | Symbol | Contract | | --------------------- | ------ | -------------------------------------------- | | Stargate Bridged USDC | USDC.e | `0xF1815bd50389c46847f0Bda824eC8da914045D14` | | Stargate Bridged WETH | WETH | `0xBAb93B7ad7fE8692A878B95a8e689423437cc500` | Need a chain or token that's not listed here? [Contact us](https://wavynode.com) and we can evaluate adding it. # Transactions Source: https://docs.wavynode.com/concepts/transactions How Wavy Node monitors and analyzes on-chain transactions in real time Wavy Node analyzes blockchain transactions in real time to detect suspicious patterns, fraud, and money laundering. Each analyzed address receives a risk score and a set of detected patterns. ## How it works Add the relevant on-chain addresses for your project using the [Addresses API](/api-reference/endpoint/list-addresses). These are the wallets you want to monitor for compliance. Submit addresses for analysis using the [Scan Risk](/api-reference/endpoint/get-scan-risk-results) endpoint. The system traverses the transaction graph to detect suspicious patterns. Each address receives a risk score (0-100), a risk level, and a list of detected patterns with confidence scores. Based on the results, you can approve, investigate, or escalate. Wavy Node sends real-time alerts to your [integration webhook](/integrations/endpoints) when suspicious activity is detected. ## Detected patterns When analyzing the transaction graph, Wavy Node can identify the following suspicious patterns: | Pattern | Severity | Description | | ---------------------- | -------- | ------------------------------------------------------ | | `mixing` | Critical | Use of mixing services to hide fund origins | | `peel_chain` | High | Transaction chains to fragment and obscure funds | | `structuring` | High | Splitting amounts to avoid reporting thresholds | | `round_tripping` | Medium | Funds returning to origin after multiple hops | | `mass_wallet_creation` | Medium | Coordinated creation of multiple wallets | | `wash_trading` | Medium | Artificial transactions to simulate volume | | `exchange_hopping` | Low | Rapid movement between exchanges to break traceability | ## Risk levels | Level | Score | Recommended action | | -------- | ------ | ------------------------------------ | | Minimal | 0-19 | No action needed | | Low | 20-39 | Passive monitoring | | Medium | 40-59 | Investigation recommended | | High | 60-79 | Priority investigation | | Critical | 80-100 | Immediate action / regulatory report | ## Response example ```json theme={null} { "address": "0xabcd...", "chainId": "1", "status": "completed", "riskScore": 45, "riskLevel": "medium", "riskReason": "Clustering pattern detected, requires investigation", "suspiciousActivity": false, "patterns": [ { "type": "clustering", "confidence": 0.75, "severity": "medium" } ], "transactionGraph": { "rootAddress": "0xabcd...", "totalNodes": 1107, "totalEdges": 2000, "maxDepth": 3 } } ``` Addresses with `riskLevel: "critical"` should be reported to the regulator per applicable regulations. See [Regulations](/concepts/regulations) for details. # Welcome to Wavy Node Source: https://docs.wavynode.com/index Enterprise-grade automated compliance, regulatory monitoring and reporting for stablecoin payments. ## The best shield for your company! At Wavy Node, we protect companies that are leading the stablecoin-based financial future, reducing the risk of fines for regulatory non-compliance. We **simplify compliance through a fully integrated system** that includes: * On-chain screening and risk scoring in real-time. * Cross-checking against wallet and user blacklists. * Automatic generation of background review using AI. * Creation of reporting formats that Virtual Asset Service Providers (VASPs) require to submit to their regulator. Our software **reduces the need for multiple vendors** and is perfect for infrastructure companies in the payments ecosystem: payment processors, remittances, exchanges, P2P solutions, international payment processors, and payment gateways. ## We're ready to take care of you! Ready to integrate into your system easily and quick, with the best industry standards. Real-time transaction and user monitoring, risk scoring, alert sending, and review generation. We manage your risk internationally, with information on lists and regulations. Not only on-chain screening. We automatically create the report formats that you have to submit to your regulator. ## Use cases With real-time behavioral algorithms and a risk matrix based on international standards, we review your users' activity and assign risk weights to protect your business. We alert you to suspicious transactions and generate a review of wallet behavior for your compliance team, saving time for decision-making. Create in-depth investigations of your users' activity in a simple way to strengthen your folders. We monitor regulatory requirements and automate the creation of regulatory report formats that you have to submit to your regulators on a regular basis, without complications. ## Quickstart Integrate Wavy Node in minutes, and protect your company today! Set up your API key and create a complete analysis of your ecosystem. *** Schedule a call and our support team will help you step by step to protect your company. Check our real-time system status and uptime monitoring. # Authentication Source: https://docs.wavynode.com/integrations/authentication Learn how to verify that incoming requests to your integration are authentically from Wavy Node using HMAC-SHA256. Wavy Node uses HMAC-SHA256 to sign every request it sends to your integration. This guarantees that requests are legitimate and haven't been tampered with in transit. Think of it as a seal of authenticity: only someone with the shared `SECRET` can generate a valid signature. ## How it works ```mermaid theme={null} sequenceDiagram participant WN as Wavy Node participant YS as Your Server WN->>WN: 1. Build canonical message WN->>WN: 2. Sign with HMAC-SHA256 using SECRET WN->>YS: 3. Send request + headers (x-wavynode-hmac, x-wavynode-timestamp) YS->>YS: 4. Rebuild canonical message YS->>YS: 5. Recalculate signature with SECRET alt Signatures match YS-->>WN: 200 OK ✅ else Signatures don't match YS-->>WN: 401 Unauthorized ❌ end ``` ### Step by step 1. Wavy Node builds a canonical message from: HTTP method, path, body, and timestamp 2. Signs that message with HMAC-SHA256 using the shared SECRET 3. Sends the request with two extra headers: * `x-wavynode-hmac` — the generated signature * `x-wavynode-timestamp` — the timestamp in milliseconds 4. Your server receives the request 5. Recalculates the signature using the same SECRET and request data 6. If signatures match → the request is legitimate (200). If not → reject it (401) ## The shared SECRET The SECRET is a 32-character hex string that both sides know: ``` 615d9b7ea991acfa33f823c374c3a062 ``` It must be configured in two places: | Location | How to configure | | -------------------- | ----------------------------------------------- | | Wavy Node dashboard | **Settings → Integración → Integration Secret** | | Your server (`.env`) | `SECRET=615d9b7ea991acfa33f823c374c3a062` | Both values must be exactly the same. If they differ, signatures won't match and all requests will fail with 401. ### Generate a new SECRET ```bash theme={null} openssl rand -hex 16 ``` ## Authentication headers Every request from Wavy Node includes these headers: | Header | Type | Description | | ---------------------- | ------ | ------------------------------------------------------------- | | `x-wavynode-hmac` | string | Base64 encoded HMAC-SHA256 signature of the canonical message | | `x-wavynode-timestamp` | string | Timestamp in milliseconds (epoch) | ## Canonical message The signature is not calculated on the raw request, but on a standardized canonical message. This ensures both sides build exactly the same string before signing. The canonical message is formed by concatenating these values separated by `::`: * The uppercase HTTP method (`GET`, `POST`, etc.) * The lowercase request path (e.g., `/webhook`) * The stringified request body with keys sorted alphabetically, or `{}` if no body * The timestamp from the `x-wavynode-timestamp` header ``` GET::/users/123::{}::1757050233763 ``` ## Using `@wavynode/utils` The easiest way to verify requests is with the `validateSignature` function: ```typescript theme={null} import { validateSignature } from '@wavynode/utils'; const isValid = validateSignature({ method: 'POST', path: '/webhook', body: req.body, timestamp: parseInt(req.headers['x-wavynode-timestamp']), secret: process.env.SECRET, timeTolerance: 300000, signature: req.headers['x-wavynode-hmac'] }); if (!isValid) { // The request is not from Wavy Node // or has been tampered with. // Reject the request. } ``` | Parameter | Type | Description | | --------------- | ------ | -------------------------------------------------------------------------------- | | `method` | string | The HTTP method of the request | | `path` | string | The path of the request | | `body` | object | The request body | | `timestamp` | number | The timestamp from the `x-wavynode-timestamp` header | | `secret` | string | Your integration's secret from **Settings → Integración** in the dashboard | | `timeTolerance` | number | Time tolerance in milliseconds to prevent replay attacks (recommended: `300000`) | | `signature` | string | The signature from the `x-wavynode-hmac` header | You can also build the canonical message manually with `formCanonicalMessage`: ```typescript theme={null} import { formCanonicalMessage } from "@wavynode/utils"; const canonicalMessage = formCanonicalMessage({ method: "GET", path: "/users/user-123", body: {}, timestamp: 1712764800000 }); ``` ## Manual authentication If you are not using the `@wavynode/utils` package, you can implement the authentication logic yourself. Concatenate the values separated by `::` as described above: ``` GET::/users/123::{}::1757050233763 ``` Create a `sha256` HMAC of the canonical string using your integration's secret as the key. Base64 encode the result. ```javascript theme={null} import crypto from 'node:crypto'; const createHmacSignature = (message, secret) => { const hmac = crypto.createHmac('sha256', secret); hmac.update(message); return hmac.digest('base64'); }; ``` Compare the signature you created with the one from the `x-wavynode-hmac` header. If they match, the request is authentic. ## Why is HMAC necessary? Without HMAC authentication, anyone who knows your integration URL could: * Send fake webhooks simulating transactions that never happened * Query user data without authorization * Inject false notifications into your system HMAC guarantees that only Wavy Node can communicate with your integration server. # Endpoints Source: https://docs.wavynode.com/integrations/endpoints Implement the two required routes in your integration server to receive user data requests and real-time notifications from Wavy Node. Your integration is a **single server** (one URL) that exposes **two routes**. When you configure the integration URL in the Wavy Node dashboard (e.g., `https://your-server.com`), Wavy Node appends the route paths automatically: * `GET {integrationUrl}/users/{foreign_user_id}` * `POST {integrationUrl}/webhook` You only need **one server** and **one integration URL**. Do not create separate servers or URLs for each route. Wavy Node sends requests to both routes on the same base URL. ## `GET /users/{foreign_user_id}` Wavy Node calls this endpoint to retrieve information about a specific user. The `{foreign_user_id}` parameter is the user's ID in your system (the same ID you provided when registering the wallet address). The `foreign_user_id` is the identifier you send when creating an address via `POST /projects/{projectId}/addresses`. This is how Wavy Node links wallets to users in your system. Your endpoint should return a JSON object with the following structure: ```json theme={null} { "givenName": "Maria Guadalupe", "maternalSurname": "Sánchez", "paternalSurname": "Rodríguez", "birthdate": "1992-05-15", "nationality": "MX", "phoneNumber": { "countryCode": "+52", "phoneNumber": 5512345678 }, "email": "maria.guadalupe@example.com", "address": { "country": "MX", "region": "CDMX", "city": "Ciudad de México", "street": "Avenida Insurgentes Sur", "colonia": "Condesa", "exteriorNumber": "123", "interiorNumber": "4B", "postalCode": "06100" }, "mexico": { "rfc": "ROSM920515XXX", "curp": "ROSM920515MDFRXXXX", "actividadEconomica": 612012, "cuentaRelacionada": "1234567890", "monedaCuentaRelacionada": 1, "documentoIdentificacion": { "tipoIdentificacion": 1, "numeroIdentificacion": "IDMEX12345678" } } } ``` | Field | Type | Description | | ------------------------- | ------ | ---------------------------------------------------------- | | `givenName` | string | The individual's given name(s) | | `maternalSurname` | string | Maternal surname | | `paternalSurname` | string | Paternal surname | | `birthdate` | string | Date of birth in `YYYY-MM-DD` format (ISO 8601) | | `nationality` | string | ISO 3166-1 alpha-2 country code | | `phoneNumber.countryCode` | string | Phone country code | | `phoneNumber.phoneNumber` | number | Phone number | | `email` | string | Email address | | `address` | object | Physical address | | `mexico` | object | Fields required for Mexican legislation reports (optional) | The `mexico` object is only needed if you have Mexican compliance enabled in your dashboard. ### Person types for Mexican reports When Mexican legislation is active, the `mexico` data feeds the AVI report. A report supports three mutually exclusive person types, and exactly one applies per user. An individual account holder. At least one of `rfc`, `curp`, or `birthdate` is required. ```json theme={null} { "givenName": "Maria Guadalupe", "paternalSurname": "García", "maternalSurname": "López", "birthdate": "1990-05-15", "nationality": "MX", "mexico": { "rfc": "GALM900515XXX", "curp": "GALM900515MDFRPN09", "actividadEconomica": 8140001, "cuentaRelacionada": "012180001234567890", "monedaCuentaRelacionada": 1, "documentoIdentificacion": { "tipoIdentificacion": 1, "numeroIdentificacion": "INE123456789" } } } ``` A legal entity. At least one of `rfc` or `fechaConstitucion` is required, and a legal representative (`representanteApoderado`) is mandatory. ```json theme={null} { "tipoPersona": "moral", "denominacionRazon": "Empresa Ejemplo SA de CV", "fechaConstitucion": "2015-03-20", "nationality": "MX", "representanteApoderado": { "givenName": "Juan Carlos", "paternalSurname": "Martínez", "maternalSurname": "Ruiz", "birthdate": "1985-08-10", "rfc": "MARJ850810XXX", "curp": "MARJ850810HDFRRL09", "documentoIdentificacion": { "tipoIdentificacion": 1, "numeroIdentificacion": "INE987654321" } }, "mexico": { "rfc": "EEJ150320XXX", "giroMercantil": 5612001, "actividadEconomica": 5612001, "cuentaRelacionada": "014320001234567890", "monedaCuentaRelacionada": 1, "documentoIdentificacion": { "tipoIdentificacion": 4, "numeroIdentificacion": "ACTA-CONST-2015" } } } ``` A trust. At least one of `rfc` or `identificadorFideicomiso` is required, and a fiduciary delegate (`delegadoFiduciario`) is mandatory. ```json theme={null} { "tipoPersona": "fideicomiso", "denominacionRazon": "Fiduciario Ejemplo SA", "nationality": "MX", "delegadoFiduciario": { "givenName": "Ana María", "paternalSurname": "Torres", "maternalSurname": "Vega", "birthdate": "1980-02-25", "rfc": "TOVA800225XXX", "curp": "TOVA800225MDFRRN09", "documentoIdentificacion": { "tipoIdentificacion": 1, "numeroIdentificacion": "INE555444333" } }, "mexico": { "rfc": "FEJ800101XXX", "identificadorFideicomiso": "FID-2020-00123", "cuentaRelacionada": "012180009876543210", "monedaCuentaRelacionada": 1, "documentoIdentificacion": { "tipoIdentificacion": 4, "numeroIdentificacion": "CONTRATO-FID-2020" } } } ``` Codes such as `tipoIdentificacion` (1=INE, 2=Passport, 4=Incorporation deed), `actividadEconomica`, and `giroMercantil` follow the SAT catalogs, published at [sppld.sat.gob.mx](https://sppld.sat.gob.mx/pld/interiores/activos.html). ## `POST /webhook` Wavy Node sends real-time notifications to this endpoint. The request body contains: | Field | Type | Description | | ------ | ---------------- | ----------------------------------------- | | `type` | string | `notification` or `error` | | `data` | object or string | The notification payload or error message | ### Notification payload When `type` is `notification`, the `data` object contains transaction and compliance details: ```json theme={null} { "type": "notification", "data": { "id": 1, "projectId": 1, "chainId": 42161, "address": { "id": 543, "userId": "user-in-your-db-123", "address": "0xyour-address-involved", "description": "Your address' description" }, "txHash": "some-tx-hash", "timestamp": "2025-08-20T05:10:57.228Z", "amount": { "value": 1000000000000000000, "usd": 3000 }, "token": { "name": "Ethereum", "symbol": "ETH", "decimals": 18, "address": null }, "inflictedLaws": [ { "name": "The name of the law inflicted", "description": "Description of the law", "source": "Source of the law", "risk": "warn", "country": "mexico", "countryCode": "MX" } ] } } ``` | Field | Type | Description | | ----------------------------- | ------ | ---------------------------------------------------------------------------------------- | | `id` | number | Notification ID | | `projectId` | number | Project ID | | `chainId` | number | Chain ID where the transaction occurred | | `address.id` | number | Address ID | | `address.userId` | string | User ID in your system (the `foreign_user_id` you provided when registering the address) | | `address.address` | string | Wallet address | | `address.description` | string | Address description | | `txHash` | string | Transaction hash | | `timestamp` | string | Transaction timestamp (ISO 8601) | | `amount.value` | number | Amount in the token's smallest unit | | `amount.usd` | number | Amount in USD | | `token.name` | string | Token name | | `token.symbol` | string | Token symbol | | `token.decimals` | number | Token decimals | | `token.address` | string | Token contract address (`null` for native tokens) | | `inflictedLaws` | array | Laws inflicted by the transaction | | `inflictedLaws[].name` | string | Law name | | `inflictedLaws[].description` | string | Law description | | `inflictedLaws[].source` | string | Law source | | `inflictedLaws[].risk` | string | `warn` or `illegal` | | `inflictedLaws[].country` | string | Country name | | `inflictedLaws[].countryCode` | string | ISO country code | ### Error payload When `type` is `error`, the `data` field is a string containing the error message. # Overview Source: https://docs.wavynode.com/integrations/overview Connect your application with Wavy Node by setting up a single integration server with two routes to receive real-time compliance notifications and serve user data. Integrations connect your application with Wavy Node. By creating an integration, you set up a single server that Wavy Node communicates with to receive real-time notifications about your users' on-chain activity and to retrieve the user data needed for compliance. ## How it works Your integration is a **single server** that exposes **two routes** under the same base URL. When you configure the integration URL in the dashboard (e.g., `https://your-server.com`), Wavy Node calls both routes on that same server: 1. `GET {integrationUrl}/users/{foreign_user_id}` — Wavy Node requests user data from your system for compliance checks and report generation. 2. `POST {integrationUrl}/webhook` — Wavy Node sends you real-time alerts when suspicious activity is detected. You only need **one server** and **one integration URL**. Do not create separate servers or separate URLs for each route — both routes live on the same server. ```mermaid theme={null} sequenceDiagram participant You as Your App participant WN as Wavy Node participant BC as Blockchain You->>WN: 1. Register addresses with foreign_user_id WN->>BC: 2. Monitor on-chain activity BC-->>WN: Transaction detected WN-->>You: 3. POST /webhook (real-time alert) WN->>You: 4. GET /users/{foreign_user_id} You-->>WN: User data for compliance WN->>WN: 5. Generate compliance report ``` ### Wallet-to-user matching The match between wallets and users happens when you register addresses in our system. When you create an address via the API, you include the `foreign_user_id`, which is the user's ID in your system. This is how we know which user owns each wallet. If a user has multiple wallets, register each wallet with the same `foreign_user_id`. We handle the linking automatically. When we need user data (for example, to generate a compliance report), we call your integration endpoint `/users/{foreign_user_id}`. You must return the required user data for each legislation you have enabled in your project. For example, if you have Mexican legislation active, all users must include the `mexico` field populated with the user's personal and fiscal information: ```json theme={null} { "givenName": "Juan", "paternalSurname": "Pérez", "maternalSurname": "López", "nationality": "MX", "mexico": { "rfc": "PELJ900101XXX", "curp": "PELJ900101HDFRPN09", "actividadEconomica": 1234567, "documentoIdentificacion": { "tipoIdentificacion": 1, "numeroIdentificacion": "ABC123456" } } } ``` See [Endpoints](/integrations/endpoints) for the full response schema. The complete type definitions for each legislation are available in the `@wavynode/utils` package. Your endpoint must return the required data for all active legislations in your project. Missing or empty fields will cause compliance report generation to fail. | Active Legislation | Required Field | Content | | ------------------ | -------------- | ------------------------------------------------ | | Mexico (MX) | `mexico` | Personal data, RFC/CURP, address, ID document | | Colombia (CO) | `colombia` | User data required by Colombian AML regulations | | El Salvador (SV) | `elSalvador` | User data required by Salvadoran AML regulations | | Guatemala (GT) | `guatemala` | User data required by Guatemalan AML regulations | ### Integration flow Use `POST /projects/{projectId}/addresses` to add wallet addresses you want to monitor. Include the `foreign_user_id` parameter to link each wallet to a user in your system. Wavy Node watches your registered addresses for suspicious transactions, regulatory violations, and interactions with blacklisted wallets. When Wavy Node needs user information (e.g., to generate a compliance report), it calls your `GET /users/{foreign_user_id}` endpoint. You must return the required user data for all the legislations you have enabled in your project. See the type definitions in `@wavynode/utils` for the exact fields required by each legislation. When suspicious activity is detected, Wavy Node sends a notification to your `POST /webhook` endpoint with the transaction details and regulatory violations. All requests from Wavy Node are signed with HMAC-SHA256 so you can verify their authenticity. ### Organization compliance data Before Wavy Node can generate regulatory reports, you must configure your organization's compliance data in the dashboard. Navigate to **Management → Organization** in the sidebar and fill in the **Compliance Data** section. This includes: * **Platform domain** — Your platform's domain (auto-formatted to uppercase, e.g., `wavynode.com` → `WAVYNODE`). * **Tax IDs** — The tax identifier for each country where you have active legislation: This information is required to generate regulatory reports. Without it, reports will not be generated. | Country | Field | Example | | ---------------- | ----- | ------------------- | | Mexico (MX) | RFC | `XAXX010101000` | | Colombia (CO) | NIT | `900123456-7` | | El Salvador (SV) | NIT | `0614-123456-001-0` | | Guatemala (GT) | NIT | `1234567-8` | ## Getting started There are two ways to create a new integration: A ready-to-go Nitro application with all required endpoints and authentication already set up. Ideal for local development. Use any framework or language. Start by setting up authentication. ## `@wavynode/utils` package We provide an npm package with utilities to simplify the integration process: ```bash theme={null} npm install @wavynode/utils ``` This package includes: * `validateSignature` — Verify the authenticity of requests from Wavy Node. * Type definitions for each legislation's required user data (e.g., `MexicoUserData`, `ColombiaUserData`). ## Next steps Learn how to verify requests from Wavy Node. Implement the required endpoints for your integration. Explore the full API documentation. # Setup with template Source: https://docs.wavynode.com/integrations/setup Step-by-step guide to set up a local development environment for your Wavy Node integration using the official template. This guide walks you through setting up a local development environment using the [official template](https://github.com/wavy-node/integration). By the end, you'll have a running server that receives real-time compliance alerts and serves user data to Wavy Node. This setup is intended for local development and testing. For production deployments, replace ngrok with your own publicly accessible server and use environment-specific secrets. ## Prerequisites * [Node.js](https://nodejs.org/) or [Bun](https://bun.sh/) installed * [ngrok](https://ngrok.com/) installed (to expose your local server) * A [Wavy Node](https://wavynode.com/dashboard) account with a project created * An API key from your project ## Organization compliance data Before anything else, configure your organization's compliance data in the dashboard. Navigate to **Management → Organization** in the sidebar and fill in the **Compliance Data** section: 1. **Platform domain** — Your platform's domain. It's auto-formatted to uppercase (e.g., `wavynode.com` → `WAVYNODE`). 2. **Tax IDs** — The tax identifier for each country where you have active legislation: This information is required to generate regulatory reports. Without it, reports will not be generated. | Country | Field | Example | | ---------------- | ----- | ------------------- | | Mexico (MX) | RFC | `XAXX010101000` | | Colombia (CO) | NIT | `900123456-7` | | El Salvador (SV) | NIT | `0614-123456-001-0` | | Guatemala (GT) | NIT | `1234567-8` | ## Step 1: Clone and install ```bash theme={null} git clone https://github.com/wavy-node/integration cd integration bun install ``` You can also use `npm install` if you prefer Node.js over Bun. ## Step 2: Configure environment variables Copy the template and edit: ```bash theme={null} cp .env.template .env ``` Your `.env` file needs these values: ```bash .env highlight={2} theme={null} SECRET=your_32_character_hex_secret WAVYNODE_API_KEY=ApiKey wavy_your_api_key_here PROJECT_ID=1 PORT=3001 ``` ### Generate the `SECRET` The `SECRET` is a 32-character hex string used to sign requests between Wavy Node and your integration. Generate one with: ```bash theme={null} openssl rand -hex 16 ``` This outputs something like `615d9b7ea991acfa33f823c374c3a062`. Save this value — you'll also need to configure it in the Wavy Node dashboard. The `SECRET` in your `.env` must match the `integration_secret` configured in your Wavy Node project. If they don't match, all requests will fail signature verification. ### Get your API key Find your API key in the Wavy Node dashboard under your project's **API Keys** section. The format is `ApiKey wavy_...`. When making API requests, the `x-api-key` header must include the `ApiKey` prefix: ```highlight={1} theme={null} x-api-key: ApiKey wavy_your_api_key_here ``` Sending only the key without the prefix will result in an authentication error. ## Step 3: Implement your routes The template includes two routes on the same server that you need to customize: ### `GET /users/{userId}` Wavy Node calls this endpoint to get user data for compliance reports. Return a JSON object with the user's information: ```typescript theme={null} // Return user data from your database { givenName: "Maria Guadalupe", maternalSurname: "Sánchez", paternalSurname: "Rodríguez", birthdate: "1992-05-15", nationality: "MX", phoneNumber: { countryCode: "+52", phoneNumber: 5512345678 }, email: "maria.guadalupe@example.com", address: { country: "MX", region: "CDMX", city: "Ciudad de México", street: "Avenida Insurgentes Sur", colonia: "Condesa", exteriorNumber: "123", interiorNumber: "4B", postalCode: "06100" }, mexico: { rfc: "ROSM920515XXX", curp: "ROSM920515MDFRXXXX", actividadEconomica: 612012, cuentaRelacionada: "1234567890", monedaCuentaRelacionada: 1, documentoIdentificacion: { tipoIdentificacion: 1, numeroIdentificacion: "IDMEX12345678" } } } ``` The `mexico` object is required only if you have Mexican legislation active in your project. See [Endpoints](/integrations/endpoints) for the full response schema. ### `POST /webhook` Wavy Node sends real-time notifications when suspicious activity is detected. The template already handles signature verification — you just need to add your business logic: ```typescript theme={null} // Notification payload { type: "notification", data: { id: 1, projectId: 1, chainId: 42161, address: { userId: "user-123", address: "0x..." }, txHash: "0x...", amount: { value: 1000000000000000000, usd: 3000 }, inflictedLaws: [{ name: "...", risk: "warn", countryCode: "MX" }] } } ``` ## Step 4: Start the server ```bash theme={null} bun run dev ``` The server runs at `http://localhost:3001`. ## Step 5: Expose with ngrok In a separate terminal: ```bash theme={null} ngrok http 3001 ``` This generates a public URL like `https://abc123.ngrok-free.dev`. ```mermaid theme={null} flowchart LR WN[Wavy Node] -->|HTTPS| NG[ngrok URL] NG -->|tunnel| LS[localhost:3001] ``` ## Step 6: Configure your project in Wavy Node Update your project with the integration URL and secret. In the dashboard, go to **Settings → Integración** and fill in: * **Integration URL** — Your ngrok public URL (e.g., `https://abc123.ngrok-free.dev`). This is the single base URL for your server — Wavy Node appends `/users/{id}` and `/webhook` automatically. * **Integration Secret** — The same 32-character secret from your `.env` file Click **Save changes** when done. Do not include route paths in the integration URL. Use `https://abc123.ngrok-free.dev`, not `https://abc123.ngrok-free.dev/webhook`. The `integration_secret` must be exactly the same as the `SECRET` in your `.env` file. ## Step 7: Register addresses Register the wallet addresses you want to monitor, linking them to users in your system: ```bash theme={null} curl -X POST "https://api.wavynode.com/v1/projects/$PROJECT_ID/addresses" \ -H "Content-Type: application/json" \ -H "x-api-key: $WAVYNODE_API_KEY" \ -d '{ "address": "0x2c63bbbcc4b40ca0f149717195fea66a8f1a0395", "description": "Main wallet", "foreign_user_id": "user-123" }' ``` The `foreign_user_id` is the user's ID in your system. When Wavy Node needs data for this user, it calls `GET /users/user-123` on your integration. If the address already exists in the project, the `foreign_user_id` and `description` are updated instead of creating a duplicate. ## Step 8: Test the integration The template includes a test script that simulates the calls Wavy Node makes to your server. With the server running and ngrok active: ```bash theme={null} bun run test-integration.ts ``` The script runs three tests: 1. `GET /users/user-123` — verifies your user data endpoint responds correctly with a valid HMAC signature 2. `POST /webhook` — sends a simulated notification with a sample transaction and inflicted laws 3. Invalid signature — sends a request with a fake signature to verify your middleware rejects it with 401 ```bash theme={null} === WavyNode Integration Test === Server: http://localhost:3001 Secret: 615d9b7e... --- Testing GET /users/user-123 --- Status: 200 OK ✅ GET /users passed --- Testing POST /webhook --- Status: 200 OK ✅ POST /webhook passed --- Testing invalid signature (should fail with 401) --- Status: 401 Unauthorized ✅ Invalid signature correctly rejected === Results: 3 passed, 0 failed === ``` The third test shows ✅ even though the server returned 401. This is a negative test — it verifies your server correctly rejects unauthorized requests. If it returned 200 instead, that would mean your server accepts any request, which is a security issue. ## Compliance reports Once your integration is running, compliance reports are generated automatically. Here's how the report lifecycle works: ```mermaid theme={null} flowchart TD A[Wavy Node monitors registered addresses] --> B[Transactions detected and stored with USD value] B --> C{Monthly cron - 1st of each month} C --> D[Group transactions by user] D --> E{User total > 210 UMAs?} E -->|Yes| F[GET /users/foreign_user_id] F --> G[Generate compliance XML] G --> H[Upload report to storage] H --> I[Notify project admins by email] E -->|No| J[No report needed] ``` For Mexican legislation, reports are generated when a user's monthly transaction total exceeds 210 UMAs (\~\$24,635 MXN). The threshold is updated automatically based on the current UMA value. Query your reports via the API: ```bash theme={null} curl -H "x-api-key: $WAVYNODE_API_KEY" \ "https://api.wavynode.com/v1/reports?projectId=$PROJECT_ID&period=2026-04&countryCode=MX" ``` ## Next steps Understand how HMAC signature verification works. Full reference for the user data and webhook endpoints. # Quickstart Source: https://docs.wavynode.com/quickstart Integrate Wavy Node into your platform in minutes This guide gets you from zero to monitoring wallet addresses and receiving compliance alerts. By the end, you'll have registered an address, run a risk scan, and know how to access your compliance reports. ## Prerequisites * A [Wavy Node](https://wavynode.com/dashboard) account * Your API key (available in the dashboard) * A project with a `projectId` (found in **Project Settings**) ## Step 1: Set up your credentials Sign up on the Wavy Node dashboard and copy your API key from **Project Settings**. ```bash highlight={1} theme={null} export WAVYNODE_API_KEY="ApiKey wavy_your_api_key_here" export PROJECT_ID="your_project_id" ``` The `x-api-key` header must include the `ApiKey` prefix followed by your key. The correct format is: ```highlight={1} theme={null} x-api-key: ApiKey wavy_your_api_key_here ``` A common mistake is sending only the key without the prefix. Requests without `ApiKey` will be rejected with an authentication error. ## Step 2: Check supported chains Verify which blockchain networks are available: ```bash theme={null} curl -H "x-api-key: $WAVYNODE_API_KEY" \ https://api.wavynode.com/v1/chains ``` ```json theme={null} { "success": true, "data": [ { "id": 42161, "name": "Arbitrum", "rpc_url": "https://arb1.arbitrum.io/rpc", "active": true, "explorer_url": "https://arbiscan.io", "currency_symbol": "ETH", "currency_decimals": 18 } ] } ``` ## Step 3: Register an address for monitoring Add a wallet address to your project so Wavy Node can monitor it: ```bash theme={null} curl -X POST "https://api.wavynode.com/v1/projects/$PROJECT_ID/addresses" \ -H "Content-Type: application/json" \ -H "x-api-key: $WAVYNODE_API_KEY" \ -d '{ "address": "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045", "description": "Main treasury wallet", "foreign_user_id": "user-001" }' ``` The `foreign_user_id` links this wallet to a user in your system. When you set up an [integration](/integrations/overview), Wavy Node uses this ID to request user data for compliance reports. ## Step 4: Run a risk scan Query risk analysis results for the registered address: ```bash theme={null} curl -H "x-api-key: $WAVYNODE_API_KEY" \ "https://api.wavynode.com/v1/projects/$PROJECT_ID/addresses/scan-risk?addresses=0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045&chainId=1" ``` ```json theme={null} { "success": true, "data": { "total": 1, "missing": 0, "results": [ { "analysisId": "550e8400-e29b-41d4-a716-446655440000", "address": "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045", "chainId": "1", "riskScore": 5, "riskLevel": "minimal", "riskReason": "Normal activity, no suspicious patterns detected", "suspiciousActivity": false, "patternsDetected": [], "transactionsAnalyzed": 150, "completedAt": "2024-02-13T10:30:00Z" } ] } } ``` A `riskScore` under 20 indicates minimal risk. Addresses scoring above 60 should be investigated further. ## Step 5: Access compliance reports Compliance reports are generated automatically based on your project's activity and active legislations. Retrieve them with: ```bash theme={null} curl -H "x-api-key: $WAVYNODE_API_KEY" \ "https://api.wavynode.com/v1/reports?projectId=$PROJECT_ID&period=2026-04&countryCode=MX" ``` Download a specific report: ```bash theme={null} curl -H "x-api-key: $WAVYNODE_API_KEY" \ "https://api.wavynode.com/v1/reports/rpt_abc123" ``` ```json theme={null} { "success": true, "data": { "name": "LFPIORPI_April_2026.pdf", "signedUrl": "https://storage.wavynode.com/reports/...", "period": "2026-04" } } ``` Reports are available for México (MX), Colombia (CO), El Salvador (SV), and Guatemala (GT). ## What's next You've registered an address and run your first risk scan. To receive real-time alerts and enable automatic compliance report generation, set up an integration: ```mermaid theme={null} flowchart LR A[✅ Quickstart] --> B[Set up Wavy Node integration] B --> C[Scan risk on addresses] B --> D[Receive real-time alerts] B --> E[Auto-generate compliance reports] ``` Connect your app to receive webhooks and serve user data for compliance. Understand how risk scores are calculated. Explore the regulations Wavy Node covers. Browse all available endpoints.