# Range AI Source: https://docs.range.org/ai/introduction Connect your AI assistant to Range's workspace data and onchain intelligence over MCP. Range AI exposes your existing Range API key as an **MCP (Model Context Protocol) server**: the open standard for giving AI assistants access to external tools. Once connected, you can pull up your workspace's accounts and alerts, screen addresses for risk and sanctions, trace fund flows, and analyze cross-chain activity entirely through natural language, using any MCP-compatible client. No new credentials. No separate service. The same API key you already use. Most tools are **read-only**. Four mutating tools (`add_accounts`, `create_counterparty`, `add_counterparty_addresses`, `create_alert_rule`) can create workspace records. They require a workspace-user key whose member has **EDITOR** role or higher. The API keys the dashboard issues are managed workspace keys, which carry no member and cannot call them. See [key types](/ai/quickstart#key-types-and-workspace-access). ## What you can do Pull up tracked accounts, balances, alert rules, counterparties, and transfer categorization from your own workspace. Run the v2 screening pipeline or the v1 risk score, check OFAC, UK, EU, and other sanctions lists plus token blacklists, across Ethereum, Tron, Solana, and more. Trace fund flows, identify counterparties, find the origin of funds, and produce investigation reports, all from a single prompt. Add the MCP endpoint to Claude Desktop, Claude.ai, or Cursor. Your API key is the only thing required. ## What's available today 85 tools across these categories: | Category | Tools | What it covers | | - | - | - | | Workspace & Account Management | 7 | Tracked accounts, balances, groups, linked connections; add on-chain wallets | | Workspace Admin & Plans | 6 | Workspace identity, plans, member counts, credit usage, masked API key inventory | | Alerts & Rules | 9 | Alert rules, fired events, templates, delivery channels; create a rule from a template | | Counterparties & Enrichment | 7 | Vendors/customers/partners, transfer notes and categories; create counterparties and addresses | | Documentation | 3 | Product overview, docs search, and full page fetch by slug | | Screening & Risk | 13 | v2 screening pipeline (attribution/exposure/behaviour), v1 graph-based risk score, sanctions/blacklist checks | | Address Intelligence | 11 | Labels, connections, transactions, payments, asset flow, balances, stats, funded-by | | Transfers & Transaction Detail | 3 | Token transfer history, transfers between two addresses, transaction details | | Network & Token Stats | 12 | Whale moves, network volume, active accounts, token supply and holders | | Explorer Stats & Utilities | 14 | Leaderboards, cross-chain flow, transaction search, plain-language transaction explanation, entity directory | **MCP endpoint:** `https://api.range.org/ai/mcp` ## What's coming * **Investigation Copilot**: a chat interface inside the Range dashboard for instant wallet investigations * **Automated report generation**: one prompt produces a structured investigation report ready for compliance review * **Alert narratives**: AI explanations attached to real-time risk alerts ("why did this address flag?") * **Natural language queries**: "show all wallets that received funds from Tornado Cash in the last 30 days" Connect your AI client in 5 minutes. Browse all 85 available MCP tools. # Investigation Playbook Source: https://docs.range.org/ai/investigation-playbook How to investigate a suspicious blockchain wallet from first look to final report using Range AI tools. This playbook shows how to run a complete blockchain investigation using Range MCP tools inside any AI client. The workflow applies to any suspicious address, whether you received it as a counterparty, found it in a transaction, or are screening for compliance. Before starting, make sure Range is connected to your AI client. See the [Quickstart](/ai/quickstart) if you haven't done that yet. *** ## The investigation workflow The first call in any investigation. Get the address risk score to understand the severity before going deeper. **Tool:** `get_address_risk` Ask your AI: ``` What is the risk score for [address] on [network]? ``` **What to look for:** * Risk level CRITICAL or HIGH → escalate, investigate thoroughly * Malicious hops in the graph → the address is connected to known bad actors even if not directly flagged * Entity attribution → if it's labeled as a mixer, exchange, or sanctioned entity, that's immediately actionable Independent of risk scoring, check whether the address appears on a sanctions list (OFAC, UK, EU, France, Japan, and more) or has been blacklisted by stablecoin issuers. **Tool:** `check_sanctions` Ask your AI: ``` Is [address] on any sanctions list or token blacklist? ``` **What to look for:** * `is_sanctioned: true` → immediate compliance action required; `sanctions` names each list (`is_ofac_sanctioned` covers OFAC only) * `lists_checked: false` → a list could not be read; the result is unknown, not clean * `is_token_blacklisted: true` → USDT/USDC/USDC.e transfers may be frozen * Check the event history for when and why it was listed Identify who the address has been transacting with. This is the core of any fund flow investigation. **Tool:** `get_address_connections` Ask your AI: ``` Who are the top counterparties for [address] on [network]? Show me their labels if available. ``` **What to look for:** * Direct connections to exchanges (good, funds may be traceable) * Direct connections to mixers or privacy protocols (red flag) * Unlabeled counterparties that appear frequently (investigate those too) Dig into the actual transfers, amounts, tokens, timing, and direction. **Tools:** `get_transfers`, `get_transfers_between` Ask your AI: ``` Show me the largest transfers in and out of [address] in the last 90 days. Are there any transfers between [address] and [suspicious counterparty]? ``` **What to look for:** * Rapid in/out patterns (layering behavior) * Large USD amounts with no clear business purpose * Bridge transfers (IBC, CCTP) used to move funds cross-chain quickly * Time clustering, many transactions in a short window Trace where the address got its initial funding. The funding source often reveals the true nature of the wallet. **Tool:** `get_address_funded_by` This tool is not available on every network, and not on Solana. For a Solana address, use `get_transfers` or `get_address_payments` to see its funding activity instead. Ask your AI: ``` What address initially funded [address] and when? ``` **What to look for:** * Funded by a sanctioned or high-risk address → high concern * Funded by a known exchange with a verified withdrawal → lower concern * Funded by another unlabeled address → continue tracing that address too For any addresses you don't recognize, look them up in Range's entity database. **Tools:** `search_entities`, `get_address_info` Ask your AI: ``` What entity is [address]? Does Range have any labels for it? Search for any entities matching "Binance" on Ethereum. ``` **What to look for:** * Known exchange hot/cold wallets * Mixer or tumbler addresses * Protocol contracts (DEXes, bridges, lending protocols) * Previously flagged addresses in Range's database If transfers crossed chains via bridges (IBC, CCTP, Wormhole), follow the funds to the destination chain and repeat the investigation there. Ask your AI: ``` Were any funds from [address] bridged to another chain? If so, what is the risk score of the receiving address on that chain? ``` Range covers Cosmos, Solana, EVM, Stellar, and Tron, you can pivot across all of them without switching tools. *** ## Complete investigation prompt Paste this into Claude Desktop or Claude.ai for a full investigation in one shot: ``` Using Range tools, run a complete investigation on this address: [address] on [network] 1. Get its risk score and explain the risk level 2. Check if it's on any sanctions list or token blacklist 3. Show its top 10 counterparties and label any known entities 4. List the 10 largest transfers in the last 6 months 5. Find the original funding source for this address 6. If any transfers crossed chains via a bridge, check the receiving address risk too Summarize your findings with a risk verdict: LOW / MEDIUM / HIGH / CRITICAL Include the key evidence that supports your verdict. ``` *** ## Example output **Address:** `5Q544fKrFoe6tsEbD7S8EmxGTJYAKtTVhAW5Q5pge4j1` **Network:** Solana **Risk Assessment** * Risk level: VERY\_LOW (score: 1/10) * Entity: Raydium Protocol (DEX liquidity authority) * No OFAC sanctions, no token blacklist entries **Connection Graph** * 500+ unique counterparties * Primarily interacts with known Solana DeFi protocols and user wallets * No connections to mixers or sanctioned addresses **Verdict: LOW RISK** This is a verified Raydium Protocol contract address used for AMM liquidity management. The volume and counterparty diversity are consistent with a legitimate high-traffic DeFi protocol. *** ## Using your workspace data If your API key is workspace-scoped, you can fold your own workspace's accounts, alerts, and screening config into the same investigation instead of only looking at public on-chain data. ``` List my active alert rules, then screen this address and show me the full evidence for the result: [address] ``` The AI will call `list_alert_rules` and `screen_address` (passing `include_evidence: true`, or a follow-up `get_screening_evidence` call), scoring the address against your workspace's own risk configuration rather than the fixed public risk score. *** ## Tips for better investigations **Start broad, then narrow.** Use `get_address_risk` and `get_address_connections` first to get the big picture, then use `get_transfers_between` and `get_transaction_details` to zoom into specific relationships. **Use time filters.** If you know when a suspicious event occurred, filter transfers and payments to that window. This dramatically reduces noise and focuses the AI on what matters. **Chain the graph.** Each suspicious counterparty you find can be a new starting point. Ask the AI to run `get_address_risk` on any unlabeled counterparty that shows up frequently. # AI Quickstart Source: https://docs.range.org/ai/quickstart Connect Claude, Cursor, or any MCP-compatible AI client to Range in under 5 minutes. ## Prerequisites * A Range API key, get one at [app.range.org/keys](https://app.range.org/keys) * An MCP-compatible AI client (Claude Desktop, Claude.ai, Cursor, or any OpenAI-compatible tool) You use the same API key you already have. No new credentials, no separate signup. ## MCP endpoint ``` https://api.range.org/ai/mcp ``` This endpoint speaks the [Model Context Protocol](https://modelcontextprotocol.io) over Streamable HTTP. Every call is authenticated with your existing API key. ### Key types and workspace access * **`Authorization: Bearer `** is the recommended way to authenticate. An `x-api-key: ` header is also accepted as an alternative. * The server is **stateless**: no session id is issued or required. Every request is independent and authenticated on its own, so connections are unaffected by server maintenance or restarts. The server accepts three types of key. What a key can call depends on whether it carries a workspace and a workspace member: | Key type | Format | Workspace member and role | What it can call | | - | - | - | - | | Managed workspace key | `.` | None | Every read tool, including the workspace-scoped tools. Not the four mutating tools or `get_current_member`. | | Workspace-user key | `.` | One member, with a role (**READER**, **EDITOR**, or **ADMIN**) | Every read tool, including the workspace-scoped tools. The four mutating tools require **EDITOR** or higher. | | Legacy/global key | No workspace prefix | None | Only the tools that are not workspace-scoped (address intelligence, risk, network/token stats, explorer tools, and the global screening/plan catalogues). | * **The API keys you create in the dashboard at [app.range.org/keys](https://app.range.org/keys) are managed workspace keys.** They are scoped to your workspace but carry no member and no role. They can call every read tool, but not the four mutating tools (`add_accounts`, `create_counterparty`, `add_counterparty_addresses`, `create_alert_rule`) or `get_current_member`. A mutating tool called with a managed key returns an error instead of making a change. * A **workspace-user key** is the `.` credential a signed-in Range app session presents. It identifies one workspace member and that member's role. The dashboard's API keys page does not issue this type of key. * The **workspace-scoped** tools cover accounts, balances, alerts, counterparties, transfer enrichment, and the v2 screening pipeline. Calling one with a legacy key returns a clear error asking for a workspace-scoped key instead of silently returning empty data. ### API key scopes When creating an API key you choose which APIs it can read: * **Risk API** covers risk scoring, sanctions/OFAC checks, and the screening pipeline (risk scores, screening evidence and history). * **Data API** covers blockchain data reads: addresses, transactions, transfers, tokens, and network/explorer analytics. * **Platform API** covers your workspace's own product data: accounts, balances, groups, alert rules and events, counterparties, and transfer notes. **A managed key needs the Data API scope to connect.** The MCP endpoint checks the key's Data API scope on every request and refuses a managed key that does not have it enabled. The tools span all three areas, so enable all three scopes when you create a key for MCP. Scopes do not grant write access: the mutating tools require a workspace-user key whose member has **EDITOR** role or higher. See the [Tools Reference](/ai/tools-reference) for which tools are workspace-scoped or mutating. *** ## Connect your client Open your Claude Desktop config file: * **macOS:** `~/Library/Application Support/Claude/claude_desktop_config.json` * **Windows:** `%APPDATA%\Claude\claude_desktop_config.json` Add the Range server under `mcpServers`: ```json theme={null} { "mcpServers": { "range": { "type": "http", "url": "https://api.range.org/ai/mcp", "headers": { "Authorization": "Bearer YOUR_API_KEY" } } } } ``` Restart Claude Desktop. You should see "range" appear in the tools panel (hammer icon). In [Claude.ai](https://claude.ai), go to **Settings → Integrations → Add MCP Server**: * **Name:** Range * **URL:** `https://api.range.org/ai/mcp` * **Authentication:** Custom header * Header: `Authorization` * Value: `Bearer YOUR_API_KEY` Save and refresh. Range tools will be available in any new conversation. Open Cursor settings (`Cmd/Ctrl + ,`) and navigate to **Features → MCP Servers**. Add a new server: ```json theme={null} { "range": { "type": "http", "url": "https://api.range.org/ai/mcp", "headers": { "Authorization": "Bearer YOUR_API_KEY", "Accept": "application/json, text/event-stream" } } } ``` Or add it to your `.cursor/mcp.json` file in any project directory to scope it per-project. The server is stateless: no session id is issued or required, and every request stands on its own. You can call any method directly. MCP clients (Claude Desktop, Claude.ai, Cursor, etc.) still send an `initialize` handshake automatically when they connect. That's part of the protocol and works as normal. Statelessness just means you don't have to manage a session id yourself when testing with `curl`, Postman, or a custom client. **List the available tools:** ```bash theme={null} curl -X POST https://api.range.org/ai/mcp \ -H "Content-Type: application/json" \ -H "Accept: application/json, text/event-stream" \ -H "Authorization: Bearer YOUR_API_KEY" \ -d '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}' ``` **Call a tool:** ```bash theme={null} curl -X POST https://api.range.org/ai/mcp \ -H "Content-Type: application/json" \ -H "Accept: application/json, text/event-stream" \ -H "Authorization: Bearer YOUR_API_KEY" \ -d '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"check_sanctions","arguments":{"address":"0x7F367cC41522cE07553e823bf3be79A889DEbe1B"}}}' ``` A successful `tools/list` response returns a JSON array of 85 tools. *** ## Your first investigation Once connected, paste this prompt into your AI client: ``` Investigate this wallet and tell me if I should be concerned about it: 5Q544fKrFoe6tsEbD7S8EmxGTJYAKtTVhAW5Q5pge4j1 Check its risk score, see if it's sanctioned, find its top counterparties, and summarize what kind of entity this appears to be. ``` The AI will call `get_address_risk`, `check_sanctions`, `get_address_connections`, and `get_address_info` autonomously and return a structured summary. *** ## Next steps Browse all 85 tools with parameters and descriptions. Learn the full step-by-step investigation workflow. # MCP Tools Reference Source: https://docs.range.org/ai/tools-reference All 85 tools available in the Range MCP server, organized by category. The Range MCP server exposes **85 tools** across 10 categories: workspace and account data, alerts, counterparties, product documentation, screening and risk, and blockchain analytics (address intelligence, transfers, network/token stats, and explorer utilities). Most tools are read-only; four mutating tools can create workspace records and require a workspace-user key whose member has EDITOR role or higher. Every tool returns JSON and handles errors gracefully: your AI client receives a clear error message rather than an exception when something goes wrong. **Endpoint:** `https://api.range.org/ai/mcp` **Auth:** `Authorization: Bearer ` (or `x-api-key: `) Tools marked **Workspace-scoped** require a key scoped to a workspace: either a managed workspace key (`.`, the type the dashboard issues) or a workspace-user key (`.`), not a legacy/global key. Calling a workspace-scoped tool with a legacy key returns a clear error asking for a workspace-scoped key instead of silently returning empty or wrong data. Tools marked **Mutating** additionally require a workspace-user key whose member has **EDITOR** role or higher. A managed workspace key carries no member and no role, so it cannot call them. See the [Quickstart](/ai/quickstart#key-types-and-workspace-access) for the key types. *** ## Workspace & Account Management Accounts, balances, groups, and connections tracked inside your Range workspace: wallets, exchange accounts, custodial accounts, multisigs, and bank accounts. List accounts tracked in the caller workspace: on-chain wallets, exchange accounts, custodial accounts, multisigs, and bank accounts. Supports filtering by group, account type, connection provider, chain, or connection id. Use this for portfolio/treasury overviews before drilling into a single account with `get_account`. **Workspace-scoped.** | Parameter | Type | Required | Description | | - | - | - | - | | `cursor` | string | No | Opaque pagination cursor from a previous response `meta.next_cursor`. | | `size` | integer | No | Number of accounts to return (1-100). Default: `20`. | | `group_id` | string | No | Filter to accounts that are members of this group id. | | `type` | string | No | Filter by account type: `eoa`, `multisig`, `contract`, `custodian`, `exchange`, `bank`, `defi`. | | `provider` | string | No | Filter to accounts held under a connection of this provider: `utila`, `kraken`, `binance`, `okx`, `bybit`, `bitget`, `gate`, `kucoin`, `plaid`, `squads`, `altitude`, `coinbase`, `realms`, `safe`, `wise`, `hyperliquid`, `cubist`, `anchorage`, `privy`, `dfns`, `revolut_business`, `turnkey`, `fordefi`, `coins_ph`, `fireblocks`, `pave_bank`, `copper`, `custom`. | | `chain` | string | No | Filter by network/chain identifier. Examples: `ethereum`, `solana`, `stellar`. | | `connection_id` | string | No | Filter to accounts held under this account-connection id. | Get a single account in the caller workspace by its id, including balances, connection details, and group membership. Returns null if no account with that id exists in the workspace. **Workspace-scoped.** | Parameter | Type | Required | Description | | - | - | - | - | | `id` | string | Yes | Account id, as returned by `list_accounts`. | Get current balances for every account stored in the caller workspace, grouped by address/network with per-asset amounts and USD values. Use for a quick total-holdings snapshot across the whole workspace. **Workspace-scoped.** No parameters. List all groups defined for the caller workspace, including built-in system groups. Groups are used to tag/organize accounts (e.g. "Finance", "Cold Storage") and can be passed as `group_id` to `list_accounts`. **Workspace-scoped.** No parameters. List account connections (linked custodian/exchange/bank/multisig integrations such as Utila, Kraken, Plaid, Safe, Squads) configured in the caller workspace. Only non-sensitive public metadata is returned; provider credentials and secrets are never exposed. **Workspace-scoped.** | Parameter | Type | Required | Description | | - | - | - | - | | `cursor` | string | No | Opaque pagination cursor from a previous response `meta.next_cursor`. | | `size` | integer | No | Number of connections to return (1-100). Default: `20`. | Get transactions merged across every connection-linked account in the caller workspace (e.g. Kraken trades, Utila custody transfers, bank transactions), sorted newest-first. Cursor-paginated: pass `meta.next_cursor` back as `cursor` to fetch the next page. Optionally filter by asset symbols, date range, status, USD amount, or a free-text search. Connections whose provider doesn't support transactions, or that fail to fetch, are skipped. **Workspace-scoped.** | Parameter | Type | Required | Description | | - | - | - | - | | `cursor` | string | No | Opaque pagination cursor from a previous response `meta.next_cursor`. | | `size` | integer | No | Maximum transactions to return after merging and sorting newest-first (1-100). Default: `20`. | | `tokens` | string\[] | No | Asset symbols to filter by, e.g. `["USDC", "ETH"]`. Matched case-insensitively against the transaction's displayed asset. | | `start_time` | string | No | Start of date range (ISO 8601). | | `end_time` | string | No | End of date range (ISO 8601). | | `status` | string\[] | No | Transaction statuses to include: `PENDING`, `CONFIRMED`, `FAILED`. | | `min_usd` | number | No | Minimum USD amount. | | `max_usd` | number | No | Maximum USD amount. | | `string_search` | string | No | Case-insensitive substring search over id, hash, network, assets, and counterparty addresses. | Add one or more on-chain wallet accounts to the caller workspace, each identified by address + network with an optional display name. ADD ONLY: cannot update or remove existing accounts, link groups, or attach provider connections. **Workspace-scoped. Mutating**: requires a workspace-user key whose member has EDITOR role or higher. A managed workspace key cannot call it. | Parameter | Type | Required | Description | | - | - | - | - | | `accounts` | object\[] | Yes | Accounts to add (1-1000). Each entry: `address` (string), `network` (string), optional `name` (string; omit to leave unnamed, an empty string is rejected). | *** ## Workspace Admin & Plans Workspace identity, member counts, credit usage, masked API key inventory, and the global Range plan catalogue. Get the calling workspace's identity: workspace id and name, resolved server-side from the caller's API key. Use when the user asks about their own workspace. Per-workspace plan assignment is not yet accessible via the Range API, so no plan is returned; use `get_workspace_plans` for the global plan catalogue. Returns `found: false` if the workspace has no stored record yet. **Workspace-scoped.** No parameters. Get every Range subscription plan definition, with numeric rank and per-feature limits (max alert rules, trail/investigation tabs, tracked addresses). This is the global plan catalogue, not the caller workspace's current plan assignment. **Not workspace-scoped**: works with any valid API key. No parameters. Get the caller's own workspace-member identity (user id, email, role, workspace id), resolved server-side from the caller's key. Only available with a workspace-user key. Managed workspace keys and legacy keys have no associated member; called with one, this tool returns an explanatory message instead of an identity. **Workspace-scoped.** No parameters. Get the caller workspace's member headcount plus a breakdown by role (ADMIN/EDITOR/READER). Returns aggregate counts only, never individual member identities. **Workspace-scoped.** No parameters. Get the caller workspace's API credit usage for the current billing period: credits used/limit/remaining, reset date, and a breakdown by operation family. Reflects traffic charged against API keys only: calls made from the Range app web UI are not metered against credits and do not appear here. **Workspace-scoped.** No parameters. List API keys provisioned for the caller workspace. Raw secrets are never returned; each key is identified by its last 4 characters plus enabled feature scopes (risk/data/platform). **Workspace-scoped.** No parameters. *** ## Alerts & Rules Alert rules, fired events, templates, and delivery channels configured for your workspace. List the active alert rules configured for the authenticated workspace. An alert rule is a live subscription (created from a template) that fires alert events when its trigger condition is met. Filter by network, severity, or a name search. **Workspace-scoped.** | Parameter | Type | Required | Description | | - | - | - | - | | `network` | string | No | Comma-separated network slugs to filter by. Examples: `eth,sol`. | | `severity` | string | No | Comma-separated severities to filter by. Examples: `low,medium,high`. | | `search_string` | string | No | Case-insensitive substring search against the rule name. | | `limit` | integer | No | Maximum rules to return (1-100). Default: `20`. | Get a single alert rule by id, including its parameters, trigger, version, subscribed channels, and the template it was created from. **Workspace-scoped.** | Parameter | Type | Required | Description | | - | - | - | - | | `rule_id` | string | Yes | The alert rule id. | Create an alert rule from a registered template. Supply the template id; `rule_type`, `network`, and `runner_id` are copied from it. Creates a live, enabled rule in the caller workspace. **Workspace-scoped. Mutating**: requires a workspace-user key whose member has EDITOR role or higher. A managed workspace key cannot call it. | Parameter | Type | Required | Description | | - | - | - | - | | `template_id` | string (uuid) | Yes | Alert rule template to instantiate (see `list_alert_templates`). | | `name` | string | Yes | Display name for the new rule. | | `severity` | string | No | Severity override; defaults to the template severity. | | `parameters` | object | No | Rule parameter values as `{field: value}` (an array of `{field, value}` pairs is also accepted). Defaults to the template defaults. | | `trigger` | string | No | Trigger cadence override: `BLOCK` or `TICK`. Defaults to the template trigger. | List alert events (fired instances of alert rules) for the authenticated workspace, newest first. Filter by network, severity, exact transaction hash, a UTC date range, or a full-text search across the event caption and involved addresses. Cursor-paginated. **Workspace-scoped.** | Parameter | Type | Required | Description | | - | - | - | - | | `network` | string | No | Filter by network slug. Example: `ethereum`. | | `severity` | string | No | Comma-separated severities to filter by. Examples: `low,medium,high`. | | `tx_hash` | string | No | Filter by exact transaction hash. | | `start_date` | string | No | Start of date range, inclusive, UTC, `YYYY-MM-DD`. Example: `2026-05-01`. | | `end_date` | string | No | End of date range, inclusive, UTC, `YYYY-MM-DD`. Example: `2026-05-31`. | | `search_string` | string | No | Case-insensitive search across the event caption and involved addresses. | | `cursor` | string | No | Opaque pagination cursor from a previous response (`next_cursor`/`previous_cursor`). Omit for the first page. | | `limit` | integer | No | Maximum events to return in this page (1-100). Default: `20`. | Get a single alert event by id. Returns the fired event with its timestamp, severity, caption, involved addresses, structured details, and `access_type` (the caller workspace's relationship to the event). **Workspace-scoped.** | Parameter | Type | Required | Description | | - | - | - | - | | `event_id` | string | Yes | CUID of the alert event to retrieve. | List the alert rule templates available to the authenticated workspace, grouped by rule type with the networks each covers. A template is the blueprint an alert rule is created from. Filter by network, severity, tags, or a name/description search. **Workspace-scoped.** | Parameter | Type | Required | Description | | - | - | - | - | | `network` | string | No | Comma-separated network slugs to filter by. Examples: `eth,sol`. | | `severity` | string | No | Comma-separated severities to filter by. Examples: `low,medium,high`. | | `tag` | string | No | Comma-separated tags to filter by. Examples: `defi,transfer`. | | `search_string` | string | No | Case-insensitive search matched against the template label and description. | | `limit` | integer | No | Maximum template groups to return (1-100). Default: `20`. | Get a single alert rule template by id. Returns its message, severity, tags, trigger cadence, and the parameters required to turn it into an active alert rule. **Workspace-scoped.** | Parameter | Type | Required | Description | | - | - | - | - | | `template_id` | string | Yes | The alert rule template id (per-network template pointer). | List the alert delivery channels (Slack, Discord, PagerDuty, email, webhook, Telegram, incident.io, etc.) configured for the authenticated workspace, including disabled ones. Sensitive delivery params (email addresses, tokens) are redacted. **Workspace-scoped.** | Parameter | Type | Required | Description | | - | - | - | - | | `limit` | integer | No | Maximum channels to return (1-100). Default: `20`. | Get a single alert delivery channel by id, including its type, enabled/connected status, and type-specific delivery params. Sensitive params are redacted; this never returns raw delivery secrets. **Workspace-scoped.** | Parameter | Type | Required | Description | | - | - | - | - | | `channel_id` | string | Yes | The alert channel id. | *** ## Counterparties & Enrichment Vendors, customers, investors, and partners recorded in your workspace, plus the notes and categories attached to transfers. List counterparties (vendors, customers, investors, partners, exchanges, etc.) recorded for the workspace, with optional type/name filtering. Use this to find a counterparty before looking up its details, addresses, or bank accounts. **Workspace-scoped.** | Parameter | Type | Required | Description | | - | - | - | - | | `type` | string | No | Filter by relationship type: `vendor`, `customer`, `investor`, `partner`, `exchange`, `other`. | | `search` | string | No | Case-insensitive substring search on counterparty name. | | `limit` | integer | No | Number of counterparties to return (1-100). Default: `20`. | | `cursor` | string | No | Pagination cursor from a previous response. | Get full details for a single counterparty by id: name, type, website, notes, linked addresses, bank accounts, and document metadata. Use `list_counterparties` first to find the id. **Workspace-scoped.** | Parameter | Type | Required | Description | | - | - | - | - | | `id` | string | Yes | Counterparty id, from `list_counterparties`. | Create a counterparty (vendor, customer, investor, partner, exchange, or other) in the caller workspace, optionally with initial crypto addresses and bank accounts. **Workspace-scoped. Mutating**: requires a workspace-user key whose member has EDITOR role or higher. A managed workspace key cannot call it. | Parameter | Type | Required | Description | | - | - | - | - | | `name` | string | Yes | Display name; must be unique per workspace. | | `type` | string | Yes | `vendor`, `customer`, `investor`, `partner`, `exchange`, or `other`. | | `website` | string | No | http(s) URL. | | `notes` | string | No | Free-form notes. | | `addresses` | object\[] | No | Initial crypto addresses: `{address, network, label?}`. | | `bank_accounts` | object\[] | No | Initial fiat bank accounts (`currency`, `bank_name`, optional IBAN/SWIFT/etc.). | Add one or more crypto addresses to an existing counterparty in the caller workspace. ADD ONLY: cannot update or remove existing addresses. **Workspace-scoped. Mutating**: requires a workspace-user key whose member has EDITOR role or higher. A managed workspace key cannot call it. | Parameter | Type | Required | Description | | - | - | - | - | | `counterparty_id` | string (uuid) | Yes | Counterparty id from `list_counterparties`; must belong to the caller workspace. | | `addresses` | object\[] | Yes | Addresses to add (min 1): `{address, network, label?}`. | Look up the workspace note and category recorded against a transfer, identified by its on-chain transaction hash and network. Returns an empty result if the transfer has not been enriched or cannot be found. **Workspace-scoped.** | Parameter | Type | Required | Description | | - | - | - | - | | `tx_hash` | string | Yes | On-chain transaction hash. | | `network` | string | Yes | Blockchain network the transaction hash belongs to. Examples: `ethereum`, `solana`, `cosmoshub-4`. | List free-text notes the workspace has attached to transfers. Omit `transfer_id` to list all notes for the workspace, or pass it to fetch a single transfer's note. **Workspace-scoped.** | Parameter | Type | Required | Description | | - | - | - | - | | `transfer_id` | string | No | If provided, return only the note for this transfer id. Otherwise, list all notes for the workspace. | | `limit` | integer | No | Maximum notes to return (1-100). Default: `20`. | List the accounting/spend categories the workspace has assigned to transfers (e.g. Payroll, Revenue, Gas Fees). Optionally filter to a single transfer or a set of category names. Use `get_risk_categories`/`list_risk_signals` for risk taxonomy instead; this is transfer bookkeeping, not risk. **Workspace-scoped.** | Parameter | Type | Required | Description | | - | - | - | - | | `transfer_id` | string | No | If provided, return only the category assigned to this transfer id. | | `categories` | string\[] | No | Filter results to these category names: `Transfer`, `Revenue`, `Payroll`, `Contract Services`, `Software & Subscriptions`, `Legal & Professional Services`, `Taxes`, `Bank Fees`, `Payment Processing Fees`, `Interest Earned`, `Marketing & Advertising`, `Travel & Transportation`, `Rent & Utilities`, `Insurance`, `Gas Fees`, `Staking Rewards`, `Bridge Transfer`, `DeFi Yield`, `Swap`, `Airdrop`. Any other value is rejected. | | `limit` | integer | No | Maximum categories to return (1-100). Default: `20`. | *** ## Documentation Product documentation tools for answering "does Range support X?" style questions. Always call `get_range_overview` first for product/company questions before searching or fetching a page. Get top-level context on what Range is, plus the full table of contents of Range's product documentation (tab → group → page title/slug/description). Global tool, not workspace-scoped. **Not workspace-scoped.** No parameters. Keyword search over Range product documentation (title, description, and body). Case-insensitive term matching; title/description matches rank above body matches. Returns ranked results with a short snippet, not semantic search. **Not workspace-scoped.** | Parameter | Type | Required | Description | | - | - | - | - | | `query` | string | Yes | Keyword(s) to search for, e.g. `Plaid`, `Revolut`, `supported providers`. | | `limit` | integer | No | Max ranked results to return (1-20). Default: `5`. | Get one full documentation page (title, description, tab/group location, and full text) by its slug. Slugs come from `get_range_overview` or `search_documentation`; never guess a slug. **Not workspace-scoped.** | Parameter | Type | Required | Description | | - | - | - | - | | `slug` | string | Yes | Page slug, e.g. `risk-api/product-info/supported-chains`. | *** ## Screening & Risk The v2 screening pipeline (workspace-configurable attribution/exposure/behaviour signals) and the v1 graph-based risk tools (fixed scoring, no workspace configuration). Use `screen_address` when the workspace has customized its risk signals; use `get_address_risk` for the fixed graph-based score. Run the v2 screening pipeline against a single blockchain address: workspace-configurable attribution, exposure, and behaviour signals, reduced to an overall severity (`none`/`low`/`medium`/`high`/`severe`). Evidence is omitted by default; pass `include_evidence=true` for it inline, or fetch it later with `get_screening_evidence` using the returned `screen_id`. **Workspace-scoped.** | Parameter | Type | Required | Description | | - | - | - | - | | `address` | string | Yes | Blockchain address to screen. Accepts EVM (`0x...`), Solana (base58), Stellar (`G.../M...`), Cosmos bech32, and Tron formats. Network is derived automatically from the address format. | | `window` | string | No | Time window for analysis: `30d`, `90d`, `180d`, `365d`, or `all`. Accepted for parity with the REST endpoint; not yet wired into the scoring pipeline (all available history is currently considered regardless of this value). | | `include_evidence` | boolean | No | If true, include the full per-signal evidence breakdown inline. Solana addresses always include evidence regardless of this flag. Default: `false`. | Run the v2 screening pipeline (see `screen_address`) against up to 50 addresses in one call. Network is derived per-address from its format. Per-address failures do not fail the whole batch; check the response `meta` (total/scored/errors) for partial-failure counts. **Workspace-scoped.** | Parameter | Type | Required | Description | | - | - | - | - | | `addresses` | string\[] | Yes | Addresses to screen (1-50). Mixed networks are fine; network is derived per-address. | | `include_evidence` | boolean | No | If true, include the full per-signal evidence breakdown inline for each result. Solana addresses always include evidence regardless of this flag. Default: `false`. | List past v2 screening results (`screen_address` / `screen_addresses_batch` calls) for the calling workspace, most recent first. Use this to re-find a `screen_id` without re-running a screen. **Workspace-scoped.** | Parameter | Type | Required | Description | | - | - | - | - | | `offset` | integer | No | Number of records to skip, for pagination. Default: `0`. | | `limit` | integer | No | Page size (1-100). Default: `20`. | Get the full evidence breakdown for a previously issued `screen_id` (from `screen_address`, `screen_addresses_batch`, or `get_screening_history`), grouped by pillar (attribution, exposure, behaviour) and signal, alongside the original risk assessment. **Workspace-scoped**: the `screen_id` must belong to the calling workspace. | Parameter | Type | Required | Description | | - | - | - | - | | `screen_id` | string | Yes | `screen_id` returned by `screen_address`, `screen_addresses_batch`, or `get_screening_history`. | Get the calling workspace's active v2 risk configuration: which attribution signals, exposure signals, and behaviours are enabled and at what severity/thresholds. A workspace with no stored config gets a seeded default on first read. Use `list_risk_signals` to see the full catalogue available to configure. **Workspace-scoped.** No parameters. List the global catalogue of attribution signals, exposure signals, and behaviours available across all workspaces for the v2 screening pipeline. This is read-only reference metadata. It is not auto-applied to any workspace; see `get_screening_config` for what a specific workspace actually has enabled. **Not workspace-scoped**: works with any valid API key. No parameters. Get the calling workspace's v1 risk category settings (legacy category taxonomy used for address/entity labelling, e.g. sanctions, mixer, scam). This is a separate, older configuration surface from the v2 signals/behaviours exposed via `get_screening_config`/`list_risk_signals`. **Workspace-scoped.** No parameters. Get the calling workspace's v1 behavior pattern settings (legacy behaviour taxonomy, e.g. smurfing, structuring). This is a separate, older configuration surface from the v2 behaviours exposed via `get_screening_config`/`list_risk_signals`. **Workspace-scoped.** No parameters. Get the v1 risk score for a blockchain address. Returns a risk level (VERY\_LOW to CRITICAL), numeric score, reasoning, malicious addresses found in the transaction graph, and entity attribution. Often the first call in an investigation. | Parameter | Type | Required | Description | | - | - | - | - | | `address` | string | Yes | Blockchain address. EVM: `0x...` (42 chars). Solana: base58 (32-44 chars). Stellar: `G...` or `M...` (56 chars). Cosmos: network-prefixed bech32. | | `network` | string | No | Network ID. Examples: `eth`, `solana`, `stellar`, `cosmoshub-4`, `osmosis-1`, `dydx-mainnet-1`, `neutron-1`, `tron`. Auto-detected for EVM/Solana/Stellar if omitted. | Get the risk score for a transaction by hash. Evaluates all addresses involved and returns the highest risk score found with per-address risk details. | Parameter | Type | Required | Description | | - | - | - | - | | `transaction` | string | Yes | Transaction hash to assess. | | `network` | string | No | Network of the transaction. Examples: `solana`, `ethereum`, `cosmoshub-4`. Defaults to `solana` if omitted. | Assess the risk of a proposed cross-chain payment between two addresses. Analyzes sender/recipient risk, interaction history, address poisoning, malicious connections, and behavioral indicators. Returns `overall_risk_level` (LOW/MEDIUM/HIGH/UNKNOWN) with detailed risk factors. | Parameter | Type | Required | Description | | - | - | - | - | | `sender_address` | string | Yes | Sender blockchain address. | | `recipient_address` | string | Yes | Recipient blockchain address. | | `amount` | number | Yes | Payment amount in USD equivalent (must be > 0). | | `sender_network` | string | Yes | Sender network. Examples: `solana`, `ethereum`, `osmosis-1`. | | `recipient_network` | string | Yes | Recipient network. | | `sender_token` | string | No | Token/denom being sent (enables token risk). Example: `EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v`. | | `recipient_token` | string | No | Token/denom being received. | | `timestamp` | string | No | Payment timestamp (ISO 8601). Example: `2025-01-15T10:30:00Z`. | Get the risk score for a token/asset by its contract/mint address. Returns risk level, score, and reasoning for whether a token is associated with scams, rug pulls, or malicious activity. Currently supports Solana tokens. | Parameter | Type | Required | Description | | - | - | - | - | | `asset_address` | string | Yes | Token contract or mint address. Example: `EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v` (USDC on Solana). | | `network` | string | No | Blockchain network. Currently only `solana` is supported. Default: `solana`. | Check if a blockchain address is on a sanctions list or blacklisted by token issuers (Tether, Circle, Coinbase, PayPal, Paxos, Agora, Ripple). Lists: OFAC SDN, UK OFSI, EU (sanctions and Russia packages), France, and Japan, plus Israeli NBCTF seizure orders and FBI IC3 advisories. Returns the same result as [Sanctions & Blacklist Check](/risk-api/risk/get-sanctions-blacklist-check): `is_sanctioned` (any government sanctions list), `sanctions` (one entry per list with `source`, `jurisdiction`, `listed_at`, `programs`, and `basis`), `is_ofac_sanctioned` (OFAC only), and `is_token_blacklisted`, with detailed event history. `lists_checked: false` means a list could not be read: `is_sanctioned` is then `null` unless a listing was found, so treat the address as unknown, not clean. Supports Ethereum, Tron, Solana, Base, Arbitrum, Optimism, Polygon, and Avalanche. | Parameter | Type | Required | Description | | - | - | - | - | | `address` | string | Yes | Blockchain address. Supports EVM (`0x...`), Solana (base58), and Tron (`T...`) formats. | | `network` | string | No | `ethereum`, `tron`, `solana`, `base`, `arbitrum`, `optimism`, `polygon`, or `avalanche`. Any other value is rejected. Does not narrow the check: the address is looked up across every network. | | `include_details` | boolean | No | Include full blacklist event history and attribution. Default: `true`. | *** ## Address Intelligence Labels, connections, transaction history, balances, and behavioral stats for any blockchain address. Get information about a blockchain address including labels, entity name, category, and tags. Identifies whether an address belongs to a known exchange, mixer, protocol, or other entity. | Parameter | Type | Required | Description | | - | - | - | - | | `address` | string | Yes | Blockchain address. | | `network` | string | Yes | Network ID. Examples: `eth`, `solana`, `stellar`, `cosmoshub-4`, `osmosis-1`. | Get counterparty addresses that a given address has interacted with. Essential for tracing money flows and building a transaction graph. Returns connected addresses with labels and transfer statistics. | Parameter | Type | Required | Description | | - | - | - | - | | `address` | string | Yes | Blockchain address to find counterparties for. | | `network` | string | Yes | Network ID. | | `size` | integer | No | Number of counterparty addresses to return (1-100). Default: `10`. | | `start_time` | string | No | Filter connections from this time (ISO 8601). Example: `2024-01-01T00:00:00Z`. | | `end_time` | string | No | Filter connections until this time (ISO 8601). | Get transaction history for a blockchain address with optional filters by time range and status. Returns a paginated list of transactions with amounts, counterparties, and timestamps. Only supports networks with full transaction indexing (Cosmos-ecosystem chains, Stellar, and XRPL EVM, for example `cosmoshub-4`, `osmosis-1`, `celestia`, `stellar`). Not available for EVM networks such as `eth`, `bnb`, `base`, `arb1`, and `pol`, or for `solana`; for those, use `get_transfers` or `get_address_payments`. | Parameter | Type | Required | Description | | - | - | - | - | | `address` | string | Yes | Blockchain address. | | `network` | string | Yes | Network ID. | | `limit` | integer | No | Number of transactions to return (1-500). Default: `50`. | | `offset` | integer | No | Transactions to skip for pagination. Default: `0`. | | `startTime` | string | No | Filter from this time (ISO 8601). | | `endTime` | string | No | Filter until this time (ISO 8601). | | `status` | string | No | Filter by transaction status: `success` or `failed`. | | `msgTypes` | string | No | Filter by message types (comma-separated). | Get detailed statistical features for a blockchain address: transaction counts, volumes, token interactions, active duration, unique counterparties, and daily activity patterns. Use for behavioral analysis. | Parameter | Type | Required | Description | | - | - | - | - | | `address` | string | Yes | Blockchain address. | | `network` | string | Yes | Network ID. | Find the source of funds for a blockchain address: which address initially funded it, when, and with what amount. Critical for tracing the origin of funds in an investigation. Not available on every network, and not on Solana; for funding activity on Solana, use `get_transfers` or `get_address_payments`. | Parameter | Type | Required | Description | | - | - | - | - | | `address` | string | Yes | Blockchain address to find the funding source for. | | `network` | string | Yes | Network ID. | Get current token balances for a blockchain address across all tokens it holds. | Parameter | Type | Required | Description | | - | - | - | - | | `address` | string | Yes | Blockchain address. | | `network` | string | Yes | Network ID. | | `network_type` | string | No | Network architecture type. Examples: `evm`, `solana`, `cosmos`. | | `token_contracts` | string | No | Comma-separated token contract addresses to filter balances. | Get aggregate statistics for a blockchain address: total transaction count, total volume, unique counterparties, active days, and more. Useful for quickly profiling how active an address is. | Parameter | Type | Required | Description | | - | - | - | - | | `address` | string | Yes | Blockchain address. | | `network` | string | Yes | Network ID. Examples: `ethereum`, `solana`, `cosmoshub-4`. | Get the payment history for a blockchain address. Payments are cross-chain and intrachain value transfers. Supports filtering by direction (incoming/outgoing), time range, counterparty address, and message type. | Parameter | Type | Required | Description | | - | - | - | - | | `address` | string | Yes | Blockchain address. | | `network` | string | No | Network ID. Examples: `ethereum`, `solana`, `cosmoshub-4`. | | `limit` | integer | No | Number of payments to return (1-500). Default: `50`. | | `offset` | integer | No | Payments to skip for pagination. Default: `0`. | | `direction` | string | No | Filter by payment direction: `incoming`, `outgoing`, or `both`. Default: `both`. | | `start_time` | string | No | Filter from this time (ISO 8601). Example: `2024-01-01T00:00:00Z`. | | `end_time` | string | No | Filter until this time (ISO 8601). | | `receiver` | string | No | Filter payments involving this counterparty address. | | `receiver_network` | string | No | Network of the counterparty address. | Get full details of a specific payment by its transaction hash. Returns sender, receiver, amounts, token details, and timestamps for a single payment event. | Parameter | Type | Required | Description | | - | - | - | - | | `hash` | string | Yes | Payment or transaction hash to look up. | Get asset flow summary for a blockchain address showing net inflows and outflows per token. Useful for understanding which tokens an address has been accumulating or distributing over time. | Parameter | Type | Required | Description | | - | - | - | - | | `address` | string | Yes | Blockchain address. | | `network` | string | Yes | Network ID. Examples: `ethereum`, `solana`, `cosmoshub-4`. | | `network_type` | string | No | Network architecture type. Examples: `evm`, `solana`, `cosmos`. | Search for known blockchain entities and addresses by name or label. Find exchanges (Binance, Coinbase), mixers (Tornado Cash), protocols (Uniswap), and other labeled addresses. | Parameter | Type | Required | Description | | - | - | - | - | | `search_term` | string | Yes | Name or partial name to search for. Examples: `"Binance"`, `"Coinbase"`, `"Tornado Cash"`. | | `networks` | string | No | Comma-separated blockchain networks to filter by. Examples: `ethereum,solana`. | *** ## Transfers & Transaction Detail Token transfer history and full transaction detail lookups. Get token transfer history for a blockchain address with rich filtering options. Returns transfers with sender, receiver, token symbol, USD amount, timestamp, and bridge type. Supports cross-chain and intrachain transfers. **Workspace-scoped when `only_workspace` is set to true**: otherwise usable with any valid API key. | Parameter | Type | Required | Description | | - | - | - | - | | `address` | string | Yes | Blockchain address to get token transfers for. | | `network` | string | No | Filter by network. Examples: `solana`, `ethereum`, `cosmoshub-4`. | | `size` | integer | No | Number of transfers to return (1-10000). Default: `25`. | | `cursor` | string | No | Pagination cursor from previous response. | | `token_symbols` | string | No | Comma-separated token symbols. Examples: `USDC,DAI,SOL`. | | `status` | string | No | Comma-separated statuses: `SUCCEEDED`, `PENDING`, `ERROR_ON_DESTINATION`, `TIMEOUT`. | | `min_usd` | number | No | Minimum USD amount filter. | | `max_usd` | number | No | Maximum USD amount filter. | | `start_time` | string | No | Filter from this time (ISO 8601). Example: `2024-01-01T00:00:00Z`. | | `end_time` | string | No | Filter until this time (ISO 8601). | | `source_networks` | string | No | Comma-separated source networks. | | `destination_networks` | string | No | Comma-separated destination networks. | | `bridges` | string | No | Comma-separated bridge types. Examples: `ibc,cctp`. | | `only_workspace` | boolean | No | If true, only return transfers the authenticated workspace has labelled with a category. Requires a workspace-scoped API key. | | `direction` | string | No | Comma-separated directions relative to the workspace's saved addresses: `in`, `out`, `internal`. Requires `only_workspace` set to true. | Get all transfers directly between two specific blockchain addresses, even across different networks. Useful for investigating direct relationships and money flows between two wallets. | Parameter | Type | Required | Description | | - | - | - | - | | `address_a` | string | Yes | First blockchain address. | | `network_a` | string | Yes | Network of address A. Examples: `solana`, `ethereum`, `osmosis-1`. | | `address_b` | string | Yes | Second blockchain address. | | `network_b` | string | Yes | Network of address B. | | `size` | integer | No | Number of transfers to return (1-100). Default: `10`. | | `start_time` | string | No | Filter from this time (ISO 8601). | | `end_time` | string | No | Filter until this time (ISO 8601). | | `types` | string | No | Transfer types (comma-separated). Examples: `ibc,cctp`. | | `cursor` | string | No | Pagination cursor. | Get full details of a blockchain transaction by network and hash. Returns sender, receiver, amounts, token transfers, fees, and timestamp. Use this to understand exactly what happened in a specific transaction. | Parameter | Type | Required | Description | | - | - | - | - | | `network` | string | Yes | Blockchain network. Examples: `ethereum`, `solana`, `cosmoshub-4`, `osmosis-1`, `dydx-mainnet-1`, `neutron-1`, `stellar`. | | `hash` | string | Yes | Transaction hash to look up. | *** ## Network & Token Stats Aggregate network activity (whale moves, volume, active accounts, message-type breakdowns) and token supply/holder data. Get large-value transactions ("whale moves") on a blockchain network within a time range. Returns the biggest transfers sorted by USD value. Useful for identifying market-moving activity, suspicious large flows, or tracking major players. | Parameter | Type | Required | Description | | - | - | - | - | | `network` | string | Yes | Blockchain network. Examples: `ethereum`, `solana`, `cosmoshub-4`, `osmosis-1`. | | `start_time` | string | Yes | Start of time range (ISO 8601). Example: `2024-01-01T00:00:00Z`. | | `end_time` | string | Yes | End of time range (ISO 8601). Example: `2024-01-07T23:59:59Z`. | | `limit` | integer | No | Number of whale moves to return (1-100). Default: `10`. | | `symbol` | string | No | Filter by token symbol. Examples: `USDC`, `ETH`, `SOL`. | Get total transaction volume for a blockchain network within a specific time range in USD. Useful for understanding overall network activity levels during an investigation time window. | Parameter | Type | Required | Description | | - | - | - | - | | `network` | string | Yes | Blockchain network. Examples: `ethereum`, `solana`, `cosmoshub-4`. | | `start_time` | string | Yes | Start of time range (ISO 8601). | | `end_time` | string | Yes | End of time range (ISO 8601). | Get transaction counts for one or more blockchain networks, bucketed over time. Returns per-network time-series points (count, failed count) plus a running total. Useful for spotting activity spikes or comparing throughput across networks. | Parameter | Type | Required | Description | | - | - | - | - | | `networks` | string | Yes | Comma-separated list of networks. Examples: `ethereum,solana,cosmoshub-4`. | | `interval_seconds` | integer | Yes | Size of each time bucket, in seconds. Example: `3600`. | | `buckets` | integer | No | Number of time buckets to return, counting back from now (1-100). Default: `24`. | Get the count of distinct active accounts on a blockchain network within a time range. Useful for gauging user/address engagement on a network over a given window. | Parameter | Type | Required | Description | | - | - | - | - | | `network` | string | Yes | Blockchain network. Examples: `ethereum`, `solana`, `cosmoshub-4`. | | `start_time` | string | Yes | Start of time range (ISO 8601). | | `end_time` | string | Yes | End of time range (ISO 8601). | Get the top sending and top receiving addresses on a network, ranked by an aggregated numeric field (e.g. transfer amount) within a time range. Returns two ranked lists: `topSenders` and `topReceivers`. | Parameter | Type | Required | Description | | - | - | - | - | | `network` | string | Yes | Blockchain network. Examples: `ethereum`, `solana`, `cosmoshub-4`. | | `start_time` | string | Yes | Start of time range (ISO 8601). | | `end_time` | string | Yes | End of time range (ISO 8601). | | `limit` | integer | No | Number of addresses to return per list (1-100). Default: `20`. | | `field` | string | Yes | Numeric field to aggregate and sort by. Example: `amount`. | | `symbol` | string | No | Filter by token symbol. Examples: `USDC`, `ETH`, `SOL`. | Get the addresses holding the largest USD-denominated balances on a network, as of the latest snapshot. Useful for identifying whales or high-value holders on a chain. | Parameter | Type | Required | Description | | - | - | - | - | | `network` | string | Yes | Blockchain network. Examples: `ethereum`, `solana`, `cosmoshub-4`. | | `limit` | integer | No | Number of addresses to return (1-100). Default: `20`. | Get the distribution of message/transaction types seen on a network (e.g. Cosmos SDK Msg types), with counts. Useful for understanding what kinds of activity dominate a chain. | Parameter | Type | Required | Description | | - | - | - | - | | `network` | string | Yes | Blockchain network. Examples: `cosmoshub-4`, `osmosis-1`. | Search for a transaction by its hash across supported networks without knowing which network it belongs to. Returns matching hash/height/network/time records; use `get_transaction_details` afterwards for full transaction data once the network is known. | Parameter | Type | Required | Description | | - | - | - | - | | `hash` | string | Yes | Transaction hash to search for. | Get the latest indexed summary for a token (supply, holder count, etc.) on a given network. Returns `{ found: false }` if no summary has been indexed yet for the token/network pair. | Parameter | Type | Required | Description | | - | - | - | - | | `token` | string | Yes | Token symbol or identifier. Example: `USDtb`. | | `network` | string | Yes | Blockchain network. Example: `eth`, `solana`. | Get the on-chain total supply of a token, read live from the network. Supports Solana (SPL mint address) and EVM-compatible networks (ERC-20 contract address). Only a small set of tokens are currently mapped. | Parameter | Type | Required | Description | | - | - | - | - | | `network` | string | Yes | Blockchain network. Examples: `eth`, `solana`. | | `token` | string | Yes | Token symbol. Example: `USDtb`. | Get mint and burn events for a token. For EVM networks these are Transfer events to/from the zero address; for Solana these are mintTo/burn SPL-token instructions. Useful for tracking supply inflation/deflation over time. | Parameter | Type | Required | Description | | - | - | - | - | | `network` | string | Yes | Blockchain network. Examples: `eth`, `solana`. | | `token` | string | Yes | Token symbol. Example: `USDtb`. | | `limit` | integer | No | Maximum events to return (1-100). Default: `20`. | | `cursor` | string | No | Pagination cursor (`next_cursor` value from a previous page). | Get the top holders of a token, ranked by balance, from the latest indexed snapshot. Useful for concentration analysis (e.g. how much of supply is held by the top N wallets). | Parameter | Type | Required | Description | | - | - | - | - | | `token` | string | Yes | Token symbol or identifier. Example: `USDtb`. | | `network` | string | Yes | Blockchain network. Example: `eth`. | | `size` | integer | No | Number of holders to return (1-100). Default: `20`. | | `cursor` | string | No | Pagination cursor. Use `"A"` for the first page, `"Z"` for the last page, or a cursor from a previous response. | *** ## Explorer Stats & Utilities Explorer-level leaderboards, cross-chain flow, transaction search, plain-language transaction explanation, and the entity directory. Get the top addresses on an explorer/network by transaction volume and by transaction count over a given duration. Returns two ranked lists (`topAddressesByVolume`, `topAddressesByTransactions`). | Parameter | Type | Required | Description | | - | - | - | - | | `duration` | string | Yes | Lookback window. Examples: `1h`, `24h`, `7d`. | | `explorer` | string | No | Explorer/network key to scope results to. Example: `solana`. | | `assets` | string | No | Comma-separated asset symbols to filter by. Example: `USDC,USDT`. | Get the top protocols on an explorer/network by transaction volume and by transaction count over a given duration. Returns two ranked lists (`topProtocolsByVolume`, `topProtocolsByTransactions`). | Parameter | Type | Required | Description | | - | - | - | - | | `duration` | string | Yes | Lookback window. Examples: `1h`, `24h`, `7d`. | | `explorer` | string | No | Explorer/network key to scope results to. Example: `solana`. | | `assets` | string | No | Comma-separated asset symbols to filter by. Example: `USDC,USDT`. | Get the top assets on an explorer/network ranked by transaction volume over a given duration. Useful for seeing which tokens are moving the most value right now. | Parameter | Type | Required | Description | | - | - | - | - | | `duration` | string | Yes | Lookback window. Examples: `1h`, `24h`, `7d`. | | `explorer` | string | No | Explorer/network key to scope results to. Example: `solana`. | Get cross-network transfer flow over a given duration: which network pairs are sending value to each other, broken down by transfer type. Useful for visualizing or reasoning about interchain money movement. | Parameter | Type | Required | Description | | - | - | - | - | | `duration` | string | Yes | Lookback window. Examples: `1h`, `24h`, `7d`. | | `explorer` | string | No | Explorer/network key to scope results to. Example: `solana`. | | `protocols` | string | No | Comma-separated protocol names to filter by. Example: `cctp,union`. | | `assets` | string | No | Comma-separated asset symbols to filter by. Example: `USDC,USDT`. | Get cross-chain (interchain) transfer volume over time, grouped by a field (e.g. token) and bucketed into an interval. Returns periodic series per group plus totals, with smaller groups rolled into an "Others" bucket. | Parameter | Type | Required | Description | | - | - | - | - | | `duration` | string | Yes | Lookback window. Examples: `1h`, `24h`, `7d`. | | `explorer` | string | No | Explorer/network key to scope results to. Example: `solana`. | | `assets` | string | No | Comma-separated asset symbols to filter by. Example: `USDC,USDT`. | | `group_by` | string | No | Field to group series by. Example: `token`. | | `type` | string | No | Aggregation type: `tx` for transaction counts, otherwise USD sum. | | `interval` | string | No | Calendar interval for the time series. Example: `1d`. | List all stablecoin token symbols tracked in the stablecoin transfers index. Useful as a reference lookup before filtering other tools (e.g. `get_top_assets`, `get_transfers`) to stablecoin activity only. No parameters. Get aggregate statistics for a named protocol (interchain payments type) within a time range: total transaction count, total USD volume, and a per-denom breakdown. | Parameter | Type | Required | Description | | - | - | - | - | | `protocol` | string | Yes | Protocol name to filter by. Example: `interchain_payments`. | | `begin_timestamp` | string | Yes | Start of time range (ISO 8601). Example: `2024-04-09T00:00:00Z`. | | `end_timestamp` | string | Yes | End of time range (ISO 8601). Example: `2024-04-10T00:00:00Z`. | Search/list transactions on a single network with optional filters (address, tx hash, message types, status, time range). Returns a cursor-paginated page of transactions. Use `get_transaction_details` instead if you already know the exact network+hash. | Parameter | Type | Required | Description | | - | - | - | - | | `network` | string | Yes | Blockchain network to search. Example: `cosmoshub-4`. | | `cursor` | string | No | Pagination cursor from a previous response. | | `types` | string | No | Filter by message/transaction type. Example: `ExecuteContract`. | | `size` | integer | No | Number of transactions to return (1-100). Default: `20`. | | `tx_hash` | string | No | Filter by an exact transaction hash. | | `address` | string | No | Filter to transactions involving this address. | | `status` | string | No | Filter by transaction status: `SUCCEEDED` or `ERROR`. | | `start_time` | string | No | Filter from this time (ISO 8601). | | `end_time` | string | No | Filter until this time (ISO 8601). | Explain a blockchain transaction in plain language. Given just a network and transaction hash, returns a human-readable narrative of what happened: the primary action (e.g. swap, transfer, stake, contract call), who the parties are, and any token or native-asset movements with resolved amounts and USD value. Supports Solana and EVM (Ethereum-family) networks. Use this when you need to describe a transaction to a person or triage an unfamiliar transaction quickly. | Parameter | Type | Required | Description | | - | - | - | - | | `hash` | string | Yes | Transaction hash to explain. | | `network` | string | Yes | Blockchain network. Examples: `solana`, `ethereum`. | Get a single transfer by its opaque transfer id (as returned in transfer lists, e.g. from `get_transfers`). Returns full transfer detail including sender/receiver, token, USD amount, and bridge type. | Parameter | Type | Required | Description | | - | - | - | - | | `id` | string | Yes | Transfer id, as returned by other transfer tools. | Get the busiest networks for transfers over the last 7 days, split into `sender_networks` and `receiver_networks` with counts. Useful for understanding which chains dominate transfer volume right now. | Parameter | Type | Required | Description | | - | - | - | - | | `explorer` | string | No | Explorer/network key to scope results to. Example: `solana`. | Get the most-transferred assets over the last 7 days, with counts. Useful for understanding which tokens dominate transfer activity right now. | Parameter | Type | Required | Description | | - | - | - | - | | `explorer` | string | No | Explorer/network key to scope results to. Example: `solana`. | Browse the curated entity directory: named organizations, protocols, exchanges, DAOs, bridges, and similar entities, each with tags, verification status, TVL, and monthly volume, sorted by monthly volume. Cursor-paginated, optionally filtered by network. Different from `search_entities`, which does free-text lookup over individually labeled addresses; this browses the entity-level registry itself. | Parameter | Type | Required | Description | | - | - | - | - | | `cursor` | string | No | Pagination cursor from a previous response. | | `size` | integer | No | Number of entities to return (1-100). Default: `20`. | | `networks` | string | No | Comma-separated networks to filter by. Example: `ethereum,solana`. | Get an enriched block for a network at a given height (for Solana, the slot number). Returns the decoded block payload. Useful for inspecting everything that happened in a specific block. | Parameter | Type | Required | Description | | - | - | - | - | | `network` | string | Yes | Blockchain network. Examples: `ethereum`, `cosmoshub-4`, `solana`. | | `height` | integer | Yes | Block height (or Solana slot number). | # Multisig and Governance Source: https://docs.range.org/alerting/catalogue/multisig-governance Monitor the full lifecycle of Squads, Safe (Gnosis), and Realms DAO operations, proposals, approvals, member and threshold changes, timelocks, and vault flows. Multisigs and DAOs are where the highest-value, highest-trust decisions happen. These rules give you a complete audit trail and real-time alerts across the multisig and governance stacks your organization uses, Squads and Realms, and Safe (Gnosis). ## Summary | Rule | Account types | Status | | - | - | - | | Squads Multisig V4 Tracker | Multisig (Squads V4) + vaults | 🟢 Active | | Squads Multisig V3 Tracker | Multisig (Squads V3) + vaults | 🟢 Active | | Squads Multisig Member Change | Multisig (Squads V3/V4) | 🟢 Active | | Squads Risky Member Add Proposal | Multisig + screened member wallet | 🟢 Active | | Squads V4 Timelock Monitor | Multisig (Squads V4) + proposals | 🟢 Active | | Squads Multisig Member Active | Multisig member wallets | 🟢 Active | | Squads Multisig Large Transaction | Multisig + vault accounts | 🟢 Active | | Realms Governance Tracker | DAO / Governance + treasury | 🟢 Active | | Realms Proposal Monitor | DAO / Governance (proposals) | 🟢 Active | | Realms Council Member Change | DAO / Governance + member wallets | 🟢 Active | | Realms Council Member Active | Council member wallets | 🟢 Active | | Realms Risky Member Proposal | DAO / Governance + member wallet | 🟢 Active | | Safe Multisig Tx Executed | Safe (Gnosis) multisig | 🟢 Active | | Safe Multisig Member Change | Safe (Gnosis) multisig | 🟢 Active | | Safe Multisig Threshold Change | Safe (Gnosis) multisig | 🟢 Active | | Safe Multisig Config Change | Safe (Gnosis) multisig | 🟢 Active | | Safe Multisig Module Change | Safe (Gnosis) multisig | 🟢 Active | | Safe Multisig Approve | Safe (Gnosis) multisig | 🟢 Active | | Safe Multisig Pending Approvals | Safe (Gnosis) multisig | 🟢 Active | | New Squads Multisig Created (V3 / V4) | Multisig (Squads) | ⚪ Deprecated | ## Rules **Detects.** Full lifecycle monitoring of a Squads V4 multisig, one rule that covers governance, proposals, batch execution, spending limits, and treasury flows. | | | | - | - | | **Trigger** | Any V4 multisig activity: member add/remove (with risk scoring), threshold changes, proposal create/approve/reject/execute/cancel, batch transactions, spending-limit use, and vault transfers (USD thresholds for financial movements). | | **Account types** | Multisig (Squads V4) + vaults | | **Status** | Active | **Detects.** Full lifecycle monitoring of a Squads V3 multisig, governance, proposals, authority changes, and treasury flows. | | | | - | - | | **Trigger** | Any V3 multisig activity: member additions/removals, threshold modifications, proposal create/approve/reject/execute, authority changes, and vault transfers (USD thresholds for financial movements). | | **Account types** | Multisig (Squads V3) + vaults | | **Status** | Active | **Detects.** A member is added to or removed from a monitored Squads multisig. | | | | - | - | | **Trigger** | A membership change (addition or removal) on the monitored multisig. Supports both V3 and V4. | | **Account types** | Multisig (Squads V3/V4) | | **Status** | Active | **Detects.** A proposal to add a member whose Range risk score is at or above a threshold, caught before it executes. | | | | - | - | | **Trigger** | A V4 proposal to add a member, where the proposed member's Range risk score ≥ the configured minimum. | | **Account types** | Multisig (Squads V4) + screened member wallet | | **Status** | Active | **Detects.** Approved-but-still-timelocked V4 proposals, with a countdown to when they can execute. | | | | - | - | | **Trigger** | A V4 proposal has passed its approval threshold and is in its timelock window; re-alerts on a configurable interval with the remaining time. *(Scheduled; recommended 60-minute ticker.)* | | **Account types** | Multisig (Squads V4) + proposal accounts | | **Status** | Active | **Detects.** A multisig member signs a transaction *outside* the Squads program, i.e. acting independently with their own wallet. | | | | - | - | | **Trigger** | A known multisig member is a signer on a non-Squads transaction. Specific members can be excluded. Supports V3 and V4. | | **Account types** | Multisig member wallets | | **Status** | Active | **Detects.** A large transfer in or out of a Squads multisig vault. | | | | - | - | | **Trigger** | A vault-executed transfer whose USD value exceeds the configured minimum. Vault accounts are derived automatically from the multisig. | | **Account types** | Multisig + vault accounts | | **Status** | Active | **Detects.** A Realms (SPL Governance) proposal executes onchain, or a realm / governance authority or config is changed. | | | | - | - | | **Trigger** | A proposal-executed instruction lands, or the realm authority/config or a governance config is updated; tracks associated treasury flows above a USD threshold. | | **Account types** | DAO / Governance + program + treasury accounts | | **Status** | Active | **Detects.** Every stage of a Realms proposal's lifecycle, including timelock countdowns. | | | | - | - | | **Trigger** | New proposals and every state transition (Draft → Signing Off → Voting → Succeeded → Executing → Completed, plus Cancelled / Defeated / Vetoed / Executing-with-errors), and Succeeded-awaiting-execution with a timelock countdown. *(Scheduled.)* | | **Account types** | DAO / Governance (proposals) | | **Status** | Active | **Detects.** A wallet joins or leaves a Realms DAO council. | | | | - | - | | **Trigger** | SPL-Governance deposit/withdraw against the council holding account (ongoing membership), or `mintTo` / `burn` on the council mint (bootstrap / reset events). | | **Account types** | DAO / Governance + member wallets + council mint | | **Status** | Active | **Detects.** A known council member's wallet acts outside the DAO governance program. | | | | - | - | | **Trigger** | A council member is a signer or writable account on a transaction that does not invoke the governance program. Specific members can be excluded. | | **Account types** | Council member wallets | | **Status** | Active | **Detects.** A pending proposal that would add a high-risk wallet as a council member, caught before execution. | | | | - | - | | **Trigger** | A proposal whose action would mint the council token to a wallet whose Range risk score ≥ the configured minimum. *(Scheduled.)* | | **Account types** | DAO / Governance + prospective member wallet + council mint | | **Status** | Active | **Detects.** A transaction is executed (or fails) through a monitored Safe. | | | | - | - | | **Trigger** | `ExecutionSuccess` / `ExecutionFailure` on the Safe; includes value moved and flags risky `DelegateCall` use. Can escalate on large total transfers. | | **Account types** | Safe (Gnosis) multisig | | **Status** | Active | **Detects.** An owner is added, removed, or swapped on a monitored Safe. | | | | - | - | | **Trigger** | Owner add/remove/swap events; flags newly added owners that have a high Range risk score. | | **Account types** | Safe (Gnosis) multisig | | **Status** | Active | **Detects.** The number of required signatures on a monitored Safe changes. | | | | - | - | | **Trigger** | The signing threshold is changed, especially dangerous when lowered to 1. | | **Account types** | Safe (Gnosis) multisig | | **Status** | Active | **Detects.** A monitored Safe changes or removes its security Guard or Fallback Handler. | | | | - | - | | **Trigger** | `ChangedGuard` / `ChangedFallbackHandler` events (Safe ≥ 1.3.0). Removing a Guard removes a key safety control. | | **Account types** | Safe (Gnosis) multisig | | **Status** | Active | **Detects.** A module is enabled or disabled on a monitored Safe. | | | | - | - | | **Trigger** | `EnabledModule` / `DisabledModule` events. An enabled module can move funds bypassing the signing threshold, so additions warrant scrutiny. | | **Account types** | Safe (Gnosis) multisig | | **Status** | Active | **Detects.** An owner signs / approves a pending Safe transaction. | | | | - | - | | **Trigger** | An onchain approval for a transaction hash, including the count of confirmations collected so far. | | **Account types** | Safe (Gnosis) multisig | | **Status** | Active | **Detects.** A monitored Safe has a new off-chain pending transaction awaiting signatures, and again when it's ready to execute. | | | | - | - | | **Trigger** | Polls the Safe Transaction Service: fires when a new pending tx appears, then again when it reaches off-chain consensus (ready to execute). *(Scheduled.)* | | **Account types** | Safe (Gnosis) multisig | | **Status** | Active | All Safe (Gnosis) rules support Safe contract versions 1.1.1 through 1.5.0. ## Deprecated Retired from the current runner, kept for completeness: * **New Squads Multisig Created (V3 / V4)**: creation of a new Squads multisig account (separate V3 and V4 rules on the previous runner; the V4 variant could be filtered by member account). # Operational and Network Monitoring Source: https://docs.range.org/alerting/catalogue/operational-network-monitoring Track network and infrastructure health, gas pressure, transaction failure rates, call spikes, liquidity and price breaches, and pipeline heartbeats. These rules watch the health of the networks and markets you depend on, rather than a specific account, congestion, failure spikes, anomalous contract usage, and market-data breaches. They're the early-warning layer for operational risk. ## Summary | Rule | Account types | Status | | - | - | - | | Gas Pressure | Network | 🟢 Active | | High Transaction Count | Network | 🟢 Active | | High Transaction Failure Rate | Network | 🟢 Active | | Spike in Contract Calls | Contract | 🟢 Active | | Block Liveness / Heartbeat | Network / operational | 🟢 Active | | Liquidity Alert (Flux) | Exchange venue / pair | 🟢 Active | | Price Breach Alert (Flux) | Asset price feeds / pair | 🟢 Active | | Fee Spike | Network | 🟡 Building | | Feature Gate Watcher | Network / program | 🟣 Internal | ## Rules **Detects.** Network congestion, blocks where gas utilization runs hot. | | | | - | - | | **Trigger** | A block's gas utilization exceeds the configured threshold. | | **Account types** | Network | | **Status** | Active | **Detects.** A block packs an unusually high number of transactions. | | | | - | - | | **Trigger** | A block contains more transactions than the configured threshold. | | **Account types** | Network | | **Status** | Active | **Detects.** An abnormally large share of transactions fail. | | | | - | - | | **Trigger** | The percentage of failed transactions in a block (or rolling window) exceeds the configured threshold. | | **Account types** | Network | | **Status** | Active | **Detects.** A sudden burst of transactions hitting a watched contract. | | | | - | - | | **Trigger** | Calls to a monitored contract exceed a minimum count within a configurable time window, useful for spam attacks, bot activity, or anomalous usage. | | **Account types** | Contract | | **Status** | Active | **Detects.** That the alerting pipeline is alive. | | | | - | - | | **Trigger** | Fires a notification every N blocks as a liveness heartbeat, useful for verifying the pipeline is operational. | | **Account types** | Network / operational | | **Status** | Active | **Detects.** An exchange's order-book liquidity for a pair drops too low and stays there. | | | | - | - | | **Trigger** | Order-book depth for a venue / pair falls below a threshold for a sustained duration, via Flux. *(Scheduled; off-chain market data.)* | | **Account types** | Exchange venue / trading-pair markets | | **Status** | Active | **Detects.** An asset's price breaches set bounds across multiple venues at once. | | | | - | - | | **Trigger** | Price moves outside defined lower/upper bounds on a configurable number of venues for a sustained duration, via Flux. *(Scheduled; off-chain market data.)* | | **Account types** | Asset price feeds / trading-pair markets | | **Status** | Active | **Detects.** A fee spike, the recent average fee runs well above its baseline. | | | | - | - | | **Trigger** | The average fee in the last hour is significantly higher (by a configurable percentage) than the average of the previous six hours. *(Scheduled.)* | | **Account types** | Network | | **Status** | Building: logic implemented; data source not yet wired. | **Detects.** Solana protocol feature-gate proposals and activations. | | | | - | - | | **Trigger** | A new feature is proposed or activated on testnet (upcoming change), or a feature goes live on mainnet; reports the feature pubkey and activation slot. *(Scheduled.)* | | **Account types** | Network / program (Feature Gate accounts) | | **Status** | Internal: limited to an internal workspace; not generally available. | Internal liveness / benchmarking rules (block and tick heartbeats, indexer firehose) exist for pipeline testing but are not customer-facing, so they're omitted from this catalogue. # Sanctions and Compliance Source: https://docs.range.org/alerting/catalogue/sanctions-compliance Alert rules for OFAC-sanctioned, blacklisted, malicious, or high-risk counterparties, and for sanctions or blacklist changes on monitored addresses. These rules keep you on the right side of compliance by flagging interactions with sanctioned, blacklisted, malicious, or high-risk addresses, and by alerting when a monitored address's sanctions/blacklist status itself changes. ## Summary | Rule | Account types | Status | | - | - | - | | Sanctions Check | Wallet (EOA) + counterparty | 🟢 Active | | High-Risk Counterparty | Wallet (EOA) + counterparty | 🟢 Active | | Risky Address Interaction | Wallet (EOA) / contract | 🟢 Active | | Sanctions and Blacklist List Change | Any monitored address | 🟢 Active | | Sanctioned Address Token Interaction | Wallet (EOA) + token / mint | 🟡 Building | | Blacklisted Address Token Interaction | Wallet (EOA) + token / mint | 🟡 Building | | Malicious Address Token Interaction | Wallet (EOA) + token / mint | 🟡 Building | | Labelled Address Transaction | Wallet (EOA) | ⚪ Deprecated | **Status note.** *Sanctions Check*, *High-Risk Counterparty*, *Risky Address Interaction*, and *Sanctions and Blacklist List Change* are live, they screen counterparties directly against the Range risk and sanctions APIs. The three **Address Token Interaction** rules are 🟡 **Building**: the rule logic is implemented, but they depend on per-block sanctioned / blacklisted / malicious address lists being fed in by the enrichment pipeline, which isn't wired up yet, so they don't emit alerts today. ## Rules **Detects.** A monitored wallet transacts with an OFAC-sanctioned or blacklisted address. | | | | - | - | | **Trigger** | A transfer where the counterparty is sanctioned or blacklisted, checked via the Range sanctions API. | | **Account types** | Wallet (EOA) + counterparty | | **Status** | Active | **Detects.** A monitored wallet transacts with a counterparty whose Range risk score exceeds a threshold. | | | | - | - | | **Trigger** | A transfer (above an optional minimum USD) where the counterparty's Range risk score ≥ the configured threshold. | | **Account types** | Wallet (EOA) + counterparty | | **Status** | Active | **Detects.** A monitored address that carries a non-zero Range risk score has new transactions. | | | | - | - | | **Trigger** | A monitored address with a non-zero risk score is seen in new transactions, indicating possible association with malicious activity. *(Scheduled.)* | | **Account types** | Wallet (EOA) / contract | | **Status** | Active | **Detects.** A monitored address is added to or removed from the OFAC sanctions list or a stablecoin issuer blacklist. | | | | - | - | | **Trigger** | A watched address newly appears on, or drops off, the OFAC list or a stablecoin issuer blacklist (USDT, USDC, etc.). Filter by list type and change type (added / removed). *(Scheduled.)* | | **Account types** | Any monitored address (wallet / contract) | | **Status** | Active | **Detects.** A sanctioned address sends or receives a monitored token. | | | | - | - | | **Trigger** | A sanctioned address sends, receives, or holds the configured token. | | **Account types** | Wallet (EOA) + token / mint | | **Status** | Building: implemented, but not yet emitting (see note above). | **Detects.** An address on an issuer's blocklist sends or receives a monitored token. | | | | - | - | | **Trigger** | A blocklisted address (issuer blocklists, e.g. Circle / Tether) interacts with the configured token. | | **Account types** | Wallet (EOA) + token / mint | | **Status** | Building: implemented, but not yet emitting (see note above). | **Detects.** An address flagged for malicious activity (scams, exploits, wallet drainers) sends or receives a monitored token. | | | | - | - | | **Trigger** | A malicious-flagged address interacts with the configured token. | | **Account types** | Wallet (EOA) + token / mint | | **Status** | Building: implemented, but not yet emitting (see note above). | ## Deprecated Retired from a previous runner, kept for completeness: * **Labelled Address Transaction**: transactions involving labelled addresses (superseded by the risk- and sanctions-based rules above). # Smart Contract and Program Security Source: https://docs.range.org/alerting/catalogue/smart-contract-program-security Alert rules for program and proxy contract upgrades, program authority and contract ownership changes, proxy admin changes, and pause or unpause events. The control surface of a protocol is its code and the keys that can change it. These rules alert you the moment a monitored program or contract is upgraded, has its authority or ownership changed, or is paused, the events most associated with takeovers and rug-pulls. ## Summary | Rule | Account types | Status | | - | - | - | | Program Upgrade | Program | 🟢 Active | | Program Authority Change | Program (upgradeable) | 🟢 Active | | Proxy Upgrade Monitor | Upgradeable proxy contracts | 🟢 Active | | Proxy Admin Changed | Upgradeable proxy contracts | 🟢 Active | | Contract Ownership Transfer | Ownable contracts | 🟢 Active | | Contract Pause / Unpause | Pausable / token contracts | 🟢 Active | | Program and token lifecycle | Program / token | ⚪ Deprecated | ## Rules **Detects.** A monitored program's onchain code is upgraded. | | | | - | - | | **Trigger** | A program is upgraded (or deployed). One rule can monitor multiple programs. | | **Account types** | Program | | **Status** | Active | **Detects.** A program's upgrade authority is changed or removed. | | | | - | - | | **Trigger** | The authority of a monitored program is reassigned to a new key or removed entirely. | | **Account types** | Program (upgradeable) | | **Status** | Active | **Detects.** A monitored upgradeable proxy swaps its implementation to a new address. | | | | - | - | | **Trigger** | An ERC-1967 proxy upgrade event; the proxy points to new implementation code. | | **Account types** | ERC-1967 upgradeable proxy contracts | | **Status** | Active | **Detects.** The admin that controls upgrading a proxy is changed. | | | | - | - | | **Trigger** | An ERC-1967 proxy admin change; whoever can upgrade the implementation is now a different account. | | **Account types** | ERC-1967 upgradeable proxy contracts | | **Status** | Active | **Detects.** A contract's owner changes, or ownership is permanently renounced. | | | | - | - | | **Trigger** | An OpenZeppelin Ownable ownership transfer; renunciation (transfer to the zero address) is flagged as the most serious case. | | **Account types** | OpenZeppelin Ownable contracts | | **Status** | Active | **Detects.** A contract is paused (frozen) or unpaused (re-enabled). | | | | - | - | | **Trigger** | A pause or unpause event, supporting both OpenZeppelin Pausable and stablecoin-style pause events. | | **Account types** | OZ Pausable / token contracts | | **Status** | Active | ## Deprecated Retired from a previous runner, kept for completeness: * **New Program Deployed**: a new program is deployed. * **Program Account Closed**: a program account is closed. * **Program Interaction**: a program instruction is executed. * **Program Error**: a program error occurs. * **SPL Token Authority Change**: an SPL token authority is changed. * **Attestation Service New Accounts**: new attestation accounts are created. # Stablecoins and Tokens Source: https://docs.range.org/alerting/catalogue/stablecoins-tokens Monitor stablecoin supply events, issuer freezes, treasury issuer concentration, and peg deviations. For issuers, treasuries, and anyone exposed to stablecoins, these rules track the events that matter most: supply changes (mint / burn), issuer freezes, over-exposure to a single issuer, and a stablecoin drifting off its peg. ## Summary | Rule | Account types | Status | | - | - | - | | Stablecoin Supply Change | Token / mint (stablecoins) + holders | 🟢 Active | | Stablecoin Issuer Freeze and Blacklist | Token / mint + token accounts | 🟢 Active | | Asset Price Deviation | Token / mint (stablecoins) | 🟢 Active | | Stablecoin Issuer Concentration | Treasury wallets; token / mint | 🟢 Active | | SPL token lifecycle | Token / mint | ⚪ Deprecated | | Asset metrics | Token / mint | ⚪ Deprecated | ## Rules **Detects.** A supported stablecoin is minted or burned. | | | | - | - | | **Trigger** | A `mintTo` / mint or burn of a supported stablecoin whose USD value exceeds a configurable threshold. Coverage spans a set of supported stablecoin mints / contracts. | | **Account types** | Token / mint (stablecoins) + holder addresses | | **Status** | Active | **Detects.** A stablecoin issuer freezes (or blacklists) an address, or unfreezes it. | | | | - | - | | **Trigger** | A `freezeAccount` on a token account, or an address being added to / removed from a stablecoin blacklist, above a configurable threshold where applicable. | | **Account types** | Token / mint (stablecoins) + token accounts / blacklisted address | | **Status** | Active | **Detects.** A stablecoin's price drifts off its peg. | | | | - | - | | **Trigger** | Cross-checks aggregated pricing against an oracle for supported stablecoins; alerts escalate with the size of the deviation, and emit recovery events when the peg is restored. *(Scheduled.)* | | **Account types** | Token / mint (stablecoins) | | **Status** | Active | **Detects.** Too large a share of a treasury's stablecoin holdings sits with one issuer. | | | | - | - | | **Trigger** | The percentage of stablecoin holdings from a single issuer (e.g. Circle / USDC, Tether / USDT) across monitored treasury wallets exceeds a configurable threshold. *(Scheduled.)* | | **Account types** | Treasury wallets; token / mint (stablecoins) | | **Status** | Active | ## Deprecated Retired from a previous runner, kept for completeness: * **SPL Token Mint / Burn / New / Freeze**: individual SPL token supply and freeze events (superseded by the stablecoin rules above). * **Large Memecoin Swap**: large memecoin swaps. * **HUGE Whale Dump**: a whale dumps a large amount of an asset. * **Total Asset Holders Change / Limit Crossed**: holder count changes by, or crosses, a threshold. * **Total Asset Marketcap Change / Limit Crossed**: marketcap changes by, or crosses, a threshold. * **Risky Total Asset Marketcap Limit Crossed**: a risky asset's marketcap crosses a threshold. # Treasury and Asset Monitoring Source: https://docs.range.org/alerting/catalogue/treasury-asset-monitoring Watch treasury wallets for large transfers, balance thresholds, dormant-wallet reactivation, unknown counterparties, and unusual activity or flow spikes. These rules protect the wallets that hold and move funds. Point them at your treasury, operational, and cold-storage addresses to get alerted on material movements, unusual behaviour, and interactions you didn't expect. ## Summary | Rule | Account types | Status | | - | - | - | | Large Transfer | Wallet / contract; native + tokens | 🟢 Active | | Activity Spike | Wallet (EOA) | 🟢 Active | | Flow Spike | Wallet (EOA) | 🟢 Active | | Transfer Deviation | Wallet (EOA) | 🟢 Active | | Dormant Wallet Reactivation | Wallet (EOA), cold / dormant | 🟢 Active | | Unknown Counterparty Interaction | Wallet (EOA) + counterparty | 🟢 Active | | Balance Threshold Alert | Wallet / contract; tokens | 🟢 Active | | Balance Change Delta | Wallet (EOA) / program | 🟢 Active | | Large Cross-Chain Transfer | Bridge protocols; sender / receiver | 🟢 Active | | Successful Transaction | Any account | 🟢 Active | | Full Balance Sweep | Wallet (EOA) | ⚪ Deprecated | | Suspicious Multi Send | Wallet (EOA) | ⚪ Deprecated | | Account Closed | Wallet / program | ⚪ Deprecated | ## Rules **Detects.** A monitored wallet sends or receives a transfer above a USD threshold. | | | | - | - | | **Trigger** | A native or token transfer involving a monitored address exceeds the configured USD minimum. Supports inbound / outbound / both, with optional address, token, and amount filters. | | **Account types** | Wallet / contract senders and receivers; native + tokens | | **Status** | Active | **Detects.** A wallet's outbound transaction count spikes far above its normal rate. | | | | - | - | | **Trigger** | Outbound transaction count per time window exceeds the address's baseline by a configurable Z-score. *(Scheduled.)* | | **Account types** | Wallet (EOA) | | **Status** | Active | **Detects.** A wallet's outbound USD volume spikes far above its normal level. | | | | - | - | | **Trigger** | Outbound USD volume per time window exceeds the address's baseline by a configurable Z-score. *(Scheduled.)* | | **Account types** | Wallet (EOA) | | **Status** | Active | **Detects.** A single transfer that is far larger than the wallet's historical norm. | | | | - | - | | **Trigger** | A transfer deviates significantly from the address baseline (Z-score ≥ 3). Supports inbound / outbound / both. *(Scheduled, baseline-driven.)* | | **Account types** | Wallet (EOA) | | **Status** | Active | **Detects.** A long-inactive wallet suddenly transacts again, useful for spotting unauthorized use of cold or dormant treasury accounts. | | | | - | - | | **Trigger** | A monitored address with no activity for a configurable number of days signs a new transfer. Supports inbound / outbound / both. *(Scheduled.)* | | **Account types** | Wallet (EOA), cold / dormant treasury | | **Status** | Active | **Detects.** A monitored wallet transacts with a counterparty that isn't on your allow-list. | | | | - | - | | **Trigger** | A transfer to or from a wallet not in the provided allow-list. Supports inbound / outbound / both. | | **Account types** | Wallet (EOA) + counterparty | | **Status** | Active | **Detects.** A watched wallet's balance crosses a floor or ceiling. | | | | - | - | | **Trigger** | A monitored account's native or token balance falls below a lower bound or rises above an upper bound. *(Scheduled.)* | | **Account types** | Wallet / contract addresses; tokens | | **Status** | Active | **Detects.** A monitored account's balance changes beyond a threshold. | | | | - | - | | **Trigger** | A transaction changes the account's native or token balance past a configurable token and/or USD threshold. Supports inbound / outbound / both. | | **Account types** | Wallet (EOA) / program; tokens | | **Status** | Active | **Detects.** A large amount bridges into or out of a network. | | | | - | - | | **Trigger** | A cross-chain inflow or outflow over a USD minimum across any supported bridge. Filter by direction and specific bridges. *(Scheduled.)* | | **Account types** | Bridge protocols; cross-chain sender / receiver addresses | | **Status** | Active | **Detects.** A monitored account is part of any successful transaction, a basic activity / audit-trail signal. | | | | - | - | | **Trigger** | The monitored account appears in a successful transaction. | | **Account types** | Any account (wallet / program / contract) | | **Status** | Active | ## Deprecated Retired from a previous runner, kept for completeness: * **Full Balance Sweep**: a full balance sweep out of an account. * **Token Transfer**: a large token transfer (superseded by *Large Transfer*). * **Suspicious Multi Send**: a wallet sends to multiple recipients in a single transaction. * **Account Closed**: an account is closed. # Request a rule Source: https://docs.range.org/alerting/contributing How to ask for a new alert rule, or a change to one that's here. This catalogue grows through customer conversations. If you want a rule that isn't here, or a change to one that is, we'd like to hear about it. Coverage on a new chain counts too: if a rule exists for one network and you need it on another, we extend it. Describe what the rule should detect, the trigger condition, and which accounts or assets it applies to. The clearer the use case, the faster we can scope it. [Get in touch](https://www.range.org/get-in-touch) or talk to your Range contact. We review feasibility and where it fits in the catalogue. The outcome is a decision: it goes on the roadmap as **Planned**, needs more detail, or isn't a fit. As the rule is built it moves **Planned → Building → Active**, and the catalogue is updated to match. ## What makes a good request The more of these you can give us, the better (see [Conventions](/alerting/conventions) for definitions): * A one-line **Detects** summary in plain language. * A concrete **trigger condition**. * The **account types** it applies to. * Any chains you specifically need it on. # Conventions Source: https://docs.range.org/alerting/conventions How to read status badges, account types, and trigger model in the catalogue. The legend for every field on a rule card. ## Status Every rule carries one status badge. | Badge | Status | Meaning | | - | - | - | | 🟢 | **Active** | Live in production today. You can enable it now. | | 🟡 | **Building** | Implemented but not yet emitting alerts, typically waiting on a data source. Close to ready. | | 🔵 | **Planned** | On the roadmap. Not available yet. | | 🟣 | **Internal** | Used internally or for a single workspace; not generally available. | | ⚪ | **Deprecated** | Retired from a previous runner. Listed for migration context. | ## Account types What you point a rule at when you configure it: * **Wallet (EOA)**: an externally-owned account / individual wallet. * **Multisig**: a Squads or Safe / Gnosis multisig. * **DAO / Governance**: a Realms (SPL Governance) realm or governance account. * **Contract**: a smart contract (proxy, Ownable, Pausable, etc.). * **Program**: an onchain program. * **Token / Mint**: an SPL mint or ERC-20 token, including stablecoins. * **Network**: chain-wide signals not tied to a specific account. ## Trigger model * **Per-block**: evaluated on every block; alerts fire as the triggering transaction lands. * **Scheduled (tick)**: evaluated on a timer. Used for polling external state, time-window comparisons, and timelock countdowns. ## Chains Rules describe a capability, not a chain. Coverage spans Solana and EVM, and we extend rules to new networks on request. Where a rule uses a chain-specific mechanism (for example Squads on Solana or Safe on EVM), that's clear from the rule itself. Severity and destinations aren't rule properties, you set them per instance. See [How alerting works](/alerting/how-alerting-works) and [Supported destinations](/alerting/supported-destinations). # How alerting works Source: https://docs.range.org/alerting/how-alerting-works How a rule in the catalogue becomes a live alert, targeting accounts, setting thresholds, and routing notifications. The catalogue tells you **what** each rule detects. This page covers **how** you turn one on and where the alerts go. ## The shape of an alert A live alert is a rule, pointed at specific accounts, with the thresholds and destinations you choose: Browse the [catalogue](/alerting/introduction) and choose a rule that matches what you want to watch, a multisig, a treasury wallet, a token, a program. Configure the rule against the accounts, contracts, or assets you care about. The same rule can be applied to many targets. Most rules take parameters, USD minimums, time windows, allow-lists, risk-score cut-offs. These are yours to set per rule instance; the catalogue lists what's configurable under each rule's **Trigger condition**. Route the alert to any destination your workspace has connected. See [Supported destinations](/alerting/supported-destinations). ## Configure in the dashboard or via the API You can manage rules two ways: Turn rules on, set thresholds, and connect destinations from the Range dashboard, no code required. Manage alert rules programmatically through the Platform API, list available rules, create rule instances against your accounts, and keep them in sync with your own tooling. The alerting endpoints live under the [Platform API](/platform-api/platform-introduction), alongside accounts, counterparties, and connections, so the accounts you monitor and the rules that watch them share one API surface and one API key. ## Severity is yours to set Rules don't ship with a fixed severity. You decide how urgent each alert is for your workspace when you configure it, and some rules can escalate at runtime based on context (for example, the USD value moved or a counterparty's risk score). # Alerting Source: https://docs.range.org/alerting/introduction The catalogue of Range Protect alert rules, what each one detects, what you point it at, and how to turn it on. Range Protect watches onchain activity for the accounts, contracts, and assets you care about, and alerts when something matters. This catalogue lists the rules we offer and what each one detects. Rules are grouped by **use case**, not by chain. Coverage spans Solana and EVM, and we extend rules to new networks on request, so each rule describes a capability, not a fixed chain list. Roadmap rules are marked **Planned**. See [Conventions](/alerting/conventions) for the full status legend. ## How rules are organized Squads, Safe (Gnosis), and Realms DAO lifecycle: proposals, approvals, member and threshold changes, timelocks, and vault flows. Large transfers, balance thresholds, dormant-wallet reactivation, unknown counterparties, and unusual activity or flow spikes. OFAC sanctions, issuer blacklists, malicious-address interaction, and Range risk-score screening of counterparties. Program upgrades and authority changes; proxy upgrades, ownership transfers, and pause events. Stablecoin mint, burn, and freeze, issuer concentration, and peg-deviation monitoring. Network health: gas pressure, transaction failure rates, call spikes, liquidity and price breaches, and pipeline heartbeats. ## Reading a rule Every rule card lists the same fields: * **Detects**: what the rule is for, in plain language. * **Trigger condition**: the onchain event or threshold that fires the alert. * **Account types**: what you point the rule at (wallet, multisig, contract, token, program). * **Status**: Active, Building, Planned, Internal, or Deprecated. Severity and destinations aren't rule properties, you set them per instance when you turn a rule on. See [How alerting works](/alerting/how-alerting-works). ## Want a rule that isn't here? The catalogue grows through customer conversations, and we extend rules to new chains on request. See [Request a rule](/alerting/contributing). # Multisig monitoring guidelines Source: https://docs.range.org/alerting/multisig-monitoring-guidelines The standard alerting setup Range suggests for Safe and Squads multisig wallets. This is a suggested baseline for monitoring multisig wallets, a sensible starting point you can adopt as-is or tune. Thresholds, voter sets, and destinations are configured per workspace during setup, so treat the numbers here as recommended defaults rather than fixed values. The rules below build on the [Multisig and Governance](/alerting/catalogue/multisig-governance) catalogue and apply to **each Safe (EVM) or Squads (Solana) wallet** in scope. Wallets on different chains or addresses are monitored as separate units. ## What's covered Each Safe or Squads address gets the standard wallet rule pack: proposals, configuration changes, value thresholds, and balance monitoring. Range reads the signer addresses from the multisig configuration and applies voter rules to those wallets. A compromised signer key can enable a malicious approval or execution even without direct treasury access. ## Suggested wallet rules Applied to each multisig wallet in scope. | Rule | What it monitors | | - | - | | Proposal Tracker | The full proposal lifecycle: new proposal creation/submission and successful execution. | | Config Tracker | Structural changes: member/owner add and remove, threshold modifications, permission changes, modules, and guards. Can indicate compromise or unauthorised access. | | High-Value Governance Action | An executed proposal or transaction above the high-value threshold (suggested \$1k). | | Large-Value Governance Action | An execution above the larger threshold (suggested \$10k), worth a formal acknowledgment. | | New Contract Interaction | A monitored wallet interacts with a contract it has never transacted with before, a common phishing and malicious-approval vector. | | Balance Drop | Balance falls below an absolute floor, or below 20% of its 30-day rolling average. | ## Suggested voter rules Derived from the multisig, applied to the signer addresses Range reads from the wallet configuration. | Rule | What it monitors | | - | - | | Non-Multisig Tx Monitoring | Any transaction by a monitored signer that's unrelated to the multisig; activity outside governance may indicate key compromise. | | Timezone Tx Monitoring | Signer transactions outside the configured core timezone or operating window. | ## Suggested thresholds | Threshold | Suggested default | | - | - | | High-value governance action | \$1,000 | | Large-value governance action | \$10,000 | | Balance drop | Below an absolute floor **or** 20% of the 30-day rolling average | | Voter timezone window | Your defined core hours | ## How an alert flows ```mermaid theme={null} flowchart LR A[On-chain event] --> B[Rule match] --> C[Alert raised] --> D[Your destinations] ``` Each alert is routed to any destination your workspace has connected, see [Supported destinations](/alerting/supported-destinations). You choose where each alert goes; the rule just decides when one fires. ## Setting it up Configured with you during onboarding: Provide the multisig addresses (Safe and/or Squads), chains, and signer list. Range sets up the standard rule pack and destination routing in your workspace. Confirm alerts arrive as expected in a staging or dry-run period. Production monitoring is enabled. What you can tune at setup or later: the wallet inventory, the voter set, value thresholds, balance floors, timezone windows, and destinations. See [How alerting works](/alerting/how-alerting-works) for the general model. # Supported destinations Source: https://docs.range.org/alerting/supported-destinations Where Range Protect alerts can be delivered. When a rule fires, the alert is delivered to the destinations you've connected. Destinations are configured **per rule instance**, not per rule, any rule can route to any destination your workspace has set up, and a single rule can notify several at once. ## Where alerts can go Post alerts to a channel for your team to triage. Deliver alerts to a Telegram chat or group. Send alerts to your own endpoint to drive downstream automation. Receive alerts in your inbox. Connect and manage destinations from the [Range platform](https://app.range.org). For how rules, thresholds, and destinations fit together, see [How alerting works](/alerting/how-alerting-works). # Complete Cubist login with TOTP code Source: https://docs.range.org/api-reference/account-connections/complete-cubist-login-with-totp-code /api-reference/platform-api.json post /v2/account-connections/cubist/login/{loginId}/mfa/totp # Complete FIDO MFA for Cubist login Source: https://docs.range.org/api-reference/account-connections/complete-fido-mfa-for-cubist-login /api-reference/platform-api.json post /v2/account-connections/cubist/login/{loginId}/mfa/fido/complete # Create a Plaid Link token Source: https://docs.range.org/api-reference/account-connections/create-a-plaid-link-token /api-reference/platform-api.json post /v2/account-connections/plaid/link-token Returns a short-lived link_token the client passes to Plaid Link. Optionally scope which institutions Link shows by passing country_codes (e.g. the country of the customer being onboarded); defaults to all approved countries. After the user completes the flow, POST /account-connections with the returned public_token. # Create a Plaid Link update-mode token to reconnect a dead item Source: https://docs.range.org/api-reference/account-connections/create-a-plaid-link-update-mode-token-to-reconnect-a-dead-item /api-reference/platform-api.json post /v2/account-connections/{id}/plaid/reconnect-link-token Mints a link_token scoped to this connection's own stored access_token (Plaid Link "update mode"), so the client can re-run Plaid Link to re-authenticate the item without deleting and recreating the connection. The same access_token remains valid afterwards — no further exchange step is needed; re-check GET :id/status once Link's onSuccess fires. Only valid for plaid connections. # Create a QuickBooks Online OAuth authorize URL Source: https://docs.range.org/api-reference/account-connections/create-a-quickbooks-online-oauth-authorize-url /api-reference/platform-api.json post /v2/account-connections/quickbooks/authorize-url Returns an Intuit authorize URL and CSRF `state` bound to the caller workspace. Redirect the user to `authorize_url`; after Intuit redirects back to the Range app with `code`, `realmId`, and `state`, POST /account-connections with type=quickbooks. Dispatches via LedgerConnectionAdapter.beginOAuth (same path Xero will use). # Create a Xero OAuth authorize URL Source: https://docs.range.org/api-reference/account-connections/create-a-xero-oauth-authorize-url /api-reference/platform-api.json post /v2/account-connections/xero/authorize-url Returns a Xero authorize URL and CSRF `state` bound to the caller workspace. Redirect the user to `authorize_url`; after Xero redirects back to the Range app with `code` and `state`, POST /account-connections with type=xero. When the consent covers more than one organisation, create responds with code `xero_tenant_required` and the call is retried with `xero.tenant_id`. # Create account, ledger or risk connection Source: https://docs.range.org/api-reference/account-connections/create-account-ledger-or-risk-connection /api-reference/platform-api.json post /v2/account-connections Stores connection credentials. Account providers support preview/import; ledger providers (e.g. quickbooks, xero) store OAuth tokens only; risk providers (merkle_science) store a BYO screening key, verified against the vendor before it is stored, at most one per workspace. For multisig providers (safe, squads, realms), an address that fails to resolve returns a classified error body `{ statusCode, error, code, message }` with `code` one of: `invalid_address` (bad format), `multisig_not_found` (well-formed address, no multisig there), `wrong_network` (Safe only — exists, but on a different chain than selected), `upstream_unavailable` (the provider/RPC failed — transient, safe to retry). # Delete account connection Source: https://docs.range.org/api-reference/account-connections/delete-account-connection /api-reference/platform-api.json delete /v2/account-connections/{id} Deletes an account connection by id for the caller workspace. # Get one Open item by Range id Source: https://docs.range.org/api-reference/account-connections/get-one-open-item-by-range-id /api-reference/platform-api.json get /v2/account-connections/bookkeeping/{connectionId}/open-items/{id} Returns an Open item whether open or closed. 404 if missing or not on this workspace / Ledger connection. # Get the result of a custom-connection import Source: https://docs.range.org/api-reference/account-connections/get-the-result-of-a-custom-connection-import /api-reference/platform-api.json get /v2/account-connections/{id}/imports/{importId} Status, upsert counts, and per-row validation errors. # Import snapshots/movements CSV into a custom connection Source: https://docs.range.org/api-reference/account-connections/import-snapshotsmovements-csv-into-a-custom-connection /api-reference/platform-api.json post /v2/account-connections/{id}/imports multipart/form-data with `snapshots` and/or `movements` (CSV), `camt` (CAMT.053 XML), or a `zip` containing those CSV filenames. Accepted and processed asynchronously; poll GET :id/imports/:import_id for the result (counts + row errors). # Initiate FIDO MFA for Cubist login Source: https://docs.range.org/api-reference/account-connections/initiate-fido-mfa-for-cubist-login /api-reference/platform-api.json post /v2/account-connections/cubist/login/{loginId}/mfa/fido/init # List account connections Source: https://docs.range.org/api-reference/account-connections/list-account-connections /api-reference/platform-api.json get /v2/account-connections Returns the list of account connections for the caller workspace. # List persisted open Invoices and Bills Source: https://docs.range.org/api-reference/account-connections/list-persisted-open-invoices-and-bills /api-reference/platform-api.json get /v2/account-connections/bookkeeping/{connectionId}/open-items Reads Range-owned Open items for this Ledger connection. Returns only open rows (remaining balance > 0 at last sync). Does not call QuickBooks. # List the Wise profiles a token can reach Source: https://docs.range.org/api-reference/account-connections/list-the-wise-profiles-a-token-can-reach /api-reference/platform-api.json post /v2/account-connections/wise/profiles Returns the profiles reachable with a read-only Wise API token, so the connect form can ask the user which one to connect. A Wise connection is keyed on a profile id, so this runs before any connection exists and takes the token in the body; the token is used for this request only and is never stored. This must be called server-side rather than from a browser: Wise sends no CORS headers, and resolving the list here guarantees it comes from the same Wise host and API version that credential validation will use. Pass the chosen id back as `wise.profile_id` on POST /account-connections. # Poll Cubist login status Source: https://docs.range.org/api-reference/account-connections/poll-cubist-login-status /api-reference/platform-api.json get /v2/account-connections/cubist/login/{loginId} # Preview account-connection data Source: https://docs.range.org/api-reference/account-connections/preview-account-connection-data /api-reference/platform-api.json get /v2/account-connections/{id} Fetches connection accounts by id. # Pull category candidates from a ledger connection Source: https://docs.range.org/api-reference/account-connections/pull-category-candidates-from-a-ledger-connection /api-reference/platform-api.json get /v2/account-connections/bookkeeping/{connectionId}/categories Preview-only P&L category candidates (income + expense) from the linked bookkeeping system. Balance-sheet accounts (A/R, A/P, bank, equity) are omitted. Does not write workspace categories — persistence is a Range app concern. Active accounts only. # Pull counterparty candidates from a ledger connection Source: https://docs.range.org/api-reference/account-connections/pull-counterparty-candidates-from-a-ledger-connection /api-reference/platform-api.json get /v2/account-connections/bookkeeping/{connectionId}/counterparties Preview-only list of customers/vendors from the linked bookkeeping system (e.g. QuickBooks). Does not write to `counterparties` — persist via POST /v2/counterparties. Active records only — inactive/archived customers and vendors are omitted (MVP default). # Read the edit trail for a custom connection Source: https://docs.range.org/api-reference/account-connections/read-the-edit-trail-for-a-custom-connection /api-reference/platform-api.json get /v2/account-connections/{id}/revisions Newest-first attributable trail of every create/replace/delete/import on this connection. Bounded by `limit`; optionally filtered by `object`. # Soft-delete a movement on a custom connection Source: https://docs.range.org/api-reference/account-connections/soft-delete-a-movement-on-a-custom-connection /api-reference/platform-api.json delete /v2/account-connections/{id}/movements/{movementId} Marks the movement deleted so it no longer appears on account transaction reads. The trail records a delete event. # Soft-delete a snapshot on a custom connection Source: https://docs.range.org/api-reference/account-connections/soft-delete-a-snapshot-on-a-custom-connection /api-reference/platform-api.json delete /v2/account-connections/{id}/snapshots/{snapshotId} Removes one (account, asset, as_of) observation from the live bag and records a delete event on the edit trail. Sibling assets stay. # Start Cubist login Source: https://docs.range.org/api-reference/account-connections/start-cubist-login /api-reference/platform-api.json post /v2/account-connections/cubist/login/start Authenticates with CubeSigner via email/password. Returns login_id; when status is complete, pass that login_id to POST /v2/account-connections (the CubeSigner refresh token is never returned over the wire). # Sync open Invoices and Bills from a ledger connection Source: https://docs.range.org/api-reference/account-connections/sync-open-invoices-and-bills-from-a-ledger-connection /api-reference/platform-api.json post /v2/account-connections/bookkeeping/{connectionId}/open-items/sync Pulls the current open set from the bookkeeping system, upserts Open items, and marks missing rows closed (not deleted). Runs in the request. Overlapping sync on the same connection is rejected. Settlement push is out of scope. # Update account connection Source: https://docs.range.org/api-reference/account-connections/update-account-connection /api-reference/platform-api.json patch /v2/account-connections/{id} Updates mutable connection fields. Currently supports renaming only. # Upsert accounts on a custom connection Source: https://docs.range.org/api-reference/account-connections/upsert-accounts-on-a-custom-connection /api-reference/platform-api.json post /v2/account-connections/{id}/accounts Creates or updates accounts on a custom connection, keyed by `external_id` (the client id, stored as the connection object id). Idempotent: re-sending the same `external_id` updates in place. # Upsert balance snapshots on a custom connection Source: https://docs.range.org/api-reference/account-connections/upsert-balance-snapshots-on-a-custom-connection /api-reference/platform-api.json post /v2/account-connections/{id}/snapshots Appends balance snapshots (the balance tape) per account and instant. A snapshot is an independent observation — never recomputed from movements. Same (account, as_of) is superseded by the newest push. # Upsert movement legs on a custom connection Source: https://docs.range.org/api-reference/account-connections/upsert-movement-legs-on-a-custom-connection /api-reference/platform-api.json post /v2/account-connections/{id}/movements Stores classified movement legs (the transaction tape) so they return through the existing connection transaction reads. Keyed by `client_movement_id` when given, else a hash of the leg identity. # Verify Account Connection Source: https://docs.range.org/api-reference/account-connections/verify-account-connection /api-reference/platform-api.json get /v2/account-connections/{id}/status Returns the connection status for a specific account connection. `reason` distinguishes why a failure happened (when the adapter can tell): `reauth_required` (the item/session itself needs the end user to re-authenticate — rotating credentials will not fix this), `provider_unavailable` (a 5xx/429 from the provider — safe to retry), or `unknown` (anything else, including our own credentials to the provider being wrong). # Add or remove accounts Source: https://docs.range.org/api-reference/accounts/add-or-remove-accounts /api-reference/platform-api.json put /v2/accounts Batch add, update, or remove accounts for the caller workspace. Remove returns 404 when the account id is not found in the workspace. # Assign an account to a team, or detach it Source: https://docs.range.org/api-reference/accounts/assign-an-account-to-a-team-or-detach-it /api-reference/platform-api.json put /v2/accounts/{id}/team Sets team_id on the account. Admin session only (API keys are refused). team_id must be a team of the caller workspace, otherwise 400 with code UNKNOWN_TEAM; null detaches the account from its team. Returns the updated account in the same shape as GET /accounts/:id. # Detach every account from a team Source: https://docs.range.org/api-reference/accounts/detach-every-account-from-a-team /api-reference/platform-api.json delete /v2/teams/{teamId}/accounts Sets team_id to null on every account of the caller workspace that is in the given team. Admin session only. Called by range-app after a team is deleted, so the team is NOT required to still exist; an unknown or already-empty team detaches zero accounts. # Enqueue a transaction sync for the workspace or for given accounts Source: https://docs.range.org/api-reference/accounts/enqueue-a-transaction-sync-for-the-workspace-or-for-given-accounts /api-reference/platform-api.json post /v2/accounts/transfers/sync Enqueues one background job per account (including standalone Solana accounts with no connection). Returns immediately with a batch id; workers process jobs asynchronously. Accounts that already have a pending or active sync job are skipped. Unsupported accounts fail inside the worker rather than being filtered at enqueue. With no body, or an empty `account_ids`, every account in the caller workspace is covered; with `account_ids`, exactly those accounts — all of which must belong to the caller workspace, or the request fails with 404. # Enumerate manageable tokens Source: https://docs.range.org/api-reference/accounts/enumerate-manageable-tokens /api-reference/platform-api.json get /v2/accounts/tokens Returns one paginated list of every token the caller workspace can manage: held balances (canonical assets aggregated across chains, plus uncurated tokens keyed by network+denom) union tokens carrying a stored whitelist override. Always shows everything — does not accept show_all. Composable filters: state, has_override, priced, network. The two logically contradictory filter combinations (see docs) return an empty list, not a 400. refresh=true busts the cached aggregate and re-scans stored balances only — no live RPC/chain fan-out, unlike GET /accounts/concentration's refresh. # Get a single account transfer by id Source: https://docs.range.org/api-reference/accounts/get-a-single-account-transfer-by-id /api-reference/platform-api.json get /v2/accounts/transfers/{transferId} Fetches one persisted account transfer by its transfer id (the `transaction_id` field returned by the list endpoints), scoped to the caller workspace. # Get account by id Source: https://docs.range.org/api-reference/accounts/get-account-by-id /api-reference/platform-api.json get /v2/accounts/{id} Returns a single account for the caller workspace. Balances are filtered by the workspace's token whitelist by default; pass show_all=true to restore the unfiltered response. # Get workspace concentration Source: https://docs.range.org/api-reference/accounts/get-workspace-concentration /api-reference/platform-api.json get /v2/accounts/concentration Returns asset, venue, and network concentration computed over the stored balances of the caller workspace accounts, filtered by the workspace's token whitelist by default (pass show_all=true to restore the unfiltered figures). Pass refresh=true to refresh balances first (slow: live provider/chain RPC calls). Contrast with GET /accounts/tokens, whose refresh=true only re-scans stored balances — no live fan-out. # List accounts Source: https://docs.range.org/api-reference/accounts/list-accounts /api-reference/platform-api.json get /v2/accounts Returns the list of accounts for the caller workspace. Balances are filtered by the workspace's token whitelist by default; pass show_all=true to restore the unfiltered response. # List transactions across all accounts in the workspace Source: https://docs.range.org/api-reference/accounts/list-transactions-across-all-accounts-in-the-workspace /api-reference/platform-api.json get /v2/accounts/transfers Fans out across connection-linked and connectionless accounts in the caller workspace and returns the merged list of transactions, sorted newest-first, capped at `size` (default 5). Pagination is opaque token (cursor) based — pass meta.next_cursor back as `?cursor` to fetch the next page; null next_cursor means no more results. Accounts whose provider does not support transactions, or that fail to fetch, are skipped. Time filters are a half-open UTC Period [start_time, end_time): timestamp >= start_time and timestamp < end_time. A date-only YYYY-MM-DD is that UTC calendar day (start_time is that midnight; end_time is the next UTC midnight). An ISO value with a time is an instant and is not expanded — 2026-08-17T00:00:00Z is midnight, not the whole day. Naive ISO without an offset is interpreted as UTC. When changing the date range, omit cursor; the cursor only encodes { timestamp, id }. # List transactions for an account Source: https://docs.range.org/api-reference/accounts/list-transactions-for-an-account /api-reference/platform-api.json get /v2/accounts/{id}/transfers Returns paginated transactions for a single account, read from the persisted transaction history. Run POST /accounts/transfers/sync first to populate history for a newly imported account. Pagination is opaque token (cursor) based — pass meta.next_cursor back as ?cursor to fetch the next page; null next_cursor means no more results. Time filters are a half-open UTC Period [start_time, end_time): timestamp >= start_time and timestamp < end_time. A date-only YYYY-MM-DD is that UTC calendar day (start_time is that midnight; end_time is the next UTC midnight). An ISO value with a time is an instant and is not expanded — 2026-08-17T00:00:00Z is midnight, not the whole day. Naive ISO without an offset is interpreted as UTC. When changing the date range, omit cursor; the cursor only encodes { timestamp, id }. # Poll the progress of an account tx-sync batch Source: https://docs.range.org/api-reference/accounts/poll-the-progress-of-an-account-tx-sync-batch /api-reference/platform-api.json get /v2/accounts/transfers/sync/status Returns aggregate progress for the batch_id returned by POST /accounts/transfers/sync. Poll `complete`: it turns true once no job for the batch is still in-flight, which stays correct even if an account is deleted mid-sync or a state write is lost. `transactions_upserted` sums the transactions ingested by the successfully-synced accounts. Per-account outcome also appears on `AccountDto.sync_status` / `last_synced_at`. # Refresh balances for the workspace or for given accounts Source: https://docs.range.org/api-reference/accounts/refresh-balances-for-the-workspace-or-for-given-accounts /api-reference/platform-api.json post /v2/accounts/refresh Synchronously refreshes balances — connection-backed (Wise/Kraken/Safe/etc.) and standalone on-chain wallets alike — and persists them. With no body, or an empty `account_ids`, every account in the caller workspace is refreshed; with `account_ids`, exactly those accounts — all of which must belong to the caller workspace, or the request fails with 404. # Resync one account past the lookback window Source: https://docs.range.org/api-reference/accounts/resync-one-account-past-the-lookback-window /api-reference/platform-api.json post /v2/accounts/{id}/transfers/resync Enqueues the same account transaction sync worker for one account, ignoring the 90-day custodian lookback and the on-chain newest-transaction overlap. The 10,000-transaction cap and the on-chain page cap still stop the run. A waiting sync for this account is replaced. A sync that is already running returns 409. Returns a batch id; poll GET /accounts/transfers/sync/status. # Update category on an account transfer Source: https://docs.range.org/api-reference/accounts/update-category-on-an-account-transfer /api-reference/platform-api.json patch /v2/accounts/transfers/{transferId}/category Sets the user-assigned category on a persisted account transfer. The category survives subsequent provider re-syncs. # Update note on an account transfer Source: https://docs.range.org/api-reference/accounts/update-note-on-an-account-transfer /api-reference/platform-api.json patch /v2/accounts/transfers/{transferId}/note Sets the user-authored note on a persisted account transfer. Sending an empty string or null clears it. The note survives subsequent provider re-syncs. # Get Address Counterparties Source: https://docs.range.org/api-reference/address-information/get-address-counterparties /api-reference/data-api.json get /v1/address/connections Returns a list of addresses that the specified address has interacted with. # Get Address Details Source: https://docs.range.org/api-reference/address-information/get-address-details /api-reference/data-api.json get /v1/address Returns labels, entity attribution, and metadata for the specified address, with one result per network. # Get Address Funding Details Source: https://docs.range.org/api-reference/address-information/get-address-funding-details /api-reference/data-api.json get /v1/address/fundedBy Returns funding details of this address with the network. Elasticsearch only — the days-deep EVM transfers index, not full history. Other networks use the declared Elasticsearch transfers index (e.g. cosmos, stellar) or interchain payments only when no such index is declared (e.g. solana). For ClickHouse-backed first-funder lookup use `GET /v2/address/fundedBy`. Responses are cached; send `Cache-Control: no-cache` to force a fresh lookup. # Get Address Funding Details (v2) Source: https://docs.range.org/api-reference/address-information/get-address-funding-details-v2 /api-reference/data-api.json get /v2/address/fundedBy Returns the first inbound funder of this address. On range2 EVM chains (eth, base, arb1, pol, bnb) the answer is served from ClickHouse full history rather than the days-deep Elasticsearch transfers index. Other networks use the declared Elasticsearch transfers index (stellar) or interchain payments only (solana). Responses are cached; send `Cache-Control: no-cache` to force a fresh lookup. # Get Address Info with Risk Score Source: https://docs.range.org/api-reference/address-information/get-address-info-with-risk-score /api-reference/data-api.json get /v1/address/info Returns labels, entity attribution, and risk score for a single address on a network. # Get Address Payments Source: https://docs.range.org/api-reference/address-information/get-address-payments /api-reference/data-api.json get /v1/address/payments Returns a list of transactions associated with the specified address. # Get Address Statistics Source: https://docs.range.org/api-reference/address-information/get-address-statistics /api-reference/data-api.json get /v1/address/stats Returns date of last and first interaction of this address with the network. # Get Address Transactions Source: https://docs.range.org/api-reference/address-information/get-address-transactions /api-reference/data-api.json get /v1/address/transactions Returns a list of transactions associated with the specified address. # Get Asset Flow for an Address Source: https://docs.range.org/api-reference/address-information/get-asset-flow-for-an-address /api-reference/data-api.json get /v1/address/assetFlow Returns per-day, per-token asset flow for the given address: a net delta plus, depending on `source`, either the absolute balance snapshot or the received/sent split it was derived from. # Get Balances for Address List Source: https://docs.range.org/api-reference/address-information/get-balances-for-address-list /api-reference/platform-api.json get /v2/addresses/list/{hash}/balances Returns current balances for all addresses in a stored list. Each address entry includes all native and token balances, filtered by the workspace's token whitelist by default. Pass show_all=true to restore the unfiltered response. # Get Balances for Workspace Accounts Source: https://docs.range.org/api-reference/address-information/get-balances-for-workspace-accounts /api-reference/platform-api.json get /v2/addresses/workspace/balances Returns current balances for all accounts stored in the workspace, filtered by the workspace's token whitelist by default. Pass show_all=true to restore the unfiltered response. Each entry includes `account_id` matching `AccountDto.id` for stable joins; multisig accounts expose their real on-chain address and canonical network. # Get Current Token Balances of an Address Source: https://docs.range.org/api-reference/address-information/get-current-token-balances-of-an-address /api-reference/data-api.json get /v1/address/balance Returns token balances of the given address alongside the lookup outcome (`lookup_status`, and `reason` when not `ok`) on every 200. A failed, partial, or unsupported lookup is reported through `lookup_status` rather than as an empty balance set left indistinguishable from a genuinely empty address. Each entry carries the legacy `amount` (a JSON number, kept for backwards compatibility) alongside `amount_string` — the exact, lossless string rendering of that same quantity. Responses are cached for 60 seconds; send `Cache-Control: no-cache` to force a fresh lookup. # Get Last Activity for Addresses Source: https://docs.range.org/api-reference/address-information/get-last-activity-for-addresses /api-reference/platform-api.json post /v2/addresses/last-activity Returns the last on-chain activity timestamp for each supplied address. # Get Payment Source: https://docs.range.org/api-reference/address-information/get-payment /api-reference/data-api.json get /v1/address/payment Returns a payment transaction associated with the specified hash. # Get Transaction Counts for the specified addresses Source: https://docs.range.org/api-reference/address-information/get-transaction-counts-for-the-specified-addresses /api-reference/data-api.json get /v1/address/transactions/counts Returns a list of transaction counts aggregated by day. # Get Transaction Details Source: https://docs.range.org/api-reference/address-information/get-transaction-details /api-reference/data-api.json get /v1/address/transaction Returns details of a transactions associated with the specified hash. # Get Transactions Count Source: https://docs.range.org/api-reference/address-information/get-transactions-count /api-reference/data-api.json get /v1/address/transactionsCount Returns a list of counts of transactions associated with the specified address. # Search Address Details Source: https://docs.range.org/api-reference/address-information/search-address-details /api-reference/platform-api.json get /v2/addresses Returns a list of addresses that match the specified search term. # Search Address Labels Source: https://docs.range.org/api-reference/address-information/search-address-labels /api-reference/data-api.json get /v1/address/labels/search Returns a list of addresses that match the specified search term. # Store Address List Source: https://docs.range.org/api-reference/address-information/store-address-list /api-reference/platform-api.json post /v2/addresses/list Caches a list of addresses and returns a stable SHA-256 hash that identifies the list. # Get the member templates of one multisig alert pack Source: https://docs.range.org/api-reference/alert-packs/get-the-member-templates-of-one-multisig-alert-pack /api-reference/platform-api.json get /v2/risk/alert-packs/{pack_type} Returns everything needed to create a pack of this type in one call: each member template with its id, network, parameters, and whether it is required. Feed the ids and parameters into `POST /v1/risk/alert-rules/pack`. # List multisig alert packs available to the workspace Source: https://docs.range.org/api-reference/alert-packs/list-multisig-alert-packs-available-to-the-workspace /api-reference/platform-api.json get /v2/risk/alert-packs Browse the multisig alert packs (e.g. `squads`, `safe`) your workspace can create, with the networks each pack covers and how many member templates it has. # Create a multisig alert rule pack Source: https://docs.range.org/api-reference/alert-rules/create-a-multisig-alert-rule-pack /api-reference/platform-api.json post /v1/risk/alert-rules/pack Creates every member rule of one multisig pack atomically and mints a shared `pack_id`. Every referenced template must have the requested `pack_type` enabled; member rules may span networks and runners. If an existing pack already covers the same address, the request is rejected with a 409 soft-warn; re-submit with `override: true` to create anyway. Member rules stay individually editable afterwards via PATCH. # Create an alert rule Source: https://docs.range.org/api-reference/alert-rules/create-an-alert-rule /api-reference/platform-api.json post /v1/risk/alert-rules Creates an alert rule from a registered template. Supply the template id; rule_type, network, and runner_id are copied from it (not supplied). # Delete an alert rule Source: https://docs.range.org/api-reference/alert-rules/delete-an-alert-rule /api-reference/platform-api.json delete /v1/risk/alert-rules/{rule_id} Soft-deletes the rule: it is disabled and hidden from list/get, but the row is retained in the database (only `deleted_at` is stamped). # Fetch a single alert rule Source: https://docs.range.org/api-reference/alert-rules/fetch-a-single-alert-rule /api-reference/platform-api.json get /v1/risk/alert-rules/{rule_id} Returns one alert rule that belongs to your workspace. # Link channels to an alert rule Source: https://docs.range.org/api-reference/alert-rules/link-channels-to-an-alert-rule /api-reference/platform-api.json put /v1/risk/alert-rules/{rule_id}/channels Replaces the rule's subscribed channels with the supplied set. Each entry is { alert_channel_id, min_severity? }; alert_channel_id must be a channel in your workspace. Omit min_severity (or null) for no severity floor. Pass an empty array to clear. # List alert rules for the caller workspace Source: https://docs.range.org/api-reference/alert-rules/list-alert-rules-for-the-caller-workspace /api-reference/platform-api.json get /v1/risk/alert-rules Returns every active alert rule that belongs to your workspace. Filter by network, severity, or a name search. # Update an alert rule Source: https://docs.range.org/api-reference/alert-rules/update-an-alert-rule /api-reference/platform-api.json patch /v1/risk/alert-rules/{rule_id} Partially updates a rule. Only the supplied fields change. Changing `parameters` bumps the rule's `version` and archives the previous version. To change channels, use PUT /:rule_id/channels. # Get a single alert rule template Source: https://docs.range.org/api-reference/alert-templates/get-a-single-alert-rule-template /api-reference/platform-api.json get /v1/risk/alert-templates/{template_id} Returns everything about one alert rule template — its message, severity, tags, and the fields you need to fill in when turning it into an active alert rule. # List alert rule templates available to the workspace Source: https://docs.range.org/api-reference/alert-templates/list-alert-rule-templates-available-to-the-workspace /api-reference/platform-api.json get /v1/risk/alert-templates Browse the alert rule templates your workspace has access to. Narrow the results by network, severity, or tags, or type a few words to search by name, description, or tag. # Get transaction by ID Source: https://docs.range.org/api-reference/blockchain-transactions/get-transaction-by-id /api-reference/data-api.json get /v2/transactions/{id} Returns a transaction that matches the specified ID. # Get transaction by network and hash Source: https://docs.range.org/api-reference/blockchain-transactions/get-transaction-by-network-and-hash /api-reference/data-api.json get /v2/transactions/by-network/{network}/{hash} Returns a transaction with full source data that matches the specified network and hash. # Get transactions list Source: https://docs.range.org/api-reference/blockchain-transactions/get-transactions-list /api-reference/data-api.json get /v2/transactions Returns a list of transactions that match the specified search term. # Humanize a transaction Source: https://docs.range.org/api-reference/blockchain-transactions/humanize-a-transaction /api-reference/data-api.json post /v2/transactions/humanize Given a transaction hash and its network, returns a plain-language explanation of what the transaction does — the action, the parties involved, and any token/native transfers with resolved amounts and USD value. Supports Solana and Ethereum. # Add a comment to a case Source: https://docs.range.org/api-reference/cases/add-a-comment-to-a-case /api-reference/platform-api.json post /v2/cases/{id}/comments # Auto-resolve as escalated and return the evidence bundle (email delivery is a follow-up) Source: https://docs.range.org/api-reference/cases/auto-resolve-as-escalated-and-return-the-evidence-bundle-email-delivery-is-a-follow-up /api-reference/platform-api.json post /v2/cases/{id}/escalate A redemption case cannot be escalated. A redemption case closes only when its redemption is paid or dismissed. # Bulk-dismiss cases Source: https://docs.range.org/api-reference/cases/bulk-dismiss-cases /api-reference/platform-api.json patch /v2/cases/bulk # Case counts by status, plus assigned-to-me and unread Source: https://docs.range.org/api-reference/cases/case-counts-by-status-plus-assigned-to-me-and-unread /api-reference/platform-api.json get /v2/cases/counts # Create a case (manual) Source: https://docs.range.org/api-reference/cases/create-a-case-manual /api-reference/platform-api.json post /v2/cases # Delete a case Source: https://docs.range.org/api-reference/cases/delete-a-case /api-reference/platform-api.json delete /v2/cases/{id} Marks the case deleted; it disappears from every cases endpoint but the row and its timeline are kept. Admin session only (API keys are refused). Any status can be deleted, except a redemption case. A redemption case closes only when its redemption is paid or dismissed. # Full audit trail for a case Source: https://docs.range.org/api-reference/cases/full-audit-trail-for-a-case /api-reference/platform-api.json get /v2/cases/{id}/timeline # Get case detail (comments + evidence summary) Source: https://docs.range.org/api-reference/cases/get-case-detail-comments-+-evidence-summary /api-reference/platform-api.json get /v2/cases/{id} # Link a saved Trail investigation to a case Source: https://docs.range.org/api-reference/cases/link-a-saved-trail-investigation-to-a-case /api-reference/platform-api.json post /v2/cases/{id}/investigations # List cases (the compliance inbox) Source: https://docs.range.org/api-reference/cases/list-cases-the-compliance-inbox /api-reference/platform-api.json get /v2/cases # Mark cases created at or before a cutoff as read Source: https://docs.range.org/api-reference/cases/mark-cases-created-at-or-before-a-cutoff-as-read /api-reference/platform-api.json post /v2/cases/read-all # Resolve linked investigation ids to full objects Source: https://docs.range.org/api-reference/cases/resolve-linked-investigation-ids-to-full-objects /api-reference/platform-api.json get /v2/cases/{id}/investigations # Update case status, resolution, assignee, or read state Source: https://docs.range.org/api-reference/cases/update-case-status-resolution-assignee-or-read-state /api-reference/platform-api.json patch /v2/cases/{id} # Add, update, or remove alert channels Source: https://docs.range.org/api-reference/channels/add-update-or-remove-alert-channels /api-reference/platform-api.json put /v1/risk/channels Batch create, update, or soft-delete alert channels for your workspace. Each operation specifies an action ("add", "update", or "remove") and the channel data. # Create a channel Source: https://docs.range.org/api-reference/channels/create-a-channel /api-reference/platform-api.json post /v1/risk/channels Creates a single channel for your workspace. Slack, Discord, and generic webhooks require params.webhook_url; PagerDuty requires params.routing_key; Email requires params.recipients (array of addresses); incident.io requires params.url; Telegram params are generated server-side. # Delete a channel Source: https://docs.range.org/api-reference/channels/delete-a-channel /api-reference/platform-api.json delete /v1/risk/channels/{channel_id} Soft-deletes one channel owned by your workspace: it is disabled and hidden from list/get, but the row is retained (only `deleted_at` is stamped). # Fetch a single alert channel Source: https://docs.range.org/api-reference/channels/fetch-a-single-alert-channel /api-reference/platform-api.json get /v1/risk/channels/{channel_id} Returns the details of one alert channel that belongs to your workspace. Disabled channels are still returned (200); only deleted channels return 404. # List alert channels for the caller workspace Source: https://docs.range.org/api-reference/channels/list-alert-channels-for-the-caller-workspace /api-reference/platform-api.json get /v1/risk/channels Returns every non-deleted alert channel for your workspace, including disabled ones. Each item carries `enabled` (your on/off state) and `connected` (delivery readiness). To hide a channel, delete it — disabling only stops delivery. # Get Connections by Address Source: https://docs.range.org/api-reference/connections-information/get-connections-by-address /api-reference/data-api.json get /v2/connections/byAddress Returns a list of addresses that the specified address has interacted with (v2). # Get Induced Subgraph Source: https://docs.range.org/api-reference/connections-information/get-induced-subgraph /api-reference/data-api.json post /v2/connections/subgraph Given a set of addresses (e.g. every node currently on a Trail canvas), returns only the edges that exist between addresses in that set — the sibling-to-sibling connections that byAddress cannot express because it only sees one root address at a time. # Get transfers between two addresses Source: https://docs.range.org/api-reference/connections-information/get-transfers-between-two-addresses /api-reference/data-api.json get /v2/connections/transfers Returns a list of transfers between two specified addresses on their respective networks. # Cross-chain corridors between the workspace’s own Accounts Source: https://docs.range.org/api-reference/corridors/cross-chain-corridors-between-the-workspace’s-own-accounts /api-reference/platform-api.json get /v2/corridors Returns the bridged movements in a period where both ends are addresses this workspace owns — money it moved between its own Accounts across networks, rather than to anyone else. These are facts, not inferences: a bridge record links the two transactions by construction, so a corridor is reported only when both of its ends resolve to owned addresses. Ownership is tested against every address the workspace owns, including the fund-holding addresses behind multisig and governance connections, not only the addresses saved on Accounts. By default only movements that arrived are returned; use the `status` parameter to also see ones still in transit or that failed. Supported bridge protocols: across, allbridge, axelar, cctp, cctpv2, circle-gateway, debridge, hyperlane, hyperliquid-bridge2, ibc, ibcv2, layerzero, mayan, near-intents, union, wormhole. A movement through any other bridge is not detected, and is absent rather than reported as external. The workspace is taken from the authenticated key, never from a parameter. Read-only: nothing is stored, and re-running an identical query returns an identical set. # Create a counterparty Source: https://docs.range.org/api-reference/counterparties/create-a-counterparty /api-reference/platform-api.json post /v2/counterparties # Delete counterparty and all associated data Source: https://docs.range.org/api-reference/counterparties/delete-counterparty-and-all-associated-data /api-reference/platform-api.json delete /v2/counterparties/{id} # Download a document Source: https://docs.range.org/api-reference/counterparties/download-a-document /api-reference/platform-api.json get /v2/counterparties/{id}/documents/{docId} # Get counterparty details Source: https://docs.range.org/api-reference/counterparties/get-counterparty-details /api-reference/platform-api.json get /v2/counterparties/{id} # List counterparties Source: https://docs.range.org/api-reference/counterparties/list-counterparties /api-reference/platform-api.json get /v2/counterparties # Manage addresses (add/update/remove) Source: https://docs.range.org/api-reference/counterparties/manage-addresses-addupdateremove /api-reference/platform-api.json put /v2/counterparties/{id}/addresses # Manage bank accounts (add/update/remove) Source: https://docs.range.org/api-reference/counterparties/manage-bank-accounts-addupdateremove /api-reference/platform-api.json put /v2/counterparties/{id}/bank-accounts # Remove a document Source: https://docs.range.org/api-reference/counterparties/remove-a-document /api-reference/platform-api.json delete /v2/counterparties/{id}/documents/{docId} # Update counterparty fields Source: https://docs.range.org/api-reference/counterparties/update-counterparty-fields /api-reference/platform-api.json patch /v2/counterparties/{id} # Upload a document (PDF, max 10 MB) Source: https://docs.range.org/api-reference/counterparties/upload-a-document-pdf-max-10-mb /api-reference/platform-api.json post /v2/counterparties/{id}/documents # Search Entity Details Source: https://docs.range.org/api-reference/entity-information/search-entity-details /api-reference/data-api.json get /v2/entities Returns a list of entities that match the specified search term. # Create a new custom group Source: https://docs.range.org/api-reference/groups/create-a-new-custom-group /api-reference/platform-api.json post /v2/groups # Delete a custom group (associations removed, addresses kept) Source: https://docs.range.org/api-reference/groups/delete-a-custom-group-associations-removed-addresses-kept /api-reference/platform-api.json delete /v2/groups/{id} # List all groups for a workspace (including system groups) Source: https://docs.range.org/api-reference/groups/list-all-groups-for-a-workspace-including-system-groups /api-reference/platform-api.json get /v2/groups # Rename a custom group Source: https://docs.range.org/api-reference/groups/rename-a-custom-group /api-reference/platform-api.json put /v2/groups/{id} # Evaluate a proposed transaction against the treasury policies Source: https://docs.range.org/api-reference/intents/evaluate-a-proposed-transaction-against-the-treasury-policies /api-reference/platform-api.json post /v2/intents/evaluate Takes a transaction intent — the transaction you are about to sign — and answers whether Range’s treasury policies allow it. Returns every breaching policy with a reason and the projected effect, so the breach can be previewed before anything is submitted. A breach is blocking: there is no warn tier on this surface. Read-only — evaluating an intent records nothing and notifies no one. # Evaluate an unsigned transaction against the treasury policies Source: https://docs.range.org/api-reference/intents/evaluate-an-unsigned-transaction-against-the-treasury-policies /api-reference/platform-api.json post /v2/transactions/evaluate Takes the serialized unsigned transaction a wallet holds immediately before signing, simulates it, derives every outbound value movement (value leaving a signer’s accounts toward an external wallet), and evaluates them against the policy catalog listed by `GET /v2/intents/policies` — the same catalog `POST /v2/intents/evaluate` checks a hand-declared intent against. Each policy is judged at its scope: the per-transaction ceiling and the concentration projection once, on the combined value of every movement (`transaction_breaches`); sanctions screening and the unverified-counterparty threshold once per recipient, on everything sent to it (`movements[].breaches`). USD values are priced by Range at evaluation time, never taken from the caller. Any breach blocks the transaction. Advisory and read-only — evaluating records nothing and notifies no one; the caller’s signing flow owns the decision. When anything evaluable could not be evaluated (an unpriced asset, an unresolvable recipient), the response says so via `coverage: partial` and `notes` — an `allowed` with partial coverage is not a clean bill. # List the treasury policies an intent is evaluated against Source: https://docs.range.org/api-reference/intents/list-the-treasury-policies-an-intent-is-evaluated-against /api-reference/platform-api.json get /v2/intents/policies The policies are Range’s and identical for every workspace — they change by shipping code, so there is no way to create, edit or disable one. Every `policy_key` here is the identifier reported on a breach by `POST /v2/intents/evaluate`. # Fetch one investigation including canvas data Source: https://docs.range.org/api-reference/investigations/fetch-one-investigation-including-canvas-data /api-reference/platform-api.json get /v2/investigations/{id} # List workspace investigations (canvas data excluded) Source: https://docs.range.org/api-reference/investigations/list-workspace-investigations-canvas-data-excluded /api-reference/platform-api.json get /v2/investigations # Save a Trail investigation to the workspace Source: https://docs.range.org/api-reference/investigations/save-a-trail-investigation-to-the-workspace /api-reference/platform-api.json post /v2/investigations # Soft-delete an investigation Source: https://docs.range.org/api-reference/investigations/soft-delete-an-investigation /api-reference/platform-api.json delete /v2/investigations/{id} # Update an investigation (partial, last write wins) Source: https://docs.range.org/api-reference/investigations/update-an-investigation-partial-last-write-wins /api-reference/platform-api.json patch /v2/investigations/{id} # Get multisig details (Safe / Squads / Altitude / Realms) Source: https://docs.range.org/api-reference/multisig/get-multisig-details-safe-squads-altitude-realms /api-reference/data-api.json get /v2/multisig/details Stateless read of a multisig: config + members, balances, and pending proposals. Mirrors the data an account-connection exposes, so it can be used whether or not the wallet is a saved connection. `network` is required for `safe` (EVM chain) and rejected for `squads`/`altitude`/`realms` (Solana-only). # Reverse lookup: which multisigs does this address sign on Source: https://docs.range.org/api-reference/multisig/reverse-lookup:-which-multisigs-does-this-address-sign-on /api-reference/data-api.json get /v2/multisig/memberships Given a signer address, returns the Safe multisigs it co-signs, across every EVM chain Range's Safe integration supports (or a single `network` if given). Squads/Altitude/Realms are not covered yet: their membership lists live inside variable-length on-chain state with no cheap reverse index, unlike Safe's own owners API. # Get Active Accounts within time range Source: https://docs.range.org/api-reference/network-information/get-active-accounts-within-time-range /api-reference/data-api.json get /v1/network/active-accounts Returns total active accounts for network within time range. # Get Aggregated Payment field grouped by address Source: https://docs.range.org/api-reference/network-information/get-aggregated-payment-field-grouped-by-address /api-reference/data-api.json get /v1/network/payment-aggs-by-address Returns addresses with maximum aggregated field value in the network # Get all payments by network Source: https://docs.range.org/api-reference/network-information/get-all-payments-by-network /api-reference/data-api.json post /v1/network/{network}/payments Returns a list of payments for the specified network. Supports both traditional pagination and scroll API for large datasets. # Get all transactions by network Source: https://docs.range.org/api-reference/network-information/get-all-transactions-by-network /api-reference/data-api.json post /v1/network/{network}/transactions Returns a list of transactions for the specified network. Supports both traditional pagination and scroll API for large datasets. # Get Balance Changes Day wise By Network Source: https://docs.range.org/api-reference/network-information/get-balance-changes-day-wise-by-network /api-reference/data-api.json get /v1/network/balances Returns a list of balance changes associated with the specified address. # Get msg types in a network Source: https://docs.range.org/api-reference/network-information/get-msg-types-in-a-network /api-reference/data-api.json get /v1/network/msg-types Returns a list of msg types associated with the transactions of a network. # Get Net Flow Day wise By Protocol Source: https://docs.range.org/api-reference/network-information/get-net-flow-day-wise-by-protocol /api-reference/data-api.json get /v1/network/net-flow-by-protocol Returns a list net flow amounts associated with the specified protocol. # Get network volume aggregated by interval Source: https://docs.range.org/api-reference/network-information/get-network-volume-aggregated-by-interval /api-reference/data-api.json get /v1/network/volume Returns a list of aggregated volumes for each network. # Get network volume within time range Source: https://docs.range.org/api-reference/network-information/get-network-volume-within-time-range /api-reference/data-api.json get /v1/network/volume-by-time-range Returns a aggregated volume for network within time range. # Get payments for a transaction Source: https://docs.range.org/api-reference/network-information/get-payments-for-a-transaction /api-reference/data-api.json get /v1/network/payments Returns a list of payments associated with the specified transaction. # Get Search Results Source: https://docs.range.org/api-reference/network-information/get-search-results /api-reference/data-api.json get /v1/network/transactions/search Retrieves a list of transactions along with their metadata that correspond to the specified search string. # Get Top Asset Balances by Address Source: https://docs.range.org/api-reference/network-information/get-top-asset-balances-by-address /api-reference/data-api.json get /v1/network/asset-balance-by-address Returns addresses with the highest balances for a given asset in the network. # Get Top USD Balances by Address Source: https://docs.range.org/api-reference/network-information/get-top-usd-balances-by-address /api-reference/data-api.json get /v1/network/usd-balance-by-address Returns addresses with the highest USD balances in the network. # Get Transaction Count by address Source: https://docs.range.org/api-reference/network-information/get-transaction-count-by-address /api-reference/data-api.json get /v1/network/txn-count-by-address Returns a transaction count for given time range and network grouped by address. # Get Transaction Count by time range Source: https://docs.range.org/api-reference/network-information/get-transaction-count-by-time-range /api-reference/data-api.json get /v1/network/txn-count-by-time-range Returns a transaction count for given time range and network. # Get Transaction Counts Source: https://docs.range.org/api-reference/network-information/get-transaction-counts /api-reference/data-api.json get /v1/network/transactions/counts Returns a list of transaction counts for each specified interval across all requested networks. # Get Whale Moves Source: https://docs.range.org/api-reference/network-information/get-whale-moves /api-reference/data-api.json get /v1/network/whale-moves Returns addresses with maximum transfer volumes in the network # Attach accounts to / detach accounts from an entity Source: https://docs.range.org/api-reference/parties/attach-accounts-to-detach-accounts-from-an-entity /api-reference/platform-api.json put /v2/parties/{id}/accounts `add` moves each account onto this entity; `remove` moves it back to `self`. Accounts are never deleted. All operations apply in one transaction, or none do. # Create a counterparty that belongs to this client Source: https://docs.range.org/api-reference/parties/create-a-counterparty-that-belongs-to-this-client /api-reference/platform-api.json post /v2/parties/{id}/counterparties The new entity is a counterparty of this client only. Another client with the same counterparty name gets its own entity. `types` is not accepted; the row is stored as `counterparty`. # Create an entity (client and/or counterparty) Source: https://docs.range.org/api-reference/parties/create-an-entity-client-andor-counterparty /api-reference/platform-api.json post /v2/parties Tax ids are write-only: `tax_ids[].value` is accepted here and only ever read back as `masked_value`. # Delete an entity and its associated data Source: https://docs.range.org/api-reference/parties/delete-an-entity-and-its-associated-data /api-reference/platform-api.json delete /v2/parties/{id} Deleting a client also deletes the counterparties that belong to it. Accounts on the entity and on those counterparties move back to self. # Get entity details Source: https://docs.range.org/api-reference/parties/get-entity-details /api-reference/platform-api.json get /v2/parties/{id} # Get the workspace's own entity Source: https://docs.range.org/api-reference/parties/get-the-workspaces-own-entity /api-reference/platform-api.json get /v2/parties/self # List a client's counterparties Source: https://docs.range.org/api-reference/parties/list-a-clients-counterparties /api-reference/platform-api.json get /v2/parties/{id}/counterparties Same item shape as `GET /v2/parties`, restricted to counterparties whose `client_id` is this client. # List an entity's accounts Source: https://docs.range.org/api-reference/parties/list-an-entitys-accounts /api-reference/platform-api.json get /v2/parties/{id}/accounts Same items and cursor pagination as `GET /v2/accounts`, restricted to accounts attached to this entity. # List entities Source: https://docs.range.org/api-reference/parties/list-entities /api-reference/platform-api.json get /v2/parties # Update entity fields (provided fields only) Source: https://docs.range.org/api-reference/parties/update-entity-fields-provided-fields-only /api-reference/platform-api.json patch /v2/parties/{id} `tax_ids` and `persons_of_interest`, when provided, each replace the whole set: anything absent is deleted. # Get protocol statistics for a given time range Source: https://docs.range.org/api-reference/protocols/get-protocol-statistics-for-a-given-time-range /api-reference/data-api.json post /v1/protocols/stats # Multi-source reconciliation Source: https://docs.range.org/api-reference/reconciliation/multi-source-reconciliation /api-reference/platform-api.json post /v2/reconciliation/multi-source Compares a custodian account with an on-chain account over one period. Addresses do not have to match. An optional connection with type custom is a stand-in ledger. Runs each account’s roll-forward and returns them side-by-side per asset. Each asset block carries an agreement_status, a closed likely_cause tag, and any unmatched_movements (tx_hash then source_ref; SELF legs included). Unlike roll-forward this is a POST with a JSON body, and end_time is optional (defaults to and echoes server now). USD figures are display-only snapshots taken independently per tape, and agreement is on quantities. # Roll-forward balance reconciliation Source: https://docs.range.org/api-reference/reconciliation/roll-forward-balance-reconciliation /api-reference/platform-api.json get /v2/reconciliation/roll-forward For a requested period, ties each account/asset line's opening balance observation plus in-between movements to its actual closing observation — transfers and trades alike. A trade's proceeds are attributed to whichever account in the trade's connection actually holds the asset received (not only the account the trade row is attributed to), so both legs of a trade tie; a quote or fee leg with no account anywhere in the connection is declared in declared_gaps rather than silently dropped. Each movement line is labeled by kind (transfer_in, transfer_out, trade_in, trade_out, trade_fee) alongside the net movements_quantity, supporting both a quantity-conservation reading and a flow reading. Each account's effective period (the real observation timestamps actually used) is returned alongside the requested period, and may differ per account. The movement-count cap is evaluated once per connection (not per account, since a widened read spans every sibling); an affected connection returns movements_truncated and no computed closing for every account in it, rather than a partial number. USD accompanies each line for display only; it is never part of the identity or difference. Opening/closing balances and movements are both filtered through the workspace's token whitelist, per asset leg, so a hidden token cannot manufacture a phantom break on one side only; pass show_all=true to bypass filtering on both sides. account_ids can be narrowed further with the group_id, provider, network, account_type, role, and connection_id filters — a requested id failing any provided filter is dropped from the statement the same way an id outside the caller's workspace already is. reporting_currency accepts only USD today (no FX conversion exists yet); any other value is rejected. Each asset line, and each account statement, also carries a non-nullable tie_out_status (tied, explained, break, or not_evaluated) — a typed reading of the Tie-out outcome, derivable from the other fields in this response, so a consumer never has to interpret a raw difference/declared_gap_reason pair itself. tied means opening plus movements equal the closing balance for that asset; it does not mean every transaction in the period was ingested. # Candidate payouts for a redemption Source: https://docs.range.org/api-reference/redemptions/candidate-payouts-for-a-redemption /api-reference/platform-api.json get /v2/redemptions/{id}/candidates Unmatched payouts to the same address, or any address at the exact amount. all_unmatched=true returns every unmatched payout. # Count redemptions by state Source: https://docs.range.org/api-reference/redemptions/count-redemptions-by-state /api-reference/platform-api.json get /v2/redemptions/counts Same filters as the list. A dismissed redemption counts as failed. # Dismiss a failed redemption Source: https://docs.range.org/api-reference/redemptions/dismiss-a-failed-redemption /api-reference/platform-api.json post /v2/redemptions/{id}/dismiss The redemption stays failed. The reason is stored encrypted and the case resolves as dismissed. # Export the redemption register Source: https://docs.range.org/api-reference/redemptions/export-the-redemption-register /api-reference/platform-api.json get /v2/redemptions/register.csv Unpaginated CSV of the same rows the list would return. # Get a redemption Source: https://docs.range.org/api-reference/redemptions/get-a-redemption /api-reference/platform-api.json get /v2/redemptions/{id} One register row, the same shape the list returns. case_id links to the case opened when it missed its deadline. # List redemptions Source: https://docs.range.org/api-reference/redemptions/list-redemptions /api-reference/platform-api.json get /v2/redemptions Workspace redemptions for a burn-time window. Each item is a register row. # Match or inject a payout Source: https://docs.range.org/api-reference/redemptions/match-or-inject-a-payout /api-reference/platform-api.json post /v2/redemptions/{id}/payout Pairs an unmatched payout, or writes one through the payout account, then re-evaluates the redemption. # Get mint and burn events for a token Source: https://docs.range.org/api-reference/token-information/get-mint-and-burn-events-for-a-token /api-reference/data-api.json get /v2/tokens/mints-burns Returns mint and burn Transfer events for a token. For EVM networks these are Transfer events from/to the zero address. For Solana these are mintTo/burn SPL-token instructions. # Get token summary Source: https://docs.range.org/api-reference/token-information/get-token-summary /api-reference/data-api.json get /v2/tokens/summary Returns the latest token summary (supply, holders, etc.) from Elasticsearch for a given token and chain. # Get top holders for a token Source: https://docs.range.org/api-reference/token-information/get-top-holders-for-a-token /api-reference/data-api.json get /v2/tokens/top-holders Returns top holders ordered by balance from the token-holders index. Only considers the latest snapshot (nonce=1). # Get total supply for a token Source: https://docs.range.org/api-reference/token-information/get-total-supply-for-a-token /api-reference/data-api.json get /v2/tokens/total-supply Returns the total supply of a token on the specified network. Supports Solana (SPL mint address) and EVM-compatible networks (ERC-20 contract address). # Get token transfer by ID Source: https://docs.range.org/api-reference/token-transfers/get-token-transfer-by-id /api-reference/data-api.json get /v2/transfers/{id} Returns a token transfer that matches the specified ID. # Get token transfers Source: https://docs.range.org/api-reference/token-transfers/get-token-transfers /api-reference/data-api.json get /v2/transfers Returns a list of token transfers that match the specified search term. # Get top assets Source: https://docs.range.org/api-reference/token-transfers/get-top-assets /api-reference/data-api.json get /v2/transfers/top-assets Returns the top 1000 assets by transfer count over the last 7 days. # Get top sender and receiver networks Source: https://docs.range.org/api-reference/token-transfers/get-top-sender-and-receiver-networks /api-reference/data-api.json get /v2/transfers/top-networks Returns the top 1000 sender networks and top 1000 receiver networks for interchain transfers matching the given filters. # Get the workspace token whitelist Source: https://docs.range.org/api-reference/token-whitelist/get-the-workspace-token-whitelist /api-reference/platform-api.json get /v2/token-whitelist Returns the workspace's stored overrides and an updated_at. Never 404s — an empty `overrides` array is the correct steady state for a workspace that has never patched its whitelist, and `updated_at` is null until it does. # Patch the workspace token whitelist Source: https://docs.range.org/api-reference/token-whitelist/patch-the-workspace-token-whitelist /api-reference/platform-api.json patch /v2/token-whitelist Accepts a `changes` array of tagged instructions and returns 200 with the identical shape as the GET, so a client updates local state from the response without a second call. `state` is tri-state on the way in — 'on' | 'off' | 'default', where 'default' deletes the override — but the response only ever shows 'on' | 'off': a cleared override is represented by absence from `overrides`, since a delete instruction can never come back. # Create a custom transaction category Source: https://docs.range.org/api-reference/transaction-categories/create-a-custom-transaction-category /api-reference/data-api.json post /v2/transaction-categories Use this endpoint to create a custom transaction category for your workspace. The endpoint is idempotent - will return the existing category if the name is already taken. # Delete a custom transaction category Source: https://docs.range.org/api-reference/transaction-categories/delete-a-custom-transaction-category /api-reference/data-api.json delete /v2/transaction-categories/{id} # List default and workspace-custom transaction categories Source: https://docs.range.org/api-reference/transaction-categories/list-default-and-workspace-custom-transaction-categories /api-reference/data-api.json get /v2/transaction-categories # Rename a custom transaction category Source: https://docs.range.org/api-reference/transaction-categories/rename-a-custom-transaction-category /api-reference/data-api.json put /v2/transaction-categories/{id} # Create or update a transfer category Source: https://docs.range.org/api-reference/transfer-enrichments/create-or-update-a-transfer-category /api-reference/data-api.json post /v2/transfers/enrichment/categories # Create or update a transfer note Source: https://docs.range.org/api-reference/transfer-enrichments/create-or-update-a-transfer-note /api-reference/data-api.json post /v2/transfers/enrichment/notes # Delete a transfer category Source: https://docs.range.org/api-reference/transfer-enrichments/delete-a-transfer-category /api-reference/data-api.json delete /v2/transfers/enrichment/categories/{transferId} # Delete a transfer note Source: https://docs.range.org/api-reference/transfer-enrichments/delete-a-transfer-note /api-reference/data-api.json delete /v2/transfers/enrichment/notes/{transferId} # Get category for a specific transfer Source: https://docs.range.org/api-reference/transfer-enrichments/get-category-for-a-specific-transfer /api-reference/data-api.json get /v2/transfers/enrichment/categories/{transferId} # Get note and category for a transfer by tx hash and network Source: https://docs.range.org/api-reference/transfer-enrichments/get-note-and-category-for-a-transfer-by-tx-hash-and-network /api-reference/data-api.json get /v2/transfers/enrichment/lookup # List all notes for workspace Source: https://docs.range.org/api-reference/transfer-enrichments/list-all-notes-for-workspace /api-reference/data-api.json get /v2/transfers/enrichment/notes # List transfer categories for workspace Source: https://docs.range.org/api-reference/transfer-enrichments/list-transfer-categories-for-workspace /api-reference/data-api.json get /v2/transfers/enrichment/categories # List transfer notes for workspace Source: https://docs.range.org/api-reference/transfer-enrichments/list-transfer-notes-for-workspace /api-reference/data-api.json get /v2/transfers/enrichment/notes/{transferId} # Update note text Source: https://docs.range.org/api-reference/transfer-enrichments/update-note-text /api-reference/data-api.json patch /v2/transfers/enrichment/notes/{transferId} # Get bucketed cash-flow series Source: https://docs.range.org/api-reference/treasury/get-bucketed-cash-flow-series /api-reference/platform-api.json get /v2/treasury/cash-flow Inflow, outflow and net over a caller-chosen window, bucketed by day, ISO week (Monday start), or calendar month. Buckets are calendar-aligned, half-open [period_start, period_end), UTC, contiguous and ascending; a quiet bucket reports real zeros, never an absent entry. The echoed period reflects the window after it is outward-snapped to bucket boundaries, not the raw request. Flows are gross (a movement between two of your own accounts counts once as inflow and once as outflow) — filtering to a single account_id, or to only one side of such a pair, is expected to make net non-zero; this is defined behavior, not a bug. See data_availability for missing or truncated transaction history. # Get treasury cash forecast Source: https://docs.range.org/api-reference/treasury/get-treasury-cash-forecast /api-reference/platform-api.json get /v2/treasury/forecast Projects future cash position from historical transfer rates (gross — a movement between two of your own accounts counts on both sides). expenses_by_category / revenue_by_category are deferred (always empty). See data_availability for missing provider/sync data. # Get treasury summary KPIs Source: https://docs.range.org/api-reference/treasury/get-treasury-summary-kpis /api-reference/platform-api.json get /v2/treasury/summary Pre-computed workspace treasury KPIs: total funds, 30d in/out/net flows (gross — a movement between two of your own accounts counts on both sides), coverage months, and period-over-period comparison. Category breakdowns are not included (deferred). See data_availability for missing provider/sync data. # Archive an instance, cancel pending work, and retain run history Source: https://docs.range.org/api-reference/workflows/archive-an-instance-cancel-pending-work-and-retain-run-history /api-reference/platform-api.json delete /v2/workflows/{id} # Create a custom run with explicit UTC period boundaries (CARF calendar year, or treasury-statement / transfer-attribution day/month/year) Source: https://docs.range.org/api-reference/workflows/create-a-custom-run-with-explicit-utc-period-boundaries-carf-calendar-year-or-treasury-statement-transfer-attribution-daymonthyear /api-reference/platform-api.json post /v2/workflows/runs/custom # Create a workflow instance Source: https://docs.range.org/api-reference/workflows/create-a-workflow-instance /api-reference/platform-api.json post /v2/workflows Creates one instance of a template for the caller workspace. The template required fields (cnpj for CADOC) are mandatory; destinations are optional and can be configured later; cadence and formats are fixed by the template: 5711 daily XML, 5710 month-end JSON, CARF manual calendar-year XML. Optional recipients select existing delivery channels. Delivery follows the workflow definition. report_mode is no longer supported; requests containing it return 400. # Download the immutable stored workflow output Source: https://docs.range.org/api-reference/workflows/download-the-immutable-stored-workflow-output /api-reference/platform-api.json get /v2/workflows/runs/{id}/output # Get v2workflowsruns Source: https://docs.range.org/api-reference/workflows/get-v2workflowsruns /api-reference/platform-api.json get /v2/workflows/runs # List workflow templates and workspace instances Source: https://docs.range.org/api-reference/workflows/list-workflow-templates-and-workspace-instances /api-reference/platform-api.json get /v2/workflows Every workflow template with its field schema and the caller workspace instances of it. A workspace may run several instances of one template, one per regulated entity. Omitting `kind` returns the deterministic CADOC 5710/5711 and CARF templates (the pre-existing shape); pass `kind=agent` to poll the templates the Autopilot runtime executes. # List workspace registrations for a workflow template Source: https://docs.range.org/api-reference/workflows/list-workspace-registrations-for-a-workflow-template /api-reference/platform-api.json get /v2/workflows/templates/{template}/accounts Filters combine with AND before pagination. Registrations are shared by every instance of a template in the workspace. Filters affect this list only, never workflow execution. Unsupported template filters and repeated values return 400. # Queue a new execution for the stored period using current workflow settings Source: https://docs.range.org/api-reference/workflows/queue-a-new-execution-for-the-stored-period-using-current-workflow-settings /api-reference/platform-api.json post /v2/workflows/runs/{id}/rerun # Read workflow run progress and frozen evidence Source: https://docs.range.org/api-reference/workflows/read-workflow-run-progress-and-frozen-evidence /api-reference/platform-api.json get /v2/workflows/runs/{id} # Update, enable, or disable a workflow instance Source: https://docs.range.org/api-reference/workflows/update-enable-or-disable-a-workflow-instance /api-reference/platform-api.json patch /v2/workflows/{id} Partial update of one instance. Omitted fields keep their stored value; `fields` is merged into the stored fields. Disable by sending enabled=false. recipients replaces selected channels; [] clears them and omission preserves them. The template of an instance cannot change. # Get all workspace plan definitions Source: https://docs.range.org/api-reference/workspace-config/get-all-workspace-plan-definitions /api-reference/platform-api.json get /v1/workspace/config Returns every plan with its numeric rank and per-feature limits (alert rules, trail tabs, tracked addresses). The client fetches this once on startup and stores it in app context. # Get workspace request history Source: https://docs.range.org/api-reference/workspace-config/get-workspace-request-history /api-reference/platform-api.json get /v1/workspace/requests Returns the last 30 days of API requests for the workspace resolved from the API key, newest first, cursor-paginated. # Get workspace usage Source: https://docs.range.org/api-reference/workspace-usage/get-workspace-usage /api-reference/platform-api.json get /v1/workspace/usage Returns API credit consumption for the current billing period for the workspace resolved from the API key. # Get workspace usage by day Source: https://docs.range.org/api-reference/workspace-usage/get-workspace-usage-by-day /api-reference/platform-api.json get /v2/workspace/usage/daily Returns the last 30 UTC days of API credit and request counts for the workspace resolved from the API key, oldest first. Unlike the billing- period totals above, this is a fixed trailing window and takes no parameters. Every day in the window is present — a day with no traffic is returned with zero counters rather than omitted. # Authentication Source: https://docs.range.org/data-api/authentication Secure your API requests with Authorization header authentication. ## API Key Authentication All Range Data API requests require authentication using an API key passed in the request header. ### Getting Your API Key If you need access, [request a time-limited Sandbox](https://www.range.org/contact). Log in to [app.range.org](https://app.range.org) with your Sandbox or paid account Navigate to your dashboard and generate a new API key Copy your API key and store it securely. Treat it like a password, never commit it to version control. *** ## Making Authenticated Requests Include your API key in the `Authorization` header with every request: ```bash cURL theme={null} curl -X GET "https://api.range.org/v1/address?address=YOUR_ADDRESS&network=solana" \ -H "Authorization: Bearer YOUR_API_KEY" ``` ```javascript JavaScript theme={null} const response = await fetch( "https://api.range.org/v1/address?address=YOUR_ADDRESS&network=solana", { headers: { Authorization: "Bearer YOUR_API_KEY", }, } ); const data = await response.json(); ``` ```python Python theme={null} import requests headers = { 'Authorization': 'Bearer YOUR_API_KEY' } response = requests.get( 'https://api.range.org/v1/address', params={'address': 'YOUR_ADDRESS', 'network': 'solana'}, headers=headers ) data = response.json() ``` ```typescript TypeScript theme={null} const response = await fetch( "https://api.range.org/v1/address?address=YOUR_ADDRESS&network=solana", { headers: { Authorization: "Bearer YOUR_API_KEY", }, } ); const data = await response.json(); ``` *** ## Rate Limits Rate limits and quotas depend on your account. Use the `X-RateLimit-*` response headers below to check your current limit and usage. Rate limit headers are included in every API response to help you track usage: * `X-RateLimit-Limit`: Your rate limit ceiling - `X-RateLimit-Remaining`: Requests remaining in current window - `X-RateLimit-Reset`: Time when the rate limit resets (Unix timestamp) *** ## Error Responses ### 401 Unauthorized Missing or invalid API key: ```json theme={null} { "statusCode": 401, "message": "Unauthorized", "error": "Invalid or missing API key" } ``` **Solution:** Verify your API key is correct and included in the `Authorization` header. ### 429 Too Many Requests Rate limit exceeded: ```json theme={null} { "statusCode": 429, "message": "Too Many Requests", "error": "Rate limit exceeded. Please try again later." } ``` **Solution:** Wait for the rate limit window to reset (check the `X-RateLimit-Reset` header), or contact Range to discuss higher limits. *** ## Best Practices Store your API key in environment variables, never hardcode it: ```bash theme={null} export RANGE_API_KEY="YOUR_API_KEY" ``` ```javascript theme={null} const apiKey = process.env.RANGE_API_KEY; ``` Never expose your API key in client-side code (frontend JavaScript, mobile apps). Make API calls from your backend server. Rotate your API keys periodically and immediately if you suspect they've been compromised. You can generate new keys in your dashboard. Track your API usage in the Range dashboard to avoid hitting rate limits and optimize your integration. *** ## Need Help? Contact Range to discuss higher limits for your account. Having authentication issues? Our team is here to help. # Data API Source: https://docs.range.org/data-api/data-introduction Query addresses, networks, and protocols across EVM chains, Solana, Stellar, and Cosmos ecosystem networks through one API. ## Onchain data, one API Range is the platform for companies operating across stablecoins and fiat. The Data API is the data layer underneath it: a single, unified interface to query addresses, track network metrics, and analyze protocols across EVM chains, Solana, Stellar, and Cosmos ecosystem networks. Supported networks vary by endpoint. EVM chains, Solana, Stellar, and Cosmos ecosystem networks. Coverage varies by endpoint. Sub-second latency for critical data with live transaction feeds and balance updates. Built to handle millions of requests per day with 99.9% uptime SLA. RESTful design, comprehensive docs, and interactive API playground for rapid integration. *** ## What You Can Build Build comprehensive portfolio dashboards with real-time balance tracking, transaction history, and cross-chain asset aggregation. Access labeled addresses, counterparty analysis, and historical balance changes to create professional-grade wallet analytics. Monitor whale movements, track large transfers, analyze active accounts, and detect market-moving transactions before they trend. Get network-wide volume metrics and cross-chain transfer data for alpha generation. Query protocol transaction counts and transfer amounts over a specified time range. Screen addresses against labeled entities, track counterparty exposure, and monitor suspicious transaction patterns. Perfect for exchange integrations, custody solutions, and institutional treasury management. Build real-time monitoring systems with transaction error tracking, network health metrics, and custom alert triggers. Monitor active accounts, transaction throughput, and cross-chain message flows. *** ## Core Capabilities ### Address Intelligence Get complete visibility into any blockchain address with labeled entities, transaction history, balance tracking, and counterparty analysis. ```bash cURL theme={null} curl -X GET "https://api.range.org/v1/address?address=YOUR_ADDRESS&network=solana" \ -H "Authorization: Bearer YOUR_API_KEY" ``` ```javascript JavaScript theme={null} const response = await fetch( "https://api.range.org/v1/address?address=YOUR_ADDRESS&network=solana", { headers: { Authorization: "Bearer YOUR_API_KEY" }, } ); const data = await response.json(); ``` ```python Python theme={null} import requests response = requests.get( 'https://api.range.org/v1/address', params={'address': 'YOUR_ADDRESS', 'network': 'solana'}, headers={'Authorization': 'Bearer YOUR_API_KEY'} ) data = response.json() ``` **Key Features:** * **Entity Labels:** Identify exchanges, protocols, MEV bots, and known entities * **Transaction History:** Complete transaction and payment history with pagination * **Balance Tracking:** Real-time and historical balance changes by token * **Counterparty Analysis:** See who an address interacts with most frequently * **Activity Metrics:** First/last seen, transaction counts, and activity patterns ### Network Analytics Access macro-level blockchain metrics for volume analysis, network health monitoring, and market intelligence. **Available Metrics:** * Transaction volumes and counts aggregated by time interval * Active account tracking and growth trends * Whale movement detection with large transfer alerts * Cross-chain transfer monitoring (IBC, CCTP, bridges) * Network message type distribution and error rates * USD-denominated balance distributions * Geographic flow analysis for regional insights ### Protocol Intelligence Monitor DeFi protocols, bridges, and cross-chain messaging with transaction-level granularity. **Protocol Coverage:** * Cross-chain bridge statistics (volume, transaction counts, routes) * Protocol transaction history with source/destination tracking * Time-series data for protocol health and adoption metrics * Token transfer tracking across protocols * Net flow analysis by protocol and time period *** ## Why Developers Choose Range 1. **Start in Minutes**: Generate an API key from your existing Sandbox or paid account and make your first request in under 5 minutes. No blockchain infrastructure required. 2. **Scale Effortlessly**: From prototype to production, our API grows with you. Automatic rate limiting, usage analytics, and account-specific limits. 3. **Ship Faster**: Pre-indexed data, normalized schemas, and consistent APIs across chains mean less data wrangling and more feature building. API access is available through a time-limited Sandbox or paid account. [Request a Sandbox](https://www.range.org/contact) with no commitment. *** ## Supported Networks Data API endpoints cover EVM chains, Solana, Stellar, and Cosmos ecosystem networks, and the networks each endpoint accepts vary. For Risk API coverage by endpoint, see [supported chains](/risk-api/product-info/supported-chains). Need a chain we don't support yet? [Contact our team](https://www.range.org/get-in-touch) for custom integrations. *** ## Next Steps Make your first API call in under 5 minutes with real examples. Log in with your Sandbox or paid account to generate an API key. Learn about API keys, rate limits, and security best practices. Get help from our team and connect with other developers. # Data API Quickstart Source: https://docs.range.org/data-api/quickstart Make your first Data API calls in under 5 minutes and learn how to interpret the responses. This guide walks you through your first calls to the Data API. By the end, you'll understand the request format, response structure, and key fields for three flagship endpoints: one for addresses, one for transfers, and one for tokens. **You'll need an API key.** All requests require a Bearer token. If you already have a Sandbox or paid account, generate a key at [app.range.org](https://app.range.org). Otherwise, [request a time-limited Sandbox](https://www.range.org/contact). *** ## Authentication Every Data API request uses the same authentication pattern. Pass your API key in the `Authorization` header: ``` Authorization: Bearer YOUR_API_KEY ``` **Base URL:** `https://api.range.org` Keep your API key server-side. Never expose it in client-side code or public repositories. *** ## 1. Look Up an Address The [Get Address Details](/api-reference/address-information/get-address-details) endpoint is the most common starting point. It returns labels, entity attribution, and metadata for any address across [18+ supported networks](/risk-api/product-info/supported-chains). Try it with Circle's CCTP program on Solana: ```bash cURL theme={null} curl -G https://api.range.org/v1/address \ --data-urlencode "address=CCTPiPYPc6AsJuwueEnWgSgucamXDZwBd53dQ11YiKX3" \ --data-urlencode "network=solana" \ -H "Authorization: Bearer YOUR_API_KEY" ``` ```javascript JavaScript theme={null} const params = new URLSearchParams({ address: "CCTPiPYPc6AsJuwueEnWgSgucamXDZwBd53dQ11YiKX3", network: "solana", }); const response = await fetch(`https://api.range.org/v1/address?${params}`, { headers: { Authorization: "Bearer YOUR_API_KEY" }, }); const data = await response.json(); ``` ```python Python theme={null} import requests response = requests.get( "https://api.range.org/v1/address", headers={"Authorization": "Bearer YOUR_API_KEY"}, params={ "address": "CCTPiPYPc6AsJuwueEnWgSgucamXDZwBd53dQ11YiKX3", "network": "solana", }, ) data = response.json() ``` ```json theme={null} { "address": "CCTPiPYPc6AsJuwueEnWgSgucamXDZwBd53dQ11YiKX3", "network": "solana", "is_validator": false, "malicious": false, "name": "Circle CCTP", "tags_source": "range", "tags": { "entity": "Circle", "category": "Bridge" }, "type": { "is_contract": true } } ``` ### Key Response Fields | Field | What It Tells You | | - | - | | `name` | Human-readable label for the address, when known. | | `malicious` | `true` if Range has flagged this address as malicious. | | `is_validator` | `true` if the address is a known network validator. | | `tags` | Structured attribution: entity name, category, and other metadata. | | `tags_source` | Where the attribution came from. | *** ## 2. Get Token Transfers The [Get token transfers](/api-reference/token-transfers/get-token-transfers) endpoint returns cross-chain and same-chain transfers (IBC, CCTP, bridges, and more) for an address, with cursor-based pagination. Try it against the same address: ```bash cURL theme={null} curl -G https://api.range.org/v2/transfers \ --data-urlencode "address=CCTPiPYPc6AsJuwueEnWgSgucamXDZwBd53dQ11YiKX3" \ --data-urlencode "network=solana" \ --data-urlencode "size=5" \ -H "Authorization: Bearer YOUR_API_KEY" ``` ```javascript JavaScript theme={null} const params = new URLSearchParams({ address: "CCTPiPYPc6AsJuwueEnWgSgucamXDZwBd53dQ11YiKX3", network: "solana", size: "5", }); const response = await fetch(`https://api.range.org/v2/transfers?${params}`, { headers: { Authorization: "Bearer YOUR_API_KEY" }, }); const data = await response.json(); ``` ```python Python theme={null} import requests response = requests.get( "https://api.range.org/v2/transfers", headers={"Authorization": "Bearer YOUR_API_KEY"}, params={ "address": "CCTPiPYPc6AsJuwueEnWgSgucamXDZwBd53dQ11YiKX3", "network": "solana", "size": 5, }, ) data = response.json() ``` ```json theme={null} { "items": [ { "id": "9359/AX/2352", "time": "2024-05-08T13:05:57.779Z", "status": "SUCCEEDED", "type": "cctp", "sender": { "address": "AuZrspySopxfZUiXY6YxDyfS211KvXLe197kj3M2cLpq", "network": "solana" }, "receiver": { "address": "0x1da5821544e25c636c1417ba96ade4cf6d2f9b5a", "network": "ethereum" } } ], "meta": { "next_cursor": "eyJpZCI6IjkzNTkvQVgvMjM1MiJ9" } } ``` ### Key Response Fields | Field | What It Tells You | | - | - | | `status` | Current state of the transfer: `SUCCEEDED`, `PENDING`, `ERROR_ON_DESTINATION`, or `TIMEOUT`. | | `type` | Transfer mechanism, e.g. `ibc`, `cctp`, or a specific bridge name. | | `sender` / `receiver` | Address and network on each side of the transfer. Networks can differ for cross-chain transfers. | | `meta.next_cursor` | Pass this as the `cursor` parameter to fetch the next page. | `GET /v2/transfers` supports dozens of filters: `token_symbols`, `bridges`, `min_usd`/`max_usd`, `start_time`/`end_time`, and more. See the endpoint reference for the full list. *** ## 3. Get a Token's Total Supply The [Get total supply for a token](/api-reference/token-information/get-total-supply-for-a-token) endpoint returns current supply and decimals for supported tokens. Try it with USDtb on Solana: ```bash cURL theme={null} curl -G https://api.range.org/v2/tokens/total-supply \ --data-urlencode "network=solana" \ --data-urlencode "token=USDtb" \ -H "Authorization: Bearer YOUR_API_KEY" ``` ```javascript JavaScript theme={null} const params = new URLSearchParams({ network: "solana", token: "USDtb", }); const response = await fetch( `https://api.range.org/v2/tokens/total-supply?${params}`, { headers: { Authorization: "Bearer YOUR_API_KEY" } } ); const data = await response.json(); ``` ```python Python theme={null} import requests response = requests.get( "https://api.range.org/v2/tokens/total-supply", headers={"Authorization": "Bearer YOUR_API_KEY"}, params={ "network": "solana", "token": "USDtb", }, ) data = response.json() ``` ```json theme={null} { "token": "8yXrtJ54jZtE84xEBzTESKuegjcAkAuDrdAhRd8i8n3T", "network": "solana", "total_supply": 40941203.22, "total_supply_raw": "40941203220000", "decimals": 6 } ``` ### Key Response Fields | Field | What It Tells You | | - | - | | `total_supply` | Total supply with decimals already applied; use this for display. | | `total_supply_raw` | Raw on-chain integer string; use this for precise math. | | `decimals` | Number of decimal places the token uses. | *** ## Common Errors | HTTP Code | Meaning | What to Do | | -: | - | - | | **400** | Invalid parameters (missing address, bad format) | Check your query parameters. | | **401** | Invalid or missing API key | Verify your `Authorization: Bearer` header. See [Authentication](/data-api/authentication). | | **404** | Address, token, or network not found | Check the network identifier against [Supported Chains](/risk-api/product-info/supported-chains). | | **429** | Rate limit exceeded | Implement exponential backoff. See [Rate Limits](/data-api/authentication#rate-limits). | | **5xx** | Server error | Retry after a delay. Contact support if persistent. | *** ## What's Next API keys, rate limits, and security best practices. See what you can build across addresses, networks, and protocols. The full list of networks the Data API covers. Questions? Our team is here to help. # Network integrations Source: https://docs.range.org/integrations/explorer-network-integrations Get your chain or non-stablecoin asset supported in Cross-Chain Explorer and across Range's data and risk tooling. ## Get your chain or asset supported [Cross-Chain Explorer](https://explorer.range.org) is the unified block explorer for cross-chain asset flows across 100+ chains and 21 bridges, with complete visibility into cross-chain and intra-chain activity. Use this integration to get your chain or non-stablecoin asset supported in Cross-Chain Explorer and across the broader Range platform, including the Risk API, Data API, and Range Trail. ## Benefits for chains and assets Your asset becomes searchable and explorable across all supported chains in the Range ecosystem. Users see complete lifecycle flows instead of fragmented views across multiple explorers. Integrated sanctions checks (OFAC, EU, UK) and risk scoring built-in. Your chain or asset highlighted in Range cross-chain dashboards and analytics. **Zero integration overhead:** Simple support request, no SDKs required. ## How to get supported 1. **Submit your details:** Provide your chain, network, or asset information: * Chain ID and network specifications * Supported stablecoins or tokens * Bridge or interoperability connections 2. **Review and approval:** Our team will review your submission and confirm integration timeline. 3. **Integration complete:** Once approved, your ecosystem will be added to Cross-Chain Explorer with: * Full cross-chain tracking * Address and transaction lookup * Compliance and risk checks built-in Contact our team to get your chain or asset integrated into Cross-Chain Explorer. ## Explore Range's platform Cross-Chain Explorer is part of Range's intelligence platform: Screen addresses, score transactions, and enable KYT workflows. Real-time intelligence on stablecoin activity across 100+ chains. *** ## Ready to get started? Increase visibility, improve compliance, and showcase your ecosystem across the Range platform. Submit your chain, network, or asset for Cross-Chain Explorer support. View cross-chain stablecoin flows across 100+ networks. # Stablecoin Explorer integrations Source: https://docs.range.org/integrations/stablecoin-explorer-integrations Integrate unified stablecoin tracking into your wallet or application. ## Integrate Stablecoin Explorer into your wallet or app [Stablecoin Explorer](https://explorer.money/) is the unified block explorer for all USD-pegged stablecoins.\ It tracks USDC, USDT, FRAX, EURe, and 20+ more across 100+ chains and 21 bridges, plus intra-chain activity on Ethereum, Solana, BNB, Noble, and Stellar. ## Why link to Stablecoin Explorer? Most applications link users to chain-specific explorers like Etherscan or Solscan. This works for single-chain transfers but breaks down for cross-chain activity. **Example: USDC transfer from Ethereum → Solana** * Etherscan shows the burn on Ethereum * Solscan shows the mint on Solana * Neither shows the complete lifecycle of the transfer **Stablecoin Explorer solves this** by displaying the entire transaction path in one unified view. ## Comparison | **Current workflow** | **With Stablecoin Explorer** | | - | - | | Users must check two explorers for cross-chain transfers (e.g., Etherscan + Solscan). | One unified link shows all transaction legs (origin, bridge, destination). | | Apps dynamically generate chain-specific explorer links. | Apps link to a single explorer for all stablecoins, across 100+ chains. | | Users see raw hashes with little context. | Transactions enriched with verified entities, official addresses, and blacklist checks. | | Compliance checks require multiple data sources. | OFAC, EU, UK, and other sanctions lists integrated directly in the explorer. | ## Benefits for wallets and apps * **Unified explorer:** Link every stablecoin transfer (cross-chain or intra-chain) to a single destination. * **Improved user trust:** Users see exactly where funds moved without confusion. * **Co-branded transaction pages:** Add your logo and design to transaction detail pages at no cost. * **Referral attribution:** Top referring apps are featured weekly on the Stablecoin Explorer homepage. * **Zero integration effort:** Simply link using the transaction hash or wallet address. ## How to integrate Link to Stablecoin Explorer using a wallet address or transaction hash. No SDKs or backend changes required. **Search view** - returns matching transfers. Works for an address or a transaction hash: ```bash theme={null} https://explorer.money/transactions?s= ``` Optionally scope an address by source network with `sn` (comma-separated): ```bash theme={null} https://explorer.money/transactions?sn=eth,sonic&s=
``` **Direct transaction page** - links straight to a transaction's full cross-chain view. The `id` is the transaction hash, base64-encoded: ```bash theme={null} https://explorer.money/status?id= ``` **Examples:** * Address: `https://explorer.money/transactions?s=0xd15e62e64c1265dfb753ed6e7c76cb5ff8f276c7` * Transaction: `https://explorer.money/transactions?s=0x678b1fff93ed5215d0a2528cb7ffcb8d4323767352cbe000e5974132bc059063` A transaction search can match on more than one network (a hash is just a block reference); the results list shows the network for each row. ## Get free co-branded views Configure transaction pages with your application's logo and colors. Users clicking from your app will see a co-branded version of Stablecoin Explorer, improving trust and reducing support overhead. **Co-branded integrations are free.** [Contact us](https://www.range.org/get-in-touch) to set up your co-branded explorer. ## Explore Range's platform Stablecoin Explorer is part of Range's security and intelligence platform: Screen addresses, score transactions, and enable KYT workflows. Access real-time stablecoin intelligence across 100+ chains. Monitor liquidity flows across 100+ chains and 21 interoperability protocols. *** ## Ready to integrate? Use `https://explorer.money/tx/` to link stablecoin transactions. [Contact us](https://www.range.org/get-in-touch) to configure your branded explorer views. Top referring apps are showcased weekly on the Stablecoin Explorer homepage. [**Visit Stablecoin Explorer →**](https://explorer.money) # Build on Range Source: https://docs.range.org/introduction/about-range Range is the platform for companies operating across stablecoins and fiat, with a unified ledger, pre-execution controls and an API to build on. Range is the platform for companies operating across stablecoins and fiat. It connects every account, custodian, wallet and exchange into one real-time ledger, runs pre-execution controls on every transaction and exposes both through an API that finance, compliance and risk teams build on. **Trusted by** the Solana Foundation, Circle, Stellar, Squads, Jupiter and many others. Range protects over **\$30B in onchain assets** and screens **tens of billions in payment volume** every month. ## Platform and API You can run all of this inside the [Range platform](https://app.range.org). The API gives you the same capabilities programmatically, so you can build them into your own dashboards, internal tools and product flows wherever that fits better than working in the app. Most integrations start with the [Risk API](/risk-api/risk-introduction): run compliance and sanctions screening, plus wallet, token, counterparty and contract risk checks, directly inside your own programs and apps. The API also lets you: * Connect every account into one real-time ledger across wallets, banks, custodians, exchanges and PSPs * Reconcile, classify and match transactions across fiat and stablecoins * Collect and record Travel Rule data and verify counterparties across rails * Monitor treasury and portfolio risk across assets, entities and networks in real time ## The Range APIs API and endpoint availability depends on the modules activated on your account. See [Plans and pricing](/introduction/plans-and-pricing) for what each module includes. Score wallets, transactions, tokens and contracts with sanctions, counterparty and behavioral risk checks. **Use cases** * Run compliance and sanctions screening inside your own apps * Score wallet, token and counterparty risk before transacting * Screen counterparties before high-value transfers [Risk API docs](/risk-api/risk-introduction) Unified blockchain and stablecoin data: addresses, networks, protocols and analytics to power dashboards and internal tooling. **Use cases** * Power customer-facing dashboards and analytics products * Build internal treasury and reporting dashboards * Track stablecoin flows and protocol activity across networks [Data API docs](/data-api/data-introduction) Manage your workspace programmatically: counterparties, accounts, integrations and transaction activity. **Use cases** * Sync counterparties, accounts and transactions with your internal tools * Automate accounts payable and reconciliation workflows * Maintain KYB records and an auditable counterparty trail [Platform API docs](/platform-api/platform-introduction) ## Explore the docs Generate an API key and make your first authenticated request in minutes. The latest features, API changes and chain coverage. Live uptime and incident history for the Range API and all our explorers. Our team will help you scope the right integration. How we protect customer data and operate our services. # Plans and Pricing Source: https://docs.range.org/introduction/plans-and-pricing How Range is packaged: a time-limited Sandbox plus paid Unify and Protect modules priced by capability and volume. Try every Range capability in a time-limited Sandbox, then pay only for the modules your company needs. ## Sandbox Test Range with your own real accounts in a time-limited Sandbox, with no commitment. * Every Unify and Protect module unlocked * Your real accounts across banks, custodians, wallets, exchanges and PSPs * Built-in workflows for reporting, risk screening, investigations and case management * Set up with the Range team around what you want to test * Time-limited, with no commitment Tell us what you want to test and the Range team will set up your Sandbox. ## Modules Paid modules are priced by capability and volume. API and endpoint availability depend on the modules activated on your account. A single, real-time ledger across every account. * Treasury dashboard and forecasting * Transaction reconciliation * Counterparty management * Reporting and intelligence Real-time risk across every transaction, counterparty and asset. * Transaction screening * Counterparty risk and Travel Rule * Threat and fraud prevention * Treasury and portfolio risk The [Risk API](/risk-api/risk-introduction) powers the **Protect** module; the [Data API](/data-api/data-introduction) and [Platform API](/platform-api/platform-introduction) power **Unify**. ## Get a quote Pricing and packaging are tailored to your usage. Compare what each module includes. Tell us what you're running and we'll quote a plan that fits. # Quickstart Source: https://docs.range.org/introduction/quickstart Generate an API key from your Range account, authenticate, and make your first API call. Get from zero to your first authenticated API call in under five minutes. ## 1. Generate an API key from your account If you need access, [request a time-limited Sandbox](https://www.range.org/contact). The Range team will set it up with every Unify and Protect module, with no commitment. Log in at [app.range.org](https://app.range.org/login) with your Sandbox or paid account. Go to **Settings > API** ([app.range.org/keys](https://app.range.org/keys)). Generate your key and copy it to start making authenticated requests. **Copy your API key when you generate it.** Range shows it only once and does not display it again. You can revoke and rotate keys at any time from your API settings. ## 2. Authenticate All Range API requests require authentication via an API key passed in the request header. Include your API key in every request using the `Authorization` header: ```bash theme={null} Authorization: Bearer YOUR_API_KEY ``` **Keep your API key secure.** Never expose it in client-side code or public repositories. Use environment variables in production. ## 3. Make your first request Pick the API you want to start with. Each tab shows a sample call and a link to that API's own quickstart for the full walkthrough. Look up blockchain address data: ```bash theme={null} curl 'https://api.range.org/v1/address?address=CCTPiPYPc6AsJuwueEnWgSgucamXDZwBd53dQ11YiKX3&network=solana' \ --header 'Authorization: Bearer YOUR_API_KEY' ``` [Explore the Data API →](/data-api/data-introduction) Score an address for risk: ```bash theme={null} curl -G 'https://api.range.org/v1/risk/address' \ --data-urlencode 'address=TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA' \ --data-urlencode 'network=solana' \ --header 'Authorization: Bearer YOUR_API_KEY' ``` [Risk API quickstart →](/risk-api/quickstart) List the counterparties in your workspace: ```bash theme={null} curl 'https://api.range.org/v2/counterparties' \ --header 'Authorization: Bearer YOUR_API_KEY' ``` [Explore the Platform API →](/platform-api/platform-introduction) ## 4. Rate limits and best practices Rate limits and quotas depend on your account. Check the `X-RateLimit-*` response headers and monitor usage in the [Range dashboard](https://app.range.org). [Contact Range](https://www.range.org/contact) to discuss higher limits. All errors return standard HTTP status codes with JSON error messages: ```json theme={null} { "error": "Invalid API key", "status": 401, "message": "The provided API key is invalid or expired" } ``` Common status codes: * `200`: Success * `400`: Bad request (invalid parameters) * `401`: Unauthorized (invalid API key) * `429`: Rate limit exceeded * `500`: Server error * Cache responses when possible to reduce API calls * Use batch endpoints when available for multiple queries * Implement exponential backoff for rate limit errors * Monitor your usage via the [Range dashboard](https://app.range.org) * Subscribe to webhooks for real-time updates instead of polling ## Next steps Now that you've made your first request, explore the full Range API suite: Access unified blockchain data, protocol analytics and stablecoin intelligence across multiple chains. Screen wallets, transactions and tokens for sanctions, security risks and compliance checks. Manage your Range organization, API keys, users and account settings programmatically. # Getting Started Source: https://docs.range.org/platform-api/api-reference-introduction Authenticate with your API key in the X-API-KEY header and make your first Platform API call by listing the counterparties in your workspace. ## Your First API Call Let's list your counterparties in three simple steps: Sign in at [app.range.org](https://app.range.org/keys) and generate an API key from the dashboard. Keep it secure, treat it like a password. List all counterparties in your workspace: ```bash cURL theme={null} curl -X GET "https://api.range.org/v2/counterparties" \ -H "X-API-KEY: YOUR_API_KEY" ``` ```javascript JavaScript theme={null} const response = await fetch("https://api.range.org/v2/counterparties", { headers: { "X-API-KEY": "YOUR_API_KEY" }, }); const data = await response.json(); console.log(data); ``` ```python Python theme={null} import requests response = requests.get( "https://api.range.org/v2/counterparties", headers={"X-API-KEY": "YOUR_API_KEY"}, ) print(response.json()) ``` ```typescript TypeScript theme={null} const response = await fetch("https://api.range.org/v2/counterparties", { headers: { "X-API-KEY": "YOUR_API_KEY" }, }); const data = await response.json(); console.log(data); ``` You'll receive a paginated list of counterparties with their addresses, bank accounts, and metadata. ```json theme={null} { "items": [ { "id": "cp_abc123", "name": "Vercel", "type": "vendor", "website": "https://vercel.com", "notes": "Infrastructure hosting provider", "addresses": [ { "id": "08846e81-b3a8-7fd9-cc39-d4023a75dcff", "address": "0x742d35Cc6634C0532925a3b844Bc9e7595f2bD28", "network": "ethereum", "label": "payment wallet" } ], "bank_accounts": [] } ], "meta": { "next_cursor": "eyJpZCI6IjkxeFFlV3Z...", "previous_cursor": null, "total_count": 42, "page_number": 1 } } ``` *** ## API Fundamentals ### Base URL All API requests are made to: ``` https://api.range.org ``` ### Authentication Include your API key in the `X-API-KEY` header with every request: ```bash theme={null} X-API-KEY: YOUR_API_KEY ``` Never expose your API key in client-side code or public repositories. Use environment variables to store it securely. Generate and manage API keys from the Range dashboard ### Request Format All endpoints use **GET**, **POST**, **PATCH**, **PUT**, or **DELETE** methods with: * **Query parameters** for filtering and pagination (GET endpoints) * **JSON request bodies** for creates and updates (`Content-Type: application/json`) * **Multipart form data** for document uploads * **JSON responses** for all successful requests ### Response Format Successful responses return JSON directly. List endpoints include a `meta` object: ```json theme={null} { "items": [ /* array of results */ ], "meta": { "next_cursor": "eyJpZCI6...", "previous_cursor": null, "first_page_cursor": "eyJpZCI6...", "last_page_cursor": "eyJpZCI6...", "total_count": 100, "page_number": 1 } } ``` *** ## Pagination The Platform API uses **cursor-based pagination** for all list endpoints. | Parameter | Type | Description | | - | - | - | | `limit` | number | Results per page (default 50, max 200) | | `cursor` | string | Opaque cursor from a previous response's `meta` | **Example, fetch the next page:** ```bash theme={null} curl "https://api.range.org/v2/counterparties?limit=50&cursor=eyJpZCI6IjkxeFFlV3Z..." \ -H "X-API-KEY: YOUR_API_KEY" ``` Use `meta.next_cursor` to advance forward. When `next_cursor` is `null`, you've reached the last page. Cursors are opaque strings, do not parse or construct them manually. Always use the cursor value returned in the response. *** ## Common Use Cases Add vendors, customers, and partners with crypto addresses and bank details `POST /v2/counterparties` Find and filter your workspace accounts by type, network, or group `GET /v2/accounts` Link a Kraken, Coinbase, or Hyperliquid account to sync balances `POST /v2/account-connections` Fetch canonical transfer and trade history across workspace accounts ` GET /v2/accounts/transfers` *** ## Error Handling The API uses standard HTTP status codes: | Status Code | Meaning | Common Causes | | - | - | - | | **200** | Success | Request completed successfully | | **201** | Created | Resource created successfully | | **400** | Bad Request | Invalid parameters or malformed request | | **401** | Unauthorized | Missing or invalid API key | | **404** | Not Found | Resource doesn't exist | | **429** | Too Many Requests | Rate limit exceeded | | **500** | Server Error | Internal server error (rare) | **Error Response Format:** ```json theme={null} { "statusCode": 400, "message": "name should not be empty", "error": "Bad Request" } ``` Implement retry logic with exponential backoff for 429 and 5xx errors. *** ## Next Steps Browse all available endpoints with interactive examples below Learn what you can build with the Platform API Query blockchain addresses, networks, and stablecoin analytics Questions? Our team is here to help # Platform API Source: https://docs.range.org/platform-api/platform-introduction Workspace management, counterparties, accounts, and operational tooling for building on top of Range. ## Manage Your Range Workspace Programmatically The Range Platform API gives you full programmatic control over your workspace, manage counterparties with their crypto addresses and bank accounts, organize and monitor onchain accounts, configure integrations, and track transaction activity across your connected accounts. Create and manage vendors, customers, investors, and partners, each with associated crypto addresses, bank accounts, and documents. Search and update your onchain accounts across networks, grouped and organized for operational clarity. Connect and manage integrations with custodians, exchanges, and multisig providers (Utila, Kraken, Squads, Coinbase, Realms, and more). Query canonical transaction history across all connected accounts, transfers and trades in a unified format. *** ## What You Can Build Automate your accounts payable and receivable workflows. Create counterparties for each vendor, attach their crypto addresses and bank details, and upload supporting documents, all via API so your internal tools stay in sync with Range. Pull real-time account balances, group accounts by team or purpose, and build internal dashboards showing your full treasury picture across custodians, exchanges, and self-custody wallets. Upload KYB/KYC documents to counterparty records, track counterparty relationships over time, and maintain an auditable trail of who you transact with and why. Connect multiple custodians and exchanges through a single API (Utila, Kraken, Binance, OKX, Bybit, Bitget, Gate, KuCoin, Coinbase, Squads, Realms, Wise, and Hyperliquid) and query all account activity in one place with a canonical transaction format. Track Squads multisig proposals and Realms DAO governance activity. Monitor pending proposals, approval counts, and voting state for any connected multisig or governance account. *** ## Core Capabilities ### Counterparty Management Create a structured record for every external entity you work with, vendors, customers, investors, and partners. Attach multiple crypto addresses across any network, bank account details, and supporting documents. ```bash cURL theme={null} curl -X POST "https://api.range.org/v2/counterparties" \ -H "X-API-KEY: YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "Vercel", "type": "vendor", "website": "https://vercel.com", "notes": "Infrastructure hosting provider", "addresses": [ { "address": "0x742d35Cc6634C0532925a3b844Bc9e7595f2bD28", "network": "ethereum", "label": "payment wallet" } ] }' ``` ```javascript JavaScript theme={null} const response = await fetch("https://api.range.org/v2/counterparties", { method: "POST", headers: { "X-API-KEY": "YOUR_API_KEY", "Content-Type": "application/json", }, body: JSON.stringify({ name: "Vercel", type: "vendor", website: "https://vercel.com", addresses: [ { address: "0x742d35Cc6634C0532925a3b844Bc9e7595f2bD28", network: "ethereum", label: "payment wallet", }, ], }), }); const counterparty = await response.json(); ``` ```python Python theme={null} import requests response = requests.post( "https://api.range.org/v2/counterparties", headers={ "X-API-KEY": "YOUR_API_KEY", "Content-Type": "application/json", }, json={ "name": "Vercel", "type": "vendor", "website": "https://vercel.com", "addresses": [ { "address": "0x742d35Cc6634C0532925a3b844Bc9e7595f2bD28", "network": "ethereum", "label": "payment wallet", } ], }, ) data = response.json() ``` **Key Features:** * **Relationship Types:** Vendor, customer, investor, partner, exchange, or other * **Crypto Addresses:** Attach up to 100 addresses across any network per counterparty * **Bank Accounts:** Store IBAN, SWIFT, routing/account numbers, and sort codes (up to 50 per counterparty) * **Documents:** Upload and manage PDF documents (up to 10 MB each) * **Search & Filter:** Find counterparties by name or relationship type with cursor-based pagination ### Account Management Search across all your workspace accounts, EOAs, multisigs, smart contracts, custodian accounts, exchanges, and bank accounts. Organize them into groups and bulk-update metadata. **Account Types Supported:** * `eoa`, Externally owned wallets * `multisig`, Squads, Realms, Safe, and other multisig programs * `contract`, Smart contracts with onchain metadata * `custodian`, Utila, Cubist, Privy, Dfns, Anchorage, Turnkey, Fireblocks, Fordefi, Copper, and similar custody accounts * `exchange`, Kraken, Binance, OKX, Bybit, Bitget, Gate, KuCoin, Coinbase, Hyperliquid, and Coins.ph accounts * `bank`, Plaid, Wise, Revolut Business, Altitude, and Pave Bank accounts * `defi`, DeFi protocol positions enriched onto on-chain wallets ### Account Connections Connect your custodians, exchanges, banks, and bookkeeping systems directly. Each connection syncs account balances and transaction history automatically. **Supported Providers:** MPC custody with service account authentication Exchange accounts via API key and secret Coinbase accounts via key ID and private key Exchange accounts via API key and secret Exchange accounts via API key, secret, and passphrase Exchange accounts via API key and secret Exchange accounts via API key, secret, and passphrase Exchange accounts via APIv4 key and secret Exchange accounts via API key, secret, and passphrase EVM multisig wallets across Ethereum, Arbitrum, Base, Optimism, Polygon, and BNB Solana multisig, full proposal and member visibility Solana DAO governance with treasury and proposal tracking Fiat accounts via API token and profile ID Perp exchange accounts via wallet address MPC custody via refresh-token login Embedded and custodial wallets via app credentials Institutional custody via API access key Custodial or delegated wallets via service account token Bank accounts via Plaid Link public token Squads-based Solana smart accounts via deposit or Settings address Business accounts via OAuth refresh token and API certificate Embedded wallets via API key pair and organization ID Exchange accounts via API key and secret Institutional custody via API user id and RSA private key Custodial wallets via read-only API User bearer token Institutional custody via Platform API key and secret Bank accounts via OAuth client id and secret Ledger connection for bookkeeping pulls via OAuth authorize URL Ledger connection for bookkeeping pulls via OAuth authorize URL Risk screening via a Merkle Science Compass API key Client-pushed accounts, balance snapshots, and movements *** ## Why Use the Platform API 1. **Single Source of Truth**: Keep your internal tools, ERPs, and dashboards in sync with your Range workspace without manual data entry. 2. **Audit-Ready Records**: Every counterparty relationship, document, and address change is timestamped and queryable, making compliance reviews straightforward. 3. **Unified Transaction Data**: Query trades and transfers across exchanges, custodians, and self-custody wallets in a single canonical format, no more stitching together provider-specific APIs. **Authentication:** The Platform API uses an `X-API-KEY` header. Generate your key from the [Range dashboard](https://app.range.org/keys). *** ## Next Steps Explore all endpoints with interactive examples and response schemas. Browse the Range Protect alert-rule catalogue and configure monitoring on the accounts you manage here. Generate your API key from the Range dashboard. New to Range? Start here for a guided walkthrough. Questions? Our team is here to help. # Bug bounty Source: https://docs.range.org/resources/bug-bounty Report security vulnerabilities in Range products and earn rewards for verified findings. Range runs a bug bounty program that rewards security researchers who help protect our platform and customers. Submit vulnerabilities in any Range product or infrastructure to [security@range.org](mailto:security@range.org). ## Rewards Rewards are paid at the discretion of the Range security team based on severity, exploitability, and real-world impact. | Severity | Reward (up to) | | - | - | | Critical | \$5,000 | | High | \$1,000 | | Medium | \$250 | | Low | \$50 | Final amounts, including whether a finding qualifies, are determined by the Range team. ## Scope ### In scope * app.range.org, api.range.org, explorer.range.org, and explorer.money * Any Range-owned host or IP that is unintentionally exposed to the public internet, including internal domains and infrastructure leaking data * Range platform, APIs (Risk, Data, Platform), and dashboards * Authentication and authorization flows * Remote code execution, SQL injection, SSRF, and server-side template injection * Broken access control, IDOR, and privilege escalation * Authentication bypass and account takeover * Sensitive data exposure and information disclosure * Stored or reflected XSS with demonstrable impact ### Out of scope * stage.range.org and other non-production environments * [www.range.org](http://www.range.org) and other marketing, blog, or campaign pages, including forms and pages served by third-party platforms such as HubSpot * Third-party SaaS we do not operate, including HubSpot, marketing automation, our support desk, status page, and CDN. Report those to the vendor * Social engineering, phishing, or physical attacks * Denial of service (DoS/DDoS) and volumetric testing * Issues in third-party services we do not control * Reports from automated scanners without a working proof of concept * Best-practice recommendations without a demonstrable vulnerability * Missing security headers (CSP, HSTS, X-Frame-Options) without a demonstrated exploit * SPF, DKIM, or DMARC configuration issues * Self-XSS, clickjacking on pages *without sensitive actions*, and CSRF on logout or non-state-changing endpoints * Rate limiting or brute-force concerns without a clear impact path * Username or email enumeration * Vulnerabilities in outdated browsers or already-patched dependencies without a working proof of concept * Issues already known to the team or previously reported ## How to report Email **[security@range.org](mailto:security@range.org)** with: * A clear description of the issue * Steps to reproduce, including a proof of concept * Potential impact * Any suggested remediation Do not publicly disclose the vulnerability before our team has investigated and remediated it. **Do not** open a public GitHub issue. Range acknowledges reports within 2 business days. ## Disclosure timeline Researchers may publicly disclose findings 90 days after the initial report, or sooner with written approval from the Range security team. We will work with you to coordinate disclosure once a fix is in place. ## Eligibility and testing rules * Submit only to [security@range.org](mailto:security@range.org). Reports sent through sales contact forms, support channels, social media, or employee inboxes are not eligible for a reward * Do not submit test or spam entries through marketing or sales forms. Doing so voids eligibility and safe harbor * Only the first reporter of a unique, valid finding is eligible for a reward * Duplicate reports of an already-submitted vulnerability are not eligible for a payout; only the first report qualifies * Range employees, contractors, and their immediate family members are not eligible * Use only your own test accounts; do not access, modify, or exfiltrate other users' data * Do not run automated scanners at high volume against production systems * You must comply with all applicable laws and sanctions regulations ## Safe harbor Range will not pursue legal action against researchers who: * Make a good-faith effort to comply with this policy * Avoid privacy violations, data destruction, and service disruption * Allow reasonable time for remediation before any public disclosure Reach out to our team for technical support, integration help, or partnership inquiries. Email [security@range.org](mailto:security@range.org) with reproduction steps and impact details. # Changelog Source: https://docs.range.org/resources/changelog API changes and updates to Range Data API and Risk API. ## v1.7.31: 7 October 2026 ### New endpoints **Platform API:** * `POST /v2/cases/read-all` marks cases created at or before a cutoff as read for the calling user. * `DELETE /v2/cases/{id}` deletes a case. * `POST` and `GET /v2/parties/{id}/counterparties` create or list counterparties owned by a client entity. * `/v2/redemptions`: list, counts, CSV register, get, candidates, payout, and dismiss for T+1 redemption monitoring. ### New fields **Platform API:** * Case counts include `unread`. `PATCH /v2/cases/{id}` accepts `read`. Case `viewed` means read-for-caller in list responses. * Case `source_type` adds `tie_out_break`, `corridor_discrepancy`, and `redemption`. Resolution adds `paid`. Timeline actions add `deleted`, `tie_out_observed`, and `corridor_observed`. * Entities accept `persons_of_interest`. Client entities expose `client_id` on counterparty rows. * `AccountDto` may include `transfer_attribution`, `redemption_monitor`, and `carf_uk_xml` registration markers. * Workflow templates include `transfer-attribution` (and corridor reconciliation). Custom runs mention transfer-attribution period boundaries. ### Behavior changes **Platform API:** * Custom workflow runs (`POST /v2/workflows/runs/custom`) accept transfer-attribution day/month/year periods alongside CARF and treasury-statement. ## v1.7.29: 2 October 2026 ### Breaking changes **Platform API:** * `POST /v2/workflows` no longer accepts `email` or `report_mode`. Destinations are optional: send `channel_id` or `recipients`, or create the instance and configure delivery later. A request that includes `report_mode` returns 400. * `PUT` and `DELETE /v2/workflows/templates/{template}/accounts/{account_id}` are removed. List registrations with `GET /v2/workflows/templates/{template}/accounts`. ### New endpoints **Platform API:** * `POST /v2/account-connections/xero/authorize-url`. `POST /v2/account-connections` also accepts `type` `xero` and `merkle_science`. * `POST /v2/accounts/{id}/transfers/resync` resyncs one account past the lookback window. * `PUT /v2/accounts/{id}/team` assigns an account to a team or detaches it. `DELETE /v2/teams/{teamId}/accounts` detaches every account in that team. * `/v2/parties`: create, list, get (including `GET /v2/parties/self`), update, and delete register entities. `GET` and `PUT /v2/parties/{id}/accounts` list or attach accounts. * `GET /v2/corridors` lists cross-chain corridors between the workspace's own accounts. * `POST /v2/reconciliation/multi-source`. * `POST /v2/transactions/evaluate` evaluates an unsigned transaction against the treasury policies. * `POST /v2/workflows/runs/custom` queues a run with explicit UTC period boundaries. ### New fields **Platform API:** * `AccountDto` includes `team`, `entity_id`, and `entity`. Account list filters accept `entity_id` and `entity_types`. Add or update account bodies accept `entity_id`. * Treasury cash-flow, summary, and forecast include `leg_count` and `spot_priced_leg_count`. * Roll-forward statements include `synced_through`. * Case list items include `available_actions`. **Risk API:** * `GET /v1/risk/sanctions/{address}` returns `is_sanctioned`, `lists_checked`, and `sanctions` (one entry per list, with `basis` `direct` or `indirect`). `is_sanctioned` is null when a list could not be read and none was found. Treat `lists_checked: false` as unknown. ### Behavior changes **Risk API:** * Sanctions `network` accepts `ethereum`, `tron`, `solana`, `base`, `arbitrum`, `optimism`, `polygon`, and `avalanche`. It does not narrow the check. Any other value returns 400. * Issuer blacklist monitoring covers Tether, Circle, Coinbase, PayPal, Paxos, Agora, and Ripple on Ethereum, Tron, Solana, Base, Arbitrum, Optimism, Polygon, and Avalanche. **Data API:** * `GET /v1/address/fundedBy` and `GET /v2/address/fundedBy` return 404 when no funder is found, and 503 when a funding source fails. * `GET /v1/address/balance` `token_contracts` accepts at most 30 contracts. ## v1.7.27: 23 September 2026 ### Breaking changes **Risk API:** * `GET /v2/risk/address` and `GET /v2/risk/address/batch` no longer return `meta` (`ScreenMetaDto` timings). `signals` still selects which catalogue ids run, and that selection is not echoed on the response. **Platform API:** * Removed the CADOC prototype report routes: `GET /v2/reports/custody/daily`, `GET /v2/reports/reserves/monthly`, `GET /v2/reports/filings`, and `POST /v2/reports/filings/{id}/resend`. Read stored output from workflow runs. * `AccountDto` no longer returns `cadoc_5710` or `cadoc_5711`. ### New endpoints **Platform API:** * Custom connections (`type: custom`): `POST /v2/account-connections/{id}/accounts`, `POST .../snapshots`, `POST .../movements`, `DELETE .../snapshots/{snapshotId}`, `DELETE .../movements/{movementId}`, `GET .../revisions`, `POST .../imports`, and `GET .../imports/{importId}`. Push accounts, balance snapshots, and movement legs, or import CSV, CAMT.053, or a zip and poll the result. * Workflow runs: `GET /v2/workflows/runs`, `GET /v2/workflows/runs/{id}`, `GET /v2/workflows/runs/{id}/output`, and `POST /v2/workflows/runs/{id}/rerun`. * Workflow template accounts: `GET /v2/workflows/templates/{template}/accounts`, plus `PUT` and `DELETE /v2/workflows/templates/{template}/accounts/{account_id}`. * `DELETE /v2/workflows/{id}` archives an instance, cancels pending work, and keeps run history. ### New fields **Data API:** * `GET /v1/address/balance`: `hidden_count`, how many tokens the workspace whitelist removed from `balances`. **Platform API:** * `AccountDto`: `books` (`house` or `client`), `hidden_count`, and `hidden_usd`. `sync_unavailable_reason` may be `account_unsupported`. * `POST /v2/accounts/refresh` and `POST /v2/accounts/transfers/sync` accept optional `account_ids`. Omit the field, or send an empty array, to cover every account in the workspace. An id outside the workspace returns 404. * `PUT /v2/accounts` may return `sync_batch_id` when the request added accounts. * Balance refresh failures include `ref`, an opaque id for support. * Workspace and address-list balance entries include `hidden_count`. * Connection `type` includes `custom`. * Workflow templates include `kind` (`deterministic` or `agent`). Run objects include `tx_sync_status`, `cases`, and `sync`. * `POST /v2/workflows` accepts `channel_id` or `email` (one is required), optional `recipients` (existing delivery channel ids), and `report_mode` (`always` or `exception_only`). ### Behavior changes **Risk API:** * `GET /v2/risk/config`: a workspace with no stored config is seeded with catalogue defaults on first read, and that config is returned. * `GET /v2/risk/history`: a bare date, or a date-time with no `Z` or offset, is UTC. A bare `to` date includes the whole UTC day. **Platform API:** * `GET /v2/workflows`: omit `kind` to list the CADOC templates. Pass `kind=agent` for Autopilot templates. ## v1.7.24: 17 September 2026 ### Breaking changes **Platform API:** * `GET` / `PUT /v2/policies` are removed. CADOC subscriptions move to workflow instances: `GET` / `POST /v2/workflows` and `PATCH /v2/workflows/{id}`. ### New endpoints **Platform API:** * `GET` / `POST /v2/workflows` and `PATCH /v2/workflows/{id}`: list CADOC workflow templates and workspace instances; create or update an instance (recipients, cadence, formats, CNPJ fields). * `GET /v2/reports/filings` and `POST /v2/reports/filings/{id}/resend`: list stored CADOC filings and re-email a generated filing. ### New fields **Data API:** * `GET /v2/transfers` response `meta` may include `own_feed_truncated` when the Solana own-feed address set exceeded the fan-out cap. **Platform API:** * `GET /v2/reports/custody/daily`: optional `workflow_id` selects which workflow instance’s CNPJ / recipients drive the document. * `GET /v2/cases` / case DTOs: `source_type` gains `regulatory_filing`; subject `type` gains `workflow`. **Risk API:** * `POST /v2/simulate/evm`: response may include `safe` (Safe metadata, `signatures_assumed`, `batch_state`) and `batch` (per-MultiSend entry status and effects). ### Behavior changes **Risk API:** * `POST /v2/simulate/evm` simulates unsigned Safe `execTransaction` (and MultiSend batches) before signatures exist, on the same seven EVM networks as before. * `GET /v2/risk/history`: `sort=newest` orders by each assessment’s `timestamp` field (not the internal `queried_at` column). **Data API / Platform API:** * Workspace transfer `direction` (and the accounts-transfers `direction` filter) treats a multisig’s fund-holding vault / treasury / smart-account addresses as owned, not only the saved Account identity. ## v1.7.22: 9 September 2026 ### New endpoints **Risk API:** * `POST /v2/simulate/evm`: simulate an unsigned EVM transaction at the latest block. Networks: `eth`, `arb1`, `base`, `oeth`, `pol`, `bnb`, `avax`. A reverted transaction is HTTP 200 with `status: reverted`. Asset objects include `icon_url`. **Platform API:** * `GET /v2/treasury/cash-flow`: bucketed inflow / outflow / net over a caller-chosen window (`day`, `week`, or `month`). Flows are gross: a movement between two of your own accounts counts once as inflow and once as outflow. * `GET /v2/risk/alert-packs` and `GET /v2/risk/alert-packs/{pack_type}`: browse multisig alert packs (e.g. `squads`, `safe`) and their member templates. Optional `network` query prefers that chain when a rule type is registered on several. ### New fields **Risk API:** * `GET /v2/risk/history`: `severity` query (set membership, not a threshold: `severe`, `high`, `medium`, `low`, `none`) and `sort` (`newest` default, or `severity` for worst-first). Metadata echoes `filtered_severity` and `applied_sort`. **Platform API:** * `GET /v2/accounts/transfers`: `direction` query (`in`, `out`, `internal`) and a workspace-level `direction` field on `CanonicalConnectionTransactionDto`. Per-account `GET /v2/accounts/{id}/transfers` is unchanged. * `GET /v2/reconciliation/roll-forward`: required `tie_out_status` (`tied`, `explained`, `break`, `not_evaluated`) on each asset line and account statement. **Data API:** * `TransactionDto.fee`: network fee paid (`amount`, `denom`). Omitted on networks without fee data. Distinct from `CanonicalConnectionTransactionDto.fee` on connection transactions. ### Behavior changes **Platform API:** * `GET /v2/treasury/summary` and `GET /v2/treasury/forecast`: in/out/net flows are gross (an internal movement counts on both sides). **Data API:** * Native balances on `apechain` and `berachain` now resolve symbol, decimals, and USD instead of raw wei. ## v1.7.21: 3 September 2026 ### Breaking changes **Platform API:** * Connection provider `octav` is removed. DeFi protocol positions are enriched onto on-chain wallets by Range; they are no longer a customer-supplied connection type. * `TreasurySummaryComparisonDto.total_funds_usd` and `total_funds_delta_usd` are nullable. `historical_balances` can be `partial`. New required field `accounts_compared` is the like-for-like subset used for those totals. **Risk API:** * Alert event `details` returns only `message` (the human-readable alert sentence), not arbitrary structured data. **Data API:** * `GET /v1/address/fundedBy` 200 body is now `FundedBy` (was incorrectly documented as `AddressStats`). Description states this path is Elasticsearch-only; ClickHouse first-funder lookup is `GET /v2/address/fundedBy`. ### New endpoints **Data API:** * `GET /v2/address/fundedBy`: first inbound funder. On range2 EVM chains (`eth`, `base`, `arb1`, `pol`, `bnb`) the answer is served from ClickHouse full history. **Risk API:** * `POST /v2/risk/transaction/scan`: pre-signature Solana scan that simulates the unsigned payload, screens counterparties through Address Risk v2, checks poisoning, and extracts intent. Evidence is retrievable via `GET /v2/risk/evidence/{screenId}`. * `GET /v2/risk/transaction/scans`: list recent scans for the workspace. Reads stored scans and consumes no scan credits. **Platform API:** * `POST /v2/intents/evaluate` / `GET /v2/intents/policies`: evaluate a proposed transaction against Range treasury policies (blocking; no warn tier). * `GET /v2/reconciliation/roll-forward`: roll-forward balance reconciliation for a requested period. * `GET /v2/reports/custody/daily` / `GET /v2/reports/reserves/monthly`: CADOC 5711 / 5710 prototype reports. * `GET` / `PUT /v2/policies`: list and upsert CADOC policy subscriptions. * Bookkeeping open items: `POST …/open-items/sync`, `GET …/open-items`, `GET …/open-items/{id}`. ### New fields **Risk API:** * `GET /v2/risk/address` and `GET /v2/risk/address/batch`: optional `signals` query (comma-separated catalogue ids). Echoed on `meta.signals` when passed. * `GET /v1/risk/alert-events/{event_id}`: `squads`, a decoded Squads proposal (`null` for non-Squads events). **Platform API:** * `CanonicalConnectionTransactionDto.fee`: network fee in native-asset base units (`amount`, `denom`), on-chain only. * `AccountDto` / account update: `regulatory`, `cadoc_5710`, `cadoc_5711`. * `AccountBalance`: `price_source`, `price_updated_at`. **Data API:** * `AddressDetails.entity_name`: human-readable entity display name. * `TxnCounts.unit`: whether `transactionsCount` was aggregated from transactions or transfers. ### Behavior changes **Platform API:** * `POST /v2/accounts/refresh` `skipped` also covers accounts whose connection provider is no longer supported. **Risk API:** * `GET /v2/risk/evidence/{screenId}` also resolves a `screen_id` issued by `POST /v2/risk/transaction/scan`, returning scan-shaped evidence. ## v1.7.20: 26 August 2026 ### Breaking changes **Platform API:** * `GET /v2/accounts/{id}` summary (and generated page slug) changed from "Get account by address" to "Get account by id". The path is unchanged. A redirect covers the old URL. * `AccountDto.name` is nullable. Omit `name` when creating an account to leave it unnamed; an empty string is rejected. **Data API:** * `POST /v2/transaction-categories` summary shortened to "Create a custom transaction category" (idempotency moved into the description). The generated page slug changes; a redirect covers the old URL. * `GET /v1/address/balance` 200 body is now `AddressBalanceResponseDto`: `lookup_status` (`ok` / `partial` / `unavailable` / `unsupported`) and `reason` travel on every response, so a failed lookup is no longer indistinguishable from a genuinely empty address. ### New endpoints **Data API:** * `POST /v2/connections/subgraph`: induced subgraph. Given a set of addresses (2-50), returns only the sibling-to-sibling edges between them. `meta.failed_nodes` counts nodes whose counterparty lookup failed or timed out. * `GET /v2/multisig/memberships`: reverse lookup of Safe multisigs a signer address co-signs. Squads/Altitude/Realms are not covered yet. ### New fields **Platform API:** * Accounts (`AccountDto`) and workspace balances: `last_balance_refresh_at`, `last_balance_refresh_status` (`succeeded` / `failed` / `unsupported`), `last_balance_refresh_reason` (stable machine code). Distinct from `sync_status`, which tracks transaction-history sync. * `GET /v2/accounts/{id}`: `show_all=true` restores the unfiltered balance shape, ignoring the workspace token whitelist. * Connection provider `copper` (custodian), with `CreateAccountConnectionCopperCredentialsDto` (`api_key`, `api_secret`, optional `environment`). * Account transfers: `CanonicalConnectionTransactionDto.account` (identity only, no balances); transfer legs gain `source_label` / `destination_label`, `source_malicious` / `destination_malicious`, and icon URL arrays. * `POST /v2/accounts/refresh`: `skipped` count and per-failure `reason_code`. * `GET /v2/accounts/tokens`: `usd_string` on each token (exact USD sum). * `GET /v2/addresses/list/{hash}/balances`: per-entry `lookup_status` and `reason`. **Data API:** * `GET /v1/address/balance` entries: `amount_string`, `base_amount`, `decimals`, plus `usd_string` / `price_string` when priced. Legacy `amount` remains as a JSON number. * `GET /v2/transfers`: `direction` query filter (`in`, `out`, `internal`; comma-separated). Requires `only_workspace=true`. Direction is classified against every workspace account, including when `group_ids` narrows the result set. ### Behavior changes **Platform API:** * Account transfer `start_time` / `end_time` are a half-open UTC period `[start, end)`. A date-only `YYYY-MM-DD` is that UTC calendar day; an ISO value with a time is an instant and is not expanded. **Risk API:** * Solana Risk v2 behaviours now run on the same ClickHouse path as EVM. Redis velocity is no longer used on v2. No endpoint or catalogue shape change. ## v1.7.19: 19 August 2026 ### Breaking changes **Platform API:** * Account transfer list, get, category, and sync endpoints renamed from `/v2/accounts/transactions*` to `/v2/accounts/transfers*`. Path parameter `{transactionId}` is now `{transferId}`. `GET /v2/accounts/{id}/transactions` is now `GET /v2/accounts/{id}/transfers`. ### New endpoints **Platform API:** * `PATCH /v2/accounts/transfers/{transferId}/note`: set or clear a user-authored note on a persisted account transfer. The `note` field is required (send `null` or `""` to clear); max length 500. The note survives provider re-syncs. * `POST /v2/account-connections/{id}/plaid/reconnect-link-token`: mint a Plaid Link update-mode token to re-authenticate a Plaid item without deleting the connection. ### New fields **Platform API:** * Connection transfers (`CanonicalConnectionTransactionDto`): `note`, a user-authored string. `null` when unset. * `GET /v2/accounts/transfers`: `account_ids` filter (comma-separated UUIDs). Supersedes `account_id` when both are sent. * `GET /v2/account-connections/{id}/status` documents `reason` on failure: `reauth_required`, `provider_unavailable`, or `unknown`. * `GET /v2/accounts` `chain` and account-update `network` now take canonical Range slugs (`eth`, `bnb`, `solana`); known aliases (`ethereum`, `binance`, …) are normalised. Off-chain balances use the sentinel `off_chain`. **Risk API:** * `GET /v2/risk/history` metadata: `filtered_address`, the normalised address the `address` filter matched on. Omitted when no address filter was supplied. * Screening timings (`ScreenMetaDto`): `solana_address_risk_ms`. * `GET /v2/risk/signals`: catalogue adds behaviour `fraud-ml-liquidity-rug` (Solana liquidity-rug / abandoned-pool ML score; default severity `medium`; thresholds 0.75 / 0.85 / 0.90 / 1.0). ### Behavior changes **Platform API:** * `GET /v1/risk/alert-templates` `search_string` also matches template `tags`. * Plaid connections can be reconnected in place after `ITEM_LOGIN_REQUIRED` via the new reconnect-link-token endpoint; rotating credentials will not fix that failure. ## v1.7.18: 14 August 2026 ### New endpoints **Platform API:** * `GET /v2/workspace/usage/daily`: last 30 UTC days of API credit and request counts for the caller workspace, oldest first. Days with no traffic are returned with zero counters rather than omitted. ## v1.7.17: 13 August 2026 ### Breaking changes **Platform API:** * Account transaction list, get, category, and sync endpoints moved from `/v2/account-connections/transactions*` to `/v2/accounts/transactions*`. `GET /v2/account-connections/{id}/transactions` is replaced by `GET /v2/accounts/{id}/transactions`. Sync now enqueues one job per workspace account, including standalone Solana accounts with no connection. * `AccountConnectionDto` no longer returns `last_synced_at`, `sync_status`, or `sync_unavailable_reason`. Those fields now live on `AccountDto`. ### New fields **Platform API:** * Accounts (`AccountDto`): `last_synced_at`, `sync_status`, and `sync_unavailable_reason` for per-account transaction sync. Always present on persisted account responses; omitted on connection-preview stubs. * Connection transactions (`CanonicalConnectionTransactionDto`): `provider` is nullable. `null` means the row was sourced on-chain rather than from a connection provider. * Workspace account transactions (`GET /v2/accounts/transactions`): `network` filter. Restricts on-chain rows to the given networks; connection rows (banks, exchanges, custodians) are always returned. **Data API:** * Transfers (`TransferDto`): `direction` is `in`, `out`, or `internal` relative to the workspace's saved addresses. `null` when the request has no workspace context or neither party is a saved address. ### Behavior changes **Platform API:** * `POST /v1/risk/alert-rules/pack`: `pack_address` is optional. When present it drives the duplicate-pack 409 soft-warn and list grouping; membership is keyed on `pack_id`. * `GET /v2/accounts/transactions` `categories` filter matches category labels or catalog ids (labels are case-insensitive). **Data API:** * `GET /v1/address/balance`, `GET /v1/address/assetFlow`, and `GET /v2/transactions` accept optional `workspace_id` to filter by that workspace's token whitelist, and `show_all=true` to restore the unfiltered response. `GET /v2/transfers` accepts `workspace_id` for client compatibility; auth still comes from the API key. ## v1.7.16: 5 August 2026 ### Breaking changes **Data API:** * `GET /v1/address/assetFlow` now returns an **array** of per-day, per-token asset flow entries instead of a single object. Each entry carries a net delta plus, depending on `source`, either the absolute balance snapshot or the received/sent split it was derived from. * `GET /v2/transfers` with `only_workspace=true` also applies own-feed token whitelist filtering: transfers hidden by the workspace token whitelist are excluded. Pass `show_all=true` to restore the previous unfiltered response. **Platform API:** * Counterparty addresses (`CounterpartyAddressDto`) no longer return `name`. Use `label` for the human-readable annotation and `id` to reference the address in `PUT /v2/counterparties/{id}/addresses` operations. * Balances are now filtered by the workspace token whitelist by default on `GET /v2/accounts`, `GET /v2/accounts/concentration`, `GET /v2/addresses/list/{hash}/balances`, and `GET /v2/addresses/workspace/balances`. Pass `show_all=true` to restore the previous unfiltered response. ### New endpoints **Platform API:** * Case management: `GET /v2/cases`, `POST /v2/cases`, `GET /v2/cases/counts`, `GET /v2/cases/{id}`, `PATCH /v2/cases/{id}`, `PATCH /v2/cases/bulk`, `POST /v2/cases/{id}/comments`, `GET /v2/cases/{id}/timeline`, `POST /v2/cases/{id}/investigations`, `GET /v2/cases/{id}/investigations`, `POST /v2/cases/{id}/escalate` * `GET /v2/treasury/summary` and `GET /v2/treasury/forecast`: treasury KPIs and cash forecast * `GET /v2/token-whitelist` and `PATCH /v2/token-whitelist`: read and patch the workspace token whitelist * `GET /v2/accounts/tokens`: enumerate manageable tokens * `POST /v2/account-connections/wise/profiles`: list the Wise profiles a token can reach * `POST /v1/risk/alert-rules/pack`: create a multisig alert rule pack **Data API:** * `DELETE /v2/transaction-categories/{id}`: delete a custom transaction category ### New fields **Platform API:** * Account connections (`AccountConnectionDto`): `provider_display_name`, the canonical brand label for `type` (`okx` → OKX, `plaid` → Bank, `gate` → Gate.io), also present on the per-provider `*ConnectionDetails` objects; and `sync_unavailable_reason`, set to `provider_region_unsupported` when the provider cannot serve transaction history for the account's country. Balances are unaffected and keep syncing, so this is not a broken connection or a bad credential. * Alert rules (`AlertRuleDto`): `pack_id`, `pack_type`, `pack_label`, and `pack_address` for multisig rule packs. `GET /v1/risk/alert-rules` accepts matching `pack_id` and `pack_type` filters. * Alert templates (`AlertTemplateDto`, `TemplateGroupDto`): `packs`. * Account balances (`AccountBalance`): `denom`, the raw on-chain denom (contract address, mint, or IBC denom) the balance line was fetched under. Absent for exchange and custodian sources, which have no on-chain denom, and for balances persisted before the field existed. **Risk API:** * Behaviour results (`BehaviourSignalResultDto`): `ignored`, true when the workspace set the behaviour to detect-only. Reported for visibility and excluded from the screen severity. * Risk configuration (`RiskConfigSpecDto`, `PatchRiskConfigDto`): `case_auto_create`, controlling whether a screen at or above `min_tier` auto-creates a case. ### Behavior changes **Risk API:** * `GET /v2/risk/history` accepts an `address` filter to restrict the page to screens requested for one address; `limit=1` then returns just the latest screening for it. The value is normalised exactly as `GET /v2/risk/address` normalises it, so equivalent forms of the same address match the same records. `metadata.total` reflects the filtered count. **Platform API:** * Account and counterparty writes normalise before validating: `network` is trimmed and lowercased, addresses are trimmed only (several supported chains are case-sensitive, so lowercasing corrupts them). Malformed `address` and `network` values are rejected rather than stored. Counterparty address `network` is stored and echoed back lowercased regardless of the casing submitted. * Unpriced Tron tokens report `null` USD instead of `$0`. EVM native-balance failures now propagate instead of reporting `$0`; when only the native lookup fails, the token half of the response is still returned. * `GET /v2/accounts/concentration` only refreshes balances when `refresh=true`. ## v1.7.15: 30 July 2026 ### New fields **Platform API:** * Connection transactions (`CanonicalConnectionTransactionDto`): `provider_transaction_id` on persisted reads; `id` is the stable DB row id on persisted reads (provider-native id on live adapter responses). `transaction_id` matches `id` when present. ### Behavior changes **Data API:** * Duplicate OpenAPI operation summaries uniquified so Mintlify pages no longer collide on slugs (`Get Address Details`, `Get Address Info with Risk Score`, `Get Asset Flow for an Address`, `Get Top USD/Asset Balances by Address`, `Get Connections by Address`). ## v1.7.14: 29 July 2026 ### New account-connection providers **Platform API:** * `fordefi`: custodial wallets via API User bearer token * `coins_ph`: Coins.ph exchange accounts via API key and secret * `fireblocks`: Fireblocks custody via API user id and RSA private key (optional `region`) * `pave_bank`: Pave Bank accounts via OAuth client credentials (optional `environment`) * `quickbooks`: QuickBooks Online ledger connection (`kind: ledger`) via OAuth authorize URL + realm/state ### New endpoints **Platform API:** * `POST /v2/account-connections/quickbooks/authorize-url`: start QuickBooks OAuth; returns `authorize_url` and CSRF `state` * `GET /v2/account-connections/transactions/sync/status`: poll a sync batch (`batch_id`); authoritative completion is `complete` * `GET /v2/account-connections/bookkeeping/{connectionId}/counterparties`: preview customers/vendors from a ledger connection * `GET /v2/account-connections/bookkeeping/{connectionId}/categories`: preview P\&L category candidates from a ledger connection **Data API:** * `GET /v2/transaction-categories`: list default + workspace-custom transaction categories * `POST /v2/transaction-categories`: create a custom category (idempotent on name) * `PUT /v2/transaction-categories/{id}`: rename a custom category ### New fields * Account connections gain `kind` (`account` | `ledger`), `last_synced_at`, and `sync_status`; `GET /v2/account-connections` accepts `kind` (defaults to `account`) * `GET /v2/addresses/workspace/balances`: each balance includes `account_id` (joins to `AccountDto.id`); response schema is `WorkspaceBalancesResponseDto` * `AssetBalanceDto` / account balance payloads: `amount` and `usd` are decimal **strings** (`usd` is `null` when unknown); assets gain `name` * Counterparties list: optional `include_addresses=true` returns each counterparty's saved addresses inline * Risk v2 config behaviours: optional `tokens[]` on `watched-token` (max 200) * `GET /v2/risk/signals`: each attribution signal includes a `description`; catalogue adds eight signals (`ransomware`, `eu-sanctioned`, `eu-sanction-ru`, `uk-sanctioned`, `japan-sanctioned`, `france-sanctioned`, `fbi-fraud`, `nbctf-terror-financing`) and behaviours `token-activity` / `watched-token` ### Behavior changes * Altitude-connected accounts classify as `bank` (previously `multisig`) * Transfer enrichment category upserts accept any workspace-resolved category name (defaults ∪ custom), not a fixed enum; defaults gain `Swap` and `Airdrop` * Range MCP: **85** tools, adding documentation tools (`get_range_overview`, `search_documentation`, `get_documentation`) and four mutating tools (`add_accounts`, `create_counterparty`, `add_counterparty_addresses`, `create_alert_rule`) gated to workspace members with EDITOR role or higher ## v1.7.13: 22 July 2026 ### New endpoints **Platform API:** * `GET /v2/account-connections/transactions/{transactionId}`: fetch one persisted connection transaction by id * `GET /v2/multisig/details`: stateless multisig read (config, members, balances, pending proposals) without saving a connection ### New fields * `POST /v2/accounts/refresh`: response gains `failures[]` (`account_id`, `label`, `reason`), always present; length matches `failed` ### Behavior changes * `POST /v2/account-connections` (Safe / Squads / Realms): failed multisig resolve returns a classified error body with `code` one of `invalid_address`, `multisig_not_found`, `wrong_network` (Safe only), or `upstream_unavailable` * `GET /v2/risk/address` / batch: rejects inputs that cannot be a real address (empty, too short/long, whitespace, or characters outside address alphabets) with `400` instead of scoring them as `severity: none` * `GET /v2/risk/signals`: `velocity` behaviour description updated to pass-through / money-mule framing (EVM Risk v2 now uses ClickHouse Rule B + Rule A; Solana keeps Redis velocity) ## v1.7.11 (hotfix): 17 July 2026 ### New account-connection providers **Data API:** * `altitude`: connect Squads-based Solana smart accounts via a deposit or Settings address * `revolut_business`: connect Revolut Business accounts via OAuth refresh token and API certificate * `turnkey`: connect Turnkey-managed wallets via API key pair and organization id ### New endpoints * `PATCH /v2/account-connections/transactions/{transactionId}/category`: set a user-assigned category label on a persisted connection transaction. The category survives subsequent provider re-syncs. * `GET /v2/accounts/concentration`: asset, venue, and network concentration computed over the stored balances of the caller workspace accounts (`refresh=true` to refresh balances first). ### New fields * `GET /v2/account-connections/transactions`: response gains `meta.next_cursor`; new `cursor`, `start_time`, `end_time`, `status`, `min_usd`, `max_usd`, `string_search`, `account_id`, `group_ids`, and `categories` filters. * Canonical connection-transaction objects gain `transaction_id`, `usd_amount`, and `category`. ### Behavior changes * `GET /v2/account-connections/transactions`: pagination is now cursor-based (`meta.next_cursor` / `?cursor`) instead of an unpaginated "recent activity" list. ## v1.7.11: 15 July 2026 ### New account-connection providers **Data API:** * `octav`: track DeFi protocol positions (lending, staking, LP, and more) across up to 20 EVM wallet addresses ### New fields * `GET /v2/accounts`, `GET /v2/accounts/{id}`: `AccountType` gains `defi` (used by `octav` connections). * `GET /v1/risk/alert-events`: added `alert_rule_id` filter to narrow events to a specific alert rule. ### Behavior changes * `POST /v2/account-connections/{id}/transactions/sync` is replaced by `POST /v2/account-connections/transactions/sync`: instead of syncing one connection synchronously, it now enqueues an async background job per connection across the whole workspace and returns immediately (`202`) with a batch id. No longer limited to Kraken; works for every persisted provider. * `GET /v2/account-connections/{id}/transactions`: now reads exclusively from persisted transaction history for every provider (previously fell back to a live provider fetch for non-persisted connections). Run the sync endpoint above first to populate history for a newly connected account. ## v1.7.10: 14 July 2026 ### New account-connection providers **Data API:** * `binance`: connect Binance accounts via API key and secret * `okx`: connect OKX accounts via API key, secret, and passphrase * `bybit`: connect Bybit accounts via API key and secret * `bitget`: connect Bitget accounts via API key, secret, and passphrase * `gate`: connect Gate.io accounts via APIv4 key and secret * `kucoin`: connect KuCoin accounts via API key, secret, and passphrase (optional `api_key_version`, defaults to `3`) ### New fields * `GET /v2/account-connections`, `GET /v2/account-connections/{id}`: Squads pending-proposal entries gain `approved` and `rejected` (arrays of signer pubkeys). Absent on connections persisted before this field existed, until their next refresh. ### Behavior changes * `POST /v1/risk/alert-rules`: `name` is now required (previously optional). * `PATCH /v1/risk/alert-rules/{rule_id}`: `name`, if provided, must be non-empty. ## v1.7.9: 8 July 2026 ### New account-connection providers **Data API:** * `anchorage`: connect Anchorage-custodied wallets * `dfns`: connect Dfns-managed wallets (`dfns_custody`: `organization` or `end_user`) ### New fields * `GET /v2/accounts`, `GET /v2/accounts/{id}`: `AccountDto` gains `balances_usd` (total USD value across balances, `null` when no asset has a known price) and `balances_updated_at`. * `GET /v2/addresses/{address}/balances`: each balance entry gains `updated_at` (omitted when never refreshed). * `GET /v1/risk/alert-rules`, `GET /v1/risk/alert-rules/{rule_id}`: `AlertRuleDto` gains `alert_template`, the full template the rule was created from (`null` if the template has since been removed). ### Behavior changes * `GET /v1/risk/alert-templates`: response reshaped from a flat, cursor-paginated list of templates to `groups`, one entry per rule type with the networks and per-network template IDs it covers (`groups[].templates[].template_id`). The `limit` and `cursor` query params are removed; `network`/`search_string`/`tags` filtering still applies. ## v1.7.8: 1 July 2026 ### New endpoints **Risk API / Alerting:** * `GET /v1/risk/channels`, `POST /v1/risk/channels`, `PUT /v1/risk/channels`, `GET /v1/risk/channels/{channel_id}`, `DELETE /v1/risk/channels/{channel_id}`: manage alert delivery channels (Slack, Telegram, Discord, webhook, PagerDuty, email, Incident.io) * `GET /v1/risk/alert-templates`, `GET /v1/risk/alert-templates/{template_id}`: browse alert rule templates * `GET /v1/risk/alert-rules`, `POST /v1/risk/alert-rules`, `GET /v1/risk/alert-rules/{rule_id}`, `PATCH /v1/risk/alert-rules/{rule_id}`, `DELETE /v1/risk/alert-rules/{rule_id}`, `PUT /v1/risk/alert-rules/{rule_id}/channels`: create and manage workspace alert rules and their channel subscriptions * `GET /v1/risk/alert-events`, `GET /v1/risk/alert-events/{event_id}`: list and retrieve fired alert events ### New account-connection providers **Data API:** * `cubist`: connect Cubist-custodied wallets * `privy`: connect Privy-managed wallets ### Enhanced parameters * `GET /v2/account-connections/transactions`: added `tokens` filter (comma-separated asset symbols, matched against each transaction's displayed asset). `size` now caps the merged, newest-first result across all connections, rather than being applied to each connection independently. * `GET /v2/account-connections/{id}/transactions`: `account_id` must be the Range account UUID. ### Behavior changes * Alert channels now report `enabled` (your on/off toggle) and `connected` (delivery readiness) separately. A Telegram channel is `connected: false` until its chat is linked; disabled channels are still returned by `GET /v1/risk/channels` (only deleted channels 404). * `AlertRuleDto.parameters` is now a flat object (e.g. `{ "threshold": 90 }`) instead of an array of `{ field, value }` pairs. *** ## v1.2.0: 14 May 2026 ### New endpoints **Data API:** * `GET /v2/account-connections`: List account connections * `POST /v2/account-connections`: Create an account connection * `GET /v2/account-connections/{id}`: Get account connection by ID * `GET /v2/account-connections/{id}/status`: Get connection status * `DELETE /v2/account-connections/{id}`: Delete an account connection * `POST /v2/account-connections/plaid/link-token`: Generate a Plaid link token * `GET /v2/accounts`: List accounts * `GET /v2/accounts/{id}`: Get account by ID * `PUT /v2/accounts`: Update accounts * `GET /v2/groups`: List groups * `POST /v2/groups`: Create a group * `PUT /v2/groups/{id}`: Update a group * `DELETE /v2/groups/{id}`: Delete a group ### Enhanced parameters * `GET /v2/transfers`: added `tx_hashes` filter *** ## v1.1.2: May 2026 ### New endpoints **Data API:** * `POST /v2/addresses/list`: Store an address list * `GET /v2/addresses/list/{hash}`: Retrieve an address list * `GET /v2/addresses/list/{hash}/balances`: Balances for an address list * `GET /v2/connections/byAddress`: Address counterparties * `GET /v2/connections/transfers`: Transfers between two addresses * `GET /v2/screening/addresses/{address}/risk`: Address risk (auto-detect network) * `GET /v2/screening/{network}/addresses/{address}/risk`: Address risk (explicit network) * `GET /v2/tokens/mints-burns`: Token mint and burn events * `GET /v2/tokens/summary`: Token summary * `GET /v2/tokens/top-holders`: Top holders for a token * `GET /v2/tokens/total-supply`: Total supply for a token * `GET /v2/transactions`: List transactions * `GET /v2/transactions/{id}`: Get transaction by ID * `GET /v2/transactions/by-network/{network}/{hash}`: Get transaction by network and hash * `GET /v2/transfers/top-assets`: Top assets by transfer volume * `GET /v2/transfers/top-networks`: Top sender/receiver networks **Risk API:** * `POST /v1/simulate/solana/transactions`: Batch simulate multiple Solana transactions ### Enhanced parameters * `GET /v1/address/balance`: added `network_type` and `token_contracts` filters * `GET /v2/addresses`: added `cursor` and `size` for pagination * `GET /v2/transfers`: added `address_list_hash` and `addresses` filters ### Deprecated endpoints The following v1 endpoints have been removed in favor of v2 equivalents: * `GET /v1/address/balances` → use `/v1/address/balance` * `GET /v1/network/relevant-cross-chain-transfers` → use `/v2/transfers` * `GET /v1/network/transactions/errors` * `GET /v1/network/transfers` → use `/v2/transfers` * `POST /v1/protocols/transactions` → use `/v2/transactions` * `GET /v1/protocols/transactions/{hash}` → use `/v2/transactions/by-network/{network}/{hash}` *** ## v1.1.1: November 2025 * Documentation restructure with dedicated tabs for Data, Risk, and Faraday APIs * Expanded cross-chain coverage to 100+ networks * Enhanced address labeling with entity recognition ## v1.0: March 2025 * Initial release of Data API and Risk API * Core blockchain data endpoints across 18+ networks * Address risk scoring with proximity analysis # Glossary Source: https://docs.range.org/resources/glossary A comprehensive reference for key terms used throughout Range documentation and the blockchain ecosystem. ## General terms **Address Poisoning:** A scam technique where attackers send small amounts of tokens from addresses similar to a user's legitimate contacts, hoping the user will accidentally copy the malicious address. **AMM (Automated Market Maker):** A type of decentralized exchange protocol that uses mathematical formulas to price assets, enabling permissionless trading without order books. **API Key:** A unique identifier used to authenticate requests to the Range API. Keep this confidential and never expose it in client-side code. **Blockchain:** A distributed ledger technology that records transactions across multiple computers in a way that ensures security, transparency, and immutability. **Bridge:** A protocol that enables the transfer of assets or data between different blockchain networks. **CEX (Centralized Exchange):** A cryptocurrency exchange operated by a centralized entity, such as Binance or Coinbase. **Cross-Chain:** Refers to operations, transactions, or protocols that work across multiple blockchain networks. **DEX (Decentralized Exchange):** A peer-to-peer marketplace for trading cryptocurrencies without intermediaries or central authority. **DeFi (Decentralized Finance):** Financial services built on blockchain technology, removing intermediaries and enabling open, permissionless access to financial products. ## Compliance and risk **AML (Anti-Money Laundering):** Regulations and procedures designed to prevent criminals from disguising illegally obtained funds as legitimate income. **Blacklist:** A list of addresses or entities that are blocked from transacting due to suspected malicious activity or regulatory restrictions. **KYC (Know Your Customer):** The process of verifying the identity of users to prevent fraud, money laundering, and terrorist financing. **KYT (Know Your Transaction):** Real-time monitoring and analysis of blockchain transactions to detect suspicious activity and ensure compliance. **OFAC (Office of Foreign Assets Control):** A U.S. Treasury department that enforces economic and trade sanctions. Many blockchain addresses are sanctioned by OFAC. **Risk Score:** A numerical value assigned to an address or transaction indicating the level of risk based on various factors like sanctions, prior illicit activity, and behavioral patterns. **Sanctions List:** A list of addresses or entities restricted from transacting due to regulatory or legal reasons (e.g., OFAC, EU, UK, UN sanctions). Not every list publishes crypto addresses; see [Risk Data Sources](/risk-api/product-info/risk-data-sources) for the lists Range screens. **Travel Rule:** A regulatory requirement (FATF Recommendation 16) that mandates Virtual Asset Service Providers (VASPs) to share customer information for transactions above certain thresholds. ## Stablecoin and payments **Aggregator:** A service that sources liquidity from multiple DEXs or exchanges to provide users with the best possible price for trades. **Fiat On/Off-Ramp:** Services that allow users to convert between fiat currency (e.g., USD, EUR) and cryptocurrencies. **Liquidity:** The ease with which an asset can be bought or sold without significantly affecting its price. **Liquidity Pool:** A collection of funds locked in a smart contract, used to facilitate trading on DEXs and AMMs. **Slippage:** The difference between the expected price of a trade and the actual execution price, typically caused by market volatility or low liquidity. **Stablecoin:** A cryptocurrency designed to maintain a stable value, typically pegged to a fiat currency like USD (e.g., USDC, USDT, DAI). **Swap:** The exchange of one cryptocurrency for another, typically executed on a DEX or through an aggregator. ## DeFi metrics **APY (Annual Percentage Yield):** The annualized rate of return on an investment, accounting for compound interest. **Borrowing Rate:** The interest rate paid by users who borrow assets from a lending protocol. **Lending Rate:** The interest rate earned by users who supply assets to a lending protocol. **TVL (Total Value Locked):** The total value of assets deposited in a DeFi protocol or smart contract, used as a measure of protocol adoption and size. **Utilization Rate:** The ratio of borrowed assets to total supplied assets in a lending protocol, indicating how efficiently capital is being used. **Yield Farming:** The practice of staking or lending crypto assets to generate high returns, often by providing liquidity to DeFi protocols. ## Blockchain concepts **Block Explorer:** A web interface that allows users to view transactions, addresses, and other onchain data for a specific blockchain. **Gas Fee:** The cost required to execute a transaction or smart contract operation on a blockchain network like Ethereum. **Mempool:** The waiting area for unconfirmed transactions before they are included in a block by miners or validators. **Non-Custodial:** A system where users maintain complete control of their private keys and assets without relying on a third-party custodian. **Oracle:** A service that provides external, real-world data to smart contracts on the blockchain. **Smart Contract:** Self-executing code deployed on a blockchain that automatically enforces the terms of an agreement when predefined conditions are met. **Transaction Hash (TxHash):** A unique identifier for a blockchain transaction, used to track and verify its status. **Validator:** A network participant responsible for verifying transactions and maintaining the integrity of a proof-of-stake blockchain. **Wallet:** A software application or hardware device that stores private keys and allows users to interact with blockchain networks. ## Range-specific terms **Data API:** Range's API for onchain data: addresses, entities, transactions, token transfers, tokens, and network and protocol analytics. See the [Data API](/data-api/data-introduction). **Entity Labeling:** The process of identifying and tagging blockchain addresses with known entities (e.g., exchanges, protocols, institutions). **Malicious Address:** A wallet address flagged for involvement in scams, hacks, phishing, or other illicit activities. **Network Tag:** A label identifying which blockchain network an address belongs to (e.g., Ethereum, Solana, Polygon). **Onchain Risk Verifier:** A Range integration for Solana programs that verifies wallet and counterparty risk from the Risk API inside the program, using Switchboard On-Demand Oracles. See the [Onchain Risk Verifier](/risk-api/guides/onchain-risk-verifier) guide. **Platform API:** Range's API for your own workspace: accounts, account connections, groups, counterparties, alert rules and channels, and workspace configuration. See the [Platform API](/platform-api/platform-introduction). **Range AI:** Range's MCP (Model Context Protocol) server, which lets an MCP-compatible AI client call Range tools with your Range API key. See [Range AI](/ai/introduction). **Risk API:** Range's API for risk scoring and screening: address, token, payment, and transaction risk, sanctions and blacklist checks, and transaction simulation. See the [Risk API](/risk-api/risk-introduction). **Stablecoin Explorer:** Range's block explorer for stablecoins at [explorer.money](https://explorer.money), which shows a stablecoin transfer's full path across chains in one view. See [Stablecoin Explorer integrations](/integrations/stablecoin-explorer-integrations). **Wallet Cohorting:** Grouping wallets by type or behavior (e.g., retail, institutional, exchange, smart contract, validator). **Whale:** A wallet or entity holding a large amount of a particular cryptocurrency, capable of significantly influencing market prices. *** ## Need more information? Explore detailed API references and integration guides. Have questions? Our team is here to help. # Security at Range Source: https://docs.range.org/resources/security How Range protects customer data and operates its services, including security controls, compliance posture, and responsible disclosure. Range is the risk and compliance infrastructure platform for institutions operating across stablecoins and fiat. This page summarizes the controls, processes, and policies that govern how we protect customer data and operate our services. ## Security program Range operates a security program covering identity, access, infrastructure, data protection, monitoring, and response. ## Identity and access * Mandatory multi-factor authentication for all workforce accounts. * Single sign-on for internal systems. * Role-based access control with least-privilege defaults. * Production access restricted to authorized personnel. * Production and development environments are logically separated. * Infrastructure credentials and secrets are centrally managed and rotated. ## Device security All workforce devices are subject to: * Enforced MFA. * Automatic screen locking. * Full-disk encryption. * Endpoint protection. * Device compliance monitoring. ## Data hosting and jurisdiction Customer data is held in the **EU** under GDPR-compliant hosting. Range maintains a Data Processing Agreement (DPA) with its infrastructure provider. Sensitive data is isolated per workspace. Screening activity, risk policy, and related workspace data belonging to one customer are not visible to another. ## Encryption and data protection Range uses industry-standard encryption to protect sensitive data. * Data in transit is protected with HTTPS and TLS. * Sensitive customer data is encrypted at rest, including workspace-level encryption for sensitive fields. * Infrastructure secrets are securely stored and rotated. Range does not custody assets or hold customer private keys. Where customers provide API credentials for read-only synchronization with their custodial accounts, those credentials are encrypted and access-restricted within our backend. We process blockchain, payment, and account-related data on a read-only basis. Range does not initiate transactions or payments on behalf of customers. ## Monitoring and availability Range runs centralized logging, monitoring, and alerting across production systems to detect operational anomalies and security events. On-call engineering and infrastructure teams monitor alerts continuously. We target 99.9% service availability for production systems. ## Vulnerability management Range maintains processes to identify, review, and remediate vulnerabilities, including: * Dependency and software package scanning. * Infrastructure patch management. * Mandatory code review on changes to production systems. * Penetration testing. * Remediation tracking and validation. Findings from security assessments and penetration tests are reviewed and remediated according to internal risk procedures. ## Incident response Range maintains a formal Incident Response Plan covering identification, classification, containment, remediation, recovery, and notification. The plan defines: * Severity classification. * Escalation paths. * Documented response procedures. * Evidence preservation. * Root cause analysis. * Customer and regulatory notification processes. * Post-incident reviews. * Annual testing and continuous improvement. The plan is maintained internally and reviewed regularly. ## Backup and recovery Range performs hourly backups of critical systems and data. Recovery procedures are tested: * Automatically each week. * Manually at least twice per year. ## Compliance and privacy Range is currently undergoing a SOC 2 Type II audit. We maintain policies and controls aligned to the SOC 2 Trust Services Criteria covering security, availability, confidentiality, and privacy. Range maintains processes for compliance with applicable privacy and data protection requirements, including GDPR. ## Responsible disclosure Range runs a bug bounty program for verified security findings. See [Bug bounty](/resources/bug-bounty) for scope, rewards, and reporting guidelines, or email [security@range.org](mailto:security@range.org) directly. # Get an Alert Event Source: https://docs.range.org/risk-api/alerts/get-alert-event api-reference/risk-api.json get /v1/risk/alert-events/{event_id} Retrieve one alert event by ID, with its severity, transaction hash, involved addresses, alert message, and decoded proposal for Squads multisig events. # List Alert Events Source: https://docs.range.org/risk-api/alerts/list-alert-events api-reference/risk-api.json get /v1/risk/alert-events Returns a cursor-paginated list of the workspace alert events, newest first. # Building a Compliance Screening Pipeline Source: https://docs.range.org/risk-api/guides/compliance-screening-pipeline Combine multiple Risk API endpoints to build an automated AML/KYC compliance workflow for blockchain transactions. This guide walks through building an automated compliance screening pipeline using Range's Risk API. You'll learn how to choose the right endpoint for your use case and build a multi-layered screening flow. **Prerequisites:** You need a [Risk API key](/introduction/getting-started) and familiarity with the [Address Risk Score](/risk-api/risk/get-address-risk-score), [Sanctions & Blacklist Check](/risk-api/risk/get-sanctions-blacklist-check), and [Payment Risk Assessment](/risk-api/risk/get-payment-risk-assessment) endpoints. *** ## Choosing the Right Approach Range's risk endpoints are layered - each higher-level endpoint includes the checks of the ones below it: | Endpoint | What It Includes | Best For | | - | - | - | | [Sanctions & Blacklist Check](/risk-api/risk/get-sanctions-blacklist-check) | Sanctions lists (OFAC, UK, EU, France, Japan, and more), stablecoin issuer blacklists | Fast pass/fail sanctions screening | | [Address Risk Score](/risk-api/risk/get-address-risk-score) | Everything in Sanctions + proximity analysis + ML-based threat detection | Screening a single address | | [Payment Risk Assessment](/risk-api/risk/get-payment-risk-assessment) | Everything in Address Risk + new wallet detection, dormant wallet detection, address poisoning, interaction history, token risk, cross-chain analysis | Assessing a payment between two addresses | You don't need to call all three endpoints sequentially - each higher-level endpoint already includes the checks from the ones below it. Choose based on your use case and how much context you have. ## Architecture Overview A compliance pipeline typically uses one of two patterns: ### Pattern A: Payment Flow (Recommended for Transactions) When you have both sender and recipient, use Payment Risk Assessment as the primary check. It includes address risk scoring and sanctions/attribution data for both addresses, plus payment-specific analysis. ``` Sender + Recipient + Amount │ ▼ ┌───────────────────────────┐ │ Payment Risk Assessment │──── High risk? → FLAG / REJECT │ (8 dimensions including │ Unknown? → FLAG for review │ address risk + sanctions│ │ for both addresses) │ └───────────────────────────┘ │ Low/Medium ▼ ALLOW ``` ### Pattern B: Address Screening (No Payment Context) When screening a single address (e.g., during onboarding, before allowing deposits), use Address Risk Score - which already includes sanctions and blacklist data. ``` Inbound Address │ ▼ ┌─────────────────────┐ │ Address Risk Score │──── Score ≥ threshold? → FLAG / REJECT │ (Includes sanctions│ │ + ML + proximity) │ └─────────────────────┘ │ Acceptable ▼ ALLOW ``` ### When to Use the Standalone Sanctions Endpoint The [Sanctions & Blacklist Check](/risk-api/risk/get-sanctions-blacklist-check) endpoint is still useful when you need: * **Explicit sanctions compliance documentation** - a dedicated sanctions check provides a clear audit record specifically for sanctions screening, with one entry per list the address is on * **High-volume, low-latency pre-filtering** - the sanctions endpoint is the fastest and cheapest check, useful as a first gate before more expensive analysis * **Detailed blacklist event data** - with `include_details=true`, it returns specific blacklist/unblacklist events from stablecoin issuers that aren't available through the other endpoints *** ## Screening a Payment When you have sender, recipient, and amount, the Payment Risk Assessment is the single endpoint you need. It analyzes both addresses across 8 risk dimensions - including malicious connection analysis and attributed address checks (which cover sanctions and blacklist data). ```bash theme={null} curl -G https://api.range.org/v1/risk/payment \ --data-urlencode "sender_address=SENDER_ADDRESS" \ --data-urlencode "recipient_address=RECIPIENT_ADDRESS" \ --data-urlencode "amount=1000" \ --data-urlencode "sender_network=solana" \ --data-urlencode "recipient_network=solana" \ -H "Authorization: Bearer YOUR_API_KEY" ``` ```javascript theme={null} async function checkPaymentRisk(sender, recipient, amount, network) { const params = new URLSearchParams({ sender_address: sender, recipient_address: recipient, amount: amount.toString(), sender_network: network, recipient_network: network, }); const response = await fetch( `https://api.range.org/v1/risk/payment?${params}`, { headers: { Authorization: `Bearer ${API_KEY}` } } ); return response.json(); } ``` ### Decision Matrix Rows are listed in the order the `screenPayment()` example below checks them. The first match wins, so a stronger signal is never masked by a weaker one. | Payment Risk Level | Risk Factors | Action | | :-: | :-: | - | | Any | `directly_malicious_address`, `malicious_attributed_sender` or `malicious_attributed_recipient` at HIGH | **REJECT** - Address flagged as malicious | | High | More than one HIGH factor | **REJECT** - High risk on multiple signals | | High | A single HIGH factor that is not a malicious address flag | **FLAG** - Manual review required | | Unknown | - | **FLAG** - Insufficient data, treat with caution | | Medium | - | **FLAG** - Elevated risk, needs review | | Low | - | **ALLOW** - Low risk | The malicious address flag arrives under more than one factor name. Live responses use `directly_malicious_address` when an address is flagged directly, and `malicious_attributed_sender` or `malicious_attributed_recipient` when it matches a known malicious entity. The [Attributed Address Check](/risk-api/risk/get-payment-risk-assessment) also documents `malicious_address_sender` and `malicious_address_recipient`. Match every one of these names. A filter that matches a single name, or that matches on a name prefix such as `malicious_address`, misses real hits and never rejects. These thresholds are recommendations. Calibrate them based on your risk appetite, regulatory requirements, and use case. See the calibration guidance below. *** ## Screening a Single Address When you don't have payment context (e.g., during onboarding or deposit screening), use Address Risk Score. It includes sanctions and blacklist data along with proximity analysis and ML-based threat detection. ```bash theme={null} curl -G https://api.range.org/v1/risk/address \ --data-urlencode "address=COUNTERPARTY_ADDRESS" \ --data-urlencode "network=solana" \ -H "Authorization: Bearer YOUR_API_KEY" ``` ```javascript theme={null} async function checkAddressRisk(address, network) { const params = new URLSearchParams({ address, network }); const response = await fetch( `https://api.range.org/v1/risk/address?${params}`, { headers: { Authorization: `Bearer ${API_KEY}` } } ); return response.json(); } ``` ### Decision Thresholds | Score | Risk Level | Action | | -: | - | - | | **8-10** | Critical / Extremely high | **REJECT** - Directly or closely connected to malicious activity | | **6-7** | High | **FLAG** or **REJECT** - Depends on risk tolerance | | **4-5** | Medium | **FLAG** - Manual review recommended | | **1-3** | Low / Very low | **ALLOW** | *** ## Adding a Dedicated Sanctions Check For compliance teams that need an explicit, documented sanctions screening step - separate from the broader risk analysis - add a standalone Sanctions & Blacklist Check as a fast pre-filter: ```javascript theme={null} async function checkSanctions(address) { const response = await fetch( `https://api.range.org/v1/risk/sanctions/${address}?include_details=false`, { headers: { Authorization: `Bearer ${API_KEY}` } } ); const data = await response.json(); return { // is_sanctioned covers every government list; is_ofac_sanctioned is OFAC only blocked: data.is_sanctioned === true || data.is_token_blacklisted, // A list could not be read: the result may be incomplete, so fail closed unknown: data.lists_checked === false || data.is_sanctioned === null, lists: data.sanctions.map((s) => s.source), blacklisted: data.is_token_blacklisted, }; } ``` Never read `lists_checked: false` or `is_sanctioned: null` as clean. A store could not be read, so `false` in the other flags proves nothing. Flag or retry before allowing the address. This is optional since Address Risk Score and Payment Risk Assessment already include sanctions data, but useful for: * Creating a separate audit record specifically for sanctions compliance * Fast pre-filtering before more expensive checks * Getting detailed blacklist event history with `include_details=true` *** ## Log and Audit For compliance, store the raw API responses alongside your decision. This creates an audit trail showing what data was available at the time of the decision. ```javascript theme={null} async function logComplianceDecision(transaction, checks, decision) { const record = { timestamp: new Date().toISOString(), transaction_id: transaction.id, counterparty: transaction.counterparty, checks: { payment_risk: checks.paymentRisk, // or address_risk for single-address screening sanctions: checks.sanctions || null, // if standalone sanctions check was used }, decision: decision, // "allow", "flag", "reject" reasoning: decision.reasoning, }; // Store in your compliance database await complianceDB.insert(record); } ``` Key fields to retain: * **Timestamp** of each check * **Raw API responses** (scores, risk levels, reasoning, individual risk factors) * **Decision** and the logic that produced it * **Operator overrides** if a flagged transaction was manually approved or rejected *** ## Threshold Calibration Different use cases warrant different risk tolerances. These thresholds apply to Address Risk Score (`riskScore` 1-10): | Use Case | Reject At | Flag At | Rationale | | - | :-: | :-: | - | | **Consumer wallet** | Score ≥ 8 | Score ≥ 6 | Protect retail users, fewer false positives | | **Exchange compliance** | Score ≥ 6 | Score ≥ 3 | Regulatory obligation, tighter screening | | **Institutional treasury** | Score ≥ 4 | Score ≥ 2 | Maximum caution for large value flows | | **DeFi protocol** | Score ≥ 8 | Score ≥ 6 | Balance usability with risk mitigation | *** ## Full Pipeline Examples ### Payment Flow ```javascript theme={null} // Every factor name that means "this address is flagged as malicious". // Live responses use directly_malicious_address and the // malicious_attributed_* pair; the Attributed Address Check also documents // the malicious_address_* pair. Match all of them, not a name prefix. const MALICIOUS_ADDRESS_FACTORS = [ "directly_malicious_address", "malicious_attributed_sender", "malicious_attributed_recipient", "malicious_address_sender", "malicious_address_recipient", ]; async function screenPayment(sender, recipient, amount, network) { // Payment Risk Assessment - comprehensive check for both addresses const paymentRisk = await checkPaymentRisk(sender, recipient, amount, network); const highFactors = (paymentRisk.risk_factors || []).filter( (f) => f.risk_level === "high" ); // Check for malicious address flags in risk factors const maliciousFlags = highFactors.filter((f) => MALICIOUS_ADDRESS_FACTORS.includes(f.factor) ); if (maliciousFlags.length > 0) { return { decision: "reject", reasoning: `Address flagged as malicious: ${maliciousFlags .map((f) => f.factor) .join(", ")}`, }; } if (highFactors.length > 1) { return { decision: "reject", reasoning: "High risk on multiple signals" }; } if (paymentRisk.overall_risk_level === "high") { return { decision: "flag", reasoning: "High payment risk - manual review required" }; } if (paymentRisk.overall_risk_level === "unknown") { return { decision: "flag", reasoning: "Insufficient data - proceed with caution" }; } if (paymentRisk.overall_risk_level === "medium") { return { decision: "flag", reasoning: "Elevated risk - review before releasing funds" }; } return { decision: "allow", reasoning: "Payment risk assessment passed" }; } ``` ### Address Screening with Optional Sanctions Audit ```javascript theme={null} async function screenAddress(address, network, requireSanctionsAudit = false) { // Optional: Dedicated sanctions check for audit trail if (requireSanctionsAudit) { const sanctions = await checkSanctions(address); if (sanctions.blocked) { return { decision: "reject", reasoning: sanctions.lists.length ? `Address is on: ${sanctions.lists.join(", ")}` : "Address is token blacklisted", }; } if (sanctions.unknown) { return { decision: "flag", reasoning: "Sanctions lists could not be checked - retry before allowing" }; } } // Address Risk Score - includes sanctions + proximity + ML analysis const addressRisk = await checkAddressRisk(address, network); if (addressRisk.riskScore >= 8) { return { decision: "reject", reasoning: `Risk score ${addressRisk.riskScore}/10: ${addressRisk.reasoning}`, }; } if (addressRisk.riskScore >= 6) { return { decision: "flag", reasoning: "Elevated risk - manual review required" }; } return { decision: "allow", reasoning: "Address screening passed" }; } ``` *** ## What's Next Deep dive into how risk scores are calculated and how to interpret them. Manage counterparties, accounts and workspace settings programmatically. # Onchain Risk Verifier Source: https://docs.range.org/risk-api/guides/onchain-risk-verifier Verify wallet and counterparty risk directly inside Solana programs using Range's Risk API and Switchboard On-Demand Oracles. This guide covers how to integrate Range's Onchain Risk Verifier (ORV) into a Solana program. The ORV brings real-world risk intelligence onchain - allowing programs to reject high-risk or sanctioned addresses at the protocol level using cryptographically signed, tamper-proof data. **Prerequisites:** You need a [Risk API key](/introduction/getting-started), a Solana development environment (Anchor or Pinocchio), and familiarity with [Switchboard On-Demand Oracles](https://docs.switchboard.xyz/). *** ## How It Works The Onchain Risk Verifier uses [Switchboard On-Demand Oracles](https://docs.switchboard.xyz/) to fetch signed risk data from Range's Risk API and verify it inside your Solana program. No persistent data feeds are required - quotes are requested on demand. ```mermaid theme={null} sequenceDiagram participant C as Client (off-chain) participant O as Switchboard Oracle (TEE) participant S as Solana Program (onchain) C->>C: 1. Define OracleJob
(Range API → parse → scale) C->>O: 2. Request signed quote O->>O: Fetch Range Risk API
Sign result in TEE O->>C: Return signed quote C->>C: 3. Build transaction
ix[0]: Ed25519 sig verify
ix[1]: Program instruction C->>S: Submit transaction S->>S: 4. Verify Ed25519 signature
Reconstruct feed → hash
Compare feed IDs
Check quote freshness
Use verified risk score ``` ### Security Model * **Tamper-proof**: The program reconstructs the exact same feed definition onchain and hashes it. Any change to the URL, headers, or processing tasks changes the hash, causing verification to fail. * **Cryptographic verification**: Switchboard oracles run in Trusted Execution Environments (TEEs) and sign results with Ed25519. The program verifies these signatures Onchain. * **Freshness checks**: The program rejects quotes older than a configurable number of slots (e.g., 50 slots ≈ 20 seconds). * **API keys stay off-chain**: Range API keys are injected as variable overrides at the oracle level - they never appear Onchain. *** ## Use Cases | Scenario | How ORV Helps | | - | - | | **Privacy protocols** | Screen deposits to prevent illicit funds from entering the pool | | **Lending protocols** | Reject deposits or borrows from high-risk wallets | | **Treasury management** | Gate payouts to wallets below a risk threshold | | **Governance** | Only allow proposals or votes from verified-clean addresses | | **Bridges** | Block transfers involving sanctioned or malicious addresses | | **DEX / AMM** | Warn or block swaps with flagged counterparties | *** ## Step 1: Define the Oracle Job (TypeScript) The Oracle Job tells Switchboard what data to fetch and how to process it. This job calls Range's [Address Risk Score](/risk-api/risk/get-address-risk-score) endpoint, parses the `riskScore`, scales it to 0-100, and bounds the result. ```typescript theme={null} import { OracleJob } from '@switchboard-xyz/common'; function getRangeRiskScoreJob(address: string): OracleJob { return OracleJob.fromObject({ tasks: [ { httpTask: { url: `https://api.range.org/v1/risk/address?address=${address}&network=solana`, headers: [ { key: 'accept', value: 'application/json' }, // Resolved by Switchboard oracle via variable override - never Onchain { key: 'X-API-KEY', value: '${RANGE_API_KEY}' }, ], }, }, // Extract the numeric risk score from the response { jsonParseTask: { path: '$.riskScore' } }, // Scale from 0-10 to 0-100 for integer precision Onchain { multiplyTask: { scalar: 10 } }, // Bound the result { boundTask: { lowerBoundValue: '0', onExceedsLowerBoundValue: '0', upperBoundValue: '100', onExceedsUpperBoundValue: '100', }, }, ], }); } ``` The address is embedded directly in the Oracle Job URL. This is intentional, the Switchboard feed ID is a deterministic hash of the entire feed definition (including the URL). Your onchain program reconstructs the same URL using the `query_account` pubkey and hashes it to verify the oracle returned data for the correct address. A new Oracle Job must be created for each address you want to check. The `${RANGE_API_KEY}` placeholder is resolved by the Switchboard oracle at runtime using variable overrides. Your API key is never exposed onchain or in transaction data. *** ## Step 2: Request a Signed Quote (TypeScript) Use the Switchboard SDK to request a signed quote and build the Ed25519 verification instruction. ```typescript theme={null} import { PublicKey, Keypair, TransactionInstruction } from '@solana/web3.js'; import { CrossbarClient, IOracleFeed } from '@switchboard-xyz/common'; import * as sb from '@switchboard-xyz/on-demand'; import { getDefaultQueue } from '@switchboard-xyz/on-demand'; async function getOracleQuote( payer: Keypair, addressToCheck: string, ): Promise<{ queueAccount: PublicKey; sigVerifyIx: TransactionInstruction; }> { const { gateway, rpcUrl } = await sb.AnchorUtils.loadEnv(); // Use devnet queue for testing, getDefaultQueue(rpcUrl) for mainnet const queue = await sb.getDefaultDevnetQueue(rpcUrl); const crossbar = CrossbarClient.default(); // Build the feed specification with the target address baked in const feed: IOracleFeed = { name: 'Risk Score', jobs: [getRangeRiskScoreJob(addressToCheck)], minJobResponses: 1, minOracleSamples: 1, maxJobRangePct: 100, }; // Request a signed quote from the oracle network const sigVerifyIx = await queue.fetchQuoteIx(crossbar, [feed], { variableOverrides: { RANGE_API_KEY: process.env.RANGE_API_KEY! }, numSignatures: 1, instructionIdx: 0, // Ed25519 verify must be at this index in the transaction }); return { queueAccount: queue.pubkey, sigVerifyIx }; } ``` *** ## Step 3: Build and Send the Transaction (TypeScript) Combine the signature verification instruction with your program instruction in a single transaction. The Switchboard SDK (`@switchboard-xyz/on-demand`) uses `@solana/web3.js` types internally. The transaction building code below uses web3.js for compatibility with the SDK. ```typescript theme={null} import { Connection, Transaction, sendAndConfirmTransaction, SYSVAR_CLOCK_PUBKEY, SYSVAR_SLOT_HASHES_PUBKEY, SYSVAR_INSTRUCTIONS_PUBKEY, PublicKey, Keypair, TransactionInstruction, } from '@solana/web3.js'; import { createHash } from 'crypto'; // 8-byte Anchor discriminator for the instruction const VERIFY_IX = createHash('sha256') .update('global:verify_risk_score_feed') .digest() .subarray(0, 8); function buildProgramIx( programId: PublicKey, queue: PublicKey, queryAccount: PublicKey, ): TransactionInstruction { return new TransactionInstruction({ programId, keys: [ { pubkey: queue, isSigner: false, isWritable: false }, { pubkey: SYSVAR_CLOCK_PUBKEY, isSigner: false, isWritable: false }, { pubkey: SYSVAR_SLOT_HASHES_PUBKEY, isSigner: false, isWritable: false }, { pubkey: SYSVAR_INSTRUCTIONS_PUBKEY, isSigner: false, isWritable: false }, { pubkey: queryAccount, isSigner: false, isWritable: false }, ], data: VERIFY_IX, }); } // Full transaction flow async function verifyRiskScore( connection: Connection, payer: Keypair, programId: PublicKey, addressToCheck: PublicKey, ) { // Get the signed oracle quote for the target address const { queueAccount, sigVerifyIx } = await getOracleQuote( payer, addressToCheck.toBase58(), ); // Build the program instruction const programIx = buildProgramIx(programId, queueAccount, addressToCheck); // Transaction: [sigVerify at index 0, program ix at index 1] const tx = new Transaction().add(sigVerifyIx, programIx); tx.feePayer = payer.publicKey; tx.recentBlockhash = ( await connection.getLatestBlockhash('confirmed') ).blockhash; const signature = await sendAndConfirmTransaction(connection, tx, [payer]); console.log('Risk score verified onchain. Tx:', signature); } ``` *** ## Step 4: Verify Onchain (Rust) The Solana program reconstructs the same feed definition, hashes it, and compares against the oracle quote to ensure data integrity. ```rust Anchor theme={null} #![allow(deprecated)] #![allow(unexpected_cfgs)] use anchor_lang::prelude::*; use anchor_lang::solana_program::hash::hash; use prost::Message; use switchboard_on_demand::{default_queue, QueueAccountData}; use switchboard_on_demand::{Instructions, QuoteVerifier, SlotHashes}; use switchboard_protos::oracle_job::oracle_job::http_task::Header; use switchboard_protos::oracle_job::oracle_job::multiply_task; use switchboard_protos::oracle_job::oracle_job::task; use switchboard_protos::oracle_job::oracle_job::{ BoundTask, HttpTask, JsonParseTask, MultiplyTask, Task, }; use switchboard_protos::{OracleFeed, OracleJob}; declare_id!("YOUR_PROGRAM_ID"); #[program] pub mod risk_oracle { use super::*; pub fn verify_risk_score_feed(ctx: Context) -> Result<()> { let mut verifier = QuoteVerifier::new(); let slot = Clock::get()?.slot; // Configure the verifier with required sysvars verifier .queue(ctx.accounts.queue.as_ref()) .slothash_sysvar(ctx.accounts.slothashes.as_ref()) .ix_sysvar(ctx.accounts.instructions.as_ref()) .clock_slot(slot); // Verify the Ed25519 signature at instruction index 0 let quote = verifier.verify_instruction_at(0).unwrap(); let quote_slot = quote.slot(); // Ensure the quote is fresh (within 50 slots ≈ 20 seconds) if slot.saturating_sub(quote_slot) > 50 { return Err(ErrorCode::StaleQuote.into()); } // Extract the verified feed data let feeds = quote.feeds(); require!(!feeds.is_empty(), ErrorCode::NoOracleFeeds); let feed = &feeds[0]; // Reconstruct the feed ID onchain and compare let expected_feed_id = create_risk_score_feed_id( &ctx.accounts.query_account.key() )?; require!( *feed.feed_id() == expected_feed_id, ErrorCode::FeedMismatch ); // The risk score is now verified - use it in your program logic msg!( "Verified risk score feed! Value: {}", feed.value().to_string().as_str() ); Ok(()) } } // Account structure for the verify_risk_score_feed instruction #[derive(Accounts)] pub struct VerifyRiskScoreFeed<'info> { #[account(address = default_queue())] pub queue: AccountLoader<'info, QueueAccountData>, pub clock: Sysvar<'info, Clock>, pub slothashes: Sysvar<'info, SlotHashes>, pub instructions: Sysvar<'info, Instructions>, /// CHECK: Only the pubkey is needed to reconstruct the feed ID pub query_account: UncheckedAccount<'info>, } #[error_code] pub enum ErrorCode { #[msg("No oracle feeds available")] NoOracleFeeds, #[msg("Feed hash mismatch - oracle feed does not match expected configuration")] FeedMismatch, #[msg("Stale quote - the quote is too old")] StaleQuote, #[msg("Risk score exceeds allowed threshold")] RiskTooHigh, } // Helper function to reconstruct the feed ID onchain fn create_risk_score_feed_id(query_pubkey: &Pubkey) -> Result<[u8; 32]> { let addr = bs58::encode(query_pubkey).into_string(); let url = format!( "https://api.range.org/v1/risk/address?address={}&network=solana", addr ); let feed = OracleFeed { name: Some("Risk Score".to_string()), jobs: vec![OracleJob { tasks: vec![ Task { task: Some(task::Task::HttpTask(HttpTask { url: Some(url), headers: [ Header { key: Some("accept".to_string()), value: Some("application/json".to_string()), }, Header { key: Some("X-API-KEY".to_string()), value: Some("${RANGE_API_KEY}".to_string()), }, ] .into(), ..Default::default() })), }, Task { task: Some(task::Task::JsonParseTask(JsonParseTask { path: Some("$.riskScore".to_string()), ..Default::default() })), }, Task { task: Some(task::Task::MultiplyTask(MultiplyTask { multiple: Some(multiply_task::Multiple::Scalar(10.0)), })), }, Task { task: Some(task::Task::BoundTask(BoundTask { lower_bound_value: Some("0".into()), upper_bound_value: Some("100".into()), on_exceeds_lower_bound_value: Some("0".into()), on_exceeds_upper_bound_value: Some("100".into()), ..Default::default() })), }, ], weight: None, }], min_job_responses: Some(1), min_oracle_samples: Some(1), max_job_range_pct: Some(100), }; // Hash the protobuf-encoded feed to get the deterministic feed ID let bytes = OracleFeed::encode_length_delimited_to_vec(&feed); Ok(hash(&bytes).to_bytes()) } ``` ```rust Pinocchio theme={null} #![no_std] #![allow(unexpected_cfgs)] extern crate alloc; use alloc::{format, string::ToString, vec}; use pinocchio::{ account_info::AccountInfo, program_error::ProgramError, pubkey::Pubkey, ProgramResult, }; use pinocchio_log::log; use prost::Message; use sha2::{Digest, Sha256}; use switchboard_on_demand::{get_slot, QuoteVerifier}; use switchboard_protos::{ oracle_job::oracle_job::{ http_task::Header, multiply_task, task, BoundTask, HttpTask, JsonParseTask, MultiplyTask, Task, }, OracleFeed, OracleJob, }; #[inline(never)] fn process_instruction( _program_id: &Pubkey, accounts: &[AccountInfo], _instruction_data: &[u8], ) -> ProgramResult { let [queue, clock_sysvar, slothashes_sysvar, instructions_sysvar, query_account]: &[AccountInfo; 5] = accounts .try_into() .map_err(|_| ProgramError::NotEnoughAccountKeys)?; // Build the feed proto on-chain (must match client exactly) let addr_b58 = bs58::encode(query_account.key()).into_string(); let url = format!( "https://api.range.org/v1/risk/address?address={}&network=solana", addr_b58 ); let feed = OracleFeed { name: Some("Risk Score".to_string()), jobs: vec![OracleJob { tasks: vec![ Task { task: Some(task::Task::HttpTask(HttpTask { url: Some(url), headers: [ Header { key: Some("accept".to_string()), value: Some("application/json".to_string()) }, Header { key: Some("X-API-KEY".to_string()), value: Some("${RANGE_API_KEY}".to_string()) }, ].into(), ..Default::default() }))}, Task { task: Some(task::Task::JsonParseTask(JsonParseTask { path: Some("$.riskScore".to_string()), ..Default::default() }))}, Task { task: Some(task::Task::MultiplyTask(MultiplyTask { multiple: Some(multiply_task::Multiple::Scalar(10.0)), }))}, Task { task: Some(task::Task::BoundTask(BoundTask { lower_bound_value: Some("0".into()), upper_bound_value: Some("100".into()), on_exceeds_lower_bound_value: Some("0".into()), on_exceeds_upper_bound_value: Some("100".into()), ..Default::default() }))}, ], weight: None, }], min_job_responses: Some(1), min_oracle_samples: Some(1), max_job_range_pct: Some(100), }; // Hash the protobuf bytes to derive feed ID let bytes = OracleFeed::encode_length_delimited_to_vec(&feed); let mut hasher = Sha256::new(); hasher.update(&bytes); let derived_feed_hash: [u8; 32] = hasher.finalize().into(); // Verify the quote let slot = get_slot(clock_sysvar); let mut quote_verifier = QuoteVerifier::new(); let quote_data = quote_verifier .slothash_sysvar(slothashes_sysvar) .ix_sysvar(instructions_sysvar) .clock_slot(slot) .queue(queue) .max_age(30) .verify_instruction_at(0) .map_err(|_| ProgramError::Custom(0))?; // Check freshness if slot.saturating_sub(quote_data.slot()) > 50 { return Err(ProgramError::Custom(1)); // StaleQuote } // Match feed ID and log the verified risk score for feed_info in quote_data.feeds().iter() { if feed_info.feed_id() == &derived_feed_hash { log!("Risk Score {}", feed_info.value().to_string().as_str()); return Ok(()); } } Err(ProgramError::Custom(2)) // FeedIdMismatch } ``` ## Step 5: Run the Example Range provides a complete working example with both Anchor and Pinocchio implementations. ```bash theme={null} # Clone the example repository git clone https://github.com/rangesecurity/oracle-example.git cd oracle-example/anchor/client # Install dependencies npm install # Set your Range API key export RANGE_API_KEY="YOUR_API_KEY" # Set the RPC URL (defaults to http://127.0.0.1:8899 if not set) export RPC_URL="https://api.devnet.solana.com" # Set the path to your devnet wallet keypair (defaults to ../keypair.json) export DEV_WALLET_KEYPAIR_PATH="/path/to/your/keypair.json" # Run the test npm test ``` The test requires a funded Solana devnet wallet. If you don't have one, generate a keypair with `solana-keygen new -o keypair.json` and airdrop devnet SOL with `solana airdrop 2 --keypair keypair.json --url devnet`. Expected output: ``` Program log: Verified risk score feed! Value: 100 ``` The repository includes both an [Anchor](https://github.com/rangesecurity/oracle-example/tree/master/anchor) and [Pinocchio](https://github.com/rangesecurity/oracle-example/tree/master/pinocchio) implementation. Both are functionally identical - choose whichever framework your project uses. *** ## Customizing for Your Program ### Adjusting the Risk Threshold Modify the onchain program to enforce your risk policy: ```rust theme={null} let risk_score = feed.value(); // 0-100 scale (original 0-10 × 10) // Block wallets with risk score > 7 (70 on the 0-100 scale) if risk_score > 70.into() { return Err(ErrorCode::RiskTooHigh.into()); } ``` ### Checking Different Networks Update the URL in both the TypeScript OracleJob and the Rust feed reconstruction to query different networks: ```rust theme={null} let url = format!( "https://api.range.org/v1/risk/address?address={}&network={}", addr, network ); ``` The feed definition must be **identical** in both the client-side OracleJob and the onchain feed reconstruction. Any difference - even in field ordering or default values - will change the hash and cause verification to fail. ### Production Considerations * **Increase `numSignatures`** - Use more than 1 signature for production to increase consensus requirements. * **Tune staleness** - The example uses 50 slots (\~20 seconds). Tighten this for time-sensitive operations. * **Use mainnet queue** - Switch from `getDefaultDevnetQueue` to `getDefaultQueue` for production deployments. * **Handle errors gracefully** - Decide whether a failed risk check should block the transaction or allow it with a warning flag. *** ## Cross-Chain Support The Onchain Risk Verifier is currently implemented for Solana. The same architecture could be adapted for EVM (Solidity) and CosmWasm smart contracts, the core pattern of oracle-fetched signed data with onchain signature and feed integrity verification is framework-agnostic. If you're interested in an EVM or CosmWasm implementation, [get in touch](https://www.range.org/get-in-touch). *** ## What's Next Full endpoint reference for the Risk API endpoint used by the oracle job. Switchboard On-Demand Oracle documentation and SDK reference. Complete working implementation with Anchor and Pinocchio frameworks. For off-chain risk screening in wallets and dApps. # Payment Scam Prevention Source: https://docs.range.org/risk-api/guides/payment-scam-prevention Use Payment Risk Assessment to detect and prevent common crypto payment scams including address poisoning, new wallet fraud, and social engineering. Crypto payment scams cost users billions annually. Address poisoning, fake recipient wallets, and social engineering attacks all exploit a fundamental gap: users can't easily verify whether a payment is safe before sending. The [Payment Risk Assessment](/risk-api/risk/get-payment-risk-assessment) endpoint closes that gap by analyzing 8 risk dimensions in real time - before funds leave the wallet. This guide covers the three risk factors most relevant to scam prevention and how to build them into your payment flow. **Prerequisites:** You need a [Risk API key](/introduction/getting-started) and familiarity with the [Payment Risk Assessment](/risk-api/risk/get-payment-risk-assessment) endpoint. *** ## The Three Scam-Relevant Risk Factors Payment Risk Assessment evaluates 8 independent risk dimensions. Three are directly designed to catch common payment scams: | Risk Factor | What It Catches | Risk Level | | - | - | :-: | | **Address Poisoning Detection** | Scammer creates a lookalike address that matches the first/last 4 characters of a real contact | HIGH | | **New Wallet Detection** | Recipient is a freshly created wallet with no history - common in advance-fee fraud and impersonation scams | MEDIUM-HIGH | | **Interaction History** | Sender has never transacted with this recipient before - flags unfamiliar counterparties | HIGH | Together, these factors catch the majority of common crypto scam patterns without false-positiving on legitimate transactions to known contacts. *** ## How Address Poisoning Works Address poisoning is one of the most common crypto scams. Here's the attack: 1. The scammer monitors the victim's transaction history 2. They generate an address that matches the **first and last 4 characters** of a real recipient the victim has sent to before 3. They send a small "dust" transaction from the poisoned address to the victim 4. The victim later copies the address from their transaction history, unknowingly selecting the scammer's lookalike address 5. Funds are sent to the scammer instead of the intended recipient ### How Payment Risk Assessment Detects It The `address_poisoning_attack` factor compares the recipient address against known poison address patterns associated with the sender. If the recipient's prefix and suffix match a poisoning pattern, it returns **HIGH** risk. ```json theme={null} { "factor": "address_poisoning_attack", "risk_level": "high", "description": "Potential address poisoning attack detected - recipient matches poison address pattern" } ``` This check happens automatically - no configuration needed. Just pass the sender and recipient addresses to the Payment Risk endpoint. *** ## How New Wallet Scams Work Many scams involve directing victims to send funds to newly created wallets: * **Impersonation scams** - "Send funds to this new wallet for verification" * **Fake investment schemes** - Scammer provides a brand-new deposit address * **Romance scams** - Victim is given a fresh wallet address to "help" with * **Phishing** - Fake dApp or site provides a newly generated receiving address Legitimate recipients (exchanges, protocols, contacts) almost always have established wallet history. A brand-new wallet with zero transactions is a strong signal that something is wrong. ### How Payment Risk Assessment Detects It The `new_wallet_recipient` factor analyzes the recipient's onchain transaction history: | Recipient History | Risk Level | Factor | | - | :-: | - | | 0 transactions | **HIGH** | `new_wallet_recipient` | | \<3 transactions OR \<7 days old | **MEDIUM** | `new_wallet_recipient` | | ≥3 transactions AND >7 days old | **LOW** | `established_wallet_recipient` | ```json theme={null} { "factor": "new_wallet_recipient", "risk_level": "high", "description": "Recipient is a completely new wallet with no transaction history" } ``` *** ## How First-Interaction Risk Works Even without address poisoning or a new wallet, sending to someone you've never transacted with before carries inherent risk. Scams overwhelmingly involve first-time interactions - the victim has no prior relationship with the scammer's address. ### How Payment Risk Assessment Detects It The `first_interaction` factor examines the transaction history between sender and recipient across both same-network and cross-chain indices: | Prior Interactions | Risk Level | Factor | | - | :-: | - | | 0 (first time) | **MEDIUM** | `first_interaction` | | 1-2 interactions | **MEDIUM** | `limited_interaction_history` | | 3+ interactions | **LOW** | `established_interaction_history` | ```json theme={null} { "factor": "first_interaction", "risk_level": "medium", "description": "First ever interaction between these addresses" } ``` A first interaction is not inherently malicious - everyone has a first transaction. The value is in combining it with other factors. A first interaction with an established wallet is normal. A first interaction with a brand-new wallet that matches a poisoning pattern is almost certainly a scam. *** ## Building a Scam Prevention Flow ### Step 1: Check Payment Risk Before Sending ```javascript theme={null} // Your Range API key. Read it from the environment; never hardcode it. const API_KEY = process.env.RANGE_API_KEY; async function checkPaymentForScams(sender, recipient, amount, network) { const params = new URLSearchParams({ sender_address: sender, recipient_address: recipient, amount: amount.toString(), sender_network: network, recipient_network: network, }); const response = await fetch( `https://api.range.org/v1/risk/payment?${params}`, { headers: { Authorization: `Bearer ${API_KEY}` } } ); return response.json(); } ``` ### Step 2: Extract Scam-Relevant Factors ```javascript theme={null} function analyzeScamRisk(paymentRisk) { const factors = paymentRisk.risk_factors || []; const highRisk = (...names) => factors.find((f) => names.includes(f.factor) && f.risk_level === "high"); const scamIndicators = { addressPoisoning: factors.find((f) => f.factor === "address_poisoning_attack"), newWallet: factors.find((f) => f.factor === "new_wallet_recipient"), firstInteraction: factors.find((f) => f.factor === "first_interaction"), limitedHistory: factors.find((f) => f.factor === "limited_interaction_history"), // The Attributed Address Check names this factor // `malicious_address_recipient`; live responses also return // `malicious_attributed_recipient` for the same signal, so match both. maliciousRecipient: highRisk( "malicious_address_recipient", "malicious_attributed_recipient" ), maliciousConnection: highRisk("malicious_connection_recipient_high"), }; // Branches run strongest signal first, so a weaker one never masks a // stronger one. Interaction history is always checked last. // A recipient flagged as a known malicious address is never safe to pay if (scamIndicators.maliciousRecipient) { return { level: "critical", warning: "Known malicious recipient", description: "This address is flagged as malicious in Range's attribution data. " + "Funds sent to it are very unlikely to reach a legitimate counterparty.", recommendation: "Do NOT send to this address.", }; } // Address poisoning is always a critical warning if (scamIndicators.addressPoisoning) { return { level: "critical", warning: "Address poisoning detected", description: "This address closely matches another address you've transacted with. " + "Scammers create lookalike addresses to trick you into sending funds to them.", recommendation: "Do NOT send to this address. Verify the full address character by character.", }; } // A recipient within 2 hops of known malicious addresses if (scamIndicators.maliciousConnection) { return { level: "high", warning: "Recipient is closely connected to malicious addresses", description: "This recipient is within 2 hops of addresses known to be malicious. " + "That pattern is common for compromised and scammer-controlled accounts.", recommendation: "Verify the recipient through a trusted channel before sending.", }; } // New wallet + first interaction = strong scam signal if ( scamIndicators.newWallet?.risk_level === "high" && scamIndicators.firstInteraction ) { return { level: "high", warning: "Possible scam - new wallet with no prior interaction", description: "This recipient has no transaction history and you've never sent to them before. " + "This pattern is common in impersonation, phishing, and advance-fee scams.", recommendation: "Verify the recipient through a trusted channel before sending.", }; } // First interaction alone is a caution if (scamIndicators.firstInteraction) { return { level: "medium", warning: "First-time recipient", description: "You've never sent to this address before. Double-check the address is correct.", recommendation: "Consider sending a small test amount first.", }; } // One or two previous payments is still thin history if (scamIndicators.limitedHistory) { return { level: "medium", warning: "Limited history with this recipient", description: "You have sent to this address only once or twice before. " + "Confirm it still belongs to the person you expect.", recommendation: "Consider sending a small test amount first.", }; } return { level: "low", warning: null }; } ``` ### Step 3: Display Warnings to Users ```javascript theme={null} async function protectedSend(sender, recipient, amount, network) { const paymentRisk = await checkPaymentForScams( sender, recipient, amount, network ); const scamAnalysis = analyzeScamRisk(paymentRisk); switch (scamAnalysis.level) { case "critical": // Block and show red warning - do not allow without explicit override return showCriticalWarning(scamAnalysis); case "high": // Show prominent warning, require confirmation const confirmed = await showHighRiskWarning(scamAnalysis); if (!confirmed) return { status: "cancelled" }; break; case "medium": // Show informational notice await showCautionNotice(scamAnalysis); break; } // Proceed with transaction return await executeTransaction(sender, recipient, amount); } ``` *** ## Scam Pattern Reference Rows are listed in the order `analyzeScamRisk()` checks them. The first match wins, so a stronger signal is never masked by a weaker one. | Scam Type | Triggered Factors | Combined Risk | | - | - | :-: | | **Known malicious recipient** | `malicious_address_recipient` or `malicious_attributed_recipient` at HIGH | Critical | | **Address poisoning** | `address_poisoning_attack` | Critical | | **Compromised account** | `malicious_connection_recipient_high` at HIGH | High | | **Impersonation / phishing** | `new_wallet_recipient` at HIGH + `first_interaction` | High | | **Advance-fee fraud** | `new_wallet_recipient` at HIGH + `first_interaction` | High | | **Fake investment** | `new_wallet_recipient` at HIGH + `first_interaction` | High | | **Typo / wrong address** | `first_interaction` (no poisoning) | Medium | | **Legitimate new contact** | `first_interaction` + `established_wallet_recipient` | Medium | | **Thin history** | `limited_interaction_history` | Medium | | **Regular payment** | `established_interaction_history` + `established_wallet_recipient` | Low | *** ## Integration Recommendations ### For Wallets * Run Payment Risk Assessment on every send before the user signs * Display scam warnings inline - not as a separate step users can skip * For address poisoning: show a full-screen blocker, not a dismissable toast * Cache results briefly (30 seconds) to avoid re-querying if the user adjusts the amount ### For Payment Processors * Check both directions: screen the sender when receiving, screen the recipient when sending * Log all risk assessments for dispute resolution and fraud investigation * Set automated hold policies for first-interaction payments above a threshold amount ### For Exchanges * Run Payment Risk Assessment on withdrawal requests before processing * Flag `address_poisoning_attack` results for manual review - these are almost never false positives * Use `first_interaction` + `new_wallet_recipient` to trigger additional verification (email confirmation, 2FA) on withdrawals to new addresses *** ## What's Next Full endpoint reference with all 8 risk dimensions explained. Add address screening and transaction simulation to your wallet. # Privacy Protocol Screening Source: https://docs.range.org/risk-api/guides/privacy-protocol-screening Screen wallets before deposits to prevent tainted funds from entering your privacy protocol on Solana. Privacy protocols on Solana - mixers, privacy pools, confidential transfer programs - face a unique challenge: they need to prevent sanctioned or stolen funds from entering the protocol while preserving user privacy for legitimate users. If tainted funds flow through your protocol, it taints the entire pool and exposes your project to regulatory risk. Range's [Address Risk Score](/risk-api/risk/get-address-risk-score) provides a straightforward solution: screen the depositor's wallet before accepting funds. Block high-risk wallets at the door - before they can contaminate the pool. **Prerequisites:** You need a [Risk API key](/introduction/getting-started) and familiarity with the [Address Risk Score](/risk-api/risk/get-address-risk-score) endpoint. For onchain enforcement, see the [Onchain Risk Verifier](/risk-api/guides/onchain-risk-verifier) guide. *** ## Why Screen Deposits? | Without screening | With screening | | - | - | | Stolen funds enter your privacy pool | Stolen funds are rejected before deposit | | OFAC-sanctioned addresses mix freely | Sanctioned addresses are blocked at the door | | Your protocol becomes a laundering vector | Your protocol stays clean for legitimate users | | Regulators target your protocol | Demonstrable compliance controls | | Honest users' funds are tainted by association | Pool integrity is preserved | Privacy and compliance are not mutually exclusive. Screening depositors (not tracking what happens inside the pool) lets you maintain privacy guarantees for legitimate users while blocking bad actors. *** ## Architecture ``` User wants to deposit │ ▼ ┌──────────────────────────┐ │ Screen depositor wallet │ │ (Address Risk Score) │ │ │ │ riskScore 1-10 │ │ Includes sanctions + │ │ ML + proximity analysis │ └──────────────────────────┘ │ ├── Score ≥ 7 ──────► REJECT deposit │ Show reason │ ├── Score 4-6 ──────► FLAG for review │ Optional: require │ additional verification │ └── Score 1-3 ──────► ALLOW deposit Proceed normally ``` Address Risk Score already includes sanctions and blacklist screening. You do not need a separate sanctions check - OFAC-flagged and stablecoin-blacklisted addresses are factored into the risk score. *** ## Step 1: Screen the Depositor Before accepting a deposit, check the wallet's risk score. This single API call covers malicious proximity, ML-based behavioral analysis, sanctions, and blacklist screening. ```bash theme={null} curl -G https://api.range.org/v1/risk/address \ --data-urlencode "address=DEPOSITOR_ADDRESS" \ --data-urlencode "network=solana" \ -H "Authorization: Bearer YOUR_API_KEY" ``` ```typescript theme={null} async function screenDepositor(address: string) { const params = new URLSearchParams({ address, network: 'solana', }); const response = await fetch( `https://api.range.org/v1/risk/address?${params}`, { headers: { Authorization: `Bearer ${API_KEY}` } }, ); return response.json(); } ``` ### Example Response - Flagged Wallet ```json theme={null} { "riskScore": 9, "riskLevel": "Extremely high risk", "numHops": 1, "maliciousAddressesFound": [ { "address": "SuspiciousAddr...", "distance": 1, "name_tag": "Exploit Funds", "entity": null, "category": "hack_funds" } ], "reasoning": "Address is 1 hop from known exploit funds.", "attribution": null } ``` This wallet is 1 hop from known hack funds - it should be rejected. *** ## Step 2: Make a Deposit Decision ```typescript theme={null} interface RiskData { riskScore: number; riskLevel: string; reasoning: string; attribution: { name_tag: string; entity: string } | null; } interface DepositDecision { decision: 'allow' | 'reject' | 'flag'; reason: string; } function evaluateDeposit(riskData: RiskData): DepositDecision { const { riskScore, reasoning, attribution } = riskData; // Known system addresses and verified entities are always safe if (attribution) { return { decision: 'allow', reason: `Verified entity: ${attribution.name_tag} (${attribution.entity})`, }; } // High risk - reject if (riskScore >= 7) { return { decision: 'reject', reason: `Risk score ${riskScore}/10: ${reasoning}`, }; } // Medium risk - flag for review or require additional verification if (riskScore >= 4) { return { decision: 'flag', reason: `Elevated risk (${riskScore}/10): ${reasoning}`, }; } // Low risk - allow return { decision: 'allow', reason: 'Address screening passed', }; } ``` *** ## Step 3: Integrate into Your Deposit Flow ### Off-Chain (Backend / Frontend) Screen wallets in your dApp frontend or backend before constructing the deposit transaction: ```typescript theme={null} async function handleDeposit(depositorAddress: string, amount: number) { // Screen the wallet const riskData = await screenDepositor(depositorAddress); const evaluation = evaluateDeposit(riskData); if (evaluation.decision === 'reject') { return { status: 'rejected', message: 'This wallet has been flagged for connections to malicious activity. ' + 'Deposit not permitted.', }; } if (evaluation.decision === 'flag') { // Optional: require additional verification for medium-risk wallets const verified = await requestAdditionalVerification(depositorAddress); if (!verified) { return { status: 'rejected', message: 'Additional verification required.', }; } } // Proceed with deposit return await executeDeposit(depositorAddress, amount); } ``` ### Onchain (Solana Program) For protocol-level enforcement that can't be bypassed by calling the program directly, use the [Onchain Risk Verifier](/risk-api/guides/onchain-risk-verifier). This verifies risk scores inside your Solana program using Switchboard oracles: ```rust theme={null} // In your deposit instruction handler: let risk_score = verified_feed.value(); // 0-100 scale (original 0-10 × 10) // Reject deposits from high-risk wallets if risk_score >= 70 { return Err(ErrorCode::HighRiskDepositor.into()); } // Proceed with deposit logic ``` Onchain enforcement is stronger than off-chain screening alone. Users can bypass your frontend, but they can't bypass your program's instruction logic. For maximum protection, use both: off-chain screening for UX (show the user why they're blocked) and onchain verification as the enforcement layer. **Alternative: Signed message attestation.** Instead of using Switchboard oracles, you can implement a lighter-weight pattern where your backend signs an attestation message containing the screened wallet address and a timestamp. The Solana program then uses Ed25519 signature verification (via the Ed25519 precompile) and instruction introspection to confirm: (1) the message was signed by your trusted attestation key, (2) the depositor matches the approved address in the message, and (3) the timestamp is fresh. This approach trades the decentralized oracle model for a simpler trusted-backend pattern. *** ## Choosing Your Risk Threshold The right threshold depends on your protocol's risk tolerance and regulatory posture: | Threshold | Rejects | Trade-off | | :-: | - | - | | **Score ≥ 8** | Only directly malicious or 1-hop addresses | Permissive - blocks clear threats, allows most users | | **Score ≥ 7** | Addresses within 2 hops of malicious actors | Balanced - recommended starting point | | **Score ≥ 6** | Addresses within 2 hops (with multiple malicious connections) | Strict - fewer false negatives, more false positives | | **Score ≥ 4** | Addresses within 3 hops | Very strict - suitable for regulated environments | Setting the threshold too low (e.g., ≥ 3) will reject a significant number of legitimate users. Many clean addresses are naturally within 4-5 hops of flagged addresses through shared exchange or program interactions. Start with ≥ 7 and adjust based on your data. *** ## Handling Edge Cases ### What If the Risk Check Fails? Network errors or API timeouts shouldn't block legitimate deposits indefinitely. Implement a fallback policy: ```typescript theme={null} async function screenWithFallback(address: string) { try { const result = await Promise.race([ screenDepositor(address), new Promise((_, reject) => setTimeout(() => reject(new Error('timeout')), 5000), ), ]); return evaluateDeposit(result); } catch (error) { // Fallback: allow with logging for manual review console.warn(`Risk check failed for ${address}: ${error}`); return { decision: 'allow', reason: 'Risk check unavailable - allowed with manual review flag', requiresReview: true, }; } } ``` ### Known System Addresses Some addresses that interact with your protocol will be system programs, token programs, or exchange hot wallets. These will have an `attribution` field in the response - use it to fast-path known entities: ```typescript theme={null} if (riskData.attribution) { // Verified non-malicious entity - skip further checks console.log(`Known entity: ${riskData.attribution.name_tag}`); return { decision: 'allow' }; } ``` ### Rate Limits If you're processing high deposit volume, see [Rate Limits & Plans](/risk-api/product-info/rate-limits) for scaling options. For onchain enforcement via Switchboard oracles, rate limits apply to the oracle quote requests, not the onchain verification. *** ## Compliance Considerations Screening deposits demonstrates that your protocol has taken reasonable steps to prevent misuse. Document your screening policy and keep records: * **Policy document** - Define your risk threshold and what happens when a deposit is rejected * **Audit log** - Store the risk score, reasoning, and decision for each screened deposit * **Threshold rationale** - Document why you chose your threshold and any adjustments over time * **False positive handling** - Have a process for users to contest rejections ```typescript theme={null} async function logScreeningResult( depositor: string, riskData: RiskData, decision: DepositDecision, ) { await complianceDB.insert({ timestamp: new Date().toISOString(), depositor_address: depositor, risk_score: riskData.riskScore, risk_level: riskData.riskLevel, reasoning: riskData.reasoning, decision: decision.decision, decision_reason: decision.reason, }); } ``` *** ## What's Next Full endpoint reference with scoring logic and examples. Enforce risk checks directly in your Solana program. Build a full compliance screening workflow. See which networks are supported for address risk scoring. # SigVerify Onchain Attestation Source: https://docs.range.org/risk-api/guides/sigverify-onchain-attestation Verify wallet risk directly inside Solana programs using backend-signed Ed25519 attestations, no oracles required. This guide covers how to integrate Range's SigVerify pattern into a Solana program. SigVerify is a lightweight alternative to the [Onchain Risk Verifier](/risk-api/guides/onchain-risk-verifier), instead of relying on oracle networks, your backend calls the Range API, signs an attestation, and your onchain program verifies the signature directly using Ed25519. **Prerequisites:** You need a [Risk API key](/introduction/getting-started), a Solana development environment (Anchor), and a backend service that holds an Ed25519 keypair. *** ## How It Works Your backend screens the user's wallet via the Range API, then signs a time-stamped attestation message. The user submits this attestation in a Solana transaction, and the onchain program verifies the signature, signer identity, and freshness, all without any oracle dependency. ```mermaid theme={null} sequenceDiagram participant U as User participant B as Backend participant R as Range API participant S as Solana Program U->>B: 1. Request access B->>R: 2. Screen wallet
GET /v1/risk/address R-->>B: Risk score + level B->>B: 3. Check risk threshold
Generate riskCallId B->>B: 4. Sign attestation
"{timestamp}_{pubkey}_{riskCallId}" B-->>U: Return signature + message U->>S: 5. Submit transaction
with signature + message S->>S: 6. Verify Ed25519 signature
Match signer to message pubkey
Check timestamp freshness
Grant access ``` ### How It Compares to the Oracle Approach | | SigVerify | [Onchain Risk Verifier](/risk-api/guides/onchain-risk-verifier) | | - | - | - | | **Trust model** | Trust your backend signer | Trust Switchboard TEE oracles | | **Dependencies** | None (Ed25519 only) | Switchboard SDK + oracle network | | **Latency** | Single API call + sign | Oracle request + quote fetch | | **Cost** | \~40k CUs | \~20k Cus | | **Best for** | Apps with an existing backend | Fully decentralized protocols | ### Security Model * **Ed25519 signature verification**: The onchain program verifies the backend's signature using Ed25519. This example uses the [`brine-ed25519`](https://crates.io/crates/brine-ed25519) crate for in-program verification. Alternatively, you can use Solana's native [Ed25519 SigVerify precompile](https://solana.com/docs/core/programs#ed25519-program) , this requires an additional instruction and onchain introspection to validate the signature (similar to what Switchboard does under the hood), but avoids depending on a third-party crate. Either way, forged attestations are rejected. * **Signer binding**: The message embeds the user's pubkey. The program verifies it matches the transaction signer, preventing replay attacks. * **Freshness check**: Attestations expire after 60 seconds (configurable). The program compares the message timestamp against the onchain clock. * **Audit trail**: Each attestation includes a unique `riskCallId` that links the onchain verification to the original API call. * **API keys stay off-chain**: The Range API key is only used by your backend, it never appears in transaction data. *** ## Use Cases | Scenario | How SigVerify Helps | | - | - | | **Privacy protocols** | Screen deposits to prevent illicit funds from entering the pool | | **Token launches** | Gate participation to wallets below a risk threshold | | **Airdrops** | Screen recipients before distributing tokens | | **DAO treasuries** | Require risk attestation before withdrawals | | **NFT mints** | Block mints from sanctioned or malicious wallets | | **DeFi protocols** | Require fresh risk screening before deposits | | **Payment rails** | Verify sender/recipient risk before processing transfers | *** ## Step 1: Screen the Wallet (TypeScript) Your backend calls the Range API to get the wallet's risk score and generates a unique `riskCallId` for audit tracking. ```typescript theme={null} import { randomBytes } from 'crypto'; interface RiskScreenResult { score: number; level: string; reasoning: string; riskCallId: string; } async function screenRecipient( userAddress: string, apiKey: string, network: string = 'solana', ): Promise { const params = new URLSearchParams({ address: userAddress, network }); const response = await fetch( `https://api.range.org/v1/risk/address?${params}`, { headers: { Authorization: `Bearer ${apiKey}` } }, ); if (!response.ok) { throw new Error( `Range API error: ${response.status} ${response.statusText}`, ); } const data = await response.json(); // Unique identifier that ties the onchain attestation // back to this specific API call for compliance tracking const riskCallId = randomBytes(16).toString('hex'); return { score: data.riskScore, level: data.riskLevel, reasoning: data.reasoning, riskCallId, }; } ``` The `riskCallId` is generated client-side as a random 16-byte hex string. This ties the onchain attestation to a specific screening event for auditability. *** ## Step 2: Sign the Attestation (TypeScript) After screening, your backend signs a message that binds the risk result to the user's wallet and a specific point in time. ```typescript theme={null} import nacl from 'tweetnacl'; function createSignedMessage( timestamp: number, userAddress: string, riskCallId: string, backendSecretKey: Uint8Array, ): { signature: Uint8Array; message: Uint8Array } { // Message format: "{timestamp}_{pubkey}_{riskCallId}" const messageStr = `${timestamp}_${userAddress}_${riskCallId}`; const message = new TextEncoder().encode(messageStr); const signature = nacl.sign.detached(message, backendSecretKey); return { signature: new Uint8Array(signature), message: new Uint8Array(message), }; } ``` The message format is `{timestamp}_{pubkey}_{riskCallId}` where: * **timestamp**: Unix timestamp in seconds (used for freshness check onchain) * **pubkey**: The user's Solana wallet address (base58) * **riskCallId**: Unique identifier linking to the API screening result The backend secret key must be kept secure. If compromised, an attacker could forge attestations. Rotate the backend keypair and update the onchain program's `BACKEND_PUBKEY` constant if a key is ever leaked. *** ## Step 3: Build and Send the Transaction (TypeScript) The user submits the backend's attestation in a Solana transaction. The SDK's `buildVerifyRiskInstruction` constructs the instruction with the Anchor discriminator, signature, and message, see the [full implementation in the example repo](https://github.com/rangesecurity/sigverify-example/blob/master/sigverify/app/sdk.ts). ```typescript theme={null} async function verifyRiskOnchain( rpc: ReturnType, rpcSubscriptions: ReturnType, userSigner: TransactionSigner, backendSecretKey: Uint8Array, apiKey: string, ) { // 1. Screen the wallet const riskResult = await screenRecipient(userSigner.address, apiKey); console.log(`Risk score: ${riskResult.score}, Level: ${riskResult.level}`); if (riskResult.score >= 10) { throw new Error('Risk score too high, blocking access.'); } // 2. Backend signs the attestation const timestamp = Math.floor(Date.now() / 1000); const { signature, message } = createSignedMessage( timestamp, userSigner.address, riskResult.riskCallId, backendSecretKey, ); // 3. Build the instruction const instruction = buildVerifyRiskInstruction( userSigner, signature, message, ); // 4. Build, sign, and send the transaction const { value: latestBlockhash } = await rpc.getLatestBlockhash().send(); const transactionMessage = pipe( createTransactionMessage({ version: 0 }), m => setTransactionMessageFeePayerSigner(userSigner, m), m => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, m), m => appendTransactionMessageInstruction(instruction, m), ); const signedTransaction = await signTransactionMessageWithSigners(transactionMessage); assertIsTransactionWithBlockhashLifetime(signedTransaction); const sendAndConfirm = sendAndConfirmTransactionFactory({ rpc, rpcSubscriptions, }); await sendAndConfirm(signedTransaction, { commitment: 'confirmed' }); const txSignature = getSignatureFromTransaction(signedTransaction); console.log('Risk attestation verified onchain. Tx:', txSignature); } ``` *** ## Step 4: Verify Onchain (Rust) The Anchor program verifies the Ed25519 signature, checks that the message signer matches the transaction signer, and enforces a freshness window. ### Program Entry Point ```rust theme={null} use anchor_lang::prelude::*; declare_id!("YOUR_PROGRAM_ID"); #[program] pub mod sigverify { use super::*; pub fn verify_risk_signature( ctx: Context, args: VerifyRangeArgs, ) -> Result<()> { ctx.accounts.verify(args) } } #[derive(AnchorSerialize, AnchorDeserialize)] pub struct VerifyRangeArgs { pub signature: Vec, // 64-byte Ed25519 detached signature pub message: Vec, // UTF-8: "{timestamp}_{pubkey}_{riskCallId}" } #[derive(Accounts)] pub struct VeriFyRiskAccounts<'info> { #[account(mut)] pub signer: Signer<'info>, } ``` ### Verification Logic ```rust theme={null} impl<'info> VeriFyRiskAccounts<'info> { pub fn verify(&self, args: VerifyRangeArgs) -> Result<()> { let user_key = self.signer.key(); let signature = args.signature; let message = args.message; // 1. Verify the Ed25519 signature against the backend's public key let backend_pubkey = Pubkey::from_str_const(BACKEND_PUBKEY); ScoreVerifier::sig_verify( &backend_pubkey.to_bytes(), &signature, &message, )?; // 2. Parse the message into its components let ExtractedMessage { timestamp, riskscore_pubkey, risk_call_id, } = ScoreVerifier::extract_message(&message)?; // 3. Verify the message pubkey matches the transaction signer require_keys_eq!(user_key, riskscore_pubkey, CustomErrorCode::SignersMismatch); // 4. Verify the attestation is fresh (within MAX_SCORE_LIFETIME seconds) let clock = Clock::get()?; let current_timestamp = clock.unix_timestamp as u64; let time_diff = current_timestamp.saturating_sub(timestamp); require!( time_diff <= MAX_SCORE_LIFETIME, CustomErrorCode::ScoreLifetimeExpired ); msg!("Signature verified successfully for risk call ID: {}", risk_call_id); msg!("User can now be granted access to the protocol."); Ok(()) } } ``` ### Signature Verification and Message Parsing ```rust theme={null} use brine_ed25519::sig_verify; pub struct ExtractedMessage { pub timestamp: u64, pub riskscore_pubkey: Pubkey, pub risk_call_id: String, } pub struct ScoreVerifier; impl ScoreVerifier { /// Verify an Ed25519 signature against the backend's public key pub fn sig_verify(pubkey: &[u8], sig: &[u8], message: &[u8]) -> Result<()> { sig_verify(pubkey, sig, message) .map_err(|_| CustomErrorCode::CouldntVerifySignature)?; Ok(()) } /// Parse the attestation message: "{timestamp}_{pubkey}_{riskCallId}" pub fn extract_message(message_bytes: &[u8]) -> Result { let message_string = String::from_utf8_lossy(message_bytes); let parts: Vec<&str> = message_string.split('_').collect(); require_eq!(parts.len(), 3, CustomErrorCode::WrongMessageSplitLength); let timestamp = parts[0] .parse::() .map_err(|_| CustomErrorCode::TimestampParsingFailed)?; let riskscore_pubkey = Pubkey::from_str(parts[1]) .map_err(|_| CustomErrorCode::PubkeyParsingFailed)?; let risk_call_id = parts[2].to_string(); Ok(ExtractedMessage { timestamp, riskscore_pubkey, risk_call_id, }) } } ``` *** ## Step 5: Run the Example Clone the [example repository](https://github.com/rangesecurity/sigverify-example) and set up your own keys. ```bash theme={null} # Clone the example repository git clone https://github.com/rangesecurity/sigverify-example.git cd sigverify-example/sigverify # Install dependencies yarn install # Generate your own backend and user keypairs solana-keygen new --outfile app/backend_keypair.json --no-bip39-passphrase solana-keygen new --outfile app/user_keypair.json --no-bip39-passphrase ``` Update `BACKEND_PUBKEY` in `programs/sigverify/src/constants.rs` with your backend's public key: ```bash theme={null} solana-keygen pubkey app/backend_keypair.json ``` ```rust theme={null} // programs/sigverify/src/constants.rs pub const BACKEND_PUBKEY: &str = ""; ``` Since you're deploying your own copy of the program, you'll also need to generate a new program keypair and update the program ID: ```bash theme={null} # Generate a new program keypair solana-keygen new --outfile target/deploy/sigverify-keypair.json --no-bip39-passphrase # Get the new program ID solana-keygen pubkey target/deploy/sigverify-keypair.json ``` Update the program ID in both `programs/sigverify/src/lib.rs` (`declare_id!`) and `Anchor.toml` (`[programs.devnet]`) with the output, and update `PROGRAM_ID` in `app/sdk.ts` to match. ```bash theme={null} # Set your Range API key echo "RANGE_API_KEY=YOUR_API_KEY" > .env # Build and deploy anchor build anchor deploy --provider.cluster devnet # Fund the user wallet solana airdrop 2 $(solana-keygen pubkey app/user_keypair.json) --url devnet # Run the example cd app && npx tsx index.ts ``` Expected output: ``` Wallet: Risk score: 0 Level: Very low risk Transaction confirmed: ``` For local development, you can use [Surfpool](https://www.surfpool.xyz/) to run a local Solana validator that auto-deploys your program on file changes. *** ## Customizing for Your Program ### Adjusting the Risk Threshold Modify the screening threshold in your backend to match your risk policy: ```typescript theme={null} // Block wallets with risk score >= 7 (out of 10) if (riskResult.score >= 7) { throw new Error('Risk score too high, blocking access.'); } ``` ### Adjusting the Attestation Lifetime Update the constant in your onchain program: ```rust theme={null} // Allow attestations up to 5 minutes old pub const MAX_SCORE_LIFETIME: u64 = 300; ``` Longer lifetimes reduce the number of API calls but increase the window for stale risk data. For high-value operations, keep the lifetime short (60 seconds or less). ### Adding the Risk Score Onchain You can extend the message format to include the risk score itself, allowing your program to enforce thresholds onchain: ```rust theme={null} // Extended message format: "{timestamp}_{pubkey}_{riskCallId}_{riskScore}" // Then in your verification logic: if risk_score > MAX_ALLOWED_RISK_SCORE { return Err(CustomErrorCode::RiskTooHigh.into()); } ``` ### Production Considerations * **Rotate backend keys**: Have a key rotation strategy. Update `BACKEND_PUBKEY` in your program via an upgrade or a config PDA. * **Use HTTPS everywhere**: Ensure your backend-to-Range-API communication uses TLS. * **Log `riskCallId`**: Store the mapping between `riskCallId` and screening results for compliance audits. *** ## What's Next Full endpoint reference for the Risk API used in the screening step. Oracle-based alternative using Switchboard On-Demand for fully decentralized verification. Complete working implementation with Anchor program and TypeScript SDK. For off-chain risk screening in wallets and dApps. # Token Due Diligence Source: https://docs.range.org/risk-api/guides/token-due-diligence Build a Solana token assessment request, handle validation errors, and request an address risk score for a deployer. This guide shows the token assessment request and its validation errors, followed by a separate address risk request for a deployer. **Prerequisites:** You need a [Risk API key](/introduction/getting-started) and familiarity with the [Token Risk Assessment](/risk-api/risk/get-token-risk-assessment) and [Address Risk Score](/risk-api/risk/get-address-risk-score) endpoints. *** ## When to Use This * **Exchanges** - Before listing a new token for trading * **DEX aggregators** - Before including a token in routing * **Portfolio trackers** - Before displaying a token's price and details * **DeFi protocols** - Before accepting a token as collateral or in liquidity pools * **Wallet providers** - Before showing token metadata to users *** ## Step 1: Assess Token Risk Submit the token's mint address as `asset_address` to `GET /v1/risk/token`. Both `asset_address` and `network` are required; `solana` is the only supported network. ```bash theme={null} curl -X GET "https://api.range.org/v1/risk/token?asset_address=EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v&network=solana" \ -H "Authorization: Bearer YOUR_API_KEY" ``` ```javascript theme={null} async function assessToken(mintAddress) { const params = new URLSearchParams({ asset_address: mintAddress, network: "solana", }); const response = await fetch( `https://api.range.org/v1/risk/token?${params}`, { headers: { Authorization: `Bearer ${API_KEY}` } } ); return response.json(); } ``` ### Unsupported Network A request to `GET /v1/risk/token` with `asset_address=EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v` and `network=ethereum` returns HTTP 400: ```json theme={null} { "message": [ "network must be one of the following values: solana" ], "error": "Bad Request", "statusCode": 400 } ``` *** ## Step 2: Check the Deployer Address If you have identified the token deployer onchain, submit its address to the Address Risk Score endpoint. The request below uses a known high-risk address to demonstrate the request format. ```bash theme={null} curl -G https://api.range.org/v1/risk/address \ --data-urlencode "address=42RLPACwZPx3vYYmxSueqsogfynBDqXK298EDsNoyoHi" \ --data-urlencode "network=solana" \ -H "Authorization: Bearer YOUR_API_KEY" ``` *** ## What's Next Request parameters, documented response contract, and validation errors. Risk scoring methodology. # Transaction Simulation Guide Source: https://docs.range.org/risk-api/guides/transaction-simulation Validate Solana and EVM transactions before broadcasting using the Transaction Simulator for pre-flight checks, debugging, and risk assessment. This guide covers how to use Range's Transaction Simulator to validate transactions before they hit the blockchain. The walkthrough below is Solana-specific (single vs batch simulation, compute units, program errors). For unsigned EVM transactions, including a Safe `execTransaction` before any signatures exist, use [Simulate an EVM Transaction](/risk-api/simulator/simulate-evm-transaction) (`POST /v2/simulate/evm`) on `eth`, `arb1`, `base`, `oeth`, `pol`, `bnb`, and `avax`. A reverted EVM transaction is still HTTP 200 with `status: reverted`. Safe responses add a `safe` block and per-MultiSend `batch` entries when the calldata decodes as a Safe. **Prerequisites:** You need a [Risk API key](/introduction/getting-started) and familiarity with the [Transaction Simulator](/risk-api/simulator/simulate-solana-transaction) endpoint. You should also know how to construct Solana transactions using `@solana/kit` or equivalent. *** ## When to Simulate | Scenario | Why Simulate | | - | - | | **Pre-broadcast validation** | Confirm the transaction will succeed before committing it to the blockchain | | **Cost estimation** | Get accurate compute units and fee breakdown before signing | | **Debugging** | Identify program errors, insufficient balances, or invalid instructions | | **Risk assessment** | Check if any accounts involved in the transaction are malicious or suspicious | | **User confirmation** | Show users exactly what will happen (balance changes, transfers) before they approve | *** ## Step 1: Prepare and Encode the Transaction Build your Solana transaction using any SDK and encode it as base64 or base58. ```typescript @solana/kit theme={null} import { pipe, createTransactionMessage, setTransactionMessageFeePayer, setTransactionMessageLifetimeUsingBlockhash, appendTransactionMessageInstruction, compileTransaction, getBase64EncodedWireTransaction, createSolanaRpc, address, lamports, type TransactionSigner, type Address, } from "@solana/kit"; import { getTransferSolInstruction } from "@solana-program/system"; // No-op signer for building unsigned transactions. // Simulation doesn't require signatures, but Kit instruction builders // expect a TransactionSigner interface for accounts that will sign. function createNoopSigner( pubkey: Address ): TransactionSigner { return { address: pubkey, signTransactions: async (txs) => txs, }; } const SENDER_ADDRESS = address("SenderAddress11111111111111111111111111111"); const RECIPIENT_ADDRESS = address("RecipientAddress111111111111111111111111"); const rpc = createSolanaRpc("https://api.mainnet-beta.solana.com"); const { value: latestBlockhash } = await rpc.getLatestBlockhash().send(); // Wrap sender in a no-op signer for the transfer instruction const senderSigner = createNoopSigner(SENDER_ADDRESS); // Build the transaction message const transactionMessage = pipe( createTransactionMessage({ version: 0 }), (m) => setTransactionMessageFeePayer(SENDER_ADDRESS, m), (m) => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, m), (m) => appendTransactionMessageInstruction( getTransferSolInstruction({ source: senderSigner, destination: RECIPIENT_ADDRESS, amount: lamports(1_000_000_000n), // 1 SOL }), m ) ); // Compile and encode as base64 (no signatures needed for simulation) const compiled = compileTransaction(transactionMessage); const encoded = getBase64EncodedWireTransaction(compiled); ``` ```javascript @solana/web3.js theme={null} import { Connection, Transaction, SystemProgram, PublicKey } from "@solana/web3.js"; const SENDER_PUBKEY = new PublicKey("SenderAddress11111111111111111111111111111"); const RECIPIENT_PUBKEY = new PublicKey("RecipientAddress111111111111111111111111"); const connection = new Connection("https://api.mainnet-beta.solana.com"); // Build the transaction const transaction = new Transaction().add( SystemProgram.transfer({ fromPubkey: SENDER_PUBKEY, toPubkey: RECIPIENT_PUBKEY, lamports: 1_000_000_000, // 1 SOL }) ); // Set required fields transaction.recentBlockhash = ( await connection.getLatestBlockhash() ).blockhash; transaction.feePayer = SENDER_PUBKEY; // Encode as base64 (do NOT sign yet - simulation doesn't require signatures) const encoded = transaction .serialize({ requireAllSignatures: false }) .toString("base64"); ``` You don't need to sign the transaction before simulating. The simulator accepts unsigned transactions, so you can validate before committing any signatures. *** ## Step 2: Submit for Simulation ### Single Transaction ```bash theme={null} curl -X POST "https://api.range.org/v1/simulate/solana/transaction" \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "tx": "ENCODED_TRANSACTION_BASE64", "encoding_type": "base64" }' ``` ```javascript theme={null} async function simulateTransaction(encodedTx) { const response = await fetch( 'https://api.range.org/v1/simulate/solana/transaction', { method: 'POST', headers: { Authorization: `Bearer ${API_KEY}`, 'Content-Type': 'application/json', }, body: JSON.stringify({ tx: encodedTx, encoding_type: 'base64', }), }, ); return response.json(); } ``` ### Batch Simulation Use batch simulation when you have multiple transactions to validate - either independent transactions or a sequence of dependent operations. ```javascript theme={null} async function simulateBatch(transactions) { const response = await fetch( 'https://api.range.org/v1/simulate/solana/transactions', { method: 'POST', headers: { Authorization: `Bearer ${API_KEY}`, 'Content-Type': 'application/json', }, body: JSON.stringify({ transactions: transactions.map(tx => ({ payload: tx, encoding_type: 'base64', })), }), }, ); return response.json(); } ``` ### When to Use Each | Scenario | Use | | - | - | | Single transfer or swap | Single simulation | | Multi-step workflow (approve → swap → transfer) | Batch simulation | | Validating multiple independent transactions | Batch simulation | | Portfolio rebalancing across multiple tokens | Batch simulation | ## Step 3: Analyze the Response The simulation response contains several sections. Here's what to check and in what order: ### Check for Errors First If the `error` field is present, the transaction would fail onchain. Other fields may be incomplete. ```javascript theme={null} function checkSimulationSuccess(result) { if (result.error) { return { success: false, reason: result.error, }; } return { success: true }; } ``` ### Review Asset Transfers The `asset_transfers` array shows all token and SOL movements per account. Each entry represents a balance change for a specific account and asset. ```javascript theme={null} function summarizeTransfers(result) { return (result.asset_transfers || []).map(transfer => ({ account: transfer.account, // The account affected mint: transfer.mint, // Token mint address, or "SOL" for native SOL amount: transfer.amount, // Amount transferred (human-readable, not lamports) changeType: transfer.change_type, // "Debit" (outflow) or "Credit" (inflow) })); } ``` For a simple SOL transfer, you'll see two entries: a `Debit` from the sender and a `Credit` to the recipient. For swaps or complex transactions, you'll see multiple entries across different mints and accounts. ### Check Balance Changes The `lamport_changes` array shows the net SOL balance change for each address involved in the transaction. ```typescript theme={null} function getBalanceChanges(result: SimulationResult) { return (result.lamport_changes || []).map(change => ({ account: change.account, preBalance: change.pre_balance, // Lamports before postBalance: change.post_balance, // Lamports after delta: change.post_balance - change.pre_balance, // Net change in lamports })); } ``` ### Review State Changes The `expected_state_changes` object maps each affected account to an array of state changes. Each change includes a `humanReadableDiff` for display, a `suggestedColor` (`CREDIT` or `DEBIT`), and `rawInfo` with structured data about the change type. ```typescript theme={null} function getStateChanges(result: SimulationResult) { const changes = result.expected_state_changes || {}; return Object.entries(changes).flatMap(([account, accountChanges]) => accountChanges.map(change => ({ account, description: change.humanReadableDiff, // e.g., "Sent 3.317 SOL", "Receive 268.78 USDC" color: change.suggestedColor, // "CREDIT" or "DEBIT" kind: change.rawInfo?.kind, // "SOL_TRANSFER", "SPL_TRANSFER", etc. asset: change.rawInfo?.data?.asset, // Token metadata (symbol, name, decimals, imageUrl, price) diff: change.rawInfo?.data?.diff, // { sign: "PLUS" | "MINUS", digits: bigint } counterparty: change.rawInfo?.data?.counterparty, // For SPL transfers })), ); } ``` State change types include: * `SOL_TRANSFER`, Native SOL transfers * `SPL_TRANSFER`, Token transfers, swaps, mints, burns * Account creations, closures, and other token operations ### Check Transaction Costs ```typescript theme={null} function getCosts(result: SimulationResult) { const summary = result.transaction_summary; const fee = summary.expected_fee; return { computeUnits: summary.cus_consumed, totalFee: fee.total_fee, // Total fee in lamports computeFee: fee.compute_fee, // Base compute fee prioritizationFee: fee.prioritization_fee, jitoTip: fee.jito_tip, // Jito tip if applicable feeConfidence: fee.confidence, // "High", "Medium", or "Low" programsInvoked: summary.programs_invoked, }; } ``` #### Fee Confidence Levels | Level | Meaning | Action | | - | - | - | | **High** | Derived from explicit compute budget instructions | Fee is accurate | | **Medium** | Estimated from recent prioritization fees for the locked accounts | Fee is a reasonable estimate | | **Low** | No data available; fallback logic used | Consider setting explicit compute budget | *** ## Step 4: Check Transaction Risk The `transaction_risk` section provides risk analysis for all accounts involved in the transaction. ```typescript theme={null} function analyzeRisk(result: SimulationResult) { const risk = result.transaction_risk; // Check for exploit patterns (e.g., address poisoning) const exploits = risk.exploit_risks_detected || []; // Extract account risk data from the nested structure const accountsRisk = risk.accounts_risk_score?.data?.addresses_risk || []; // Find risky accounts (score >= 6) const riskyAccounts = accountsRisk.flatMap(entry => entry.risk_scores .filter(score => score.riskScore >= 6) .map(score => ({ address: score.address, score: score.riskScore, level: score.riskLevel, numHops: score.numHops, reasoning: score.reasoning, maliciousConnections: score.maliciousAddressesFound, })), ); // Get summary stats const summary = risk.accounts_risk_score?.data?.summary; return { hasExploitRisk: exploits.length > 0, exploits, riskyAccounts, summary: summary ? { totalChecked: summary.total, criticalRisk: summary.critical_risk, highRisk: summary.high_risk, mediumRisk: summary.medium_risk, lowRisk: summary.low_risk, noRisk: summary.no_risk, } : null, isHighRisk: exploits.length > 0 || riskyAccounts.length > 0, }; } ``` Each risky account includes: * `riskScore` (1-10) and `riskLevel` (e.g., "Extremely high risk") * `numHops`, Distance to nearest malicious address * `reasoning`, Explanation of why the address is flagged * `maliciousAddressesFound`, List of connected malicious addresses with their categories (Hack, Scam, etc.) Risk analysis is performed on the main transaction level. Embedded transactions (e.g., Squads multisig operations) and nested instruction data are not currently included in risk scoring. *** ## Debugging Common Failures | Error Pattern | Likely Cause | Fix | | - | - | - | | Insufficient funds | Account doesn't have enough SOL/tokens | Check balances before building the transaction | | Account not found | Destination token account doesn't exist | Create the associated token account first | | Program error | Invalid instruction data or state | Check program-specific requirements | | Blockhash expired | Transaction took too long to simulate | Use a fresh `recentBlockhash` | | Compute budget exceeded | Transaction is too complex | Add a compute budget instruction with higher limits | ### Using Logs for Debugging The `transaction_logs` array contains the complete execution logs from the Solana runtime. Search for `"Program log: Error"` or `"failed"` to pinpoint the failing instruction: ```typescript theme={null} function findErrors(result: SimulationResult) { return (result.transaction_logs || []).filter( log => log.includes('Error') || log.includes('failed') || log.includes('insufficient'), ); } ``` *** ## Complete Simulation Workflow ```typescript theme={null} async function validateBeforeSending(encodedTx: string) { const result = await simulateTransaction(encodedTx); // 1. Check if simulation succeeded if (result.error) { return { proceed: false, reason: `Transaction would fail: ${result.error}`, }; } // 2. Check for exploit risks const risk = analyzeRisk(result); if (risk.hasExploitRisk) { return { proceed: false, reason: 'Exploit risk detected', details: risk.exploits, }; } // 3. Check for risky accounts if (risk.riskyAccounts.length > 0) { return { proceed: false, reason: 'Transaction involves high-risk accounts', riskyAccounts: risk.riskyAccounts, }; } // 4. Summarize for user confirmation return { proceed: true, transfers: summarizeTransfers(result), costs: getCosts(result), stateChanges: getStateChanges(result), }; } ``` *** ## What's Next Full endpoint reference with response schema details. Trace an unsigned EVM transaction or Safe multisig: balance deltas, transfers, approvals, attribution checks, and safe/batch detail. Integrate simulation into a wallet send flow with address screening. # Wallet & dApp Integration Source: https://docs.range.org/risk-api/guides/wallet-dapp-integration Add real-time risk protection to Solana wallets and dApps with address screening and pre-signature transaction scanning. This guide shows how to integrate Risk API into a Solana wallet or dApp to protect users from malicious addresses and risky transactions. The flow screens recipients before sending and scans the unsigned transaction before signing. **Prerequisites:** You need a [Risk API key](/introduction/getting-started) and familiarity with [Address Risk Score](/risk-api/risk/get-address-risk-score) and [Scan an Unsigned Transaction](/risk-api/risk-v2/scan-unsigned-transaction). For raw simulation without a risk verdict, see the [Transaction Simulator](/risk-api/simulator/simulate-solana-transaction). *** ## Integration Flow A typical wallet integration adds two risk gates to the send flow: ``` User enters recipient + amount │ ▼ ┌─────────────────────────┐ │ Screen recipient │──── High risk? → Show warning │ (Address Risk Score) │ └─────────────────────────┘ │ ▼ User constructs transaction │ ▼ ┌─────────────────────────┐ │ Scan unsigned tx │──── High severity? → Show warning │ (Transaction Scan) │ Findings / failed sim? → Show detail └─────────────────────────┘ │ ▼ User reviews risk info → Confirm or Cancel │ ▼ Sign and broadcast ``` *** ## Step 1: Screen the Recipient Before the user constructs a transaction, check the recipient address for connections to known malicious actors. ```typescript theme={null} async function screenRecipient(address: string, network: string = 'solana') { const params = new URLSearchParams({ address, network }); const response = await fetch( `https://api.range.org/v1/risk/address?${params}`, { headers: { Authorization: `Bearer ${API_KEY}` } }, ); const data = await response.json(); return { score: data.riskScore, level: data.riskLevel, reasoning: data.reasoning, isSafe: data.riskScore <= 3, isAttributed: data.attribution !== null, attribution: data.attribution, }; } ``` ### What to Show the User | Score | UI Treatment | | -: | - | | **1-3** | Green indicator. Proceed normally. If `attribution` is present, optionally show the entity name (e.g., "Token Program - Solana"). | | **4-5** | Yellow warning. Show `reasoning` and let the user decide. | | **6-7** | Orange warning. Recommend against proceeding. Show `reasoning` and the number of hops to malicious addresses. | | **8-10** | Red block. Strongly warn. Show `reasoning` and `maliciousAddressesFound` details. Require explicit confirmation. | Check the `attribution` field - when present, it means the address is a verified non-malicious entity (like a system program or major exchange). You can display the entity name to reassure the user. *** ## Step 2: Scan the Unsigned Transaction After the user constructs but before they sign the transaction, scan it. The scan simulates the payload, screens up to 50 counterparties through Address Risk v2, and checks recipients for address poisoning. When coverage is incomplete, `meta` says so. Solana only in this version. ```typescript theme={null} async function scanUnsignedTransaction(encodedTransaction: string) { const response = await fetch( 'https://api.range.org/v2/risk/transaction/scan', { method: 'POST', headers: { Authorization: `Bearer ${API_KEY}`, 'Content-Type': 'application/json', }, body: JSON.stringify({ network: 'solana', transaction: encodedTransaction, encoding: 'base64', }), }, ); return response.json(); } ``` ### Key Response Fields to Display | Field | What to Show | | - | - | | `severity` | Worst single-signal severity (`none` / `low` / `medium` / `high` / `severe`) | | `findings` | Transaction-native rules that fired (`signal` + `caption`) | | `counterparties` | Each touched address with its Address Risk v2 severity | | `simulation` | Predicted asset diffs. `null` when simulation failed | | `notes` | Coverage caveats such as `coverage-truncated` | | `meta` | Coverage flags. `poisoning_screened: false` means recipients were not checked for lookalikes | | `screen_id` | Fetch full evidence later via [Fetch Assessment Evidence](/risk-api/risk-v2/get-evidence) | For a raw simulation without a combined risk verdict, see the [Transaction Simulation Guide](/risk-api/guides/transaction-simulation#step-3-analyze-the-response). ### Findings and Failed Simulations Warn on a severity above `low`, on every finding except `large-transfer`, and when `meta.poisoning_screened` is `false`. `large-transfer` fires on most transfers and never affects `severity`. A failed or unavailable simulation already arrives as a `medium` finding (`simulation-error` or `simulation-unavailable`): ```typescript theme={null} function checkScanRisk(scan: { severity: string; findings: { signal: string; caption: string }[]; meta: { poisoning_screened: boolean }; }) { const warnings: string[] = []; if (scan.severity !== 'none' && scan.severity !== 'low') { warnings.push(`Transaction severity: ${scan.severity}`); } for (const finding of scan.findings || []) { if (finding.signal === 'large-transfer') continue; // informational only warnings.push(finding.caption || finding.signal); } if (!scan.meta.poisoning_screened) { warnings.push('Recipients were not checked for address poisoning'); } return { hasRisk: warnings.length > 0, warnings, }; } ``` *** ## Step 3: Display Risk Information Combine the address screening and scan results into a confirmation screen. The goal is to give users enough information to make an informed decision without overwhelming them. ### Recommended UI Pattern ``` ┌─────────────────────────────────────────┐ │ Transaction Preview │ │ │ │ Sending: 100 USDC │ │ To: 7xKX...3mN2 │ │ Fee: ~0.00025 SOL │ │ │ │ ┌─────────────────────────────────┐ │ │ │ ⚠ Recipient Risk: Medium (5/10) │ │ │ │ 3 hops from flagged address │ │ │ └─────────────────────────────────┘ │ │ │ │ Scan severity: high │ │ Intent: Swap 100 USDC for SOL │ │ │ │ Balance Changes: │ │ · USDC: -100.00 │ │ · SOL: -0.00025 (fee) │ │ │ │ [Cancel] [Send Anyway] │ └─────────────────────────────────────────┘ ``` ### Best Practices * **Don't block silently.** Always explain why a transaction is flagged. Show `reasoning` from the address screen and `findings` from the scan. * **Let users override with warning.** Even high-risk transactions should be possible to send if the user explicitly confirms - they may know something the scoring doesn't. * **Show entity attribution.** If the recipient is a known entity (exchange, protocol), display its name. * **Cache address risk cautiously.** Risk scores change as new intelligence is incorporated. For high-value transfers, always query fresh. *** ## Step 4: Handle Edge Cases ### Network Errors and Timeouts ```typescript theme={null} async function screenWithFallback(address: string, network: string) { try { const result = await Promise.race([ screenRecipient(address, network), new Promise((_, reject) => setTimeout(() => reject(new Error('timeout')), 5000), ), ]); return result; } catch (error) { // If the risk check fails, inform the user but don't block return { score: null, level: 'unknown', reasoning: 'Risk check unavailable - proceed with caution', isSafe: null, }; } } ``` ### Rate Limits If you hit rate limits (`429` responses), show a degraded state rather than blocking the user. See [Rate Limits & Plans](/risk-api/product-info/rate-limits) for retry strategies. ### Unsupported Networks Address Risk Score returns results for [18+ supported networks](/risk-api/product-info/supported-chains). For unsupported networks, partial results may be available through direct attribution or cross-chain propagation. Transaction scan is Solana only in this version. *** ## Complete Send Flow ```typescript theme={null} async function protectedSend( recipient: string, amount: number, network: string, ) { // Screen the recipient const risk = await screenWithFallback(recipient, network); if (risk.score >= 8) { // Require explicit user confirmation for high-risk const confirmed = await showHighRiskWarning(risk); if (!confirmed) return { status: 'cancelled' }; } else if (risk.score >= 4) { // Show warning for medium-risk const confirmed = await showMediumRiskWarning(risk); if (!confirmed) return { status: 'cancelled' }; } // Build and encode the transaction (see Transaction Simulation guide for SDK examples) const transaction = await buildTransaction(recipient, amount); const encoded = encodeTransactionBase64(transaction); // Scan before signing const scan = await scanUnsignedTransaction(encoded); if (!scan.simulation || scan.simulation.simulation_success === false) { return { status: 'error', reason: 'Simulation failed' }; } const scanRisk = checkScanRisk(scan); if (scanRisk.hasRisk) { const confirmed = await showExploitWarning(scanRisk.warnings); if (!confirmed) return { status: 'cancelled' }; } // Show confirmation with all risk data const confirmed = await showConfirmation({ risk, scan }); if (!confirmed) return { status: 'cancelled' }; // Sign and send return await signAndSend(transaction); } ``` For SDK-specific transaction building and encoding examples using `@solana/kit` or `@solana/web3.js`, see the [Transaction Simulation Guide](/risk-api/guides/transaction-simulation#step-1-prepare-and-encode-the-transaction). *** ## What's Next Pre-signature Solana scan: simulation, counterparty screening, and poisoning checks. Deep dive into raw simulation response interpretation and debugging. # Rate Limits Source: https://docs.range.org/risk-api/product-info/rate-limits API rate limits and how to handle them for the Risk API. The Range API enforces rate limits to keep the platform fast and reliable for everyone. Limits and quotas depend on the modules activated on your account. See [plans and pricing](/introduction/plans-and-pricing). *** ## Usage Monitoring Track your API usage in real-time through the [Range Dashboard](https://app.range.org). * **Current period usage** - Requests consumed in the current billing cycle * **Remaining quota** - Requests available before the next reset * **Historical usage** - Usage trends over time *** ## Handling Rate Limits When you exceed your rate limit, the API returns a `429 Too Many Requests` response. ### Recommended Strategy 1. **Check response headers** - every response includes `X-RateLimit-Limit`, `X-RateLimit-Remaining`, and `X-RateLimit-Reset` (Unix timestamp); on a `429`, honor the `Retry-After` header before retrying 2. **Implement exponential backoff** - Start with a 1-second delay, doubling on each retry 3. **Add jitter** - Randomize retry delays to avoid thundering herd problems 4. **Set a max retry count** - Cap retries at 3-5 attempts ```javascript theme={null} async function fetchWithRetry(url, options, maxRetries = 3) { for (let attempt = 0; attempt < maxRetries; attempt++) { const response = await fetch(url, options); if (response.status === 429) { const delay = Math.pow(2, attempt) * 1000 + Math.random() * 1000; await new Promise((resolve) => setTimeout(resolve, delay)); continue; } return response; } throw new Error("Max retries exceeded"); } ``` *** ## Need higher limits? Higher rate limits and quotas come with paid **Protect** usage and Enterprise agreements: * **Higher rate limits and quotas** tailored to your volume * **Dedicated support** with \<4-hour response times * **Custom SLAs** for uptime and latency guarantees * **Priority access** to new endpoints and features * **Bulk pricing** for high-volume screening workflows Tell us what you're running and we'll quote a plan that fits. # Risk Data Sources Source: https://docs.range.org/risk-api/product-info/risk-data-sources Data sources and intelligence feeds that power Risk API scoring, including sanctions lists, blacklists, threat intelligence, and ML models. Range's risk scoring engine aggregates data from multiple independent sources. This page describes the feeds behind [risk scoring methodology](/risk-api/product-info/understanding-risk-scores). Access to our most sensitive intelligence requires KYB verification. This includes full wallet attribution, cross-chain identity mapping, and advanced risk intelligence. To prevent misuse, these capabilities are available only to verified teams with legitimate use cases. *** ## Sanctions and compliance lists Range ingests designations from official government and authority publications. Coverage is network-agnostic for published crypto addresses, so an address listed by a sanctioning body is screened regardless of which chain you query. | Source | Jurisdiction | Type | Signal ID | | - | - | - | - | | **OFAC SDN** | United States | Sanctions | `ofac-sanctioned` | | **UK FCDO / OFSI** (UK Sanctions List, SAMLA 2018) | United Kingdom | Sanctions | `uk-sanctioned` | | **EU FSF** (Consolidated) | European Union | Sanctions | `eu-sanctioned` | | **EU Russia sanctions packages** | European Union | Sanctions (indirect designation) | `eu-sanction-ru` | | **France Trésor** (Registre national des gels) | France | Sanctions / terror financing | `france-sanctioned` | | **Japan MoF** | Japan | Sanctions / terror financing | `japan-sanctioned` | | **Israel NBCTF** | Israel | Terror financing (seizure orders) | `nbctf-terror-financing` | | **FBI IC3** | United States | Fraud and criminal advisories | `fbi-fraud` | The UN Security Council Consolidated List is not in the table because it publishes no crypto addresses (checked September 2026), so there is nothing to match an address against. A UN designation is screened only through a list above that implements it, such as OFAC, the UK, or the EU, and is reported under that list's signal ID. The signal ID is how a hit is reported: the `signal` value in [Address Risk (v2)](/risk-api/risk-v2/get-address-risk), a `risk_categories` entry in [Address Risk Score (v1)](/risk-api/risk/get-address-risk-score), and the `signal_id` of a `sanctions` entry in [Sanctions & Blacklist Check](/risk-api/risk/get-sanctions-blacklist-check). Two broader signals are not tied to a single list: `sanctioned`, for an address on a government sanctions list, and `compliance-risk`, for an address posing regulatory or compliance risk. [List Signals & Behaviours](/risk-api/risk-v2/get-signals) returns the full catalog. Sanctions and related designations are used by: * [Address Risk (v2)](/risk-api/risk-v2/get-address-risk), attribution and exposure signals * [Address Risk Score (v1)](/risk-api/risk/get-address-risk-score), incorporated into the numeric score * [Sanctions & Blacklist Check](/risk-api/risk/get-sanctions-blacklist-check), direct screening against every list above and issuer blacklists, one entry per list the address is on * [Payment Risk Assessment](/risk-api/risk/get-payment-risk-assessment), attributed address checks Many packages designate **entities** rather than publishing every wallet those entities operate. Range also attributes related addresses from entity footprints and onchain relationships. Inferred associations are distinguished from direct list hits so you can treat them differently in policy and review. The Sanctions & Blacklist Check reports this as `basis: direct` or `basis: indirect` on each list entry. *** ## Token issuer blacklists Range monitors onchain blacklist events emitted by token issuer contracts (stablecoins, tokenized gold and cbBTC). When an issuer blacklists an address, it is blocked from transferring their tokens. Address Risk (v2) and Address Risk Score (v1) report these addresses as the `blacklisted` signal. | Issuer | Tokens | Networks monitored | | - | - | - | | **Tether** | USDT | Ethereum, Tron, Solana, Arbitrum, Optimism, Polygon, Avalanche | | **Tether** | XAUT | Ethereum, Arbitrum, Polygon | | **Circle** | USDC | Ethereum, Tron, Solana, Base, Arbitrum, Optimism, Polygon, Avalanche | | **Circle** | EURC | Ethereum, Base, Avalanche | | **Coinbase** | cbBTC | Ethereum, Base, Arbitrum | | **PayPal** | PYUSD | Ethereum, Arbitrum, Solana | | **Agora** | AUSD | Ethereum, Base, Arbitrum, Polygon, Avalanche | | **Paxos** | USDP, USDG, PAXG, BUSD | Ethereum | | **Ripple** | RLUSD | Ethereum | Freezes (`blacklist`), releases (`unblacklist`) and burns of a frozen balance (`destroyedblackfunds`) are tracked, providing current status and event history back to each token's launch. See [Supported Tokens](/risk-api/product-info/supported-tokens) for the complete coverage matrix. *** ## Onchain indexing Range operates its own indexing infrastructure across supported networks. Counterparty graphs, volume context, and behavioral signals used by Address Risk (v2) are built from Range's own parsing of blocks and transactions, not from a third-party reseller feed sitting between confirmation and score. *** ## Threat intelligence Range maintains a curated attribution dataset from multiple intelligence sources: | Category | Description | | - | - | | **Confirmed exploits** | Addresses involved in verified protocol exploits, bridge hacks, and smart contract vulnerabilities | | **Scams & phishing** | Known scam addresses, phishing campaigns, and social engineering operations | | **Internal research** | Range's security research team investigates and attributes new threats | | **Security partnerships** | Intelligence shared with security companies and incident-response partners | | **Community and public sources** | Verified community reports and publicly available threat research | ### Attribution labels Attributed addresses typically include: * **`name_tag`**, human-readable label * **`entity`**, known organization or cluster * **`category`**, type of activity (e.g. `hack_funds`, `scam`, `phishing`) Blank attribution fields usually mean confidential sources that cannot be disclosed, or ML-flagged addresses without traditional labels. *** ## Machine learning models Range's ML models extend coverage beyond traditional list matching by identifying previously undetected threats through behavioral analysis: payment patterns, timing, and counterparty interactions. Addresses flagged by these models are incorporated into risk scoring alongside traditionally attributed addresses. *** ## Verified non-malicious addresses Range maintains verified infrastructure attributions to reduce false positives, including: * **System programs**, core blockchain infrastructure (e.g. Solana Token Program, System Program) * **Major exchanges**, verified exchange deposit and operational wallets * **Verified protocols**, established DeFi protocol and program addresses On Address Risk (v1), these addresses receive the minimum score. On Address Risk (v2), they are treated as known-good attribution so volume alone does not inflate severity. See [Understanding Risk Scores](/risk-api/product-info/understanding-risk-scores). *** ## Data freshness | Data source | Typical freshness | | - | - | | **Token issuer blacklists** | Near real-time, monitored from onchain events as they are emitted | | **Sanctions and compliance lists** | Continuously monitored against official publications; updates enter scoring after Range's review process | | **Threat intelligence** | Minutes to hours depending on confirmation requirements | | **Onchain activity used in scoring** | Continuous indexing on supported networks | Once a designation is in Range's attribution set, related addresses across supported networks can be reflected in subsequent screens without waiting for a separate per-chain republication. *** ## Coverage requests If you have intelligence about malicious addresses or need coverage for specific threat categories, [contact us](https://www.range.org/get-in-touch). We continuously expand data sources based on customer needs and emerging threats. # Supported Chains Source: https://docs.range.org/risk-api/product-info/supported-chains Blockchain networks supported by each Risk API endpoint. Risk API supports a growing number of blockchain networks across its endpoints. Coverage varies by endpoint - the table below shows which chains are supported where. *** ## Coverage by Endpoint *Tip: Scroll horizontally to see all endpoints.* | Chain | Identifier | Address
Risk | Sanctions
& Blacklist | Payment
Risk | Token
Risk | Transaction
Simulator | | - | - | :-: | :-: | :-: | :-: | :-: | | **Solana** | | | | | | | | Solana | `solana` | ✅ | ✅ | ✅ | ✅ | ✅ | | **Ethereum L1 and L2s** | | | | | | | | Ethereum Mainnet | `eth` | ✅ | ✅ | n/a | 🔜 | ✅ | | Optimism Mainnet | `oeth` | ✅ | ✅ | n/a | n/a | ✅ | | BNB Smart Chain | `bnb` | ✅ | ✅\* | n/a | n/a | ✅ | | Polygon Mainnet | `pol` | ✅ | ✅ | n/a | Planned | ✅ | | Polygon zkEVM | `zkevm` | ✅ | ✅\* | n/a | n/a | n/a | | Moonbeam | `moonbeam` | ✅ | ✅\* | n/a | n/a | n/a | | Base | `base` | ✅ | ✅ | n/a | Planned | ✅ | | Arbitrum One | `arb1` | ✅ | ✅ | n/a | Planned | ✅ | | Celo Mainnet | `celo` | ✅ | ✅\* | n/a | n/a | n/a | | Avalanche C-Chain | `avax` | ✅ | ✅ | n/a | n/a | ✅ | | **Other** | | | | | | | | Stellar | `stellar` | ✅ | ✅\* | ✅ | n/a | n/a | | Bitcoin Mainnet | `bitcoin` | ✅ | ✅\* | n/a | n/a | n/a | | Tron | `tron` | ✅ | ✅ | n/a | n/a | n/a | | **Cosmos Ecosystem** | | | | | | | | Celestia | `celestia` | ✅ | ✅\* | ✅ | n/a | n/a | | Osmosis | `osmosis-1` | ✅ | ✅\* | ✅ | n/a | ✅ | | Cosmos Hub | `cosmoshub-4` | ✅ | ✅\* | ✅ | n/a | n/a | | dYdX Mainnet | `dydx-mainnet-1` | ✅ | ✅\* | ✅ | n/a | n/a | | Neutron | `neutron-1` | ✅ | ✅\* | ✅ | n/a | ✅ | | Dymension | `dymension_1100-1` | ✅ | ✅\* | ✅ | n/a | n/a | | Agoric | `agoric-3` | ✅ | ✅\* | ✅ | n/a | n/a | | Mantra | `mantra-1` | ✅ | ✅\* | ✅ | n/a | n/a | | Stride | `stride-1` | ✅ | ✅\* | ✅ | n/a | n/a | | PIO Mainnet | `pio-mainnet-1` | ✅ | ✅\* | ✅ | n/a | n/a | | Noble | `noble-1` | ✅ | ✅\* | ✅ | n/a | n/a | | ZigChain | `zigchain-1` | ✅ | ✅\* | ✅ | n/a | n/a | | Union | `union-1` | ✅ | ✅\* | ✅ | n/a | n/a | | Chain | Identifier | Address
Risk | Sanctions
& Blacklist | Payment
Risk | Token
Risk | Transaction
Simulator | | - | - | :-: | :-: | :-: | :-: | :-: | | 0g | `0g` | ◐ | ✅\* | n/a | n/a | n/a | | Aaron Network | `aaronetwork` | ◐ | ✅\* | n/a | n/a | n/a | | Abstract | `abstract` | ◐ | ✅\* | n/a | n/a | n/a | | Acala | `acala` | ◐ | ✅\* | n/a | n/a | n/a | | AIOZ Network | `aioz_168-1` | ◐ | ✅\* | n/a | n/a | n/a | | Ajuna | `ajuna` | ◐ | ✅\* | n/a | n/a | n/a | | Akash | `akashnet-2` | ◐ | ✅\* | n/a | n/a | n/a | | Aleo | `aleo` | ◐ | ✅\* | n/a | n/a | n/a | | Aleph Zero | `aleph-zero-evm` | ◐ | ✅\* | n/a | n/a | n/a | | Aleph Zero EVM | `aleph-zero` | ◐ | ✅\* | n/a | n/a | n/a | | Algen | `alg` | ◐ | ✅\* | n/a | n/a | n/a | | Algorand | `algorand` | ◐ | ✅\* | n/a | n/a | n/a | | Allora | `allora-mainnet-1` | ◐ | ✅\* | n/a | n/a | n/a | | Althea | `althea_258432-1` | ◐ | ✅\* | n/a | n/a | n/a | | Ancient8 | `ancient8` | ◐ | ✅\* | n/a | n/a | n/a | | Andromeda | `andromeda-1` | ◐ | ✅\* | n/a | n/a | n/a | | ApeChain | `apechain` | ◐ | ✅\* | n/a | n/a | n/a | | Apex Fusion - Nexus | `ap3x` | ◐ | ✅\* | n/a | n/a | n/a | | AppChain | `appchain` | ◐ | ✅\* | n/a | n/a | n/a | | Aptos | `aptos` | ◐ | ✅\* | n/a | n/a | n/a | | Arbitrum Nova | `arb-nova` | ◐ | ✅\* | n/a | n/a | n/a | | Arcadia | `arcadia` | ◐ | ✅\* | n/a | n/a | n/a | | Archway | `archway-1` | ◐ | ✅\* | n/a | n/a | n/a | | Arkeo Network | `arkeo-main-v1` | ◐ | ✅\* | n/a | n/a | n/a | | Arkhadian | `arkh` | ◐ | ✅\* | n/a | n/a | n/a | | Artela Mainnet | `artela` | ◐ | ✅\* | n/a | n/a | n/a | | Arthera | `aa` | ◐ | ✅\* | n/a | n/a | n/a | | Asset Hub | `asset-hub` | ◐ | ✅\* | n/a | n/a | n/a | | AssetMantle | `mantle-1` | ◐ | ✅\* | n/a | n/a | n/a | | Astar | `astar` | ◐ | ✅\* | n/a | n/a | n/a | | Astar ZK | `astarzk` | ◐ | ✅\* | n/a | n/a | n/a | | Astria | `astria` | ◐ | ✅\* | n/a | n/a | n/a | | AtomOne | `atomone-1` | ◐ | ✅\* | n/a | n/a | n/a | | Aura Network | `aura_6322-2` | ◐ | ✅\* | n/a | n/a | n/a | | Aurora | `aurora` | ◐ | ✅\* | n/a | n/a | n/a | | Axelar | `axelar-dojo-1` | ◐ | ✅\* | n/a | n/a | n/a | | B2 | `b2-mainnet` | ◐ | ✅\* | n/a | n/a | n/a | | B3 | `b3` | ◐ | ✅\* | n/a | n/a | n/a | | Babylon | `bbn-1` | ◐ | ✅\* | n/a | n/a | n/a | | Band Protocol | `laozi-mainnet` | ◐ | ✅\* | n/a | n/a | n/a | | Battle for Blockchain | `bfb-1` | ◐ | ✅\* | n/a | n/a | n/a | | Beam | `beam` | ◐ | ✅\* | n/a | n/a | n/a | | BeeZee | `beezee-1` | ◐ | ✅\* | n/a | n/a | n/a | | Berachain | `berachain` | ◐ | ✅\* | n/a | n/a | n/a | | BEVM | `bevm` | ◐ | ✅\* | n/a | n/a | n/a | | Bifrost | `bifrost` | ◐ | ✅\* | n/a | n/a | n/a | | BitBadges | `bitbadges-1` | ◐ | ✅\* | n/a | n/a | n/a | | BitBadges | `bitbadges-2` | ◐ | ✅\* | n/a | n/a | n/a | | BitCanna | `bitcanna-1` | ◐ | ✅\* | n/a | n/a | n/a | | Bitcoin Cash | `bitcoin-cash` | ◐ | ✅\* | n/a | n/a | n/a | | Bitlayer | `btr` | ◐ | ✅\* | n/a | n/a | n/a | | Bitrock | `bitrock` | ◐ | ✅\* | n/a | n/a | n/a | | BitSong | `bitsong-2b` | ◐ | ✅\* | n/a | n/a | n/a | | Blast | `blast` | ◐ | ✅\* | n/a | n/a | n/a | | BlockX | `blockx_19191-1` | ◐ | ✅\* | n/a | n/a | n/a | | Bluzelle | `bluzelle-9` | ◐ | ✅\* | n/a | n/a | n/a | | BOB | `bob` | ◐ | ✅\* | n/a | n/a | n/a | | Boba Network | `boba` | ◐ | ✅\* | n/a | n/a | n/a | | Botanix | `btcm` | ◐ | ✅\* | n/a | n/a | n/a | | bostrom | `bostrom` | ◐ | ✅\* | n/a | n/a | n/a | | BounceBit | `bouncebit-mainnet` | ◐ | ✅\* | n/a | n/a | n/a | | Bridge Hub | `bridge-hub` | ◐ | ✅\* | n/a | n/a | n/a | | C4E | `perun-1` | ◐ | ✅\* | n/a | n/a | n/a | | Canto | `canto_7700-1` | ◐ | ✅\* | n/a | n/a | n/a | | Carbon | `carbon-1` | ◐ | ✅\* | n/a | n/a | n/a | | Cardano | `cardano` | ◐ | ✅\* | n/a | n/a | n/a | | Carrchain | `carrchain` | ◐ | ✅\* | n/a | n/a | n/a | | Centrifuge | `centrifuge` | ◐ | ✅\* | n/a | n/a | n/a | | CheeseChain | `cheesechain` | ◐ | ✅\* | n/a | n/a | n/a | | Cheqd | `cheqd-mainnet-1` | ◐ | ✅\* | n/a | n/a | n/a | | Chihuahua | `chihuahua-1` | ◐ | ✅\* | n/a | n/a | n/a | | Chiliz Chain | `chiliz` | ◐ | ✅\* | n/a | n/a | n/a | | Circuit | `circuit` | ◐ | ✅\* | n/a | n/a | n/a | | Citrea | `citrea` | ◐ | ✅\* | n/a | n/a | n/a | | Civitia | `civitia-1` | ◐ | ✅\* | n/a | n/a | n/a | | Codex PBC | `codex` | ◐ | ✅\* | n/a | n/a | n/a | | Collectives Polkadot | `collectives-polkadot` | ◐ | ✅\* | n/a | n/a | n/a | | Comdex | `comdex-1` | ◐ | ✅\* | n/a | n/a | n/a | | Composable Finance | `composablefinance` | ◐ | ✅\* | n/a | n/a | n/a | | Conflux eSpace | `cfx` | ◐ | ✅\* | n/a | n/a | n/a | | Core Blockchain | `core` | ◐ | ✅\* | n/a | n/a | n/a | | CoreDAO Mainnet | `coredao` | ◐ | ✅\* | n/a | n/a | n/a | | Coreum | `coreum-mainnet-1` | ◐ | ✅\* | n/a | n/a | n/a | | Coretime | `coretime` | ◐ | ✅\* | n/a | n/a | n/a | | coretimenegotiation | `coretimenegotiation` | ◐ | ✅\* | n/a | n/a | n/a | | Corn | `corn` | ◐ | ✅\* | n/a | n/a | n/a | | Coti | `coti` | ◐ | ✅\* | n/a | n/a | n/a | | Creditcoin | `ctc` | ◐ | ✅\* | n/a | n/a | n/a | | Crescent | `crescent-1` | ◐ | ✅\* | n/a | n/a | n/a | | Cronos | `cronosmainnet_25-1` | ◐ | ✅\* | n/a | n/a | n/a | | Cronos EVM | `crypto-org-chain-mainnet-1` | ◐ | ✅\* | n/a | n/a | n/a | | Cronos zkEVM | `zkcro` | ◐ | ✅\* | n/a | n/a | n/a | | CrossFi | `crossfi` | ◐ | ✅\* | n/a | n/a | n/a | | Crust | `crust` | ◐ | ✅\* | n/a | n/a | n/a | | CYBERTRUST | `cyber` | ◐ | ✅\* | n/a | n/a | n/a | | Darwinia Network | `darwinia` | ◐ | ✅\* | n/a | n/a | n/a | | Decentr | `mainnet-3` | ◐ | ✅\* | n/a | n/a | n/a | | DeepBrainChain | `dbc` | ◐ | ✅\* | n/a | n/a | n/a | | Degen Chain | `degen` | ◐ | ✅\* | n/a | n/a | n/a | | Desmos | `desmos-mainnet` | ◐ | ✅\* | n/a | n/a | n/a | | Dexalot Subnet | `dexalot` | ◐ | ✅\* | n/a | n/a | n/a | | DFK Chain | `dfk` | ◐ | ✅\* | n/a | n/a | n/a | | dHealth | `dhealth` | ◐ | ✅\* | n/a | n/a | n/a | | Dinari Financial Network | `dinari` | ◐ | ✅\* | n/a | n/a | n/a | | Dogechain | `dc` | ◐ | ✅\* | n/a | n/a | n/a | | Doma | `doma` | ◐ | ✅\* | n/a | n/a | n/a | | Dora Vota | `vota-ash` | ◐ | ✅\* | n/a | n/a | n/a | | Dungeon Chain | `dungeon-1` | ◐ | ✅\* | n/a | n/a | n/a | | Dymension | `dymension` | ◐ | ✅\* | n/a | n/a | n/a | | Dyson Protocol | `dyson-mainnet-01` | ◐ | ✅\* | n/a | n/a | n/a | | e-Money | `emoney-3` | ◐ | ✅\* | n/a | n/a | n/a | | Echelon | `echelon-1` | ◐ | ✅\* | n/a | n/a | n/a | | Echos Chain | `echos` | ◐ | ✅\* | n/a | n/a | n/a | | Eclipse Subnet | `eclipse` | ◐ | ✅\* | n/a | n/a | n/a | | EDU Chain | `edu-chain` | ◐ | ✅\* | n/a | n/a | n/a | | Electroneum | `etn-mainnet` | ◐ | ✅\* | n/a | n/a | n/a | | Elys Network | `elys-1` | ◐ | ✅\* | n/a | n/a | n/a | | Embr.fun | `embrmainnet-1` | ◐ | ✅\* | n/a | n/a | n/a | | EmpowerChain | `empowerchain-1` | ◐ | ✅\* | n/a | n/a | n/a | | Endurance Smart Chain | `ace` | ◐ | ✅\* | n/a | n/a | n/a | | Energy Web X | `energy-web-x` | ◐ | ✅\* | n/a | n/a | n/a | | Epix | `epix_1916-1` | ◐ | ✅\* | n/a | n/a | n/a | | Ethereal | `ethereal` | ◐ | ✅\* | n/a | n/a | n/a | | Etherlink | `etherlink` | ◐ | ✅\* | n/a | n/a | n/a | | Everclear | `everclear` | ◐ | ✅\* | n/a | n/a | n/a | | EVM on Flow | `flow-mainnet` | ◐ | ✅\* | n/a | n/a | n/a | | Evmos | `evmos_9001-2` | ◐ | ✅\* | n/a | n/a | n/a | | f(x)Core | `fxcore` | ◐ | ✅\* | n/a | n/a | n/a | | Fantom Opera | `ftm` | ◐ | ✅\* | n/a | n/a | n/a | | Fetch.ai | `fetchhub-4` | ◐ | ✅\* | n/a | n/a | n/a | | Filecoin | `filecoin` | ◐ | ✅\* | n/a | n/a | n/a | | FIRMACHAIN | `colosseum-1` | ◐ | ✅\* | n/a | n/a | n/a | | Flame | `flame` | ◐ | ✅\* | n/a | n/a | n/a | | Flare | `flare` | ◐ | ✅\* | n/a | n/a | n/a | | Fluence | `fluence` | ◐ | ✅\* | n/a | n/a | n/a | | Fogo | `fogo` | ◐ | ✅\* | n/a | n/a | n/a | | Forma | `forma` | ◐ | ✅\* | n/a | n/a | n/a | | Formicarium | `form` | ◐ | ✅\* | n/a | n/a | n/a | | Fraxtal | `fraxtal` | ◐ | ✅\* | n/a | n/a | n/a | | furya | `furya-1` | ◐ | ✅\* | n/a | n/a | n/a | | Fuse | `fuse` | ◐ | ✅\* | n/a | n/a | n/a | | Gaia | `gaianet` | ◐ | ✅\* | n/a | n/a | n/a | | Galactica | `galactica` | ◐ | ✅\* | n/a | n/a | n/a | | GateLayer | `gatelayer` | ◐ | ✅\* | n/a | n/a | n/a | | GenesisL1 | `genesis_29-2` | ◐ | ✅\* | n/a | n/a | n/a | | Gitopia | `gitopia` | ◐ | ✅\* | n/a | n/a | n/a | | Glue Mainnet | `glue` | ◐ | ✅\* | n/a | n/a | n/a | | Gnosis | `gnosis` | ◐ | ✅\* | n/a | n/a | n/a | | GOAT Network | `goat` | ◐ | ✅\* | n/a | n/a | n/a | | Gonka | `gonka-mainnet` | ◐ | ✅\* | n/a | n/a | n/a | | Gravity Alpha | `gravity` | ◐ | ✅\* | n/a | n/a | n/a | | Gravity Bridge | `gravity-bridge-3` | ◐ | ✅\* | n/a | n/a | n/a | | GUNZ Mainnet | `gunz` | ◐ | ✅\* | n/a | n/a | n/a | | Haqq Network | `haqq_11235-1` | ◐ | ✅\* | n/a | n/a | n/a | | Harmony Mainnet Shard 0 | `hmy-s0` | ◐ | ✅\* | n/a | n/a | n/a | | Harmony Mainnet Shard 1 | `hmy-s1` | ◐ | ✅\* | n/a | n/a | n/a | | HashKey Chain | `hsk` | ◐ | ✅\* | n/a | n/a | n/a | | Hedera | `hedera-mainnet` | ◐ | ✅\* | n/a | n/a | n/a | | Hemi Network | `hemi` | ◐ | ✅\* | n/a | n/a | n/a | | Hippo Protocol | `hippo-protocol-1` | ◐ | ✅\* | n/a | n/a | n/a | | Holesky | `holesky` | ◐ | ✅\* | n/a | n/a | n/a | | Horizen EON | `eon` | ◐ | ✅\* | n/a | n/a | n/a | | Humans.ai | `humans_1089-1` | ◐ | ✅\* | n/a | n/a | n/a | | Hydration | `hydration` | ◐ | ✅\* | n/a | n/a | n/a | | Hyper EVM | `hyper-evm` | ◐ | ✅\* | n/a | n/a | n/a | | Hyperbridge | `hyperbridge` | ◐ | ✅\* | n/a | n/a | n/a | | Hyperliquid | `hyperliquid` | ◐ | ✅\* | n/a | n/a | n/a | | Immutable zkEVM | `imx` | ◐ | ✅\* | n/a | n/a | n/a | | Impact Hub | `ixo-5` | ◐ | ✅\* | n/a | n/a | n/a | | Incentiv | `incentiv` | ◐ | ✅\* | n/a | n/a | n/a | | Inertia | `inertia-2` | ◐ | ✅\* | n/a | n/a | n/a | | inEVM | `inevm` | ◐ | ✅\* | n/a | n/a | n/a | | ING Network | `ingnetwork-1` | ◐ | ✅\* | n/a | n/a | n/a | | Initia | `interwoven-1` | ◐ | ✅\* | n/a | n/a | n/a | | InitVerse | `ini` | ◐ | ✅\* | n/a | n/a | n/a | | Injective | `injective-1` | ◐ | ✅\* | n/a | n/a | n/a | | Injective EVM | `injective-evm` | ◐ | ✅\* | n/a | n/a | n/a | | Ink | `ink` | ◐ | ✅\* | n/a | n/a | n/a | | Int3face | `int3face-1` | ◐ | ✅\* | n/a | n/a | n/a | | Integritee Shell | `integritee` | ◐ | ✅\* | n/a | n/a | n/a | | Intento | `intento-1` | ◐ | ✅\* | n/a | n/a | n/a | | Intergaze | `intergaze-1` | ◐ | ✅\* | n/a | n/a | n/a | | Interlay | `interlay` | ◐ | ✅\* | n/a | n/a | n/a | | InvArch | `invarch` | ◐ | ✅\* | n/a | n/a | n/a | | IOTA | `iota` | ◐ | ✅\* | n/a | n/a | n/a | | IOTA EVM | `iotaevm` | ◐ | ✅\* | n/a | n/a | n/a | | IRISnet | `irishub-1` | ◐ | ✅\* | n/a | n/a | n/a | | Irys | `irys` | ◐ | ✅\* | n/a | n/a | n/a | | Jackal | `jackal-1` | ◐ | ✅\* | n/a | n/a | n/a | | Jamton | `jamton` | ◐ | ✅\* | n/a | n/a | n/a | | Japan Open Chain | `joc` | ◐ | ✅\* | n/a | n/a | n/a | | Joltify | `joltify_1729-1` | ◐ | ✅\* | n/a | n/a | n/a | | Juno | `juno-1` | ◐ | ✅\* | n/a | n/a | n/a | | Kaia | `kaia-mainnet` | ◐ | ✅\* | n/a | n/a | n/a | | Karura Network | `kar` | ◐ | ✅\* | n/a | n/a | n/a | | Katana | `katana` | ◐ | ✅\* | n/a | n/a | n/a | | Kava | `kava_2222-10` | ◐ | ✅\* | n/a | n/a | n/a | | Ki | `kichain-2` | ◐ | ✅\* | n/a | n/a | n/a | | Kiichain | `kiichain_1783-1` | ◐ | ✅\* | n/a | n/a | n/a | | Kilt Spiritnet | `kilt-spiritnet` | ◐ | ✅\* | n/a | n/a | n/a | | Klaytn | `klaytn` | ◐ | ✅\* | n/a | n/a | n/a | | Konstellation | `darchub` | ◐ | ✅\* | n/a | n/a | n/a | | Kopi | `luwak-1` | ◐ | ✅\* | n/a | n/a | n/a | | Kroma | `kroma` | ◐ | ✅\* | n/a | n/a | n/a | | Kujira | `kaiyo-1` | ◐ | ✅\* | n/a | n/a | n/a | | KYVE | `kyve-1` | ◐ | ✅\* | n/a | n/a | n/a | | Laos | `laos` | ◐ | ✅\* | n/a | n/a | n/a | | Lava | `lava-mainnet-1` | ◐ | ✅\* | n/a | n/a | n/a | | Lens | `lens` | ◐ | ✅\* | n/a | n/a | n/a | | Lightlink | `lightlink` | ◐ | ✅\* | n/a | n/a | n/a | | LikeCoin | `likecoin-mainnet-2` | ◐ | ✅\* | n/a | n/a | n/a | | Linea | `linea` | ◐ | ✅\* | n/a | n/a | n/a | | Lisk | `lisk` | ◐ | ✅\* | n/a | n/a | n/a | | Lit Chain | `litchain` | ◐ | ✅\* | n/a | n/a | n/a | | Litecoin | `litecoin` | ◐ | ✅\* | n/a | n/a | n/a | | Litentry | `litentry` | ◐ | ✅\* | n/a | n/a | n/a | | Lombard | `ledger-mainnet-1` | ◐ | ✅\* | n/a | n/a | n/a | | Loot | `loot` | ◐ | ✅\* | n/a | n/a | n/a | | LUKSO | `lukso` | ◐ | ✅\* | n/a | n/a | n/a | | Lum Network | `lum-network-1` | ◐ | ✅\* | n/a | n/a | n/a | | Lumera | `lumera-mainnet-1` | ◐ | ✅\* | n/a | n/a | n/a | | Lumia | `lumia-mainnet` | ◐ | ✅\* | n/a | n/a | n/a | | Lyra Chain | `lyra` | ◐ | ✅\* | n/a | n/a | n/a | | Mande Network | `mande_18071918-1` | ◐ | ✅\* | n/a | n/a | n/a | | Manifest Network | `manifest-ledger-mainnet` | ◐ | ✅\* | n/a | n/a | n/a | | Manta Atlantic | `manta-atlantic` | ◐ | ✅\* | n/a | n/a | n/a | | Manta Pacific | `manta` | ◐ | ✅\* | n/a | n/a | n/a | | Mantle | `mantle` | ◐ | ✅\* | n/a | n/a | n/a | | Mars Hub | `mars-1` | ◐ | ✅\* | n/a | n/a | n/a | | Matchain | `matchain` | ◐ | ✅\* | n/a | n/a | n/a | | MAXI Chain | `maxi-mainnet` | ◐ | ✅\* | n/a | n/a | n/a | | Medas Digital Network | `medasdigital-2` | ◐ | ✅\* | n/a | n/a | n/a | | Medibloc | `panacea-3` | ◐ | ✅\* | n/a | n/a | n/a | | MegaETH | `megaeth` | ◐ | ✅\* | n/a | n/a | n/a | | MEME | `meme-1` | ◐ | ✅\* | n/a | n/a | n/a | | Merit Circle Mainnet | `meritcircle` | ◐ | ✅\* | n/a | n/a | n/a | | Merlin | `merlin-mainnet` | ◐ | ✅\* | n/a | n/a | n/a | | Metal C-Chain | `metal` | ◐ | ✅\* | n/a | n/a | n/a | | Metal L2 | `metal2` | ◐ | ✅\* | n/a | n/a | n/a | | Meter | `meter` | ◐ | ✅\* | n/a | n/a | n/a | | Metis | `metis` | ◐ | ✅\* | n/a | n/a | n/a | | Mezo | `mezo` | ◐ | ✅\* | n/a | n/a | n/a | | Migaloo | `migaloo-1` | ◐ | ✅\* | n/a | n/a | n/a | | MilkyWay | `milkyway` | ◐ | ✅\* | n/a | n/a | n/a | | MilkyWay | `moo-1` | ◐ | ✅\* | n/a | n/a | n/a | | Mint | `mint` | ◐ | ✅\* | n/a | n/a | n/a | | Miracle Chain | `miraclechain` | ◐ | ✅\* | n/a | n/a | n/a | | Mises | `mainnet` | ◐ | ✅\* | n/a | n/a | n/a | | Mitosis | `mitosis` | ◐ | ✅\* | n/a | n/a | n/a | | Mode | `mode` | ◐ | ✅\* | n/a | n/a | n/a | | Molten | `molten` | ◐ | ✅\* | n/a | n/a | n/a | | Monad | `monad` | ◐ | ✅\* | n/a | n/a | n/a | | Moonriver | `mriver` | ◐ | ✅\* | n/a | n/a | n/a | | Morph | `morph` | ◐ | ✅\* | n/a | n/a | n/a | | Movement EVM | `move` | ◐ | ✅\* | n/a | n/a | n/a | | mtgbp | `mtgbp-1` | ◐ | ✅\* | n/a | n/a | n/a | | Mythos | `mythos` | ◐ | ✅\* | n/a | n/a | n/a | | Namada | `namada.5f5de2dd1b88cba30586420` | ◐ | ✅\* | n/a | n/a | n/a | | Near | `near` | ◐ | ✅\* | n/a | n/a | n/a | | Neonlink | `neon` | ◐ | ✅\* | n/a | n/a | n/a | | Neutaro | `neutaro-1` | ◐ | ✅\* | n/a | n/a | n/a | | Nibiru | `cataclysm-1` | ◐ | ✅\* | n/a | n/a | n/a | | Nillion | `nillion-1` | ◐ | ✅\* | n/a | n/a | n/a | | Nim Network | `nim_1122-1` | ◐ | ✅\* | n/a | n/a | n/a | | Nodle | `nodle` | ◐ | ✅\* | n/a | n/a | n/a | | Nolus | `pirin-1` | ◐ | ✅\* | n/a | n/a | n/a | | Nomic | `nomic-stakenet-3` | ◐ | ✅\* | n/a | n/a | n/a | | Nym | `nyx` | ◐ | ✅\* | n/a | n/a | n/a | | Oasis Emerald | `emerald` | ◐ | ✅\* | n/a | n/a | n/a | | Odin Protocol | `odin-mainnet-freya` | ◐ | ✅\* | n/a | n/a | n/a | | OKXChain | `okt` | ◐ | ✅\* | n/a | n/a | n/a | | OmniFlix | `omniflixhub-1` | ◐ | ✅\* | n/a | n/a | n/a | | Onomy | `onomy-mainnet-1` | ◐ | ✅\* | n/a | n/a | n/a | | Oort | `ccn` | ◐ | ✅\* | n/a | n/a | n/a | | opBNB | `obnb` | ◐ | ✅\* | n/a | n/a | n/a | | Openpiece | `op` | ◐ | ✅\* | n/a | n/a | n/a | | Oraichain | `oraichain` | ◐ | ✅\* | n/a | n/a | n/a | | Orderly | `orderly` | ◐ | ✅\* | n/a | n/a | n/a | | OriginTrail | `origintrail-parachain` | ◐ | ✅\* | n/a | n/a | n/a | | Otherworld Space Mainnet | `otherworld-space` | ◐ | ✅\* | n/a | n/a | n/a | | Paradex | `paradex` | ◐ | ✅\* | n/a | n/a | n/a | | Parallel | `parallel` | ◐ | ✅\* | n/a | n/a | n/a | | Passage | `passage-2` | ◐ | ✅\* | n/a | n/a | n/a | | Peaq | `peaq` | ◐ | ✅\* | n/a | n/a | n/a | | Pendulum | `pendulum` | ◐ | ✅\* | n/a | n/a | n/a | | Penumbra | `penumbra-1` | ◐ | ✅\* | n/a | n/a | n/a | | People | `people` | ◐ | ✅\* | n/a | n/a | n/a | | Persistence | `core-1` | ◐ | ✅\* | n/a | n/a | n/a | | PGN (Public Goods Network) | `pgn` | ◐ | ✅\* | n/a | n/a | n/a | | Phala Network | `phala` | ◐ | ✅\* | n/a | n/a | n/a | | Picasso | `centauri-1` | ◐ | ✅\* | n/a | n/a | n/a | | Planq | `planq_7070-2` | ◐ | ✅\* | n/a | n/a | n/a | | Plasma FDN | `plasma` | ◐ | ✅\* | n/a | n/a | n/a | | Plume | `plume` | ◐ | ✅\* | n/a | n/a | n/a | | Polimec | `polimec` | ◐ | ✅\* | n/a | n/a | n/a | | Polkadot | `polkadot` | ◐ | ✅\* | n/a | n/a | n/a | | Polynomial | `polynomial` | ◐ | ✅\* | n/a | n/a | n/a | | Prom | `prom` | ◐ | ✅\* | n/a | n/a | n/a | | Proof of Play - Apex | `pop-apex` | ◐ | ✅\* | n/a | n/a | n/a | | Pryzm | `pryzm-1` | ◐ | ✅\* | n/a | n/a | n/a | | PulseChain | `pls` | ◐ | ✅\* | n/a | n/a | n/a | | Pylons | `pylons-mainnet-1` | ◐ | ✅\* | n/a | n/a | n/a | | Quantum Financial Systems | `qfs-1` | ◐ | ✅\* | n/a | n/a | n/a | | Quasar | `quasar-1` | ◐ | ✅\* | n/a | n/a | n/a | | Quicksilver | `quicksilver-2` | ◐ | ✅\* | n/a | n/a | n/a | | Qwoyn | `qwoyn-1` | ◐ | ✅\* | n/a | n/a | n/a | | Radix | `radix` | ◐ | ✅\* | n/a | n/a | n/a | | RARI Chain | `rari` | ◐ | ✅\* | n/a | n/a | n/a | | Rarible | `rarible` | ◐ | ✅\* | n/a | n/a | n/a | | Rave | `rave-1` | ◐ | ✅\* | n/a | n/a | n/a | | re.al | `re-al` | ◐ | ✅\* | n/a | n/a | n/a | | Realchain | `real` | ◐ | ✅\* | n/a | n/a | n/a | | Realio Network | `realionetwork_3301-1` | ◐ | ✅\* | n/a | n/a | n/a | | Rebus | `reb_1111-1` | ◐ | ✅\* | n/a | n/a | n/a | | Redbelly Network | `rbn` | ◐ | ✅\* | n/a | n/a | n/a | | Redstone | `redstone` | ◐ | ✅\* | n/a | n/a | n/a | | Regen | `regen-1` | ◐ | ✅\* | n/a | n/a | n/a | | Reya Network | `reya` | ◐ | ✅\* | n/a | n/a | n/a | | Rivalz | `rivalz` | ◐ | ✅\* | n/a | n/a | n/a | | Rizon | `titan-1` | ◐ | ✅\* | n/a | n/a | n/a | | Ronin | `ronin` | ◐ | ✅\* | n/a | n/a | n/a | | Rootstock | `rsk` | ◐ | ✅\* | n/a | n/a | n/a | | Router Protocol | `router_9600-1` | ◐ | ✅\* | n/a | n/a | n/a | | Saga | `ssc-1` | ◐ | ✅\* | n/a | n/a | n/a | | Sanko | `sanko` | ◐ | ✅\* | n/a | n/a | n/a | | Scorum Network | `scorum-1` | ◐ | ✅\* | n/a | n/a | n/a | | Scroll | `scr` | ◐ | ✅\* | n/a | n/a | n/a | | Secret | `secret-4` | ◐ | ✅\* | n/a | n/a | n/a | | SEDA | `seda-1` | ◐ | ✅\* | n/a | n/a | n/a | | Sei | `pacific-1` | ◐ | ✅\* | n/a | n/a | n/a | | Self Chain | `self-1` | ◐ | ✅\* | n/a | n/a | n/a | | Sentinel | `sentinelhub-2` | ◐ | ✅\* | n/a | n/a | n/a | | SGE | `sgenet-1` | ◐ | ✅\* | n/a | n/a | n/a | | Shentu | `shentu-2.2` | ◐ | ✅\* | n/a | n/a | n/a | | Shibarium | `shibariumecosystem` | ◐ | ✅\* | n/a | n/a | n/a | | Shido | `shido_9008-1` | ◐ | ✅\* | n/a | n/a | n/a | | ShimmerEVM | `shimmerevm` | ◐ | ✅\* | n/a | n/a | n/a | | Shrapnel Subnet | `shrapnel` | ◐ | ✅\* | n/a | n/a | n/a | | Sifchain | `sifchain-1` | ◐ | ✅\* | n/a | n/a | n/a | | SKALE Europa Hub | `europa` | ◐ | ✅\* | n/a | n/a | n/a | | SnaxChain | `snax` | ◐ | ✅\* | n/a | n/a | n/a | | Solaxy | `solaxy` | ◐ | ✅\* | n/a | n/a | n/a | | Sommelier | `sommelier-3` | ◐ | ✅\* | n/a | n/a | n/a | | Somnia | `somnia` | ◐ | ✅\* | n/a | n/a | n/a | | Soneium | `soneium` | ◐ | ✅\* | n/a | n/a | n/a | | Sonic | `sonic` | ◐ | ✅\* | n/a | n/a | n/a | | Sonic SVM | `sonic-svm` | ◐ | ✅\* | n/a | n/a | n/a | | Soon | `soon` | ◐ | ✅\* | n/a | n/a | n/a | | Sophon | `sophon` | ◐ | ✅\* | n/a | n/a | n/a | | Sora | `sora` | ◐ | ✅\* | n/a | n/a | n/a | | Source | `source-1` | ◐ | ✅\* | n/a | n/a | n/a | | Space Subnet | `space` | ◐ | ✅\* | n/a | n/a | n/a | | Stable | `stable` | ◐ | ✅\* | n/a | n/a | n/a | | StaFi Hub | `stafihub-1` | ◐ | ✅\* | n/a | n/a | n/a | | Stargaze | `stargaze-1` | ◐ | ✅\* | n/a | n/a | n/a | | Starknet | `starknet` | ◐ | ✅\* | n/a | n/a | n/a | | Starname | `iov-mainnet-ibc` | ◐ | ✅\* | n/a | n/a | n/a | | Story | `story` | ◐ | ✅\* | n/a | n/a | n/a | | Stratos | `stratos-1` | ◐ | ✅\* | n/a | n/a | n/a | | Subsocial | `subsocial` | ◐ | ✅\* | n/a | n/a | n/a | | Subtensor EVM | `bittensor-evm-mainnet` | ◐ | ✅\* | n/a | n/a | n/a | | Sui | `sui` | ◐ | ✅\* | n/a | n/a | n/a | | Sunrise | `sunrise-1` | ◐ | ✅\* | n/a | n/a | n/a | | Superposition | `spn` | ◐ | ✅\* | n/a | n/a | n/a | | SuperSeed | `superseed` | ◐ | ✅\* | n/a | n/a | n/a | | Swellchain | `swellchain` | ◐ | ✅\* | n/a | n/a | n/a | | Symphony | `symphony-1` | ◐ | ✅\* | n/a | n/a | n/a | | Synternet | `synternet-1` | ◐ | ✅\* | n/a | n/a | n/a | | Tac | `tac` | ◐ | ✅\* | n/a | n/a | n/a | | Taiko | `tko-mainnet` | ◐ | ✅\* | n/a | n/a | n/a | | Tangle | `tangle` | ◐ | ✅\* | n/a | n/a | n/a | | Taraxa | `tara` | ◐ | ✅\* | n/a | n/a | n/a | | Telos | `telos` | ◐ | ✅\* | n/a | n/a | n/a | | Telos EVM | `telosevm` | ◐ | ✅\* | n/a | n/a | n/a | | Tempo Mainnet | `tempo` | ◐ | ✅\* | n/a | n/a | n/a | | Tenet | `tenet` | ◐ | ✅\* | n/a | n/a | n/a | | Tenet | `tenet_1559-1` | ◐ | ✅\* | n/a | n/a | n/a | | Teritori | `teritori-1` | ◐ | ✅\* | n/a | n/a | n/a | | Terra | `phoenix-1` | ◐ | ✅\* | n/a | n/a | n/a | | Terra Classic | `columbus-5` | ◐ | ✅\* | n/a | n/a | n/a | | THORChain | `thorchain-1` | ◐ | ✅\* | n/a | n/a | n/a | | Tiltyard Subnet | `tiltyard` | ◐ | ✅\* | n/a | n/a | n/a | | Titan | `titan_18888-1` | ◐ | ✅\* | n/a | n/a | n/a | | TON Mainnet | `ton` | ◐ | ✅\* | n/a | n/a | n/a | | Torus | `tqf` | ◐ | ✅\* | n/a | n/a | n/a | | Treasure | `treasure` | ◐ | ✅\* | n/a | n/a | n/a | | Trump Chain | `trumpchain` | ◐ | ✅\* | n/a | n/a | n/a | | Turbochain | `turbochain` | ◐ | ✅\* | n/a | n/a | n/a | | Unichain | `unichain` | ◐ | ✅\* | n/a | n/a | n/a | | Unification | `fund-mainnet-2` | ◐ | ✅\* | n/a | n/a | n/a | | Unique Network | `unique` | ◐ | ✅\* | n/a | n/a | n/a | | UnUniFi | `ununifi-beta-v1` | ◐ | ✅\* | n/a | n/a | n/a | | Uptick | `uptick_117-1` | ◐ | ✅\* | n/a | n/a | n/a | | UX Chain | `umee-1` | ◐ | ✅\* | n/a | n/a | n/a | | Vana | `vana` | ◐ | ✅\* | n/a | n/a | n/a | | Viction | `viction` | ◐ | ✅\* | n/a | n/a | n/a | | World Chain | `wc` | ◐ | ✅\* | n/a | n/a | n/a | | Wormhole Gateway | `wormchain` | ◐ | ✅\* | n/a | n/a | n/a | | X Layer | `okb` | ◐ | ✅\* | n/a | n/a | n/a | | Xai | `xai` | ◐ | ✅\* | n/a | n/a | n/a | | XANAChain | `xanachain` | ◐ | ✅\* | n/a | n/a | n/a | | Xchain | `intd` | ◐ | ✅\* | n/a | n/a | n/a | | XDC Network | `xdc` | ◐ | ✅\* | n/a | n/a | n/a | | Xion | `xion-mainnet-1` | ◐ | ✅\* | n/a | n/a | n/a | | Xpla | `xpla` | ◐ | ✅\* | n/a | n/a | n/a | | XPLA | `dimension_37-1` | ◐ | ✅\* | n/a | n/a | n/a | | XRPL EVM | `xrplevm_1440000-1` | ◐ | ✅\* | n/a | n/a | n/a | | XRPL Ledger | `xrpl` | ◐ | ✅\* | n/a | n/a | n/a | | Yominet | `yominet-1` | ◐ | ✅\* | n/a | n/a | n/a | | Zaar | `zaar-mainnet-1` | ◐ | ✅\* | n/a | n/a | n/a | | Zcash | `zcash` | ◐ | ✅\* | n/a | n/a | n/a | | Zeitgeist | `zeitgeist` | ◐ | ✅\* | n/a | n/a | n/a | | Zenrock | `diamond-1` | ◐ | ✅\* | n/a | n/a | n/a | | ZERO Network | `zero-network` | ◐ | ✅\* | n/a | n/a | n/a | | ZetaChain | `zetachain-mainnet` | ◐ | ✅\* | n/a | n/a | n/a | | Zilliqa EVM | `zil` | ◐ | ✅\* | n/a | n/a | n/a | | Zircuit | `zircuit-mainnet` | ◐ | ✅\* | n/a | n/a | n/a | | zkLink Nova | `zklink-nova` | ◐ | ✅\* | n/a | n/a | n/a | | zkSync | `zksync` | ◐ | ✅\* | n/a | n/a | n/a | | zkVerify | `zkverify` | ◐ | ✅\* | n/a | n/a | n/a | | Zora | `zora` | ◐ | ✅\* | n/a | n/a | n/a | | Zytron Linea | `zytron-linea` | ◐ | ✅\* | n/a | n/a | n/a |
◐ Partial Address Risk coverage. Results available via direct attribution data or cross-chain propagation only. ✅\* Sanctions list data only, no issuer blacklist monitoring. 🔜 In development. **Planned** = on the roadmap. **n/a** = not supported on this network. *** ## Endpoint Details ### Address Risk Score Returns a risk score (1-10) for a blockchain address based on proximity to known malicious actors, ML-based behavioral analysis, and threat intelligence data. Fully supports 27 networks with complete transaction graph analysis and proximity scoring, and a further 400+ networks with direct attribution data or cross-chain propagation. See [Address Risk Score](/risk-api/risk/get-address-risk-score#supported-networks) for details. ### Sanctions & Blacklist Check Checks if an address is on a sanctions list (OFAC, UK, EU, France, Japan, plus Israeli NBCTF seizure orders and FBI IC3 advisories) or blacklisted by token issuers. Sanctions list data is network-agnostic. Any address published on a list is flagged across all networks we support. Token-issuer blacklist monitoring (Tether, Circle, Coinbase, PayPal, Paxos, Agora, Ripple) covers Ethereum, Tron, Solana, Base, Arbitrum, Optimism, Polygon, and Avalanche. See [Sanctions & Blacklist Check](/risk-api/risk/get-sanctions-blacklist-check) for details. ### Payment Risk Assessment Assesses risk for both sender and recipient in the context of a transaction, including new/dormant wallet detection, address poisoning, interaction history, and cross-chain analysis. Supports all chains listed above with full payment data. Networks without full payment data still benefit from attribution checks and malicious connection analysis. See [Payment Risk Assessment](/risk-api/risk/get-payment-risk-assessment) for details. ### Token Risk Assessment Evaluates the risk of individual tokens based on contract analysis, liquidity patterns, and known scam indicators. Currently supports **Solana** SPL tokens. **Ethereum** support is in development, with **Base**, **Arbitrum**, and **Polygon** on the roadmap. ### Transaction Simulator Simulates transactions before they are submitted onchain to preview outcomes and detect potential risks. Supports **Solana** (`devnet`, `testnet`, `mainnet-beta`); Cosmos networks **Osmosis** (`osmosis-1`) and **Neutron** (`neutron-1`); and EVM networks **Ethereum** (`eth`), **Arbitrum One** (`arb1`), **Base** (`base`), **Optimism** (`oeth`), **Polygon** (`pol`), **BNB Smart Chain** (`bnb`), and **Avalanche C-Chain** (`avax`). See [Simulate Cosmos Transaction](/risk-api/simulator/simulate-cosmos-transaction) and [Simulate an EVM Transaction](/risk-api/simulator/simulate-evm-transaction) for details. *** ## Requesting New Chains Need support for a chain not listed here? [Contact us](https://www.range.org/get-in-touch) with your requirements. We continuously expand network coverage based on customer needs. # Supported Tokens Source: https://docs.range.org/risk-api/product-info/supported-tokens Token coverage for risk assessment and blacklist monitoring across the Risk API. Risk API provides token-level intelligence through two capabilities: **Token Risk Assessment** for evaluating individual token safety, and **Blacklist Monitoring** for tracking token issuer blacklist events. *** ## Token Risk Assessment The [Token Risk Assessment](/risk-api/risk/get-token-risk-assessment) endpoint accepts **any Solana SPL token** by mint address. It evaluates up to 17 independent risk factors across authority controls, market structure, trading patterns, platform signals, and temporal indicators. There is no fixed list of supported tokens, any valid Solana mint address can be assessed. Data availability varies by token, and the API adjusts scoring based on how many factors can be evaluated. ### Test Tokens Use these well-known tokens to test integration and understand response patterns: | Token | Symbol | Mint Address | | - | - | - | | USD Coin | USDC | `EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v` | | Tether USD | USDT | `Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB` | | Wrapped SOL | wSOL | `So11111111111111111111111111111111111111112` | | Jupiter | JUP | `JUPyiwrYJFskUPiHa7hkeR8VUtAeFoSYbKedZNsDvCN` | | Pyth Network | PYTH | `HZ1JovNiVvGrGNiiYvEozEVgZ58xaU3RKwX8eACQBCt3` | | Bonk | BONK | `DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263` | | dogwifhat | WIF | `EKpQGSJtjMFqKZ9KQanSqYXRcF8fBopzLHYxdM65zcjm` | | Popcat | POPCAT | `7GCihgDB8fe6KNjn2MYtkzZcRjQy3t9GHdC8uHYmW2hr` | *** ## Blacklist Monitoring The [Sanctions & Blacklist Check](/risk-api/risk/get-sanctions-blacklist-check) endpoint monitors onchain blacklist events from token issuers in real-time. When an issuer blacklists an address, it is blocked from transferring their tokens. ### Coverage Matrix | Network | USDT (Tether) | USDC (Circle) | EURC (Circle) | cbBTC (Coinbase) | PYUSD (PayPal) | AUSD (Agora) | XAUT (Tether) | RLUSD (Ripple) | USDP, USDG, PAXG, BUSD (Paxos) | | - | :-: | :-: | :-: | :-: | :-: | :-: | :-: | :-: | :-: | | **Ethereum** | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | | **Tron** | ✅ | ✅ | n/a | n/a | n/a | n/a | n/a | n/a | n/a | | **Solana** | ✅ | ✅ | n/a | n/a | ✅ | n/a | n/a | n/a | n/a | | **Base** | n/a | ✅ | ✅ | ✅ | n/a | ✅ | n/a | n/a | n/a | | **Arbitrum** | ✅ | ✅ | n/a | ✅ | ✅ | ✅ | ✅ | n/a | n/a | | **Optimism** | ✅ | ✅ | n/a | n/a | n/a | n/a | n/a | n/a | n/a | | **Polygon** | ✅ | ✅ | n/a | n/a | n/a | ✅ | ✅ | n/a | n/a | | **Avalanche** | ✅ | ✅ | ✅ | n/a | n/a | ✅ | n/a | n/a | n/a | An EVM address is checked by the address alone: a freeze on any of these EVM networks flags it wherever it is screened. `token_status_summary` shows the network of each freeze. ### What's Monitored * **Blacklist events**: When an issuer adds an address to their blacklist * **Unblacklist events**: When an issuer removes an address from their blacklist * **Burns of frozen funds**: When an issuer destroys a frozen address's balance (Tether `DestroyedBlackFunds`, or `DestroyedBlockedFunds` for USDT on the EVM L2s and Avalanche and for XAUT; Paxos wipes), recorded as `destroyedblackfunds` * **Current status**: The `is_token_blacklisted` field reflects the most recent event, so an address that was blacklisted and later unblacklisted shows `false` * **Full history**: The `blacklist_event_history` array provides the complete chronological record, back to each token's launch ### How It Works Range monitors the onchain smart contracts of each token issuer for blacklist, unblacklist and burn events. Events are indexed in real-time, providing up-to-date status for any queried address. See [Risk Data Sources](/risk-api/product-info/risk-data-sources) for more on our data pipeline. *** ## Expanding Coverage Token Risk Assessment currently supports Solana. Blacklist monitoring covers the tokens and networks listed above. Both are continuously expanding. [Contact us](https://www.range.org/get-in-touch) if you need coverage for additional tokens or networks. # Test Addresses Source: https://docs.range.org/risk-api/product-info/test-addresses Test addresses and example inputs for verifying your Risk API integration across all endpoints. Use these addresses and parameters to test your Risk API integration. Each example produces a known, predictable result so you can verify correct parsing, display logic, and error handling. All examples use real onchain data. Responses may shift over time as new threat intelligence becomes available, but the general risk profile of each address should remain stable. *** ## Address Risk Score Test addresses for the [`GET /v1/risk/address`](/risk-api/risk/get-address-risk-score) endpoint. ### High Risk (Score 10 - Directly Malicious) ```bash theme={null} curl -G https://api.range.org/v1/risk/address \ --data-urlencode "address=42RLPACwZPx3vYYmxSueqsogfynBDqXK298EDsNoyoHi" \ --data-urlencode "network=solana" \ -H "Authorization: Bearer YOUR_API_KEY" ``` | Field | Expected | | - | - | | `riskScore` | `10` | | `numHops` | `0` | | `maliciousAddressesFound` | Non-empty (address itself is flagged) | ### Low Risk (Score 1 - Clean Address) ```bash theme={null} curl -G https://api.range.org/v1/risk/address \ --data-urlencode "address=6AwuGoRLd54NTjAWeYZBVHnK4reK78FYpsqe6Z2PvU27" \ --data-urlencode "network=solana" \ -H "Authorization: Bearer YOUR_API_KEY" ``` | Field | Expected | | - | - | | `riskScore` | `1` | | `numHops` | `0` | | `maliciousAddressesFound` | Empty array | ### Attribution Override (System Address) ```bash theme={null} curl -G https://api.range.org/v1/risk/address \ --data-urlencode "address=TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" \ --data-urlencode "network=solana" \ -H "Authorization: Bearer YOUR_API_KEY" ``` | Field | Expected | | - | - | | `riskScore` | `1` | | `attribution` | Present - `"Token Program"` / `"Solana"` / `"CoreToken"` | This address demonstrates the attribution override: despite being close to malicious addresses, it scores 1 because it's a verified system program. ### Additional Test Addresses | Network | Identifier | Address | Expected Score | Description | | - | - | - | :-: | - | | Solana | `solana` | `42RLPACwZPx3vYYmxSueqsogfynBDqXK298EDsNoyoHi` | 10 | Directly malicious | | Solana | `solana` | `6AwuGoRLd54NTjAWeYZBVHnK4reK78FYpsqe6Z2PvU27` | 1 | Clean address | | Ethereum | `eth` | `0x08723392ed15743cc38513c4925f5e6be5c17243` | 10 | Directly malicious | | BNB Smart Chain | `bnb` | `0x279ac60785a2fcb85550eb243b9a42a543171cc7` | 3 | Clean address | | Polygon | `pol` | `0xd56e4eab23cb81f43168f9f45211eb027b9ac7cc` | 3 | Clean address | | Base | `base` | `0x23055618898e202386e6c13955a58d3c68200bfb` | 3 | Clean address | | Arbitrum One | `arb1` | `0x0711dd777ae626ef5e0a4f50e199c7a0e0666857` | 3 | Clean address | | Bitcoin | `bitcoin` | `3BMEXs4aRnQRKBXtfrvmxYMyt3wWkSsnHb` | 3 | Clean address | | Tron | `tron` | `TXJgMdjVX5dKiQaUi9QobwNxtSQaFqccvd` | 3 | Clean address | | Stellar | `stellar` | `GB3RMPTL47E4ULVANHBNCXSXM2ZA5JFY5ISDRERPCXNJUDEO73QFZUNK` | 1 | Clean address | | Celestia | `celestia` | `celestiavaloper1vl3dkus7g0cj4lg0e2jrqk2reukmlht0ee7cr4` | 1 | Clean address | | Osmosis | `osmosis-1` | `osmo1tl43tjmylclp37jduelnwrzeyuef2unxn9c04wrlakmgvzsnmgtqqet6za` | 1 | Clean address | | Cosmos Hub | `cosmoshub-4` | `cosmos10d07y265gmmuvt4z0w9aw880jnsr700j6zn9kn` | 1 | Clean address | *** ## Sanctions & Blacklist Check Test addresses for the [`GET /v1/risk/sanctions`](/risk-api/risk/get-sanctions-blacklist-check) endpoint. ### Sanctioned Address ```bash theme={null} curl "https://api.range.org/v1/risk/sanctions/42RLPACwZPx3vYYmxSueqsogfynBDqXK298EDsNoyoHi?network=solana" \ -H "Authorization: Bearer YOUR_API_KEY" ``` Expect `is_ofac_sanctioned: true` and `is_sanctioned: true`, with an `ofac-sanctioned` entry in `sanctions`. ### Clean Address ```bash theme={null} curl "https://api.range.org/v1/risk/sanctions/6AwuGoRLd54NTjAWeYZBVHnK4reK78FYpsqe6Z2PvU27?network=solana" \ -H "Authorization: Bearer YOUR_API_KEY" ``` Expect no sanctions or blacklist flags: `is_sanctioned: false`, an empty `sanctions` array, and `lists_checked: true`. ### Additional Test Addresses | Network | Identifier | Address | Expected Result | Description | | - | - | - | - | - | | Solana | `solana` | `42RLPACwZPx3vYYmxSueqsogfynBDqXK298EDsNoyoHi` | Sanctioned | OFAC Sanctioned - Sokolovski Rolan | | Solana | `solana` | `6AwuGoRLd54NTjAWeYZBVHnK4reK78FYpsqe6Z2PvU27` | Clean | Binance Deposit | | Ethereum | `eth` | `0x08723392ed15743cc38513c4925f5e6be5c17243` | Sanctioned | OFAC Sanctioned - Lazarus Group (aka APT-C-26) | | Ethereum | `eth` | `0x4e0924d3a751be199c426d52fb1f2337fa96f736` | Clean | Uniswap: LUSD-USDC | | Tron | `tron` | `TBHTJqAy4DhHhmT3dNceJYNRz4SdLofLre` | Sanctioned | OFAC Sanctioned - Wang Yunhe (aka Trafficcarb) | | Bitcoin | `bitcoin` | `3bsyz7qrfsi3nsaov1ff724qagrepjvuhm` | Sanctioned | OFAC Sanctioned - Vasinskyi Yaroslav | | Bitcoin | `bitcoin` | `bc1q72ud4m6zf5g37jkhc2ty95zm5vel9ufdxquqpm` | Sanctioned (UK only) | UK FCDO / OFSI - Rapira Group. `is_ofac_sanctioned: false`, `is_sanctioned: true` | | Ethereum | `eth` | `0x7FF9cFad3877F21d41Da833E2F775dB0569eE3D9` | Sanctioned (OFAC, UK, EU) | Garantex. Four `sanctions` entries: OFAC SDN and UK `direct`, EU sanctions and EU Russia packages `indirect` | | Tron | `tron` | `TW5tokvhEfrb77z98Rc8HqbkzQJ6sxYtGX` | Sanctioned (OFAC, UK) | Xinbi. OFAC SDN (`TCO`) and UK FCDO / OFSI (`GLOBAL-HUMAN-RIGHTS`), both `direct`; also frozen by Tether and Circle | *** ## Payment Risk Assessment Test parameters for the [`GET /v1/risk/payment`](/risk-api/risk/get-payment-risk-assessment) endpoint. ### Payment Response Fields Use this sender and recipient to check response parsing. Read the returned risk level and factors rather than assuming a fixed scenario outcome. ```bash theme={null} curl -G https://api.range.org/v1/risk/payment \ --data-urlencode "sender_address=TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" \ --data-urlencode "recipient_address=7UX2i7SucgLMQcfZ75s3VXmZZY4YRUyJN9X1RgfMoDUi" \ --data-urlencode "amount=1000.0" \ --data-urlencode "sender_network=solana" \ --data-urlencode "recipient_network=solana" \ -H "Authorization: Bearer YOUR_API_KEY" ``` | Field | Expected | | - | - | | `overall_risk_level` | `"low"`, `"medium"`, `"high"`, or `"unknown"` | | `risk_factors` | Array of individual risk assessments | *** ## Token Risk Assessment Test mint addresses for the [`GET /v1/risk/token`](/risk-api/risk/get-token-risk-assessment) endpoint (Solana only). ### Token Request `asset_address` and `network` are required. The endpoint currently supports only `network=solana`. ```bash theme={null} curl -G https://api.range.org/v1/risk/token \ --data-urlencode "asset_address=EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v" \ --data-urlencode "network=solana" \ -H "Authorization: Bearer YOUR_API_KEY" ``` *** ## Integration Checklist Use this checklist to verify your integration handles all response variations: Call Address Risk Score with the high-risk address. Verify your UI displays the critical risk warning and `reasoning` text. Call Address Risk Score with the Token Program address. Verify your UI correctly handles the `attribution` object and shows the override explanation. Call Address Risk Score with a low-risk address. Verify your UI handles empty `maliciousAddressesFound` arrays. Call Payment Risk Assessment with the example sender and recipient. Verify your UI displays all individual `risk_factors` and the `overall_risk_level`. Send a request with an invalid address or missing parameters. Verify your integration handles 400 error responses gracefully. *** ## Error Scenarios Test these inputs to verify your error handling: | Scenario | Input | Expected | | - | - | - | | Missing address | Omit `address` param | `400` - validation error | | Unrecognized network (Address Risk Score) | `address=6AwuGoRLd54NTjAWeYZBVHnK4reK78FYpsqe6Z2PvU27&network=invalid_chain` | `200` - returns `riskScore: 1`, `numHops: 0`, and an empty `maliciousAddressesFound` array | | Zero amount (Payment) | `amount=0` | `400` - amount must be >0 | | Invalid mint address (Token) | `asset_address=not_a_real_address&network=solana` | `400` - invalid Solana address | | Unsupported network (Token) | `network=ethereum` | `400` - only Solana supported | ### Invalid Token Address Response `GET /v1/risk/token` returns HTTP 400 for `asset_address=not_a_real_address` with `network=solana`: ```bash theme={null} curl -G https://api.range.org/v1/risk/token \ --data-urlencode "asset_address=not_a_real_address" \ --data-urlencode "network=solana" \ -H "Authorization: Bearer YOUR_API_KEY" ``` ```json theme={null} { "message": [ "asset_address must be a valid Solana base58 address (32-44 chars, no 0 O I l)" ], "error": "Bad Request", "statusCode": 400 } ``` # Understanding Risk Scores Source: https://docs.range.org/risk-api/product-info/understanding-risk-scores How Range assesses risk across addresses, tokens, payments, and sanctions: methodology, scoring scales, and interpretation guidance. Range's risk scoring engine combines designation lists, counterparty analysis, behavioral detection, and threat intelligence to produce actionable risk assessments. This guide explains how to interpret results across endpoints. For the lists and feeds behind scoring, see [Risk Data Sources](/risk-api/product-info/risk-data-sources). For how customer data is hosted and protected, see [Security at Range](/resources/security). *** ## Scoring Scales Different endpoints use different scales: | Endpoint | Scale | Levels | | - | - | - | | [Address Risk (v2)](/risk-api/risk-v2/get-address-risk) | Severity tier | `none` → `low` → `medium` → `high` → `severe` | | [Address Risk Score (v1)](/risk-api/risk/get-address-risk-score) | 1-10 (numeric) | Very low risk (1) → CRITICAL RISK (10) | | [Token Risk Assessment](/risk-api/risk/get-token-risk-assessment) | 0-100% (percentage) | LOW (\<30%), MEDIUM (30-60%), HIGH (≥60%) | | [Payment Risk Assessment](/risk-api/risk/get-payment-risk-assessment) | Categorical | low, medium, high, unknown | | [Sanctions & Blacklist](/risk-api/risk/get-sanctions-blacklist-check) | Boolean, plus one entry per list | `is_sanctioned` (any government list; `null` when a list could not be read), `is_ofac_sanctioned` (OFAC only), `is_token_blacklisted`, `sanctions` | **Address Risk (v2)** is the current address-screening model. The v1 numeric score remains available for existing integrations. *** ## Address Risk (v2) [Score a Single Address](/risk-api/risk-v2/get-address-risk) evaluates an address across **three independent pillars**. Each pillar produces its own signals. A signal that fires carries a severity, and the address's overall result is the **worst single signal** across all three pillars. There is no blended composite score. | Pillar | Question it answers | Basis | | - | - | - | | **Attribution** | Is this address itself flagged? | Designation lists and threat intelligence | | **Exposure** | Who has it transacted with? | Counterparty graph and labeled entities | | **Behaviour** | Does its activity look suspicious? | Transaction-pattern detection | ### Severity | Severity | Typical meaning | | - | - | | **None** | No enabled signal fired | | **Low** | Noted, usually no action required | | **Medium** | Review at analyst discretion | | **High** | Review before proceeding | | **Severe** | Block or escalate | Alongside severity, assessments return USD volume totals and how much of that volume involved flagged counterparties. ### Configuration Scoring policy is **per workspace**. Range publishes a catalogue of signals and behaviours ([List Signals & Behaviours](/risk-api/risk-v2/get-signals)), but what runs for your workspace is what you enable and how you set severity and thresholds ([Get Risk Configuration](/risk-api/risk-v2/get-config) / [Update Risk Configuration](/risk-api/risk-v2/put-config)). You can: * Enable or disable individual attribution signals, exposure signals, and behaviours * Set the severity for attribution categories * Set exposure and behaviour thresholds that map observed activity to severity tiers * Detect a behaviour without letting it drive the overall severity Two workspaces can screen the same address and reach different conclusions when their policies differ, for example on gambling exposure or privacy-protocol usage. ### Score and evidence A score request returns severity and the signals that fired. Full justification (counterparties, designation detail, transactions, and detected patterns) is retrieved separately with the assessment's `screen_id` via [Fetch Assessment Evidence](/risk-api/risk-v2/get-evidence). You can also request evidence inline with `include_evidence=true`. That split keeps screening fast in payment and onboarding flows, while keeping an audit trail available when someone needs to explain a decision. ### Attribution, exposure, and behaviour **Attribution** answers whether the address itself is designated or identified, for example sanctions, blacklisting, hacks, scams, or other threat categories. Attribution also covers known-good infrastructure (protocols, exchanges, system programs) so high-volume legitimate activity is not treated as risk purely because of volume. **Exposure** looks at who the address has sent to and received from, and how those counterparties are labeled. Exposure is expressed as a share of counterparty activity against the thresholds you configure, not as a single opaque number that decays with distance. **Behaviour** detects suspicious transaction patterns, for example rapid movement of funds, structuring into many small transfers, or peeling funds through a chain of wallets. Detectors return a confidence that maps to severity through your workspace thresholds. ### Sources at a glance Address Risk draws on official sanctions and compliance lists, onchain stablecoin issuer blacklists, Range's own indexing and threat research, and security partnerships. The full catalogue is on [Risk Data Sources](/risk-api/product-info/risk-data-sources). Access to the most sensitive intelligence requires KYB verification. Full wallet attribution and advanced risk intelligence are available only to verified teams with legitimate use cases. *** ## Address Risk Score (v1) The [Address Risk Score](/risk-api/risk/get-address-risk-score) endpoint returns a **1-10** score based on proximity to known malicious addresses, machine-learning signals, and threat intelligence. Sanctions and stablecoin blacklist hits are included in the score. | Score | Risk Level | Typical Situation | | -: | - | - | | **10** | CRITICAL RISK (directly malicious) | Address itself is flagged (0 hops) | | **9-8** | Extremely high risk | 1 hop from malicious; ≥3 hits → 9, otherwise 8 | | **7-6** | High risk | 2 hops; ≥3 hits → 7, otherwise 6 | | **5-4** | Medium risk | 3 hops; ≥3 hits → 5, otherwise 4 | | **3-2** | Low risk | 4 hops; ≥3 hits → 3, otherwise 2 | | **1** | Very low risk | ≥5 hops OR known attributed non-malicious address | **Search depth:** Risk analysis examines paths up to 5 hops from the input address. Addresses with no connections to malicious entities within this range receive score 1. Known non-malicious addresses (system programs, verified protocols, major exchanges) receive the minimum score. Prefer **Address Risk (v2)** for new integrations: configurable pillars, severity tiers, and a dedicated evidence API. Keep v1 where you already depend on the numeric scale. *** ## Token Risk Scoring (Percentage Scale) The [Token Risk Assessment](/risk-api/risk/get-token-risk-assessment) evaluates up to 17 independent risk factors across 5 categories. Each factor scores: * **LOW** = 0 points * **MEDIUM** = 1 point * **HIGH** = 2 points The risk percentage is: `(total_score / max_possible_score) × 100` | Classification | Threshold | | - | - | | **HIGH RISK** | ≥60% of maximum possible score | | **MEDIUM RISK** | ≥30% but \<60% | | **LOW RISK** | \<30% | Not all 17 factors may be assessed for every token due to data availability. The API adjusts the maximum possible score based on how many factors were successfully evaluated. ### Token Risk Factor Summary | Factor | Category | HIGH | MEDIUM | LOW | | - | - | - | - | - | | Circulating Supply Ratio | Authority & Control | \<80% | 80-95% | >95% | | Freeze Authority | Authority & Control | Present | - | Absent/Disabled | | Mint Authority | Authority & Control | Present | - | Absent/Disabled | | Market Capitalization | Market Structure | \<\$1M | $1M-$100M | >\$100M | | Token Verification | Market Structure | Unverified | - | Verified | | Liquidity | Market Structure | \<\$10K | $10K-$100K | >\$100K | | Holder Count | Market Structure | \<100 | 100-1000 | >1000 | | Top Holder Concentration | Market Structure | >90% | 80-90% | \<80% | | Price Volatility | Trading Patterns | >50% | 20-50% | \<20% | | Wash Trading | Trading Patterns | Suspicious ≥2 TF | - | Normal | | Organic Activity | Trading Patterns | Low | Medium | High | | Developer Migrations | Platform & Social | ≥5 | 2-4 | \<2 | | Exchange Listings | Platform & Social | No listings | \<3/no major | Major exchanges | | Launchpad Platform | Platform & Social | High-risk (pump.fun) | - | Other platforms | | Social Media Presence | Platform & Social | No presence | - | Active presence | | Token Age | Temporal | \<7 days | 7-30 days | >30 days | | Graduation Status | Temporal | - | \<7 days | >7 days/N/A | See [Token Risk Assessment](/risk-api/risk/get-token-risk-assessment#risk-factors) for detailed explanations of each factor. *** ## Payment Risk Scoring (Maximum Risk Approach) The [Payment Risk Assessment](/risk-api/risk/get-payment-risk-assessment) runs up to 8 independent assessments. The overall risk level uses a **maximum risk approach**: if any individual factor returns "high", the overall risk is "high". | Assessment | What It Checks | | - | - | | New Wallet Detection | Recipient transaction history | | Dormant Wallet Detection | Recipient inactivity (>180 days) | | Address Poisoning Detection | Poison address pattern matching | | Interaction History | Previous sender-recipient relationship | | Malicious Connection Analysis | Proximity to malicious addresses | | Attributed Address Check | Known entity database lookup | | Token Risk (Solana) | Token-specific risk factors | | Cross-Chain Support | Appropriate index selection for cross-chain payments | *** ## Best Practices * **Prefer Address Risk (v2) for new screening flows.** Use severity and triggered signals; fetch evidence when you need to justify a decision. * **Calibrate policy to your use case.** Configure which signals matter and at what severity. A payments processor and a fund may disagree on the same exposure. * **Don't rely on a single endpoint for high-value flows.** Combine address screening with payment risk and sanctions checks where relevant. * **Handle "unknown" gracefully.** Payment Risk returns `"unknown"` for unsupported networks. That means insufficient data, not "safe." * **Cache cautiously.** Risk can change as designations and intelligence update. For compliance-critical flows, query in real time. * **Show context to end users.** Prefer severity (or `riskLevel` / `reasoning` on v1) over a bare number. # Risk API Quick Start Source: https://docs.range.org/risk-api/quickstart Make your first Risk API calls and learn how to interpret the responses. This guide walks you through your first calls to each Risk API endpoint. It covers request formats, address and payment response fields, sanctions results, and token validation errors. **You'll need an API key.** All requests require a Bearer token. If you don't have one yet, [get your API key →](/introduction/getting-started) *** ## Authentication Every Risk API request uses the same authentication pattern. Pass your API key in the `Authorization` header: ``` Authorization: Bearer YOUR_API_KEY ``` **Base URL:** `https://api.range.org` Keep your API key server-side. Never expose it in client-side code or public repositories. *** ## 1. Screen an Address The [Address Risk Score](/risk-api/risk/get-address-risk-score) endpoint is the most commonly used starting point. It returns a risk score (1-10) for any blockchain address across [27 supported networks](/risk-api/product-info/supported-chains). ```bash cURL theme={null} curl -G https://api.range.org/v1/risk/address \ --data-urlencode "address=TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" \ --data-urlencode "network=solana" \ -H "Authorization: Bearer YOUR_API_KEY" ``` ```javascript JavaScript theme={null} const params = new URLSearchParams({ address: "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", network: "solana", }); const response = await fetch( `https://api.range.org/v1/risk/address?${params}`, { headers: { Authorization: "Bearer YOUR_API_KEY" } } ); const data = await response.json(); ``` ```python Python theme={null} import requests response = requests.get( "https://api.range.org/v1/risk/address", headers={"Authorization": "Bearer YOUR_API_KEY"}, params={ "address": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", "network": "solana", }, ) data = response.json() ``` ```json theme={null} { "riskScore": 1, "riskLevel": "Very low risk", "numHops": 2, "maliciousAddressesFound": [ { "address": "CPMMoo8L3F4NbTegBCKVNunggL7H1ZpdTHKxQB5qKP1C", "distance": 2, "name_tag": "", "entity": "", "category": "" } ], "reasoning": "Despite being 2 hop(s) from malicious addresses, this is a known system address (Token Program - Solana). Risk overridden to very low.", "attribution": { "name_tag": "Token Program", "entity": "Solana", "category": "CoreToken" } } ``` ### Key Response Fields | Field | What It Tells You | | - | - | | `riskScore` | Numerical risk (1-10). Higher = more dangerous. | | `riskLevel` | Human-readable label for the score. | | `numHops` | Shortest path distance to a known malicious address. `0` means the address itself is malicious. | | `maliciousAddressesFound` | The evidence - which malicious addresses were found and how far away they are. | | `reasoning` | Plain-English explanation of why the score was assigned. Display this to users. | | `attribution` | If present, this is a verified non-malicious entity (exchange, system program, protocol). The score is overridden to 1. | ### What the Scores Mean | Score | Meaning | Typical Action | | -: | - | - | | **10** | Directly malicious (0 hops) | Block | | **8-9** | 1 hop from malicious | Block or flag | | **6-7** | 2 hops from malicious | Flag for review | | **4-5** | 3 hops from malicious | Monitor | | **1-3** | Low risk or verified entity | Allow | *** ## 2. Check Sanctions & Blacklists The [Sanctions & Blacklist Check](/risk-api/risk/get-sanctions-blacklist-check) endpoint screens an address against every sanctions list Range ingests (OFAC, UK, EU, France, Japan, and more) and token issuer blacklists (Tether, Circle, Coinbase, PayPal, Paxos, Agora, Ripple). ```bash cURL theme={null} curl -G "https://api.range.org/v1/risk/sanctions/0x1da5821544e25c636c1417ba96ade4cf6d2f9b5a" \ --data-urlencode "include_details=false" \ -H "Authorization: Bearer YOUR_API_KEY" ``` ```javascript JavaScript theme={null} const address = "0x1da5821544e25c636c1417ba96ade4cf6d2f9b5a"; const response = await fetch( `https://api.range.org/v1/risk/sanctions/${address}?include_details=false`, { headers: { Authorization: "Bearer YOUR_API_KEY" } } ); const data = await response.json(); ``` ```python Python theme={null} import requests address = "0x1da5821544e25c636c1417ba96ade4cf6d2f9b5a" response = requests.get( f"https://api.range.org/v1/risk/sanctions/{address}", headers={"Authorization": "Bearer YOUR_API_KEY"}, params={"include_details": "false"}, ) data = response.json() ``` The detail arrays below show only their first entry. ```json theme={null} { "address": "0x1da5821544e25c636c1417ba96ade4cf6d2f9b5a", "network": "eth", "is_token_blacklisted": true, "is_ofac_sanctioned": true, "token_status_summary": [ { "token": "USDC", "issuer": "Circle", "network": "eth", "is_currently_blacklisted": true, "first_blacklisted_date": "2021-04-21", "last_event_date": "2021-04-21", "last_event_type": "blacklist" } ], "blacklist_event_history": [ { "event_type": "blacklist", "token": "USDC", "issuer": "Circle", "network": "eth", "date": "2021-04-21", "block_number": 12285873, "block_timestamp": "2021-04-21T21:04:36.000Z", "transaction_hash": "0x72959622df120df8cfe27fa371c5b82542cda695d09568975259c0cf70430bf9" } ], "ofac_info": { "is_sanctioned": true, "name_tag": "Secondeye Solution", "category": "OFAC Sanctioned", "entity": "OFAC", "address_role": "Entity", "first_sanctioned_date": "2021-04-15", "programs": [ "CYBER2", "ELECTION-EO13848" ], "aliases": [ "Forwarderz" ] }, "attribution": { "name": "Secondeye Solution", "category": "Multi-Provider Blacklist & OFAC Sanctioned", "malicious": true }, "checked_at": "2026-10-03T15:45:58.379Z", "lists_checked": true, "sanctions": [ { "signal_id": "ofac-sanctioned", "source": "OFAC SDN", "jurisdiction": "US", "listed_at": "2021-04-15", "programs": [ "CYBER2", "ELECTION-EO13848" ], "basis": "direct" } ], "is_sanctioned": true } ``` ### Key Response Fields | Field | What It Tells You | | - | - | | `is_token_blacklisted` | `true` if **currently** blacklisted by any stablecoin issuer. | | `is_sanctioned` | `true` if the address is on any government sanctions list (OFAC, UK, EU, France, Japan). `null` when a list could not be read: treat as unknown, not clean. | | `is_ofac_sanctioned` | `true` if the address appears on the OFAC SDN list. OFAC only. | | `sanctions` | One entry per list the address is on, with `source`, `jurisdiction`, `listed_at`, `programs`, and `basis`. | | `lists_checked` | `false` when a sanctions or blacklist store could not be read and the result may be incomplete. | | `token_status_summary` | Per-token breakdown (which issuers, when blacklisted). Returned when blacklist data exists. | | `blacklist_event_history` | Full chronological event log. Returned when blacklist data exists. | | `ofac_info` | Sanction details including name, entity, and official OFAC URL. | ### Compatibility Parameter `include_details` is accepted for compatibility but ignored. Both `true` and `false` return the same detail fields; `false` does not produce a minimal response. The Address Risk Score endpoint already includes sanctions and blacklist data in its scoring. Use this standalone endpoint when you need explicit sanctions documentation for audit trails, or the detailed event history. *** ## 3. Assess Payment Risk The [Payment Risk Assessment](/risk-api/risk/get-payment-risk-assessment) endpoint is the most comprehensive check. It analyzes both sender and recipient across 8 independent risk dimensions - including everything Address Risk Score does, plus payment-specific checks. ```bash cURL theme={null} curl -G https://api.range.org/v1/risk/payment \ --data-urlencode "sender_address=TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" \ --data-urlencode "recipient_address=7UX2i7SucgLMQcfZ75s3VXmZZY4YRUyJN9X1RgfMoDUi" \ --data-urlencode "amount=1000.0" \ --data-urlencode "sender_network=solana" \ --data-urlencode "recipient_network=solana" \ -H "Authorization: Bearer YOUR_API_KEY" ``` ```javascript JavaScript theme={null} const params = new URLSearchParams({ sender_address: "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", recipient_address: "7UX2i7SucgLMQcfZ75s3VXmZZY4YRUyJN9X1RgfMoDUi", amount: "1000.0", sender_network: "solana", recipient_network: "solana", }); const response = await fetch( `https://api.range.org/v1/risk/payment?${params}`, { headers: { Authorization: "Bearer YOUR_API_KEY" } } ); const data = await response.json(); ``` ```python Python theme={null} import requests response = requests.get( "https://api.range.org/v1/risk/payment", headers={"Authorization": "Bearer YOUR_API_KEY"}, params={ "sender_address": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", "recipient_address": "7UX2i7SucgLMQcfZ75s3VXmZZY4YRUyJN9X1RgfMoDUi", "amount": "1000.0", "sender_network": "solana", "recipient_network": "solana", }, ) data = response.json() ``` Only the first two risk factors are shown. Timing values vary between requests. ```json theme={null} { "overall_risk_level": "medium", "risk_factors": [ { "risk_context": "interaction", "factor": "first_interaction", "risk_level": "medium", "description": "First ever interaction between these addresses" }, { "risk_context": "recipient", "factor": "established_wallet_recipient", "risk_level": "low", "description": "Recipient has on-chain signatures; last activity 270 days ago" } ], "processing_time_ms": 120.26670202612877, "errors": [] } ``` ### Key Response Fields | Field | What It Tells You | | - | - | | `overall_risk_level` | Final verdict: `"low"`, `"medium"`, `"high"`, or `"unknown"`. Uses maximum-risk approach - if any factor is high, the overall level is high. | | `risk_factors` | Array of individual assessments. Each has a `factor` name, `risk_level`, and `description`. | | `errors` | Non-empty if some checks couldn't be performed (e.g., unsupported network for some checks). | ### Risk Dimensions Checked | Check | What It Detects | | - | - | | New wallet detection | Recipient has no transaction history | | Dormant wallet detection | Recipient inactive for 180+ days | | Address poisoning | Recipient matches a lookalike scam address | | Interaction history | Sender and recipient have never transacted before | | Malicious connections | Sender or recipient is close to known malicious addresses | | Attributed address check | Sender or recipient is a known sanctioned or blacklisted entity | | Token risk | Sender/recipient tokens have risk factors (Solana, requires `sender_token`/`recipient_token`) | | Cross-chain analysis | Appropriate checks for same-network vs cross-chain payments | *** ## 4. Evaluate a Token The [Token Risk Assessment](/risk-api/risk/get-token-risk-assessment) endpoint accepts a Solana token mint as `asset_address` and requires `network=solana`. The request below uses USDC: ```bash cURL theme={null} curl -G "https://api.range.org/v1/risk/token" \ --data-urlencode "asset_address=EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v" \ --data-urlencode "network=solana" \ -H "Authorization: Bearer YOUR_API_KEY" ``` ```javascript JavaScript theme={null} const params = new URLSearchParams({ asset_address: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", network: "solana", }); const response = await fetch( `https://api.range.org/v1/risk/token?${params}`, { headers: { Authorization: "Bearer YOUR_API_KEY" } } ); const data = await response.json(); ``` ```python Python theme={null} import requests response = requests.get( "https://api.range.org/v1/risk/token", headers={"Authorization": "Bearer YOUR_API_KEY"}, params={ "asset_address": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", "network": "solana", }, ) data = response.json() ``` *** ## Common Errors | HTTP Code | Meaning | What to Do | | -: | - | - | | **400** | Invalid parameters (missing address, bad format) | Check your query parameters. | | **401** | Invalid or missing API key | Verify your `Authorization: Bearer` header. | | **404** | Address or network not found | Check the network identifier against [Supported Chains](/risk-api/product-info/supported-chains). | | **429** | Rate limit exceeded | Implement exponential backoff. See [Rate Limits](/risk-api/product-info/rate-limits). | | **5xx** | Server error | Retry after a delay. Contact support if persistent. | ### Invalid Token Address `GET /v1/risk/token` returns HTTP 400 for `asset_address=not_a_real_address` with `network=solana`: ```bash theme={null} curl -G https://api.range.org/v1/risk/token \ --data-urlencode "asset_address=not_a_real_address" \ --data-urlencode "network=solana" \ -H "Authorization: Bearer YOUR_API_KEY" ``` ```json theme={null} { "message": [ "asset_address must be a valid Solana base58 address (32-44 chars, no 0 O I l)" ], "error": "Bad Request", "statusCode": 400 } ``` *** ## What's Next More test addresses across all endpoints and networks for verifying your integration. Deep dive into how scores are calculated and how to interpret them. Build a multi-layered screening workflow combining multiple endpoints. Add real-time risk protection to wallets and dApps. # Risk API Source: https://docs.range.org/risk-api/risk-introduction Comprehensive risk scoring and threat detection for blockchain addresses, transactions, tokens, and smart contracts. Range's Risk API provides real-time risk intelligence for blockchain activity. Screen addresses for proximity to malicious actors, assess token legitimacy, evaluate payment safety, and check sanctions compliance - all through a unified API. **Authentication required.** All Risk API requests require a Bearer token in the `Authorization` header. [Get your API key →](/introduction/getting-started) **Base URL:** `https://api.range.org` *** ## Which Endpoint Should I Use? | I want to... | Endpoint | Networks | | - | - | - | | Screen an address with configurable severity, signals, and evidence | [Address Risk (v2)](/risk-api/risk-v2/get-address-risk) | See [Supported Chains](/risk-api/product-info/supported-chains) | | Get a classic 1-10 proximity score for an address | [Address Risk Score (v1)](/risk-api/risk/get-address-risk-score) | Solana, EVM chains, Stellar, Bitcoin, Tron, Cosmos and more [see all](/risk-api/product-info/supported-chains) | | Evaluate end-to-end payment safety between two addresses | [Payment Risk Assessment](/risk-api/risk/get-payment-risk-assessment) | Solana, Stellar, Cosmos [see all](/risk-api/product-info/supported-chains) | | Check sanctions lists (OFAC, UK, EU, and more) and token issuer blacklists | [Sanctions & Blacklist Check](/risk-api/risk/get-sanctions-blacklist-check) | All (sanctions lists), Ethereum, Tron, Solana, Base, Arbitrum, Optimism, Polygon, Avalanche (blacklists) | | Assess the risk profile of a token | [Token Risk Assessment](/risk-api/risk/get-token-risk-assessment) | Solana | | Screen an unsigned transaction before signing | [Scan an Unsigned Transaction](/risk-api/risk-v2/scan-unsigned-transaction) | Solana | | Simulate a transaction before broadcasting | [Transaction Simulator](/risk-api/simulator/simulate-solana-transaction) | Solana, Osmosis, Neutron, and EVM (`eth`, `arb1`, `base`, `oeth`, `pol`, `bnb`, `avax`). See [Simulate an EVM Transaction](/risk-api/simulator/simulate-evm-transaction) | *** ## Quick Start New to the Risk API? The [Quick Start guide](/risk-api/quickstart) walks you through your first calls to each endpoint with example requests and response interpretation. Make your first API calls and learn how to interpret the responses. *** ## Risk Endpoints Configurable address screening across attribution, exposure, and behaviour, with severity tiers and evidence. Classic 1-10 address risk score using proximity analysis and threat detection. Multi-factor risk analysis for Solana tokens across 17 independent risk factors. End-to-end risk evaluation for payment transactions and fund transfers. Sanctions list screening (OFAC, UK, EU, and more) and stablecoin issuer blacklist checks. Pre-signature Solana scan: simulate, screen counterparties, and check poisoning. ### Coming Soon Risk scoring for individual blockchain transactions. Security vulnerability assessment for Solana smart contracts. *** ## Alerts Monitor fired alert events through the Risk API. Channel, template, and rule management lives in the [Platform API](/platform-api/api-reference-introduction). List and inspect fired alert events for your workspace. Manage channels, templates, and alert rules in the Platform API reference. *** ## How Risk Scoring Works Address Risk (v2) scores addresses across **attribution**, **exposure**, and **behaviour**, with a workspace-configurable severity model and a separate evidence API. For methodology and how to interpret scores across endpoints, see [Understanding Risk Scores](/risk-api/product-info/understanding-risk-scores). Address Risk (v2) evaluates whether an address is itself flagged, who it has transacted with, and whether its activity patterns look suspicious, then takes the worst signal severity as the overall result. Workspaces choose which signals apply and how severity thresholds are set. The same address can produce different outcomes under different policies. Integrates official sanctions and compliance lists, onchain issuer blacklists, confirmed exploits, scams, phishing, and other verified malicious activity sources. See [Risk Data Sources](/risk-api/product-info/risk-data-sources). The classic Address Risk Score (v1) uses network proximity and ML behavioral signals to produce a 1-10 score. Prefer v2 for new integrations. *** ## Guides Step-by-step guides for common integration patterns: Build an automated AML/KYC workflow combining address, sanctions, and payment risk checks. Add real-time risk protection to Solana wallets and dApps. Evaluate token safety before listing, trading, or integrating. Validate transactions before broadcasting with pre-flight simulation. Verify wallet risk directly inside Solana programs using Switchboard oracles. Detect address poisoning, new wallet fraud, and social engineering scams. Screen wallets before deposits to keep tainted funds out of your protocol. # Score a Single Address Source: https://docs.range.org/risk-api/risk-v2/get-address-risk get /v2/risk/address Retrieve an address risk assessment with its overall severity and contributing signals, optionally running only the signals you select. # Score Multiple Addresses Source: https://docs.range.org/risk-api/risk-v2/get-address-risk-batch get /v2/risk/address/batch Retrieve risk assessments for up to 50 addresses in one request, with each address's network derived automatically. # Get Risk Configuration Source: https://docs.range.org/risk-api/risk-v2/get-config get /v2/risk/config Returns the workspace risk configuration including exposure signals, behaviours, tier thresholds, and defaults. # Fetch Assessment Evidence Source: https://docs.range.org/risk-api/risk-v2/get-evidence get /v2/risk/evidence/{screenId} Fetch full evidence for a previous address screen or pre-signature transaction scan using its screen ID. # List Signals & Behaviours Source: https://docs.range.org/risk-api/risk-v2/get-signals get /v2/risk/signals Returns the full catalogue of available exposure signals and behaviour detectors with default severities, weights, and supported modes. For the sanctions list each sanctions signal reports, and for related signals such as `compliance-risk` and `fbi-fraud` that are not sanctions lists, see [Risk Data Sources](/risk-api/product-info/risk-data-sources). # List Transaction Scans Source: https://docs.range.org/risk-api/risk-v2/list-transaction-scans get /v2/risk/transaction/scans List the most recent transaction scans for your workspace, newest first, without consuming scan credits. # Update Risk Configuration Source: https://docs.range.org/risk-api/risk-v2/put-config api-reference/risk-api.json patch /v2/risk/config Partially update your workspace risk configuration by sending only the fields to change, leaving omitted fields and rows as they are. # Scan an Unsigned Transaction Source: https://docs.range.org/risk-api/risk-v2/scan-unsigned-transaction post /v2/risk/transaction/scan Screens a whole Solana transaction before it is signed: simulation, Address Risk (v2) on counterparties, and address-poisoning checks. Screens a complete transaction before the user signs it and returns one verdict for the whole transaction. Send the serialized unsigned transaction exactly as the wallet holds it before signing. Range simulates it, screens up to 50 wallets whose balances change or that gain control of an account, checks recipients for address poisoning, and runs transaction-level rules such as authority changes. This version supports Solana only. The response uses the same severity ladder as [Score a Single Address](/risk-api/risk-v2/get-address-risk), so a wallet or dApp can apply one policy to address screens and transaction scans. **Gate on coverage, not only on `severity`.** `meta.poisoning_screened: false` means recipients were not checked for lookalikes, and `meta.counterparties_screened_complete: false` means at least one counterparty was not screened. Neither is a clean result. A gap in counterparty screening already raises `severity` to at least `medium`. A poisoning check that did not run does not, so check that flag separately. *** ## How the Scan Works 1. **Decode.** The `transaction` string is decoded with `encoding` (base64 by default). A payload that does not decode returns HTTP 400. 2. **Simulate.** The transaction is simulated against current chain state. It does not need to be signed. The predicted balance changes, state changes, and invoked programs are returned in `simulation`. 3. **Select counterparties.** Range picks the wallets to screen: * `asset-diff`: wallets whose balance changes, with token accounts resolved to their owner wallet. * `permission-target`: accounts that gain control through `setAuthority`, `approve`, `approveChecked`, `assign`, or `assignWithSeed`, including instructions reached through cross-program invocation (CPI). * `static-account`: the accounts declared in the payload, used only when simulation is unavailable. The signer, invoked programs, and core Solana programs (System, SPL Token, Token-2022, Associated Token, Compute Budget, Memo, Stake, Vote, Address Lookup Table) are never screened. Up to 50 counterparties are screened per scan. When more are selected, permission targets take at most 25 of the slots and the rest go to the largest balance changes. 4. **Screen in parallel.** Each counterparty runs through Address Risk (v2), credited wallets are checked for address poisoning, and transaction rules run on the simulation. 5. **Combine.** `severity` is the worst single result across `counterparties` and `findings`, ignoring informational findings. Every scan is stored for the workspace behind the API key. List them with [List Transaction Scans](/risk-api/risk-v2/list-transaction-scans) and fetch the full per-counterparty assessments with [Fetch Assessment Evidence](/risk-api/risk-v2/get-evidence) using `screen_id`. *** ## Request Body | Field | Type | Required | Description | | - | - | - | - | | `network` | string | Yes | Must be `solana`. | | `transaction` | string | Yes | The complete serialized unsigned transaction (account list, instructions, blockhash) as one encoded string. Up to 4,096 characters; a Solana transaction is at most 1,232 bytes. Legacy and versioned transactions are accepted. | | `encoding` | string | No | `base64` (default) or `base58`. | | `signer_address` | string | No | The account that will sign. Defaults to the fee payer. A value that is not a required signer of the transaction is ignored: the fee payer is used and the `signer-address-ignored` note is returned. | | `origin` | string | No | The dApp URL that produced the transaction. Stored with the scan. Up to 2,048 characters. | ## Example Request This transaction sends 0.5 SOL to the clean Solana address from [Test Addresses](/risk-api/product-info/test-addresses). Copy it as is to try the endpoint. ```bash cURL theme={null} curl -X POST "https://api.range.org/v2/risk/transaction/scan" \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "network": "solana", "transaction": "AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAEDfowIh2C/3h3dzzLBfyCbgkLuUqrxMfrNiNDqLG0LBvJM1r0sCJ2KySbkJLj1EmFlWXx/7Y4DeP3JYWhV/axT1AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAgIAAQwCAAAAAGXNHQAAAAA=", "encoding": "base64" }' ``` ```javascript JavaScript theme={null} // `transaction` is a @solana/web3.js Transaction, before signing. const encoded = transaction .serialize({ requireAllSignatures: false, verifySignatures: false }) .toString('base64'); const response = await fetch('https://api.range.org/v2/risk/transaction/scan', { method: 'POST', headers: { Authorization: 'Bearer YOUR_API_KEY', 'Content-Type': 'application/json', }, body: JSON.stringify({ network: 'solana', transaction: encoded, encoding: 'base64', origin: 'https://app.example.com', }), }); const scan = await response.json(); ``` ```python Python theme={null} import requests response = requests.post( "https://api.range.org/v2/risk/transaction/scan", headers={"Authorization": "Bearer YOUR_API_KEY"}, json={ "network": "solana", "transaction": encoded_transaction, # base64 string of the unsigned transaction "encoding": "base64", }, ) scan = response.json() ``` For a `VersionedTransaction`, encode it with `Buffer.from(transaction.serialize()).toString('base64')`; it serializes without requiring signatures. ## Example Response ```json theme={null} { "screen_id": "c1f3d878-a6e0-4c93-a4ea-dca26189b6c6", "network": "solana", "payload_sha256": "c0242054122a717af894b90f31b6cdcded6dc4cc9869583fecc552bcebc56d05", "signer": "9WzDXwBbmkg8ZTbNMqUxvQRAyrZzDsGYdLVL9zYtAWWM", "severity": "none", "intent": null, "simulation": { "simulation_success": true, "asset_diffs": [ { "account": "9WzDXwBbmkg8ZTbNMqUxvQRAyrZzDsGYdLVL9zYtAWWM", "asset": "SOL", "amount": 0.5, "direction": "debit" }, { "account": "6AwuGoRLd54NTjAWeYZBVHnK4reK78FYpsqe6Z2PvU27", "asset": "SOL", "amount": 0.5, "direction": "credit" } ], "state_changes": ["Sent 0.5 SOL", "Received 0.5 SOL"], "programs_invoked": [ { "name": "system", "id": "11111111111111111111111111111111" } ] }, "counterparties": [ { "address": "6AwuGoRLd54NTjAWeYZBVHnK4reK78FYpsqe6Z2PvU27", "source": "asset-diff", "severity": "none", "triggered_signals": [] } ], "findings": [], "notes": [], "timestamp": "2026-10-02T09:05:19.815Z", "meta": { "counterparties_screened": 1, "counterparties_screened_complete": true, "coverage_truncated": false, "poisoning_screened": true, "simulate_ms": 106, "screening_ms": 450, "poisoning_ms": 1295, "intent_ms": 0, "total_ms": 1412 } } ``` The same transfer sent to the sanctioned Solana test address `42RLPACwZPx3vYYmxSueqsogfynBDqXK298EDsNoyoHi` returns that counterparty with `severity: "severe"` and `ofac-sanctioned` in `triggered_signals`, so the scan `severity` is `severe`. *** ## Response Fields | Field | Type | Description | | - | - | - | | `screen_id` | string | ID of this scan. Pass it to [Fetch Assessment Evidence](/risk-api/risk-v2/get-evidence). | | `network` | string | Always `solana`. | | `payload_sha256` | string | SHA-256 of the decoded `transaction` bytes as sent, signature slots included. The same payload always gives the same value; the signed transaction hashes differently. | | `signer` | string | The signing account the scan assumed: `signer_address` when it is a required signer, otherwise the fee payer. | | `severity` | string | `none`, `low`, `medium`, `high`, or `severe`. The worst single result across `counterparties` and `findings`. | | `intent` | null | Reserved for the transaction's extracted intent (`summary`, `action`, `confidence`). Intent extraction is not enabled, so `intent` is always `null`. | | `simulation` | object \| null | Predicted effects of executing the transaction. `null` when the transaction could not be simulated. | | `counterparties` | array | Each screened wallet with its `source`, Address Risk (v2) `severity`, and `triggered_signals`. | | `findings` | array | Transaction-level signals. See [Findings](#findings). | | `notes` | array | Coverage caveats as `code` and `message`. See [Notes](#notes). | | `timestamp` | string | When the scan ran (ISO 8601). | | `meta` | object | Coverage flags and timings. See [Meta](#meta). | ### Simulation | Field | Type | Description | | - | - | - | | `simulation_success` | boolean | `false` when the transaction would fail if submitted. A failed transaction also raises the `simulation-error` finding. | | `asset_diffs` | array | One entry per balance change: `account`, `owner` (the wallet behind a token account, when resolved), `asset` (token mint, or `SOL`), `amount` in token units, and `direction` (`credit` or `debit`). | | `state_changes` | array | Human-readable predicted changes, for example `Sent 0.5 SOL`. | | `programs_invoked` | array | Programs the transaction calls, as `name` and `id`. Programs are listed here and are not screened. | ### Findings Each finding has a `signal`, a `severity`, a human-readable `caption`, and signal-specific `evidence`. | Signal | Severity | Fires when | | - | - | - | | `address-poisoning` | `high`, `medium`, `low` | A recipient imitates another address. `evidence` names the `address` and the address it `resembles`. | | `authority-change` | `medium` | An instruction changes a token account or mint authority (`setAuthority`), directly or through CPI. | | `owner-reassignment` | `medium` | An instruction reassigns an account's owner program (`assign`, `assignWithSeed`), directly or through CPI. | | `simulation-error` | `medium` | The simulation ran and the transaction failed. | | `high-instruction-count` | `medium` | The transaction has more than 12 instructions. | | `simulation-unavailable` | `medium` | Range could not simulate the transaction. Only the declared accounts were screened. | | `coverage-truncated` | `medium` | More accounts were selected than the 50-account cap allows. The rest were not screened. | | `counterparty-owner-unresolved` | `medium` | A credited token account could not be resolved to its owner wallet, so that recipient was not screened. | | `counterparty-screening-partial` | `medium` | At least one counterparty screen did not complete. `evidence.addresses` lists them. | | `large-transfer` | `low` | A credit exceeds 1 unit of its asset. Informational only; it never affects `severity`. | `simulation-error` and `simulation-unavailable` are different. `simulation-error` is a property of the transaction: it would fail onchain. `simulation-unavailable` is a gap in Range's coverage: the scan could not predict what the transaction does. ### Notes | Code | Meaning | | - | - | | `signer-address-ignored` | `signer_address` is not a required signer of the transaction; the fee payer was used. | | `simulation-unavailable` | Predicted balance and permission changes could not be produced. | | `coverage-truncated` | Counterparty screening stopped at 50 accounts. | | `counterparty-owner-unresolved` | Some token accounts had no resolvable owner and were excluded from counterparty and poisoning screening. | | `counterparty-screening-partial` | Some counterparty screens failed. Their `severity` reads `none`; treat them as not screened. | | `poisoning-not-screened` | The address-poisoning check did not complete. | | `poisoning-coverage-truncated` | The transaction credits more than 100 wallets; only the first 100 were checked for poisoning. | ### Meta | Field | Type | Description | | - | - | - | | `counterparties_screened` | integer | Number of entries in `counterparties`. | | `counterparties_screened_complete` | boolean | `false` when any selected counterparty was not screened: a failed screen, an unresolved token account owner, or the 50-account cap. | | `coverage_truncated` | boolean | `true` when the 50-account cap dropped accounts. | | `poisoning_screened` | boolean | `false` when the poisoning check did not run or did not complete. Treat recipients as not checked. Also `true` when there were no recipients to check. | | `simulate_ms`, `screening_ms`, `poisoning_ms`, `intent_ms`, `total_ms` | integer | Time spent in each stage, in milliseconds. Screening and poisoning run in parallel. `intent_ms` is `0` while intent extraction is not enabled. | *** ## Acting on the Result A pre-sign gate for a wallet or dApp: ```typescript theme={null} function decide(scan: { severity: 'none' | 'low' | 'medium' | 'high' | 'severe'; meta: { poisoning_screened: boolean }; }) { if (scan.severity === 'severe' || scan.severity === 'high') return 'block'; if (!scan.meta.poisoning_screened) return 'warn'; // recipients not checked for lookalikes if (scan.severity === 'medium') return 'warn'; // includes coverage gaps return 'allow'; } ``` Show the user `findings[].caption` and every counterparty with a severity above `none`. Do not warn on every finding: `large-transfer` fires on most transfers and is context, not risk. *** ## Errors | HTTP Code | Cause | Recommended Action | | -: | - | - | | **400** | `network` is not `solana`, `transaction` is empty or over 4,096 characters, `encoding` is not `base64` or `base58`, or the payload does not decode (`Invalid transaction payload`) | Send the serialized unsigned transaction with the matching `encoding`. | | **401** | Missing or invalid API key, or the key has no access to the Risk API | Check the key in the Range app. | | **429** | Rate limit exceeded | Back off and retry. See [Rate Limits](/risk-api/product-info/rate-limits). | | **5xx** | Internal error | Retry after a short delay. Do not treat a failed scan as clean. | A failed simulation or a failed counterparty screen does not fail the request. The scan returns HTTP 200 with a finding and a note that describe the gap. *** ## What's Next Where the scan fits in a pre-sign flow. Full per-counterparty assessments for a `screen_id`. Recent scans for your workspace. Raw simulation without a risk verdict. # Address Risk Score Source: https://docs.range.org/risk-api/risk/get-address-risk-score get /v1/risk/address Returns the risk score for a specific blockchain address based on network proximity analysis, machine learning, and behavioral pattern recognition. Returns a risk score (1-10) for a blockchain address based on its proximity to known malicious actors, ML-based behavioral analysis, and threat intelligence data. See [Understanding Risk Scores](/risk-api/product-info/understanding-risk-scores) for methodology details. **This endpoint includes sanctions and blacklist screening.** You do not need to call the [Sanctions & Blacklist Check](/risk-api/risk/get-sanctions-blacklist-check) separately, addresses on the sanctions lists Range screens (see [Risk Data Sources](/risk-api/product-info/risk-data-sources)) or on stablecoin issuer blacklists are already factored into the risk score. For **payment flows** where you need to assess both sender and recipient in the context of a transaction, use the [Payment Risk Assessment](/risk-api/risk/get-payment-risk-assessment) instead. It includes everything this endpoint does, plus additional payment-specific checks: new wallet detection, dormant wallet detection, address poisoning detection, interaction history between sender and recipient, token risk assessment, and cross-chain analysis. *** ## Query Parameters | Name | Type | Required | Description | | - | - | - | - | | `address` | string | Yes | The blockchain address to assess. | | `network` | string | No | Blockchain network identifier. If omitted, the API attempts to infer `eth`, `stellar`, or `solana` from the address format. See [Supported Chains](/risk-api/product-info/supported-chains). | ### Supported Networks The following 27 networks are fully supported with complete transaction graph analysis and proximity scoring: **Solana** | Network | Identifier | | - | - | | Solana | `solana` | **EVM Chains** | Network | Identifier | | - | - | | Ethereum Mainnet | `eth` | | Optimism Mainnet | `oeth` | | BNB Smart Chain | `bnb` | | Polygon Mainnet | `pol` | | Polygon zkEVM | `zkevm` | | Moonbeam | `moonbeam` | | Base | `base` | | Arbitrum One | `arb1` | | Celo Mainnet | `celo` | | Avalanche C-Chain | `avax` | **Other** | Network | Identifier | | - | - | | Stellar | `stellar` | | Bitcoin Mainnet | `bitcoin` | | Tron | `tron` | **Cosmos Ecosystem** | Network | Identifier | | - | - | | Celestia | `celestia` | | Osmosis | `osmosis-1` | | Cosmos Hub | `cosmoshub-4` | | dYdX Mainnet | `dydx-mainnet-1` | | Neutron | `neutron-1` | | Dymension | `dymension_1100-1` | | Agoric | `agoric-3` | | Mantra | `mantra-1` | | Stride | `stride-1` | | PIO Mainnet | `pio-mainnet-1` | | Noble | `noble-1` | | ZigChain | `zigchain-1` | | Union | `union-1` | Other networks may yield results in two scenarios: 1. **Direct Attribution**: When we have direct attribution data for an address on that network (e.g., a known malicious contract address) 2. **Cross-Chain Propagation**: When malicious activity propagates through inter-chain bridges or cross-chain transactions For optimal results, use one of the fully supported networks listed above. *** ## Response Schema | Field | Type | Description | | - | - | - | | `riskScore` | number (1-10) | Numerical risk value. Higher scores indicate greater risk. | | `riskLevel` | string | Human-readable risk description aligned to the score. | | `numHops` | integer (≥0) | Minimum token-transfer steps to any known malicious address. `0` means the address itself is malicious. | | `maliciousAddressesFound` | array | Evidence used in scoring (see below). | | `reasoning` | string | Plain-English explanation of why the score was assigned. | | `attribution` | object \| null | Attribution metadata for known non-malicious addresses. When present, indicates a verified entity with risk override applied. | ### Malicious Evidence Object | Field | Type | Description | | - | - | - | | `address` | string | Malicious or ML-flagged address on the path. | | `distance` | integer (≥0) | Number of hops from the input address. | | `name_tag` | string \| null | Human-readable label describing the activity. | | `entity` | string \| null | Known organization or cluster. | | `category` | string | Type of malicious activity. | When `name_tag`, `entity`, or `category` are blank or null, this indicates either: (1) data from confidential intelligence sources where attribution details cannot be disclosed, or (2) the address was identified through ML models and lacks traditional attribution data. In both cases, the address presents potential risk but detailed attribution may be limited. ### Attribution Object When present, indicates the address is a verified non-malicious entity with risk override to score 1. | Field | Type | Description | | - | - | - | | `name_tag` | string | Human-readable name (e.g., "Token Program") | | `entity` | string | Organization or protocol (e.g., "Solana") | | `category` | string | Classification type (the Token Program response returns "CoreToken") | *** ## Risk Scoring Logic | Score | Risk Level | Typical Situation | | -: | - | - | | **10** | CRITICAL RISK (directly malicious) | Address itself is flagged (0 hops) | | **9-8** | Extremely high risk | 1 hop from malicious; ≥3 hits → 9, otherwise 8 | | **7-6** | High risk | 2 hops; ≥3 hits → 7, otherwise 6 | | **5-4** | Medium risk | 3 hops; ≥3 hits → 5, otherwise 4 | | **3-2** | Low risk | 4 hops; ≥3 hits → 3, otherwise 2 | | **1** | Very low risk | ≥5 hops OR known attributed non-malicious address | Where "hits" refers to the number of malicious addresses found along the relevant paths. Risk analysis examines paths up to 5 hops from the input address. *** ## Examples ### High-Risk Address (Score 10) ```bash theme={null} curl -G https://api.range.org/v1/risk/address \ --data-urlencode "address=AuZrspySopxfZUiXY6YxDyfS211KvXLe197kj3M2cLpq" \ --data-urlencode "network=solana" \ -H "Authorization: Bearer YOUR_API_KEY" ``` ```json theme={null} { "riskScore": 10, "riskLevel": "CRITICAL RISK (Directly malicious)", "numHops": 0, "maliciousAddressesFound": [ { "address": "AuZrspySopxfZUiXY6YxDyfS211KvXLe197kj3M2cLpq", "distance": 0, "name_tag": "Layering, Swapping", "entity": null, "category": "hack_funds" } ], "reasoning": "Address is directly flagged for malicious activity." } ``` ### Malicious Solana Address (Score 10) ```bash theme={null} curl -G https://api.range.org/v1/risk/address \ --data-urlencode "address=2oP36hojo3spVLvrhqNVW8ERUEYMKFAS2XVAmFv289WJ" \ --data-urlencode "network=solana" \ -H "Authorization: Bearer YOUR_API_KEY" ``` Response (abbreviated): ```json theme={null} { "riskScore": 10, "riskLevel": "CRITICAL RISK (directly malicious)", "numHops": 0, "maliciousAddressesFound": [ { "address": "2oP36hojo3spVLvrhqNVW8ERUEYMKFAS2XVAmFv289WJ", "network": "solana", "distance": 0, "name_tag": "SOLANA Lazarus Hacker Address (89WJ)", "entity": null, "category": "Hack", "risk_categories": [ "hack", "security-risk" ] } ], "reasoning": "Address is directly flagged for malicious activity." } ``` ### System Address with Attribution Override ```bash theme={null} curl -G https://api.range.org/v1/risk/address \ --data-urlencode "address=TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" \ --data-urlencode "network=solana" \ -H "Authorization: Bearer YOUR_API_KEY" ``` Response (abbreviated): ```json theme={null} { "riskScore": 1, "riskLevel": "Very low risk", "numHops": 2, "maliciousAddressesFound": [ { "address": "CPMMoo8L3F4NbTegBCKVNunggL7H1ZpdTHKxQB5qKP1C", "distance": 2, "name_tag": "", "entity": "", "category": "" } ], "reasoning": "Despite being 2 hop(s) from malicious addresses, this is a known system address (Token Program - Solana). Risk overridden to very low.", "attribution": { "name_tag": "Token Program", "entity": "Solana", "category": "CoreToken" } } ``` ### Celestia Network ```bash theme={null} curl -G https://api.range.org/v1/risk/address \ --data-urlencode "address=DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263" \ --data-urlencode "network=celestia" \ -H "Authorization: Bearer YOUR_API_KEY" ``` ```json theme={null} { "riskScore": 1, "riskLevel": "Very low risk", "numHops": 5, "maliciousAddressesFound": [], "reasoning": "No malicious addresses found within 5 hops. This Celestia address shows no direct or indirect connections to known threats." } ``` ### Cross-Chain Address ```bash theme={null} curl -G https://api.range.org/v1/risk/address \ --data-urlencode "address=0x5d87eaeb84c694a12e01c445fca0b1c527613c25" \ --data-urlencode "network=eth" \ -H "Authorization: Bearer YOUR_API_KEY" ``` ```json theme={null} { "riskScore": 3, "riskLevel": "Low risk", "numHops": 4, "maliciousAddressesFound": [ { "address": "0xSuspicious...", "distance": 4, "name_tag": "Flagged Contract", "entity": "", "category": "Suspected" } ], "reasoning": "This address is 4 hops away from 1 suspected address, indicating low risk." } ``` *** ## Errors Omitting `network` is not an error when the address format can be inferred. For example, `address=TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA` without `network` returns HTTP 200 with `riskScore: 1` and `attribution.network: "solana"`. ```bash theme={null} curl -G https://api.range.org/v1/risk/address \ --data-urlencode "address=TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" \ -H "Authorization: Bearer YOUR_API_KEY" ``` | HTTP Code | Cause | Recommended Action | | -: | - | - | | **400** | Missing or invalid `address` | Validate the address before requesting. | | **404** | Address/network not found or unsupported | Use a supported `network` value; ensure address correctness. | | **429** | Rate limited | Reduce request rate; follow `Retry-After` header for backoff. | | **5xx** | Server error | Retry after a delay; contact support if persistent. | *** ## Best Practices * Always provide a `network` value consistent with the address format. * Use both `riskScore` and `riskLevel` in your UI, and display `reasoning` as explanatory text. * Check the `attribution` field, when present, it indicates a verified non-malicious address with risk override applied. * When multiple malicious addresses are found, display at least the entry with the smallest `distance`. * `numHops` represents the minimum token-transfer distance; greater distances generally reduce risk. ```ts theme={null} type RiskLevel = | "CRITICAL RISK (Directly malicious)" | "Extremely high risk" | "High risk" | "Medium risk" | "Low risk" | "Very low risk"; interface MaliciousEvidence { address: string; distance: number; name_tag: string | null; entity: string | null; category: string; } interface Attribution { name_tag: string; entity: string; category: string; } interface AddressRiskResponse { riskScore: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10; riskLevel: RiskLevel; numHops: number; maliciousAddressesFound: MaliciousEvidence[]; reasoning: string; attribution?: Attribution | null; } ``` # Payment Risk Assessment Source: https://docs.range.org/risk-api/risk/get-payment-risk-assessment get /v1/risk/payment End-to-end risk assessment for payments across and within chains, powered by advanced heuristic rules and machine-learning analysis. Returns a comprehensive risk assessment for blockchain payments by analyzing both sender and recipient addresses across 8 independent risk dimensions. Provides real-time risk evaluation for payment flows across multiple blockchain networks. See [Understanding Risk Scores](/risk-api/product-info/understanding-risk-scores) for general methodology. The **overall risk level** uses a **maximum risk approach**: if any individual assessment returns "high", the overall risk is "high". **This is the most comprehensive risk endpoint.** It includes address risk scoring (malicious connection analysis) and attributed address checks (including sanctions and blacklist data) for both sender and recipient, plus payment-specific risk factors. If you only need to screen a single address without payment context, use the simpler [Address Risk Score](/risk-api/risk/get-address-risk-score) endpoint. For sanctions-only pass/fail checks, use [Sanctions & Blacklist Check](/risk-api/risk/get-sanctions-blacklist-check). *** ## Query Parameters | Name | Type | Required | Description | | - | - | - | - | | `sender_address` | string | Yes | Blockchain address of the sender (min 10 characters) | | `recipient_address` | string | Yes | Blockchain address of the recipient (min 10 characters) | | `amount` | number | Yes | Payment amount in USD equivalent (must be >0) | | `sender_network` | string | Yes | Sender's blockchain network identifier. See [Supported Chains](/risk-api/product-info/supported-chains). | | `recipient_network` | string | Yes | Recipient's blockchain network identifier. See [Supported Chains](/risk-api/product-info/supported-chains). | | `sender_token` | string | No | Token/denom being sent (enables token risk assessment for Solana) | | `recipient_token` | string | No | Token/denom being received | | `timestamp` | string | No | Payment timestamp in ISO 8601 format (e.g., `2025-01-15T10:30:00Z`) | **Validation:** * Sender and recipient addresses must be different * Amount must be greater than 0 * Address minimum length: 10 characters ### Supported Networks Full payment data support for: `solana`, `stellar`, and all Cosmos ecosystem chains (`celestia`, `osmosis-1`, `cosmoshub-4`, `dydx-mainnet-1`, `neutron-1`, and others). See [Supported Chains](/risk-api/product-info/supported-chains) for the full list. Networks without full payment data (EVM chains, Bitcoin, Tron) still benefit from attribution checks and malicious connection analysis. *** ## Response Schema | Field | Type | Description | | - | - | - | | `overall_risk_level` | string | Final risk determination: `"low"`, `"medium"`, `"high"`, or `"unknown"` | | `risk_factors` | array | Individual risk assessments performed (see below) | | `processing_time_ms` | number | Processing time in milliseconds | | `errors` | array | Errors encountered during analysis (empty if none) | | `request_summary` | object | Echo of the original request parameters | ### Risk Factor Object | Field | Type | Description | | - | - | - | | `factor` | string | Unique identifier (e.g., `new_wallet_recipient`, `first_interaction`) | | `risk_level` | string | Risk level: `"low"`, `"medium"`, or `"high"` | | `description` | string | Human-readable explanation | ### Example Response Structure ```json theme={null} { "overall_risk_level": "high", "risk_factors": [ { "factor": "malicious_attributed_recipient", "risk_level": "high", "description": "Recipient is a known malicious entity: SOLANA Lazarus Hacker Address (89WJ) (Hack, Hacker)" }, { "factor": "first_interaction", "risk_level": "medium", "description": "First ever interaction between these addresses" }, { "factor": "established_wallet_recipient", "risk_level": "low", "description": "Recipient has on-chain signatures; last activity 489 days ago" }, { "factor": "no_address_poisoning", "risk_level": "low", "description": "No suspicious address patterns detected" }, { "factor": "known_safe_address_sender", "risk_level": "low", "description": "Sender: This is a known coretoken address: Token Program. Risk overridden to very low." }, { "factor": "known_attributed_sender", "risk_level": "low", "description": "Sender is a known entity: Token Program (CoreToken, Solana Program)" } ], "processing_time_ms": 637.094, "errors": [], "request_summary": { "sender_address": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", "recipient_address": "2oP36hojo3spVLvrhqNVW8ERUEYMKFAS2XVAmFv289WJ", "amount": 1000.0, "sender_network": "solana", "recipient_network": "solana", "sender_token": null, "recipient_token": null, "timestamp": null } } ``` *** ## Risk Assessments Performed Analyzes recipient's transaction history to determine if the wallet is newly created or established. **Factor names:** `new_wallet_recipient`, `established_wallet_recipient` * **HIGH**: 0 transactions (completely new wallet) * **MEDIUM**: \<3 transactions OR first transaction \<7 days ago * **LOW**: ≥3 transactions AND >7 days old Example descriptions: `"Recipient is a completely new wallet with no transaction history"`, `"Recipient has substantial transaction history (500+ transactions over 6 months)"` Checks if recipient has been inactive for an extended period and is now reactivating. **Factor names:** `dormant_wallet_recipient`, `active_wallet_recipient` * **MEDIUM**: Last transaction >180 days ago * **LOW**: Active within 180 days Example descriptions: `"Recipient wallet was dormant for 200+ days and is now reactivating"`, `"Recipient wallet was active within the last 7 days"` Detects if the recipient address matches poison address patterns associated with the sender (4-char prefix/suffix matching). **Factor names:** `address_poisoning_attack`, `no_address_poisoning` * **HIGH**: Recipient matches a poison address pattern * **LOW**: No poisoning pattern detected Example descriptions: `"Potential address poisoning attack detected - recipient matches poison address pattern"`, `"No address poisoning pattern detected between sender and recipient"` Examines previous transaction relationships between sender and recipient. Uses network-specific index for same-network payments and `payments_interchain` index for cross-chain. * `first_interaction`, **MEDIUM**: 0 interactions (first time transacting) * `limited_interaction_history`, **MEDIUM**: 1-2 interactions * `established_interaction_history`, **LOW**: 3+ interactions (established relationship) A first interaction returns MEDIUM, not HIGH. Do not gate a reject on `first_interaction` being HIGH. Example descriptions: `"First ever interaction between these addresses"`, `"Limited interaction history: 2 previous interactions found"`, `"Strong interaction history: 15 previous interactions found"` Uses Range's ML-powered malicious distance endpoint to identify connections to known malicious addresses for both sender and recipient. **Factor names returned by live responses:** `directly_malicious_address`, `clean_address_sender`, `clean_address_recipient`, `known_safe_address_sender`, `known_safe_address_recipient` `directly_malicious_address` is a single name used for either side. Its `description` begins `Sender:` or `Recipient:` to identify which address is flagged. * `directly_malicious_address`, **HIGH**: address is directly flagged, or is within 2 hops of a flagged address * **MEDIUM**: 3 hops from malicious addresses. This band was not observed, so its factor name is unconfirmed. * `clean_address_sender` / `clean_address_recipient`, **LOW**: no suspicious paths found * `known_safe_address_sender` / `known_safe_address_recipient`, **LOW**: attribution override, the address belongs to a known safe entity **Also documented, not observed:** `malicious_connection_sender_direct`, `malicious_connection_sender_high`, `malicious_connection_sender_medium`, `malicious_connection_sender_low` and the `_recipient_` counterparts. No response used to verify this page returned them. Handle them defensively rather than relying on them. Example descriptions: `"Recipient: Address is directly flagged for malicious activity."`, `"Sender: No suspicious paths found within 5 hops."`, `"Recipient: This is a known cex address: Binance Deposit (6Awu) (Binance). Risk overridden to very low."` Verifies both addresses against known entity databases. Network-independent, runs even for unsupported networks. **Factor names returned by live responses:** `malicious_attributed_sender`, `malicious_attributed_recipient`, `known_attributed_sender`, `known_attributed_recipient` * `malicious_attributed_sender` / `malicious_attributed_recipient`, **HIGH**: address matched an entity flagged with `malicious=True` * `known_attributed_sender` / `known_attributed_recipient`, **LOW**: known attributed entity (exchange, protocol, token, system address) **Also documented, not observed:** `malicious_address_sender`, `malicious_address_recipient`, `attributed_address_sender`, `attributed_address_recipient`. No response used to verify this page returned them. Match them alongside the four names above rather than dropping them from your handler. Example descriptions: `"Recipient is a known malicious entity: Lazarus Group (Hack, Hacker)"`, `"Sender is a known entity: Token Program (CoreToken, Solana Program)"`, `"Recipient is a known entity: Binance Deposit (6Awu) (cex, deposit_wallet)"` When `sender_token` or `recipient_token` is provided, evaluates token-specific risk factors. Currently Solana only. **Factor names:** `token_risk_sender_low`, `token_risk_sender_medium`, `token_risk_sender_high` (and `_recipient_` variants) Maps from token risk score to payment risk level (low/medium/high). Example descriptions: `"Sender token EPjFWdd5Au... has low risk (established stablecoin)"`, `"Recipient token shows medium risk factors"` Handles both same-network and cross-chain payment scenarios with appropriate index selection. * Same network: Uses network-specific index (e.g., `payments_solana`) * Cross-chain: Uses `payments_interchain` index *** ## Network Support | Scenario | Coverage | Processing Time | | - | - | - | | Both networks fully supported | All risk factors assessed | \~1000-3000ms | | One network supported | Partial assessment + attribution for both | \~200-600ms | | Neither network supported | Attribution check only; returns `"unknown"` if no data | \~130-500ms | *** ## Examples ### Medium Risk, First Interaction ```bash theme={null} curl -G https://api.range.org/v1/risk/payment \ --data-urlencode "sender_address=TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" \ --data-urlencode "recipient_address=7UX2i7SucgLMQcfZ75s3VXmZZY4YRUyJN9X1RgfMoDUi" \ --data-urlencode "amount=1000.0" \ --data-urlencode "sender_network=solana" \ --data-urlencode "recipient_network=solana" \ -H "Authorization: Bearer YOUR_API_KEY" ``` ```json theme={null} { "overall_risk_level": "medium", "risk_factors": [ { "factor": "first_interaction", "risk_level": "medium", "description": "First ever interaction between these addresses" }, { "factor": "established_wallet_recipient", "risk_level": "low", "description": "Recipient has on-chain signatures; last activity 259 days ago" }, { "factor": "no_address_poisoning", "risk_level": "low", "description": "No suspicious address patterns detected" }, { "factor": "known_safe_address_sender", "risk_level": "low", "description": "Sender: This is a known coretoken address: Token Program. Risk overridden to very low." }, { "factor": "clean_address_recipient", "risk_level": "low", "description": "Recipient: No suspicious paths found within 5 hops." }, { "factor": "known_attributed_sender", "risk_level": "low", "description": "Sender is a known entity: Token Program (CoreToken, Solana Program)" } ], "processing_time_ms": 167.29, "errors": [] } ``` ### Attributed Addresses on Both Sides ```bash theme={null} curl -G https://api.range.org/v1/risk/payment \ --data-urlencode "sender_address=DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263" \ --data-urlencode "recipient_address=EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v" \ --data-urlencode "amount=250.0" \ --data-urlencode "sender_network=solana" \ --data-urlencode "recipient_network=solana" \ --data-urlencode "sender_token=So11111111111111111111111111111111111111112" \ --data-urlencode "timestamp=2025-01-15T10:30:00Z" \ -H "Authorization: Bearer YOUR_API_KEY" ``` ```json theme={null} { "overall_risk_level": "medium", "risk_factors": [ { "factor": "first_interaction", "risk_level": "medium", "description": "First ever interaction between these addresses" }, { "factor": "established_wallet_recipient", "risk_level": "low", "description": "Recipient has on-chain signatures; last activity 0 days ago" }, { "factor": "no_address_poisoning", "risk_level": "low", "description": "No suspicious address patterns detected" }, { "factor": "known_safe_address_sender", "risk_level": "low", "description": "Sender: This is a known address: BONK (Bonk) SPL token mint. Risk overridden to very low." }, { "factor": "known_safe_address_recipient", "risk_level": "low", "description": "Recipient: This is a known token address: USD Coin (USDC) (Circle). Risk overridden to very low." }, { "factor": "known_attributed_sender", "risk_level": "low", "description": "Sender is a known entity: BONK (Bonk) SPL token mint" }, { "factor": "known_attributed_recipient", "risk_level": "low", "description": "Recipient is a known entity: USD Coin (USDC) (Token, token_contract)" } ], "processing_time_ms": 125.73 } ``` Both addresses here are attributed, so both sides return LOW attribution factors, but the pair has no prior interaction history, which returns `first_interaction` at MEDIUM and carries the overall level to `"medium"`. Attribution alone does not produce a `"low"` overall level. ### Cross-Chain Payment ```bash theme={null} curl -G https://api.range.org/v1/risk/payment \ --data-urlencode "sender_address=osmo1abc123def456ghi789jkl012mno345pqr678stu" \ --data-urlencode "recipient_address=cosmos1xyz987uvw654rst321nmo098lkj765ihg432fed" \ --data-urlencode "amount=5000.0" \ --data-urlencode "sender_network=osmosis" \ --data-urlencode "recipient_network=cosmoshub" \ --data-urlencode "sender_token=OSMO" \ --data-urlencode "recipient_token=ATOM" \ -H "Authorization: Bearer YOUR_API_KEY" ``` ```json theme={null} { "overall_risk_level": "medium", "risk_factors": [ { "factor": "first_interaction", "risk_level": "medium", "description": "First cross-chain interaction between these addresses (interchain index)" } ], "processing_time_ms": 3124.78 } ``` *** ## Errors | HTTP Code | Cause | Recommended Action | | -: | - | - | | **400** | Invalid parameters (same addresses, amount ≤ 0, etc.) | Validate parameters before requesting. | | **422** | Request validation error | Check parameter types and formats. | | **429** | Rate limit exceeded | Implement exponential backoff. | | **5xx** | Server error | Retry after a delay; contact support if persistent. | *** ## Best Practices * The overall risk is determined by the **highest** individual risk factor, a single "high" factor makes the entire payment "high" risk. * Always pass `sender_token`/`recipient_token` for Solana payments to get token-level risk assessment. * For cross-chain payments, provide the correct network identifiers for both sides. * Use `processing_time_ms` to monitor API performance and set appropriate timeouts. * An `"unknown"` overall risk level means insufficient data, not safety, treat it with caution. ```typescript theme={null} type PaymentRiskLevel = "low" | "medium" | "high" | "unknown"; interface PaymentRiskFactor { factor: string; risk_level: PaymentRiskLevel; description: string; } interface PaymentRiskResponse { overall_risk_level: PaymentRiskLevel; risk_factors: PaymentRiskFactor[]; processing_time_ms: number; errors: string[]; request_summary: { sender_address: string; recipient_address: string; amount: number; sender_network: string; recipient_network: string; sender_token: string | null; recipient_token: string | null; timestamp: string | null; }; } ``` # Sanctions and Blacklist Check Source: https://docs.range.org/risk-api/risk/get-sanctions-blacklist-check get /v1/risk/sanctions/{address} Check if a blockchain address is on a government sanctions list, such as OFAC, UK, or EU, or blacklisted by stablecoin issuers. Check if a blockchain address is blacklisted by token issuers (Tether, Circle, Coinbase, PayPal, Paxos, Agora, Ripple) or listed on any sanctions list Range ingests: OFAC, UK, EU, EU Russia sanctions packages, France, and Japan, plus Israeli NBCTF seizure orders and FBI IC3 advisories. See [Understanding Risk Scores](/risk-api/product-info/understanding-risk-scores) for how this fits into Range's broader risk methodology. * **Token Blacklist Events**: Real-time monitoring on Ethereum, Tron, Solana, Base, Arbitrum, Optimism, Polygon, and Avalanche for specific token issuers. * **Sanctions Lists**: Sourced from official government publications and network-agnostic. The response names every list the address is on in `sanctions`. **`is_sanctioned` and `is_ofac_sanctioned` are different flags.** `is_sanctioned` is `true` when the address is on any government sanctions list: OFAC, UK, EU, EU Russia packages, France, or Japan. `is_ofac_sanctioned` covers OFAC only, so an address sanctioned by the UK but not by OFAC returns `is_ofac_sanctioned: false` and `is_sanctioned: true`. Israeli NBCTF seizure orders and FBI IC3 advisories appear in `sanctions` but do not set `is_sanctioned`. For a broader check for malicious actors and exposure, use [Address Risk (v2)](/risk-api/risk-v2/get-address-risk) or [Address Risk Score (v1)](/risk-api/risk/get-address-risk-score). **Pre-sign gates must fail closed.** `lists_checked: false` means a sanctions or blacklist store could not be read, so the result may be incomplete. `is_sanctioned` is then `null` unless a listing was found anyway, and `false` values in `is_ofac_sanctioned` and `is_token_blacklisted` are not a clean result either. Treat the address as unknown: block or retry, never allow. *** ## How It Works The endpoint performs these checks: 1. **Token Blacklist Check**: Monitors onchain blacklist events emitted by token issuer contracts on **Ethereum, Tron, Solana, Base, Arbitrum, Optimism, Polygon, and Avalanche**. When issuers like Tether or Circle blacklist an address, it is blocked from transferring their tokens. The endpoint tracks freezes (`blacklist`), releases (`unblacklist`) and burns of a frozen balance (`destroyedblackfunds`) in real-time to determine the **current** status. 2. **OFAC Sanctions Check**: Cross-references the address against the US Treasury OFAC Specially Designated Nationals (SDN) list. OFAC data is sourced from official published reports and covers any network published by OFAC. 3. **Other Sanctions Lists**: Cross-references the address against every other list Range ingests (see [Sanctions List Coverage](#sanctions-list-coverage)). Each list the address is on, OFAC included, is one entry in `sanctions`. 4. **Attribution Data**: In addition to real-time blacklist events, the endpoint includes attribution labels that may provide extended context and information beyond what is captured in onchain events. > **Note:** The `is_token_blacklisted` field reflects the **current** status based on the most recent event. An address that was blacklisted and later unblacklisted will show `false`. Use `blacklist_event_history` to view the complete history. *** ## Path Parameters | Name | Type | Required | Description | | - | - | - | - | | address | string | ✅ | Blockchain address to check | ## Query Parameters | Name | Type | Required | Default | Description | | - | - | - | - | - | | network | string | ❌ | none | `ethereum`, `tron`, `solana`, `base`, `arbitrum`, `optimism`, `polygon`, or `avalanche`. Does not narrow the check (see below) | | include\_details | boolean | ❌ | true | Accepted for compatibility but ignored; details are always returned when available | > **Note:** `network` does not narrow the check. Blacklist status and sanctions lists are looked up by the address alone, across every network, so an EVM address frozen on any EVM network is flagged whichever network you pass. The value is only echoed in `network` when the address has no record. Accepted values are `ethereum`, `tron`, `solana`, `base`, `arbitrum`, `optimism`, `polygon`, and `avalanche`. Any other value returns HTTP 400. *** ### Sanctions List Coverage Sanctions list data is sourced from official government publications and is network-agnostic. If an address appears on a list, it is flagged across all 300+ supported networks. See [Supported Chains](/risk-api/product-info/supported-chains) for full coverage. | `signal_id` | `source` | `jurisdiction` | `basis` | Sets `is_sanctioned` | | - | - | - | - | :-: | | `ofac-sanctioned` | OFAC SDN | `US` | `direct` | ✅ | | `uk-sanctioned` | UK FCDO / OFSI | `UK` | `direct` | ✅ | | `eu-sanctioned` | EU sanctions | `EU` | `direct` or `indirect` | ✅ | | `eu-sanction-ru` | EU Russia sanctions packages | `EU` | `indirect` | ✅ | | `france-sanctioned` | France Trésor | `FR` | `direct` | ✅ | | `japan-sanctioned` | Japan MoF | `JP` | `direct` | ✅ | | `sanctioned` | Government sanctions list | `null` | `indirect` | ✅ | | `nbctf-terror-financing` | Israel NBCTF | `IL` | `direct` | ❌ | | `fbi-fraud` | FBI IC3 | `US` | `direct` | ❌ | The `signal_id` is the same signal the Address Risk endpoints fire for that list: the `signal` value in [Address Risk (v2)](/risk-api/risk-v2/get-address-risk) and a `risk_categories` entry in [Address Risk Score (v1)](/risk-api/risk/get-address-risk-score). [List Signals & Behaviours](/risk-api/risk-v2/get-signals) returns the full catalog. `sanctioned` is Range's generic label for an address on a government sanctions list with no single named list; it is left out of `sanctions` when the address is also on a named government sanctions list. NBCTF and FBI IC3 listings do not count, so an address on NBCTF and the generic label keeps both entries. See [Risk Data Sources](/risk-api/product-info/risk-data-sources) for each source. #### Direct and Indirect Listings * **`direct`**: the list names this address itself. OFAC, UK, France, Japan, NBCTF, and FBI IC3 entries are direct, and so are EU entries where the EU financial sanctions file names the address. * **`indirect`**: the list designates an entity or token, not the address, and Range attributed the address to it. The EU lists name entities rather than crypto addresses, so most EU entries are indirect, for example a wallet of an EU-sanctioned Russian entity or an A7A5 token holder. The generic `sanctioned` label is also indirect. Both set `is_sanctioned`. An indirect entry rests on Range attribution, not on the list itself, so you can route it to review instead of an automatic block if your policy distinguishes the two. ### Supported Networks & Tokens (Blacklist Events) Real-time blacklist event monitoring is available for the following token issuers: | Network | Tokens monitored | | - | - | | Ethereum | USDT, USDC, EURC, cbBTC, PYUSD, AUSD, XAUT, RLUSD, USDP, USDG, PAXG, BUSD | | Tron | USDT, USDC | | Solana | USDT, USDC, PYUSD | | Base | USDC, EURC, cbBTC, AUSD | | Arbitrum | USDT, USDC, cbBTC, PYUSD, AUSD, XAUT | | Optimism | USDT, USDC | | Polygon | USDT, USDC, AUSD, XAUT | | Avalanche | USDT, USDC, EURC, AUSD | An EVM address is looked up by the address alone, so a freeze on any EVM network flags it on every network. See [Supported Tokens](/risk-api/product-info/supported-tokens#blacklist-monitoring) for the issuer of each token. *** ## Response Schema The response contains the sanctions and blacklist status for the queried address. This example is a Bitcoin address of Rapira Group, on the UK sanctions list but not on OFAC's. ```json theme={null} { "address": "bc1q72ud4m6zf5g37jkhc2ty95zm5vel9ufdxquqpm", "network": null, "is_token_blacklisted": false, "is_ofac_sanctioned": false, "checked_at": "2026-09-30T08:00:00.000Z", "token_status_summary": null, "blacklist_event_history": null, "ofac_info": null, "attribution": null, "lists_checked": true, "sanctions": [ { "signal_id": "uk-sanctioned", "source": "UK FCDO / OFSI", "jurisdiction": "UK", "listed_at": "2026-05-26", "programs": ["RUSSIA"], "basis": "direct" } ], "is_sanctioned": true } ``` ### Top-Level Fields | Field | Type | Description | | - | - | - | | `address` | string | The blockchain address that was checked. | | `network` | string \| null | The address's network as stored with its record (a Range network id such as `eth`, `tron`, `arb1`). For an address with no record, the requested `network`, or `null`. | | `is_token_blacklisted` | boolean | `true` if the address is **currently** blacklisted by any token issuer, on any network. | | `is_ofac_sanctioned` | boolean | `true` if the address appears on the OFAC sanctions list. OFAC only; see `is_sanctioned` for every government list. | | `is_sanctioned` | boolean \| null | `true` if the address is on any government sanctions list: OFAC, UK, EU, EU Russia packages, France, or Japan, direct or indirect. `false` when every list was read and none matched. `null` when a list could not be read and no listing was found: treat it as unknown, not clean. | | `lists_checked` | boolean | `true` only when every sanctions and blacklist store answered. `false` means the result may be incomplete: fail closed or retry. | | `sanctions` | array | One entry per list the address is on, OFAC included. Empty when none. See [Sanctions](#sanctions). | | `checked_at` | string | Timestamp (ISO 8601) when this check was performed. | | `token_status_summary` | array \| null | Breakdown of blacklist status per token. `null` when no blacklist data exists. | | `blacklist_event_history` | array \| null | Chronological list of onchain blacklist, unblacklist and burn events. `null` when no events exist. | | `ofac_info` | object \| null | Details about the OFAC sanction. `null` if not sanctioned. | | `attribution` | object \| null | Additional labels and context for the address. `null` when no attribution exists. | ### Sanctions One entry per list the address is on. See [Sanctions List Coverage](#sanctions-list-coverage) for every value of `signal_id`, `source`, and `jurisdiction`. | Field | Type | Description | | - | - | - | | `signal_id` | string | The Address Risk signal for this list, e.g. `ofac-sanctioned`, `uk-sanctioned`, `eu-sanction-ru`. See [GET /v2/risk/signals](/risk-api/risk-v2/get-signals). | | `source` | string | The list the address is on, e.g. `OFAC SDN`, `UK FCDO / OFSI`. | | `jurisdiction` | string \| null | Jurisdiction of the list: `US`, `UK`, `EU`, `FR`, `JP`, or `IL`. `null` for the generic `sanctioned` label. | | `listed_at` | string \| null | Date the address was first listed (YYYY-MM-DD) when the list gives one. EU Russia packages and France currently give none. | | `programs` | array | Sanctions programs or regimes the listing falls under, e.g. `["RUSSIA"]`, `["CYBER2"]`. Empty when the list gives none. | | `basis` | string | `direct` when the list names this address, `indirect` when the list names an entity or token and Range attributed the address to it. See [Direct and indirect listings](#direct-and-indirect-listings). | ### Token Status Summary Shows the current blacklist status for each token and network that has flagged this address, one entry per token and network. | Field | Type | Description | | - | - | - | | `token` | string | Token symbol, for example `USDT`, `USDC`, `cbBTC`, `PYUSD`. See [Supported Tokens](/risk-api/product-info/supported-tokens#blacklist-monitoring). | | `issuer` | string | The company that issued the token: `Tether`, `Circle`, `Coinbase`, `PayPal`, `Paxos`, `Agora`, or `Ripple`. | | `network` | string | Network of these events, as a Range network id: `eth`, `tron`, `solana`, `base`, `arb1`, `oeth`, `pol`, `avax`. | | `is_currently_blacklisted` | boolean | `true` if the address is currently blocked from using this token on this network. | | `first_blacklisted_date` | string | When the address was first blacklisted for this token on this network (YYYY-MM-DD). | | `last_event_date` | string | Date of the most recent event. | | `last_event_type` | string | `blacklist`, `unblacklist`, or `destroyedblackfunds`. Anything but `unblacklist` means currently blacklisted. | ### Blacklist Event History A chronological record of all onchain blacklist and unblacklist events. | Field | Type | Description | | - | - | - | | `event_type` | string | `blacklist` (address blocked), `unblacklist` (address unblocked), or `destroyedblackfunds` (frozen balance burned). | | `token` | string | Token symbol. | | `issuer` | string | Token issuer. | | `network` | string | Network where the event occurred, as a Range network id: `eth`, `tron`, `solana`, `base`, `arb1`, `oeth`, `pol`, `avax`. | | `date` | string | Event date (YYYY-MM-DD). | | `block_number` | integer | Block number of the transaction. | | `block_timestamp` | string | Timestamp of the block. | | `transaction_hash` | string | Onchain transaction hash for verification. | | `token_account` | string \| null | The token account address (Solana only). `null` for EVM chains. | ### OFAC Info Details about OFAC sanctions. Only present when the address is sanctioned. | Field | Type | Description | | - | - | - | | `is_sanctioned` | boolean | Always `true` when this object is present. | | `name_tag` | string | Name of the sanctioned individual or entity. | | `category` | string | Sanction category (e.g., "OFAC Sanctioned"). | | `entity` | string | Sanctioning body (e.g., "OFAC"). | | `address_role` | string | `Individual` or `Entity`. | | `first_sanctioned_date` | string | Date when the address was first sanctioned (YYYY-MM-DD). | | `sanction_url` | string | Link to the official OFAC announcement. | | `programs` | array | OFAC sanctions programs, e.g. `["CYBER2"]`. | ### Attribution Additional context and labels for the address, which may include information beyond onchain events. | Field | Type | Description | | - | - | - | | `name` | string | Human-readable name or label for the address. | | `category` | string | Category (e.g., "USDT Blacklist", "Multi-Provider Blacklist"). | | `role` | string | Role description (e.g., "Blacklisted Address"). | | `entity` | string \| null | Associated entity, if known. | | `tags` | array \| null | List of tags (e.g., `["BLACKLISTED", "COMPLIANCE"]`). | | `malicious` | boolean | `true` if the address is considered malicious. | *** ## Examples ### UK Sanctioned Only (Not OFAC) The Rapira Group address from [Response Schema](#response-schema) is on the UK list only. `is_ofac_sanctioned` is `false`, while `is_sanctioned` is `true` and `sanctions` names the UK list. ```bash theme={null} curl -G "https://api.range.org/v1/risk/sanctions/bc1q72ud4m6zf5g37jkhc2ty95zm5vel9ufdxquqpm" \ -H "Authorization: Bearer YOUR_API_KEY" ``` ### Sanctioned on Several Lists Garantex (`0x7FF9cFad3877F21d41Da833E2F775dB0569eE3D9`) is on OFAC, UK, and EU lists and is token blacklisted. The response has `is_token_blacklisted: true`, `is_ofac_sanctioned: true`, and `is_sanctioned: true`, with one `sanctions` entry per list. The two EU entries are `indirect` because the EU designates the entity, not the address. | `signal_id` | `source` | `listed_at` | `programs` | `basis` | | - | - | - | - | - | | `ofac-sanctioned` | OFAC SDN | `2022-04-05` | `["CYBER4", "RUSSIA-EO14024"]` | `direct` | | `uk-sanctioned` | UK FCDO / OFSI | `2022-05-04` | `["RUSSIA"]` | `direct` | | `eu-sanctioned` | EU sanctions | `null` | `[]` | `indirect` | | `eu-sanction-ru` | EU Russia sanctions packages | `null` | `[]` | `indirect` | The OFAC entry's `listed_at` and `programs` come from `ofac_info.first_sanctioned_date` and `ofac_info.programs`. ### Lists Could Not Be Read When a sanctions or blacklist store does not answer and no listing is found, the response still returns 200 with these fields: ```json theme={null} { "lists_checked": false, "sanctions": [], "is_sanctioned": null } ``` `is_ofac_sanctioned` and `is_token_blacklisted` can read `false` in this case without the address being clean. Block or retry; do not allow. Some examples below omit `lists_checked`, `sanctions`, and `is_sanctioned`, which every response also carries. Responses marked abbreviated omit some metadata and show only the first entry of `token_status_summary`, `blacklist_event_history`, and `sanctions`. ### Multi-Provider Blacklisted Address An OFAC-sanctioned address blacklisted by multiple stablecoin issuers, including Tether, Circle, Paxos, and Coinbase. ```bash theme={null} curl -G "https://api.range.org/v1/risk/sanctions/0x1da5821544e25c636c1417ba96ade4cf6d2f9b5a" \ -H "Authorization: Bearer YOUR_API_KEY" ``` Response (abbreviated): ```json theme={null} { "address": "0x1da5821544e25c636c1417ba96ade4cf6d2f9b5a", "network": "eth", "is_token_blacklisted": true, "is_ofac_sanctioned": true, "token_status_summary": [ { "token": "USDC", "issuer": "Circle", "network": "eth", "is_currently_blacklisted": true, "first_blacklisted_date": "2021-04-21", "last_event_date": "2021-04-21", "last_event_type": "blacklist" } ], "blacklist_event_history": [ { "event_type": "blacklist", "token": "USDC", "issuer": "Circle", "network": "eth", "date": "2021-04-21", "block_number": 12285873, "block_timestamp": "2021-04-21T21:04:36.000Z", "transaction_hash": "0x72959622df120df8cfe27fa371c5b82542cda695d09568975259c0cf70430bf9" } ], "ofac_info": { "is_sanctioned": true, "name_tag": "Secondeye Solution", "category": "OFAC Sanctioned", "entity": "OFAC", "address_role": "Entity", "first_sanctioned_date": "2021-04-15", "programs": [ "CYBER2", "ELECTION-EO13848" ], "aliases": [ "Forwarderz" ] }, "attribution": { "name": "Secondeye Solution", "category": "Multi-Provider Blacklist & OFAC Sanctioned", "malicious": true }, "checked_at": "2026-10-03T15:51:33.917Z", "lists_checked": true, "sanctions": [ { "signal_id": "ofac-sanctioned", "source": "OFAC SDN", "jurisdiction": "US", "listed_at": "2021-04-15", "programs": [ "CYBER2", "ELECTION-EO13848" ], "basis": "direct" } ], "is_sanctioned": true } ``` ### OFAC Sanctioned and Token Blacklisted An address that is both OFAC sanctioned and token blacklisted by multiple providers. ```bash theme={null} curl -G "https://api.range.org/v1/risk/sanctions/0x8576acc5c05d6ce88f4e49bf65bdf0c62f91353c" \ -H "Authorization: Bearer YOUR_API_KEY" ``` ```json theme={null} { "address": "0x8576acc5c05d6ce88f4e49bf65bdf0c62f91353c", "network": null, "is_token_blacklisted": true, "is_ofac_sanctioned": true, "checked_at": "2025-12-01T16:06:07.870004Z", "token_status_summary": [ { "token": "USDC", "issuer": "Circle", "is_currently_blacklisted": true, "first_blacklisted_date": "2022-03-29", "last_event_date": "2022-03-29", "last_event_type": "blacklist" }, { "token": "USDT", "issuer": "Tether", "is_currently_blacklisted": true, "first_blacklisted_date": "2023-12-09", "last_event_date": "2023-12-09", "last_event_type": "blacklist" } ], "blacklist_event_history": [ { "event_type": "blacklist", "token": "USDC", "issuer": "Circle", "network": "ethereum", "date": "2022-03-29", "block_number": 14481178, "block_timestamp": "2022-03-29 14:49:03", "transaction_hash": "5906c3dac2d75f141b72baa61842a9881e9d31ee36f761ffc7059ffc86c7e452", "token_account": null }, { "event_type": "blacklist", "token": "USDT", "issuer": "Tether", "network": "ethereum", "date": "2023-12-09", "block_number": 18750100, "block_timestamp": "2023-12-09 18:17:11", "transaction_hash": "dbd24a66f187242bf3a8f8ce4a50a4b9143889dc988c7113d2e1069165332534", "token_account": null } ], "ofac_info": { "is_sanctioned": true, "name_tag": "ANDREYEV, Anton Nikolaeyvich", "category": "OFAC Sanctioned", "entity": "OFAC", "address_role": "Individual", "first_sanctioned_date": "2020-09-10", "sanction_url": "https://ofac.treasury.gov/recent-actions/20200910" }, "attribution": { "name": "USDP Blacklisted Address (353c)", "category": "Multi-Provider Blacklist", "role": "Blacklisted Address", "entity": "OFAC", "tags": ["BLACKLISTED", "STABLECOIN-ISSUER", "COMPLIANCE"], "malicious": true } } ``` ### OFAC Sanctioned and Token Blacklisted on Tron A Tron address that is both OFAC sanctioned and blacklisted by Tether and Circle. ```bash theme={null} curl -G "https://api.range.org/v1/risk/sanctions/TMGLqRQ4twjW8wJhVH1mQR7nUThpGHUsN3" \ -H "Authorization: Bearer YOUR_API_KEY" ``` Response (abbreviated): ```json theme={null} { "address": "TMGLqRQ4twjW8wJhVH1mQR7nUThpGHUsN3", "network": "tron", "is_token_blacklisted": true, "is_ofac_sanctioned": true, "token_status_summary": [ { "token": "USDT", "issuer": "Tether", "is_currently_blacklisted": true, "first_blacklisted_date": "2024-03-20", "last_event_date": "2024-03-20", "last_event_type": "blacklist" } ], "blacklist_event_history": [ { "event_type": "blacklist", "token": "USDT", "issuer": "Tether", "network": "tron", "date": "2024-03-20", "block_number": 60102381, "block_timestamp": "2024-03-20T15:20:36.000Z", "transaction_hash": "f2b566756308e42275b570dc8ecaeae7d63babb1b936810887e87d5c5bcecec2" } ], "ofac_info": { "is_sanctioned": true, "name_tag": "Gambashidze Ilya Andreevich", "category": "OFAC Sanctioned", "entity": "OFAC", "address_role": "Individual", "first_sanctioned_date": "2024-03-20", "programs": [ "RUSSIA-EO14024" ], "aliases": [ "Gambachidze Ilya Andreievitch" ] }, "attribution": { "name": "Gambashidze Ilya Andreevich", "category": "Multi-Provider Blacklist & OFAC Sanctioned", "malicious": true }, "checked_at": "2026-10-03T15:51:34.059Z", "lists_checked": true, "sanctions": [ { "signal_id": "ofac-sanctioned", "source": "OFAC SDN", "jurisdiction": "US", "listed_at": "2024-03-20", "programs": [ "RUSSIA-EO14024" ], "basis": "direct" } ], "is_sanctioned": true } ``` ### Solana Blacklisted Address A Solana address blacklisted by Tether. Note the `token_account` field which is specific to Solana. ```bash theme={null} curl -G "https://api.range.org/v1/risk/sanctions/6sEk1enayZBGFyNvvJMTP7qs5S3uC7KLrQWaEk38hSHH" \ -H "Authorization: Bearer YOUR_API_KEY" ``` ```json theme={null} { "address": "6sEk1enayZBGFyNvvJMTP7qs5S3uC7KLrQWaEk38hSHH", "network": null, "is_token_blacklisted": true, "is_ofac_sanctioned": false, "checked_at": "2025-12-01T16:06:27.732211Z", "token_status_summary": [ { "token": "USDT", "issuer": "Tether", "is_currently_blacklisted": true, "first_blacklisted_date": "2022-11-12", "last_event_date": "2022-11-12", "last_event_type": "blacklist" } ], "blacklist_event_history": [ { "event_type": "blacklist", "token": "USDT", "issuer": "Tether", "network": "solana", "date": "2022-11-12", "block_number": 160590544, "block_timestamp": "2022-11-12 07:26:36", "transaction_hash": "5vQBXFxiSgufuLUpm6ugfxynd43P8tAa94SDeqtFvvvqzXa1DW8us4GRM3MS4QFnvcSHqD9DNPihuqnYJ9GbY7Qh", "token_account": "EdP6JNB26MrKzfsieCPz593VUgrDrpziQKstzCAFvNBP" } ], "ofac_info": null, "attribution": { "name": "", "category": "", "role": "", "entity": null, "tags": ["BLACKLISTED", "STABLECOIN-ISSUER", "COMPLIANCE"], "malicious": true } } ``` ### Previously Blacklisted (Now Unblacklisted) An address that was blacklisted then unblacklisted. `is_token_blacklisted` is `false` but the full history is preserved. ```bash theme={null} curl -G "https://api.range.org/v1/risk/sanctions/0x9faf5515f177f3a8a845d48c19032b33cc54c09c" \ -H "Authorization: Bearer YOUR_API_KEY" ``` ```json theme={null} { "address": "0x9faf5515f177f3a8a845d48c19032b33cc54c09c", "network": null, "is_token_blacklisted": false, "is_ofac_sanctioned": false, "checked_at": "2025-12-01T16:06:37.232941Z", "token_status_summary": [ { "token": "USDT", "issuer": "Tether", "is_currently_blacklisted": false, "first_blacklisted_date": "2017-11-28", "last_event_date": "2017-11-28", "last_event_type": "unblacklist" } ], "blacklist_event_history": [ { "event_type": "blacklist", "token": "USDT", "issuer": "Tether", "network": "ethereum", "date": "2017-11-28", "block_number": 4638805, "block_timestamp": "2017-11-28 17:39:10", "transaction_hash": "17ce88e3e2417f6c13db93f619423cc4c5f51e89660587631dc34c823fac54a8", "token_account": null }, { "event_type": "unblacklist", "token": "USDT", "issuer": "Tether", "network": "ethereum", "date": "2017-11-28", "block_number": 4638882, "block_timestamp": "2017-11-28 17:59:39", "transaction_hash": "520a66112467b4b79016c2a62658b56e8f78049bae8bf6f4ce4bf39ec2d75ba8", "token_account": null } ], "ofac_info": null, "attribution": { "name": "USDT Unblacklisted Address (0x9fa)", "category": "USDT Blacklist", "role": "Unblacklisted Address", "entity": null, "tags": ["UNBLACKLISTED", "STABLECOIN-ISSUER", "COMPLIANCE"], "malicious": true } } ``` ### Clean Address An address with no sanctions or blacklist history. ```bash theme={null} curl -G "https://api.range.org/v1/risk/sanctions/0x1234567890abcdef1234567890abcdef12345678" \ -H "Authorization: Bearer YOUR_API_KEY" ``` ```json theme={null} { "address": "0x1234567890abcdef1234567890abcdef12345678", "network": null, "is_token_blacklisted": false, "is_ofac_sanctioned": false, "checked_at": "2025-12-01T16:07:06.387337Z", "token_status_summary": null, "blacklist_event_history": null, "ofac_info": null, "attribution": null } ``` ### Compatibility Parameter: `include_details=false` `include_details` is accepted but ignored. Setting it to `false` still returns token status, event history, OFAC information, and attribution when available. ```bash theme={null} curl -G "https://api.range.org/v1/risk/sanctions/0x1da5821544e25c636c1417ba96ade4cf6d2f9b5a" \ --data-urlencode "include_details=false" \ -H "Authorization: Bearer YOUR_API_KEY" ``` Response (abbreviated): ```json theme={null} { "address": "0x1da5821544e25c636c1417ba96ade4cf6d2f9b5a", "network": "eth", "is_token_blacklisted": true, "is_ofac_sanctioned": true, "token_status_summary": [ { "token": "USDC", "issuer": "Circle", "network": "eth", "is_currently_blacklisted": true, "first_blacklisted_date": "2021-04-21", "last_event_date": "2021-04-21", "last_event_type": "blacklist" } ], "blacklist_event_history": [ { "event_type": "blacklist", "token": "USDC", "issuer": "Circle", "network": "eth", "date": "2021-04-21", "block_number": 12285873, "block_timestamp": "2021-04-21T21:04:36.000Z", "transaction_hash": "0x72959622df120df8cfe27fa371c5b82542cda695d09568975259c0cf70430bf9" } ], "ofac_info": { "is_sanctioned": true, "name_tag": "Secondeye Solution", "category": "OFAC Sanctioned", "entity": "OFAC", "address_role": "Entity", "first_sanctioned_date": "2021-04-15", "programs": [ "CYBER2", "ELECTION-EO13848" ], "aliases": [ "Forwarderz" ] }, "attribution": { "name": "Secondeye Solution", "category": "Multi-Provider Blacklist & OFAC Sanctioned", "malicious": true }, "checked_at": "2026-10-03T15:51:34.195Z", "lists_checked": true, "sanctions": [ { "signal_id": "ofac-sanctioned", "source": "OFAC SDN", "jurisdiction": "US", "listed_at": "2021-04-15", "programs": [ "CYBER2", "ELECTION-EO13848" ], "basis": "direct" } ], "is_sanctioned": true } ``` *** ## Errors | HTTP Code | Cause | Recommended Action | | -: | - | - | | **400** | Invalid address format | Validate the address format before making the request | | **429** | Rate limit exceeded | Implement exponential backoff and retry | | **5xx** | Internal server error | Retry after a short delay; contact support if persists | *** ## Case Auto-Creation When the request uses a workspace-scoped key and `case_auto_create` is enabled in the workspace [risk configuration](/risk-api/risk-v2/get-config), a hit opens a `sanctions_screen` case: * **OFAC or an issuer blacklist**: a `severe` case, always. * **Any other government sanctions list**: a case only when that list's signal is enabled in the workspace's `attribution_signals`, at the severity the workspace configured for it. When the address is on several such lists, the case takes the highest configured severity. * **Israel NBCTF and FBI IC3 entries**: no case, since they do not set `is_sanctioned`. *** ## Best Practices * **Gate on the right flags**: For sanctions screening across every government list, check `is_sanctioned` and `is_token_blacklisted`. Check `is_ofac_sanctioned` only when a policy is OFAC-specific. * **Fail closed**: Treat `lists_checked: false` or `is_sanctioned: null` as unknown, not clean. Block or retry. * **Decide on indirect listings**: Use `sanctions[].basis` to route `indirect` entries to review if your policy treats Range attribution differently from a list naming the address. * **Real-time checks**: Blacklist status can change; avoid caching for high-risk use cases. * **Read available details**: Event history is returned when available; `include_details` does not change the response. * **Addresses are case-insensitive**: Both `0x1DA5...` and `0x1da5...` return identical results. *** ## Use Cases * **Pre-transaction screening**: Check counterparty addresses before processing payments or transfers. * **Exchange compliance**: Screen addresses during deposit/withdrawal flows. * **DeFi integration**: Add sanctions checks to smart contract interactions or front-ends. * **Audit trails**: Generate compliance reports with full event history. # Smart Contract Risk (Solana) Source: https://docs.range.org/risk-api/risk/get-smart-contract-risk Risk assessment for smart contracts on the Solana blockchain. **Coming soon.** This endpoint is under development. [Request early access →](https://www.range.org/get-in-touch) The Smart Contract Risk endpoint will provide security vulnerability assessment for Solana smart contracts, including analysis of upgrade authority, verified source code, and known vulnerability patterns. *** ## Expected Endpoint ``` GET /risk/contract/{contractAddress} ``` ## Expected Parameters | Parameter | Type | Required | Description | | - | - | - | - | | `contractAddress` | string | Yes | Solana smart contract address to assess | ## Expected Response ```json theme={null} { "contractAddress": "...", "riskScore": 85, "riskLevel": "High", "vulnerabilities": ["Upgradeable contract", "No verified source code"], "metadata": { "name": "ExampleContract" } } ``` *** ## In the Meantime Use the [Address Risk Score](/risk-api/risk/get-address-risk-score) endpoint to check if a contract address is connected to known malicious actors, and the [Transaction Simulator](/risk-api/simulator/simulate-solana-transaction) to analyze contract interactions before executing them. [Contact us](https://www.range.org/get-in-touch) for early access or updates on availability. # Token Risk Assessment Source: https://docs.range.org/risk-api/risk/get-token-risk-assessment get /v1/risk/token Request a Solana token risk assessment and inspect the documented response contract and validation errors. Requests a risk assessment for a Solana token mint. *** ## Parameters | Parameter | Type | Required | Description | | - | - | - | - | | `asset_address` | string | Yes | Solana token mint address (32-44 character base58 string) | | `network` | string | Yes | Blockchain network. The only supported value is `solana`. | *** ## Documented Response Contract The OpenAPI specification defines the following HTTP 200 response schema. ### Top-Level Fields | Field | Type | Description | | - | - | - | | `token_info` | object | Token metadata: `asset_address`, `name`, `symbol` | | `overall_assessment` | object | Risk result: `risk_level` (LOW/MEDIUM/HIGH), `risk_score`, `max_score`, `risk_percentage` | | `summary` | object | Factor counts: `total_factors`, `high_risk_count`, `medium_risk_count`, `low_risk_count` | | `risk_factors` | object | Individual assessments keyed by factor name. Each contains `level` and `explanation`. | | `processing_time_ms` | number | Processing time in milliseconds. | | `errors` | array | Non-fatal errors encountered during the assessment. | *** ## Examples ### USDC ```bash theme={null} curl -X GET "https://api.range.org/v1/risk/token?asset_address=EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v&network=solana" \ -H "Authorization: Bearer YOUR_API_KEY" ``` *** ## Errors ### Invalid Address Format (400) A request with `asset_address=invalid_address` and `network=solana` returns HTTP 400: ```json theme={null} { "message": [ "asset_address must be a valid Solana base58 address (32-44 chars, no 0 O I l)" ], "error": "Bad Request", "statusCode": 400 } ``` ### Unsupported Network (400) A request with `asset_address=EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v` and `network=ethereum` returns HTTP 400: ```json theme={null} { "message": [ "network must be one of the following values: solana" ], "error": "Bad Request", "statusCode": 400 } ``` *** ```ts theme={null} interface TokenRiskResponse { token_info: { asset_address: string; name: string; symbol: string; }; overall_assessment: { risk_level: "LOW" | "MEDIUM" | "HIGH"; risk_score: number; max_score: number; risk_percentage: number; }; summary: { total_factors: number; high_risk_count: number; medium_risk_count: number; low_risk_count: number; }; risk_factors: Record; processing_time_ms: number; errors: string[]; } ``` # Transaction Risk Score Source: https://docs.range.org/risk-api/risk/get-transaction-risk-score Returns the risk score associated with a specified blockchain transaction. **Coming soon.** This endpoint is under development. [Request early access →](https://www.range.org/get-in-touch) The Transaction Risk Score endpoint will analyze individual blockchain transactions to assess risk based on the addresses, amounts, and patterns involved. *** ## In the Meantime Use the [Payment Risk Assessment](/risk-api/risk/get-payment-risk-assessment) endpoint to evaluate risk for payment transfers between addresses. It provides comprehensive multi-factor risk analysis including malicious connection detection, interaction history, address poisoning detection, and more. [Contact us](https://www.range.org/get-in-touch) for early access or updates on availability. # Simulate Cosmos Transaction Source: https://docs.range.org/risk-api/simulator/simulate-cosmos-transaction post /v1/simulate/{network}/transaction Simulate a Cosmos-based transaction to analyze effects and risks before broadcasting. The Cosmos Transaction Simulator supports simulation of transactions across Cosmos SDK-based networks including Osmosis and Neutron, providing the same detailed analysis available for Solana, instruction parsing, balance changes, state predictions, and risk assessment. For Cosmos-based addresses, use the [Address Risk Score](/risk-api/risk/get-address-risk-score) endpoint to check risk levels before transacting. Supported Cosmos networks include `osmosis-1`, `cosmoshub-4`, `dydx-mainnet-1`, `neutron-1`, `celestia`, and [more](/risk-api/risk/get-address-risk-score#supported-networks). [Contact us](https://www.range.org/get-in-touch) for early access or updates on availability. # Simulate an EVM Transaction Source: https://docs.range.org/risk-api/simulator/simulate-evm-transaction post /v2/simulate/evm Simulate an unsigned EVM transaction, including a Safe execTransaction before any signatures exist, to inspect balance changes, transfers, and approvals. # Simulate a Solana Transaction Source: https://docs.range.org/risk-api/simulator/simulate-solana-transaction post /v1/simulate/solana/transaction Simulate a Solana transaction to get the address balance changes, state updates, and associated risk analysis. Simulate a Solana transaction to analyze its effects and risks before broadcasting it to the network. Returns detailed instruction parsing, asset transfers, balance changes, state predictions, and account risk scoring. *** ## Why Use This API? * **Pre-Broadcast Validation**: Validate a transaction's execution without committing it to the blockchain. * **Debugging**: Identify issues such as program errors or insufficient balances. * **Cost Estimation**: Assess fees and compute units before broadcasting. * **Risk Assessment**: Identify whether any accounts involved in the transaction are malicious or suspicious. *** ## How to Use Use `@solana/web3.js` or any other SDK to construct a base64-encoded or base58-encoded Solana transaction. Send a POST request with header `Content-Type: application/json` and this JSON body, where `tx` is the encoded transaction and `encoding_type` is `base64` or `base58`: ```json theme={null} { "tx": "", "encoding_type": "base64" } ``` Review `instruction_groups`, `asset_transfers`, `lamport_changes`, `expected_state_changes`, `transaction_risk`, `transaction_summary`, and `error` to understand effects and risks. **Cluster support:** `devnet`, `testnet`, `mainnet-beta` *** ## Key Features * **Instruction Parsing**: Automatic parsing for all programs with public IDLs. For programs without public IDLs, we reverse-engineer the instruction format (marked with `"reverse_engineered": true`). * **Nested Transaction Decoding**: Squads v4 embedded transaction messages and Squads v3 `addInstruction` operations are automatically decoded and parsed. * **State Change Predictions**: Predicted account and token updates based on simulation. * **Asset Movement Analysis**: Detects token and SOL transfers with source, destination, mint, and amount. * **Account Risk Scoring**: Risk assessment of all involved addresses, including malicious address proximity analysis. * **Exploit Risk Detection**: Identifies potential exploit behaviors such as address poisoning attacks. *** ## Response Breakdown | Field | Description | | - | - | | `instruction_groups` | Hierarchical view of all instructions with parsed data, program IDs, and stack depth. | | `asset_transfers` | Detected asset movements (SOL and token transfers) with source, destination, mint, and amount. | | `lamport_changes` | Balance changes by address showing pre and post-execution balances. | | `expected_state_changes` | Predicted account-level state updates with formatted details and metadata for UI rendering. | | `transaction_risk` | Risk analysis containing `accounts_risk_score` (per-address risk with summary statistics) and `exploit_risks_detected`. | | `returned_data` | Data returned by programs during execution. | | `logs` | Complete transaction execution logs from the Solana runtime. | | `transaction_summary` | Compute units consumed, fee breakdown (compute fee, prioritization fee, tips), programs invoked, and transaction version. | | `error` | Failure reason if simulation failed. Other fields may be incomplete when present. | ### Fee Confidence The `transaction_summary` includes a fee confidence indicator: | Level | Meaning | | - | - | | **High** | Derived from explicit compute budget instructions | | **Medium** | Estimated from recent prioritization fees for the locked accounts | | **Low** | No data available; fallback logic used | Risk analysis is currently performed on the main transaction level. Embedded transactions and instructions in nested instruction data are not currently included in risk scoring. We continuously add support for new program parsers. If there is a specific program you'd like included, [contact us](https://www.range.org/get-in-touch) with the request. # Simulate Solana Transactions Source: https://docs.range.org/risk-api/simulator/simulate-solana-transactions post /v1/simulate/solana/transactions Simulate multiple Solana transactions in a single request to get balance changes, state updates, and risk analysis for each. Simulate multiple Solana transactions in a single request. Returns the same detailed analysis as the [single transaction simulator](/risk-api/simulator/simulate-solana-transaction) , instruction parsing, asset transfers, balance changes, state predictions, and account risk scoring, for each transaction in the batch. *** ## When to Use Batch Simulation * **Multi-step workflows**: Simulate a sequence of dependent transactions together. * **Bulk validation**: Validate multiple independent transactions in one API call instead of separate requests. * **Portfolio operations**: Analyze multiple swap or transfer transactions simultaneously. *** ## How to Use Send a POST request with an array of transactions: ```json theme={null} { "transactions": [ { "payload": "", "encoding_type": "base64" }, { "payload": "", "encoding_type": "base64" } ] } ``` Each transaction in the array takes `payload`, the encoded transaction, and `encoding_type`, either `base64` or `base58`. The [single transaction endpoint](/risk-api/simulator/simulate-solana-transaction) names the encoded transaction field `tx` instead of `payload`. **Cluster support:** `devnet`, `testnet`, `mainnet-beta` *** ## Response Format The response contains an array of results, one per submitted transaction. Each result follows the same schema as the single transaction simulator: | Field | Description | | - | - | | `instruction_groups` | Hierarchical view of all instructions with parsed data. | | `asset_transfers` | Detected SOL and token transfers. | | `lamport_changes` | Balance changes by address. | | `expected_state_changes` | Predicted account-level state updates. | | `transaction_risk` | Risk analysis with `accounts_risk_score` and `exploit_risks_detected`. | | `returned_data` | Data returned by programs during execution. | | `logs` | Complete execution logs. | | `transaction_summary` | Compute units, fee breakdown, programs invoked. | | `error` | Failure reason if simulation failed for this transaction. | For full details on each field, see the [single transaction simulator documentation](/risk-api/simulator/simulate-solana-transaction#response-breakdown).