curl --request GET \
--url https://api.webacy.com/v3/rwa/grades \
--header 'x-api-key: <api-key>'import requests
url = "https://api.webacy.com/v3/rwa/grades"
headers = {"x-api-key": "<api-key>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {'x-api-key': '<api-key>'}};
fetch('https://api.webacy.com/v3/rwa/grades', 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.webacy.com/v3/rwa/grades",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"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"
"net/http"
"io"
)
func main() {
url := "https://api.webacy.com/v3/rwa/grades"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("x-api-key", "<api-key>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.webacy.com/v3/rwa/grades")
.header("x-api-key", "<api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.webacy.com/v3/rwa/grades")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["x-api-key"] = '<api-key>'
response = http.request(request)
puts response.read_body{
"schema_version": "3.0",
"items": [
{
"symbol": "usdb",
"name": "USDBridge",
"chain": "base",
"address": "0x100faa513ac917181eb29f73b64bf7a434a206fe",
"market_cap_usd": null,
"tier": "ok",
"composite": {
"grading_scheme": "v2",
"grade": "A-",
"stars": 5,
"score": 14.5,
"contributors": {
"smart_contract": {
"score": 41.5,
"weight": 0.2
},
"operational_governance": {
"score": 41.5,
"weight": 0.15
},
"asset_collateral": {
"score": 0,
"weight": 0.3
},
"market_liquidity": {
"score": 0,
"weight": 0.2
},
"counterparty": {
"score": 0,
"weight": 0
},
"hack_exploit_history": {
"score": 0,
"weight": 0.15
},
"chain_infrastructure": {
"score": 0,
"weight": 0
}
},
"upstream_risk": 12,
"clamped_by_upstream": false
}
}
],
"pagination": {
"total": 1,
"page": 1,
"pageSize": 50,
"totalPages": 1
},
"grade_counts": {
"A-": 1
},
"generated_at": "2026-06-02T09:49:36Z",
"stale": false
}List RWA & stablecoin grades
Paginated list of every graded RWA / stablecoin token with its v3 risk-polarity composite grade (letter + 0–100 score + per-category contributors). Filterable by chain / grade / minimum score, sortable, and paginated — the bulk companion to GET /v3/rwa/{address}. grade_counts is a histogram over the full graded universe — before every filter (segment, chain, grade, minScore) and before pagination. POLARITY: scores 0–100, higher = worse.
curl --request GET \
--url https://api.webacy.com/v3/rwa/grades \
--header 'x-api-key: <api-key>'import requests
url = "https://api.webacy.com/v3/rwa/grades"
headers = {"x-api-key": "<api-key>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {'x-api-key': '<api-key>'}};
fetch('https://api.webacy.com/v3/rwa/grades', 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.webacy.com/v3/rwa/grades",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"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"
"net/http"
"io"
)
func main() {
url := "https://api.webacy.com/v3/rwa/grades"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("x-api-key", "<api-key>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.webacy.com/v3/rwa/grades")
.header("x-api-key", "<api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.webacy.com/v3/rwa/grades")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["x-api-key"] = '<api-key>'
response = http.request(request)
puts response.read_body{
"schema_version": "3.0",
"items": [
{
"symbol": "usdb",
"name": "USDBridge",
"chain": "base",
"address": "0x100faa513ac917181eb29f73b64bf7a434a206fe",
"market_cap_usd": null,
"tier": "ok",
"composite": {
"grading_scheme": "v2",
"grade": "A-",
"stars": 5,
"score": 14.5,
"contributors": {
"smart_contract": {
"score": 41.5,
"weight": 0.2
},
"operational_governance": {
"score": 41.5,
"weight": 0.15
},
"asset_collateral": {
"score": 0,
"weight": 0.3
},
"market_liquidity": {
"score": 0,
"weight": 0.2
},
"counterparty": {
"score": 0,
"weight": 0
},
"hack_exploit_history": {
"score": 0,
"weight": 0.15
},
"chain_infrastructure": {
"score": 0,
"weight": 0
}
},
"upstream_risk": 12,
"clamped_by_upstream": false
}
}
],
"pagination": {
"total": 1,
"page": 1,
"pageSize": 50,
"totalPages": 1
},
"grade_counts": {
"A-": 1
},
"generated_at": "2026-06-02T09:49:36Z",
"stale": false
}GET /v3/rwa/{address}.
grade_counts is a histogram over the full graded universe — before every filter (segment, chain, grade, minScore) and before pagination. Grades are emitted in the resolved grading_scheme’s letters (default v2).Freshness
The response carries two top-level freshness fields:generated_at (when this snapshot was produced) and stale (true when the snapshot is older than the expected refresh cadence). Unlike the RWA detail endpoint, this list gives you a stale flag you can hard-gate on. See Hard-gating and fail behavior.
Filtering by segment
segment scopes the list to stablecoin or rwa. The two are exclusive and total, so their counts add up to the unfiltered total.
The grades universe is our grading snapshot rather than the set of classified tokens, and many tokens in it are not classified yet. Those fall to the stablecoin arm, so on this endpoint stablecoin means “pegged and not a classified RWA, including not-yet-classified”. Read each row’s asset_class to tell a confirmed fiat token ("fiat") from an unclassified one (null).
pegType is not accepted on this route: grade rows carry no denomination. Use GET /rwa for that filter.
For a stablecoin-only route that pins the segment server-side, see GET /v3/stablecoins/grades.
When the classification is unavailable
Degradation is split by risk:| Request | Behaviour |
|---|---|
No segment | 200 with the classification fields omitted from each row and classification_available: false |
Explicit segment | 503 — the filter cannot be honoured, and a superset would be a wrong answer presented as a correct one |
classification_available: false as unknown, never as “not a stablecoin”.Authorizations
Query Parameters
Filter by chain slug (e.g. eth, base, pol).
Filter by segment. A segment is a derived category over the classification dimensions, not a dimension value — do NOT pass an asset_class such as fiat or fixed-income here; each item carries both its computed segment and the dimensions it was derived from. rwa = is_rwa true and asset_class not fiat (tokenized treasuries/funds, gold); stablecoin = everything else — asset_class fiat (USDC, USDT, DAI, USDe) plus graded tokens that have not been classified yet, which fall back to stablecoin exactly as the detail asset_type does. Both values resolve through that single rule, so they are mutually exclusive and partition the graded universe: the stablecoin and rwa totals sum to the unfiltered total. grade_counts is a histogram over the full graded universe — before every filter (segment, chain, grade, minScore) and before pagination. When the classification cannot be loaded, an unfiltered request degrades to unstamped rows with classification_available: false, while an explicit segment answers 503. Unknown values are ignored.
stablecoin, rwa Filter to a single grade letter. Accepts any letter from either scheme (the enum is the union); a letter the resolved grading_scheme never emits — e.g. E under v2 or C+ under v1 — simply matches no tokens.
A+, A, A-, B+, B, B-, C+, C, C-, D, E, F Minimum composite (risk) score, 0–100.
0 <= x <= 100Sort field.
score, symbol, chain, grade, market_cap_usd Sort order. Default asc (best grade first).
asc, desc 1-based page number.
x >= 1Items per page (default 50).
Grading scheme to pin — selects the per-category weights and letter-grade band table. Default v2 (alias of v1's weights, standard 11-band grade scale). peg is the peg-loss-focused weighting. v3/v4/peg-liquidity are registered but withheld behind the v3-grading-scheme feature flag. Independent of the API version (v3) and of framework_version.
v1, v2, peg Response
Paginated list of graded tokens. grade_counts covers the full graded universe (pre-filter), not the filtered result or the returned page.
"3.0"
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Grade-letter histogram over the FULL graded universe, computed before every filter (segment, chain, grade, minScore) — not the filtered or paged subset. In the resolved scheme's letters.
Show child attributes
Show child attributes
false when the asset classification could not be loaded — rows are unstamped and any segment filter was not applied.
