curl --request POST \
--url https://api.range.org/v2/risk/transaction/scan \
--header 'Content-Type: application/json' \
--header 'X-API-KEY: <api-key>' \
--data '
{
"network": "solana",
"transaction": "AQAAAAAAAAAA…",
"signer_address": "<string>",
"origin": "<string>"
}
'import requests
url = "https://api.range.org/v2/risk/transaction/scan"
payload = {
"network": "solana",
"transaction": "AQAAAAAAAAAA…",
"signer_address": "<string>",
"origin": "<string>"
}
headers = {
"X-API-KEY": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'X-API-KEY': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
network: 'solana',
transaction: 'AQAAAAAAAAAA…',
signer_address: '<string>',
origin: '<string>'
})
};
fetch('https://api.range.org/v2/risk/transaction/scan', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.range.org/v2/risk/transaction/scan",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'network' => 'solana',
'transaction' => 'AQAAAAAAAAAA…',
'signer_address' => '<string>',
'origin' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-API-KEY: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.range.org/v2/risk/transaction/scan"
payload := strings.NewReader("{\n \"network\": \"solana\",\n \"transaction\": \"AQAAAAAAAAAA…\",\n \"signer_address\": \"<string>\",\n \"origin\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-API-KEY", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.range.org/v2/risk/transaction/scan")
.header("X-API-KEY", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"network\": \"solana\",\n \"transaction\": \"AQAAAAAAAAAA…\",\n \"signer_address\": \"<string>\",\n \"origin\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.range.org/v2/risk/transaction/scan")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-API-KEY"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"network\": \"solana\",\n \"transaction\": \"AQAAAAAAAAAA…\",\n \"signer_address\": \"<string>\",\n \"origin\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"screen_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"network": "solana",
"payload_sha256": "<string>",
"severity": "severe",
"counterparties": [
{
"address": "<string>",
"source": "asset-diff",
"severity": "severe",
"triggered_signals": [
"<string>"
]
}
],
"findings": [
{
"signal": "authority-change",
"severity": "severe",
"caption": "Token Authority … changed",
"evidence": {}
}
],
"notes": [
{
"code": "coverage-truncated",
"message": "Counterparty screening truncated to 50 accounts (63 selected)."
}
],
"timestamp": "2026-08-18T14:30:00Z",
"meta": {
"counterparties_screened": 12,
"counterparties_screened_complete": true,
"coverage_truncated": false,
"poisoning_screened": true,
"simulate_ms": 420,
"screening_ms": 610,
"poisoning_ms": 480,
"intent_ms": 900,
"total_ms": 1450
},
"signer": "<string>",
"intent": {
"summary": "Swap 100 USDC for SOL on Jupiter",
"action": "swap",
"confidence": "high"
},
"simulation": {
"simulation_success": true,
"asset_diffs": [
{
"account": "<string>",
"asset": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
"amount": 100.5,
"direction": "credit",
"owner": "<string>"
}
],
"state_changes": [
"<string>"
],
"programs_invoked": [
{
"name": "<string>",
"id": "<string>"
}
]
}
}Scan an Unsigned Transaction
Screens a whole Solana transaction before it is signed: simulation, Address Risk v2 on counterparties, poisoning checks, and intent extraction.
curl --request POST \
--url https://api.range.org/v2/risk/transaction/scan \
--header 'Content-Type: application/json' \
--header 'X-API-KEY: <api-key>' \
--data '
{
"network": "solana",
"transaction": "AQAAAAAAAAAA…",
"signer_address": "<string>",
"origin": "<string>"
}
'import requests
url = "https://api.range.org/v2/risk/transaction/scan"
payload = {
"network": "solana",
"transaction": "AQAAAAAAAAAA…",
"signer_address": "<string>",
"origin": "<string>"
}
headers = {
"X-API-KEY": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'X-API-KEY': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
network: 'solana',
transaction: 'AQAAAAAAAAAA…',
signer_address: '<string>',
origin: '<string>'
})
};
fetch('https://api.range.org/v2/risk/transaction/scan', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.range.org/v2/risk/transaction/scan",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'network' => 'solana',
'transaction' => 'AQAAAAAAAAAA…',
'signer_address' => '<string>',
'origin' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-API-KEY: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.range.org/v2/risk/transaction/scan"
payload := strings.NewReader("{\n \"network\": \"solana\",\n \"transaction\": \"AQAAAAAAAAAA…\",\n \"signer_address\": \"<string>\",\n \"origin\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-API-KEY", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.range.org/v2/risk/transaction/scan")
.header("X-API-KEY", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"network\": \"solana\",\n \"transaction\": \"AQAAAAAAAAAA…\",\n \"signer_address\": \"<string>\",\n \"origin\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.range.org/v2/risk/transaction/scan")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-API-KEY"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"network\": \"solana\",\n \"transaction\": \"AQAAAAAAAAAA…\",\n \"signer_address\": \"<string>\",\n \"origin\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"screen_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"network": "solana",
"payload_sha256": "<string>",
"severity": "severe",
"counterparties": [
{
"address": "<string>",
"source": "asset-diff",
"severity": "severe",
"triggered_signals": [
"<string>"
]
}
],
"findings": [
{
"signal": "authority-change",
"severity": "severe",
"caption": "Token Authority … changed",
"evidence": {}
}
],
"notes": [
{
"code": "coverage-truncated",
"message": "Counterparty screening truncated to 50 accounts (63 selected)."
}
],
"timestamp": "2026-08-18T14:30:00Z",
"meta": {
"counterparties_screened": 12,
"counterparties_screened_complete": true,
"coverage_truncated": false,
"poisoning_screened": true,
"simulate_ms": 420,
"screening_ms": 610,
"poisoning_ms": 480,
"intent_ms": 900,
"total_ms": 1450
},
"signer": "<string>",
"intent": {
"summary": "Swap 100 USDC for SOL on Jupiter",
"action": "swap",
"confidence": "high"
},
"simulation": {
"simulation_success": true,
"asset_diffs": [
{
"account": "<string>",
"asset": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
"amount": 100.5,
"direction": "credit",
"owner": "<string>"
}
],
"state_changes": [
"<string>"
],
"programs_invoked": [
{
"name": "<string>",
"id": "<string>"
}
]
}
}Authorizations
Authorization method required to allow user to access the api endpoints.
Body
solana "solana"
The complete serialized unsigned transaction — account list, instructions, blockhash — as one encoded string (what a wallet holds immediately before signing).
1 - 4096"AQAAAAAAAAAA…"
Encoding of transaction. Defaults to base64.
base64, base58 The signing account. Defaults to the fee payer derived from the payload.
64Origin (dApp URL) that produced this transaction. Recorded with the scan and forwarded to intent extraction.
2048Response
"a1b2c3d4-e5f6-7890-abcd-ef1234567890"
solana SHA-256 of the decoded payload bytes — the scan identity of this (still unsigned) transaction.
Worst single signal across counterparties and findings.
severe, high, medium, low, none Show child attributes
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Show child attributes
"2026-08-18T14:30:00Z"
Show child attributes
Show child attributes
The signing account this scan assumed.
LLM-extracted intent. Null when extraction was unavailable or timed out (see notes).
Show child attributes
Show child attributes
What signing actually does. Null when simulation failed.
Show child attributes
Show child attributes
Was this page helpful?