curl --request GET \
--url https://api.trustblock.run/v1/project/security \
--header 'Authorization: Bearer <token>'import requests
url = "https://api.trustblock.run/v1/project/security"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.trustblock.run/v1/project/security', 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.trustblock.run/v1/project/security",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$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.trustblock.run/v1/project/security"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
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.trustblock.run/v1/project/security")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.trustblock.run/v1/project/security")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"name": "<string>",
"domain": "<string>",
"url": "<string>",
"audits": [
{
"date": 123,
"url": "<string>",
"isAIScan": true,
"auditor": {
"name": "<string>",
"url": "<string>"
}
}
],
"activeIssues": [
{
"name": "<string>",
"description": "<string>",
"status": "fixed",
"severity": "low",
"id": "<string>",
"isAcknowledged": true
}
],
"activeRekts": [
{
"name": "<string>",
"rektAt": 123,
"description": "<string>"
}
],
"isDeemedDangerous": true,
"isAIScan": true,
"extra": {
"requestId": "<string>"
}
}{
"message": "Not found.",
"extra": {
"requestId": "<string>"
},
"code": "<string>",
"diagnoses": [
{}
]
}{
"message": "Not found.",
"extra": {
"requestId": "<string>"
},
"code": "<string>",
"diagnoses": [
{}
]
}{
"message": "Not found.",
"extra": {
"requestId": "<string>"
},
"code": "<string>",
"diagnoses": [
{}
]
}Security Data API
A project’s published audits, the findings that still stand and any recorded incidents.
curl --request GET \
--url https://api.trustblock.run/v1/project/security \
--header 'Authorization: Bearer <token>'import requests
url = "https://api.trustblock.run/v1/project/security"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.trustblock.run/v1/project/security', 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.trustblock.run/v1/project/security",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$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.trustblock.run/v1/project/security"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
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.trustblock.run/v1/project/security")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.trustblock.run/v1/project/security")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"name": "<string>",
"domain": "<string>",
"url": "<string>",
"audits": [
{
"date": 123,
"url": "<string>",
"isAIScan": true,
"auditor": {
"name": "<string>",
"url": "<string>"
}
}
],
"activeIssues": [
{
"name": "<string>",
"description": "<string>",
"status": "fixed",
"severity": "low",
"id": "<string>",
"isAcknowledged": true
}
],
"activeRekts": [
{
"name": "<string>",
"rektAt": 123,
"description": "<string>"
}
],
"isDeemedDangerous": true,
"isAIScan": true,
"extra": {
"requestId": "<string>"
}
}{
"message": "Not found.",
"extra": {
"requestId": "<string>"
},
"code": "<string>",
"diagnoses": [
{}
]
}{
"message": "Not found.",
"extra": {
"requestId": "<string>"
},
"code": "<string>",
"diagnoses": [
{}
]
}{
"message": "Not found.",
"extra": {
"requestId": "<string>"
},
"code": "<string>",
"diagnoses": [
{}
]
}Get your API key

Send it as a bearer token
curl "https://api.trustblock.run/v1/project/security?slug=uniswap" \
-H "Authorization: Bearer $TRUSTBLOCK_API_KEY"
domain, slug, or the pair chain and address.Authorization: Bearer <key> is the header to use. Calls that send the key in the older x-trustblock-api-key header are accepted too, on this route and on /v1/key; new integrations should not use it.Check your key (no credit used)
curl "https://api.trustblock.run/v1/key" -H "Authorization: Bearer $TRUSTBLOCK_API_KEY"
200 means the key works; the answer names the account, the header that carried the key and the credits left this month. The dashboard’s Test my key button makes the same call.Reading the response
activeIssueslists every finding from the audits whose findings still stand, fixed ones included. Readstatuson each item. An audit’s findings are dropped only when the same security firm audited the same contracts again.- A finding the client acknowledged without fixing keeps
status: not_fixedand carriesisAcknowledged: true. isDeemedDangerousis true when an audit whose findings still stand reports an open critical finding, or the project has a recorded incident not marked fixed. It restates the data; it is not a judgement about the project. Acknowledged findings do not set it, and High findings do not set it.isAIScanis true when the most recent audit is an automated scan.
Credits and errors
| Status | Meaning |
|---|---|
200 | The project’s state. One API credit is used. |
400 | The query is unusable, for example chain without address. |
401 / 403 | No key, a key that is not recognised (for example one that was replaced), or a key sent in Authorization without Bearer . Your dashboard shows the last refused call and the reason. |
402 | Your API credits are exhausted. |
404 | No project matched, or the project exists and has no published audit. The response does not tell the two apart, and no credit is used. |
Rotating your key
On the dashboard, Rotate key replaces your key at once. The new key is shown so you can copy it, your remaining credits move to it, and the old key stops working on this route immediately (the explorer card routes may accept it for up to 5 minutes). You can rotate once a minute.Authorizations
Authorization: Bearer <key>.
For the project and card routes, the key is an API key belonging to an onboarded integrator or
to an active audit provider. The publishing routes accept only an audit provider's credential.
Sending no Authorization header produces 401; sending one that is not recognised produces
403.
Query Parameters
The project's domain, for example example.com.
The project's Trustblock slug.
Chain of a contract belonging to the project. Must be sent with address.
The chains Trustblock records contracts on.
ethereum, polygon, avalanche, bnbchain, arbitrum, optimism, fantom, zksync, base, polygonZkEvm, scroll, blast, starknet, solana, stellar, sui, tron, injective, ton, plume, peaq, lukso, mina, astar, vana, fiveire, zircuit, cosmoshub, osmosis, neutron, terra, sei, juno, stargaze, dymension, archway, noble, stride, persistence, xrpl, sonic, linea, monad, mantle, megaeth, gnosis, plasma, berachain, celo, hyperevm, unichain, seievm, robinhood, arc, taiko, fraxtal, abstract, worldchain, apechain, xdc, katana, stable, opbnb, bttc, memecore Address of a contract belonging to the project. Must be sent with chain.
Response
The project's security state.
The project's page on Trustblock.
Every published audit of the project, most recently conducted first.
Show child attributes
Show child attributes
Every issue from every audit whose findings still stand, resolved ones included - read status on each item. The name is a misnomer and predates this document; it has never filtered by status.
An earlier audit's findings are dropped only when the same provider audited the same contracts again: a re-audit supersedes its own earlier report. A different provider's findings, and findings on contracts a later audit did not cover, remain listed.
This previously covered the most recent audit only, which meant a finding disappeared as soon as any newer audit was published, whoever wrote it and whatever it covered.
Show child attributes
Show child attributes
Show child attributes
Show child attributes
True when any audit whose findings still stand reports an unresolved critical issue, or the project has an unresolved recorded incident. It is a restatement of the data below it, not a judgement about the project.
It tests Critical only. An unresolved High finding does not set it, and
activeHighIssuesNumber on the card routes is published so a caller can apply its own
threshold. Whether High should set this flag is an open product question, not an oversight:
the great majority of unresolved High findings on this platform are advisories the client
read and accepted.
It excludes acknowledged findings. A Critical finding with isAcknowledged: true does
not set it: the client read the finding and accepted the risk, and this flag describes
unresolved findings nobody has accepted. Such a finding is still listed in activeIssues,
as not_fixed. Acknowledgement is recorded for findings ingested from 2026-09 onward.
True when the most recent audit is an automated scan rather than a human review.
Present on every response, including errors.
Show child attributes
Show child attributes