curl --request GET \
--url https://www.serializedaudit.io/api/audit-contract \
--header 'X-Auth-Key: <api-key>'import requests
url = "https://www.serializedaudit.io/api/audit-contract"
headers = {"X-Auth-Key": "<api-key>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {'X-Auth-Key': '<api-key>'}};
fetch('https://www.serializedaudit.io/api/audit-contract', 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://www.serializedaudit.io/api/audit-contract",
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-Auth-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://www.serializedaudit.io/api/audit-contract"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("X-Auth-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://www.serializedaudit.io/api/audit-contract")
.header("X-Auth-Key", "<api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://www.serializedaudit.io/api/audit-contract")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["X-Auth-Key"] = '<api-key>'
response = http.request(request)
puts response.read_body{
"audit": {
"isSafe": true,
"isTokenSafe": true,
"isHookSafe": null,
"description": "Standard ERC-20 token. No owner privileges that can harm holders were detected.",
"vulnerabilities": [],
"name": "Example Token",
"symbol": "EXMPL",
"address": "0x6D7401F6f1fB09ff24a048337ff44D890CdF86F8",
"chain": "BASE",
"sourceType": "verified",
"isProxy": false,
"implementationAddress": null,
"hookAddress": null,
"hookAudit": null,
"createdAt": "2026-06-22T10:00:00.000Z",
"auditSystemVersion": "prod-v2.10",
"latestAuditSystemVersion": "prod-v2.10"
}
}Audit a contract
Returns a safety verdict, a human-readable summary, identity, and the detected risks for the given contract. Results are returned in milliseconds when the contract has been audited before; a first-time audit may take a few seconds.
curl --request GET \
--url https://www.serializedaudit.io/api/audit-contract \
--header 'X-Auth-Key: <api-key>'import requests
url = "https://www.serializedaudit.io/api/audit-contract"
headers = {"X-Auth-Key": "<api-key>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {'X-Auth-Key': '<api-key>'}};
fetch('https://www.serializedaudit.io/api/audit-contract', 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://www.serializedaudit.io/api/audit-contract",
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-Auth-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://www.serializedaudit.io/api/audit-contract"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("X-Auth-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://www.serializedaudit.io/api/audit-contract")
.header("X-Auth-Key", "<api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://www.serializedaudit.io/api/audit-contract")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["X-Auth-Key"] = '<api-key>'
response = http.request(request)
puts response.read_body{
"audit": {
"isSafe": true,
"isTokenSafe": true,
"isHookSafe": null,
"description": "Standard ERC-20 token. No owner privileges that can harm holders were detected.",
"vulnerabilities": [],
"name": "Example Token",
"symbol": "EXMPL",
"address": "0x6D7401F6f1fB09ff24a048337ff44D890CdF86F8",
"chain": "BASE",
"sourceType": "verified",
"isProxy": false,
"implementationAddress": null,
"hookAddress": null,
"hookAudit": null,
"createdAt": "2026-06-22T10:00:00.000Z",
"auditSystemVersion": "prod-v2.10",
"latestAuditSystemVersion": "prod-v2.10"
}
}Authorizations
Your secret API key. Create one from your dashboard.
Query Parameters
Chain the contract is deployed on, as a case-insensitive symbol. See Supported Chains. SOLANA (alias SOL) audits a Solana token by its mint address.
ROBINHOOD, BSC, BASE, ETH, AVAX, STABLE, ARC, ARB, HYPE, MONAD, PLASMA, POLYGON, MEGAETH, OP, LINEA, TEMPO, MANTLE, ABSTRACT, SONIC, BLAST, APE, XLAYER, INK, UNICHAIN, STORY, ZKEVM, SCROLL, ZKSYNC, SOLANA The subject to audit: a token address, a liquidity pool (a Uniswap V2/V3 pair address or a Uniswap V4 pool id, 32 bytes), or a Uniswap V4 hook address. A pool resolves to its token: the response's audit.address is that resolved token and audit.pool describes the pool the hook verdict was computed against. A hook returns the hook's own audit: audit.address is the hook and audit.hookContext lists the pools and tokens that use it. audit.entry tells you how it was addressed. Cache your results by audit.chain + audit.address, not by the value you sent. On chain=solana: the token's base58 mint address, CASE-SENSITIVE (send it exactly as written; a lowercased mint is another account). Pool and hook entries are EVM only.
^(?:0x(?:[a-fA-F0-9]{40}|[a-fA-F0-9]{64})|[1-9A-HJ-NP-Za-km-z]{32,44})$Optional, EVM only. Pin a specific pool for a token entry: address is the token, pool is the pool whose hook drives the verdict (a V2/V3 pair address or a V4 pool id). A mismatch (the pool does not trade the token) is a 400. Not used on chain=solana (it answers 404 pool_not_found): send the mint alone.
^0x(?:[a-fA-F0-9]{40}|[a-fA-F0-9]{64})$Closed-source contracts are audited on decompiled bytecode (the most expensive tier). Set false to opt out: closed-source contracts then answer { "audit": null, "reason": "decompile_disabled" } instead of being decompiled, and cached decompiled verdicts are not served. Sent as the string "true"/"false" in the query.
true, false Async mode. false (default): the request holds until the audit is done, classic synchronous behavior. true: if no cached audit exists, the audit is started in the background and the response is { status }; poll the SAME URL every 1-2s until it flips to { audit } (typically 10-30s for a first-time audit). There is no job id: an audit is idempotent per (chain, address), so the token address is the job handle. Billing is identical in both modes; progress responses are never billed. With subscribe=true you do not even poll: the finished verdict is pushed to you (over your SSE stream or webhook) the moment it lands (see SSE & Webhooks).
true, false Subscribe this (chain, address) to push updates as part of this call. Once subscribed, any later verdict change (safe↔unsafe flip, owner change, a gate or honeypot flipping, or a closed-source token re-audited on its now-verified source) is pushed to you over a live SSE stream or a webhook, instead of you polling. Combined with async=true, the finished audit result is itself pushed when ready, so you fire the call and just consume the events. Subscribing works with or without a delivery transport configured; with neither, pull the changes from GET /api/events (see SSE & Webhooks). Charges the one-time subscribe fee for a genuinely-new token; idempotent for an already-subscribed one.
true, false Response
The audit verdict, wrapped in an audit object.
- Option 1
- Option 2
- Option 3
The response shape.
The audit result.
Show child attributes
Show child attributes
Echo of what this call was billed, present only for authenticated API-key callers (never for anonymous/browser traffic). type is the bill category (e.g. cached, fresh_no_decompile, fresh_with_decompile, refresh) or null when the call is free; credits is the amount metered.
Show child attributes
Show child attributes