curl --request POST \
--url https://api.range.org/v2/transactions/evaluate \
--header 'Content-Type: application/json' \
--header 'X-API-KEY: <api-key>' \
--data '
{
"network": "solana",
"transaction": "AQAAAAAAAAAA…",
"signer_address": "<string>"
}
'import requests
url = "https://api.range.org/v2/transactions/evaluate"
payload = {
"network": "solana",
"transaction": "AQAAAAAAAAAA…",
"signer_address": "<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>'})
};
fetch('https://api.range.org/v2/transactions/evaluate', 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/transactions/evaluate",
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>'
]),
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/transactions/evaluate"
payload := strings.NewReader("{\n \"network\": \"solana\",\n \"transaction\": \"AQAAAAAAAAAA…\",\n \"signer_address\": \"<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/transactions/evaluate")
.header("X-API-KEY", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"network\": \"solana\",\n \"transaction\": \"AQAAAAAAAAAA…\",\n \"signer_address\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.range.org/v2/transactions/evaluate")
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}"
response = http.request(request)
puts response.read_body{
"verdict": "blocked",
"coverage": "complete",
"network": "solana",
"payload_sha256": "<string>",
"transaction_breaches": [
{
"policy_key": "treasury.asset_concentration",
"policy_type": "concentration",
"policy_name": "Asset concentration bound",
"reason": "Projected asset share for USDC is 34.2%, above the 30% bound (currently 28.1%)",
"projected_effect": {
"kind": "concentration",
"dimension": "asset",
"subject": "USDC",
"current_share_percent": 28.1,
"projected_share_percent": 34.2,
"bound_percent": 30
}
}
],
"movements": [
{
"kind": "transfer",
"from": "<string>",
"to": "<string>",
"asset": "USDC",
"mint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
"amount": "100.5",
"amount_usd": "100.52",
"priced": true,
"verdict": "blocked",
"breaches": [
{
"policy_key": "treasury.asset_concentration",
"policy_type": "concentration",
"policy_name": "Asset concentration bound",
"reason": "Projected asset share for USDC is 34.2%, above the 30% bound (currently 28.1%)",
"projected_effect": {
"kind": "concentration",
"dimension": "asset",
"subject": "USDC",
"current_share_percent": 28.1,
"projected_share_percent": 34.2,
"bound_percent": 30
}
}
],
"policies_evaluated": 4,
"policies_skipped": [
{
"policy_key": "treasury.transaction_ceiling",
"policy_type": "value_ceiling",
"policy_name": "Per-transaction value ceiling",
"reason": "Not evaluated: the movement asset has no USD price and this policy is denominated in USD."
}
]
}
],
"notes": [
{
"code": "movement-unpriced",
"message": "<string>"
}
],
"policies_in_catalog": 4,
"evaluated_at": "<string>",
"meta": {
"movements_total": 123,
"authority_grants": 123,
"movements_evaluated": 123,
"self_transfers_skipped": 123,
"program_credits_skipped": 123,
"unresolved_recipients": 123,
"movements_truncated": true,
"simulate_ms": 123,
"evaluate_ms": 123,
"total_ms": 123
},
"signer": "<string>"
}Evaluate an unsigned transaction against the treasury policies
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.
curl --request POST \
--url https://api.range.org/v2/transactions/evaluate \
--header 'Content-Type: application/json' \
--header 'X-API-KEY: <api-key>' \
--data '
{
"network": "solana",
"transaction": "AQAAAAAAAAAA…",
"signer_address": "<string>"
}
'import requests
url = "https://api.range.org/v2/transactions/evaluate"
payload = {
"network": "solana",
"transaction": "AQAAAAAAAAAA…",
"signer_address": "<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>'})
};
fetch('https://api.range.org/v2/transactions/evaluate', 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/transactions/evaluate",
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>'
]),
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/transactions/evaluate"
payload := strings.NewReader("{\n \"network\": \"solana\",\n \"transaction\": \"AQAAAAAAAAAA…\",\n \"signer_address\": \"<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/transactions/evaluate")
.header("X-API-KEY", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"network\": \"solana\",\n \"transaction\": \"AQAAAAAAAAAA…\",\n \"signer_address\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.range.org/v2/transactions/evaluate")
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}"
response = http.request(request)
puts response.read_body{
"verdict": "blocked",
"coverage": "complete",
"network": "solana",
"payload_sha256": "<string>",
"transaction_breaches": [
{
"policy_key": "treasury.asset_concentration",
"policy_type": "concentration",
"policy_name": "Asset concentration bound",
"reason": "Projected asset share for USDC is 34.2%, above the 30% bound (currently 28.1%)",
"projected_effect": {
"kind": "concentration",
"dimension": "asset",
"subject": "USDC",
"current_share_percent": 28.1,
"projected_share_percent": 34.2,
"bound_percent": 30
}
}
],
"movements": [
{
"kind": "transfer",
"from": "<string>",
"to": "<string>",
"asset": "USDC",
"mint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
"amount": "100.5",
"amount_usd": "100.52",
"priced": true,
"verdict": "blocked",
"breaches": [
{
"policy_key": "treasury.asset_concentration",
"policy_type": "concentration",
"policy_name": "Asset concentration bound",
"reason": "Projected asset share for USDC is 34.2%, above the 30% bound (currently 28.1%)",
"projected_effect": {
"kind": "concentration",
"dimension": "asset",
"subject": "USDC",
"current_share_percent": 28.1,
"projected_share_percent": 34.2,
"bound_percent": 30
}
}
],
"policies_evaluated": 4,
"policies_skipped": [
{
"policy_key": "treasury.transaction_ceiling",
"policy_type": "value_ceiling",
"policy_name": "Per-transaction value ceiling",
"reason": "Not evaluated: the movement asset has no USD price and this policy is denominated in USD."
}
]
}
],
"notes": [
{
"code": "movement-unpriced",
"message": "<string>"
}
],
"policies_in_catalog": 4,
"evaluated_at": "<string>",
"meta": {
"movements_total": 123,
"authority_grants": 123,
"movements_evaluated": 123,
"self_transfers_skipped": 123,
"program_credits_skipped": 123,
"unresolved_recipients": 123,
"movements_truncated": true,
"simulate_ms": 123,
"evaluate_ms": 123,
"total_ms": 123
},
"signer": "<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. Honored only when it is a required signer of the payload; defaults to the fee payer derived from the payload.
64Response
Worst outcome across the evaluation: any transaction_breaches entry or any breached movement blocks the transaction. Both outcomes are HTTP 200. Advisory — the caller’s signing flow owns the decision.
blocked, allowed Partial when anything evaluable was not fully evaluated: an unpriced asset (its value is in no USD total), an unresolvable recipient or sender, an authority grant, a truncated movement list, an unresolved signer, or no extracted movement at all. A partial allowed is not a clean bill — read notes.
complete, partial "solana"
SHA-256 of the decoded payload bytes — the evaluation’s identity.
Breaches of per-transaction policies (the transaction value ceiling, the asset concentration projection), judged once on the combined USD value of every priced movement. They belong to no single movement, so they are not repeated under movements.
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Size of the policy catalog this evaluation ran against — the catalog at GET /v2/intents/policies.
4
When the evaluation ran (ISO 8601).
Show child attributes
Show child attributes
The signer the evaluation ran against.
Was this page helpful?