The Veriscore API.
Check creators from your own tools: a shortlist spreadsheet, a CRM, an internal vetting script. The API runs the same analysis as the website, charges the same credits, and returns the same verdict. If you can send an HTTP request, you can use it.
Three steps to your first verdict
- Create an account (new accounts get free credits) and open Dashboard, API keys.
- Create a key and copy it. It starts with
vs_live_and is shown only once. - Start a check, poll its status, then read the result:
# 1. Start a check
curl -X POST https://veriscore-production.up.railway.app/api/v1/analyses \
-H "X-Api-Key: $VERISCORE_API_KEY" \
-H "Content-Type: application/json" \
-d '{"platform": "instagram", "username": "natgeo"}'
# 2. Poll until status is "completed"
curl https://veriscore-production.up.railway.app/api/v1/analyses/ANALYSIS_ID/status \
-H "X-Api-Key: $VERISCORE_API_KEY"
# 3. Read the verdict
curl https://veriscore-production.up.railway.app/api/v1/analyses/ANALYSIS_ID \
-H "X-Api-Key: $VERISCORE_API_KEY"Base URL: https://veriscore-production.up.railway.app/api/v1
API keys
Send your key in the X-Api-Key header on every request. If your tool only supports bearer tokens, Authorization: Bearer vs_live_... works too.
- A key acts as you. Checks are charged to your credit balance, count toward your rate limits, and appear in your dashboard alongside checks made on the website.
- Keys are scoped. They can start and read analyses and read your credit balance and history. They cannot change account settings, buy credits, or create other keys. Those calls return 403.
- Keys are stored hashed. We cannot show a key again after it is created. Lost a key? Revoke it and create a new one.
- Revoke any time. A revoked key stops working on the next request. You can hold up to 10 active keys, so give each tool or teammate its own.
Keep keys on the server side. Never put one in a public web page, a mobile app, or a shared document.
Endpoints
Start an analysis
POST /analyses with a JSON body:
platform(required):instagram,youtube,tiktok, ortwitterusername(required): the handle without the @, up to 50 charactersforce_refresh(optional, default false): skip the cache and fetch fresh data
{
"analysis_id": "3f1c0b9e-6a1d-4d7e-9a43-0f8b2c1e7a55",
"status": "pending",
"message": "Analysis started for @natgeo on instagram",
"cached": false,
"cache_age_hours": null,
"cache_tier": null,
"refresh_analysis_id": null
}When a recent result already exists, status comes back as completed with cached: true and you can read the result immediately. Otherwise poll the status endpoint every 10 seconds or so. Most checks finish within a minute or two.
Read the result
GET /analyses/{id} returns the verdict once the status is completed. risk_score runs from 0 to 100, where lower is better, and maps to four tiers: Legit (0 to 25), Monitor (26 to 50), Sketchy (51 to 75), and Run (76 to 100). See the methodology for what goes into the score.
{
"analysis_id": "3f1c0b9e-6a1d-4d7e-9a43-0f8b2c1e7a55",
"status": "completed",
"platform": "instagram",
"username": "natgeo",
"risk_tier": "Legit",
"risk_score": 18,
"authenticity_score": 82,
"confidence_level": 0.86,
"report_data": { "...": "signal breakdown, flags, and recommendations" },
"created_at": "2026-10-01T09:12:44Z",
"completed_at": "2026-10-01T09:13:31Z",
"processing_time_seconds": 47.2
}The same report is viewable at https://veriscore.regnor.systems/report/{id} when you are signed in, and as a PDF from GET /analyses/{id}/pdf.
Credits
API checks cost exactly what they cost on the website, from the same balance.
- Re-checking an account you already checked in the last 4 days is free.
- If an analysis fails, its credits are refunded automatically.
- Short on credits? The API returns 402 and charges nothing. Top up here.
Rate limits
New analyses are limited to 20 per minute, 30 per hour, and 200 per day per account. Keys share your account's limits, so two keys do not double them. Reading results and polling status are limited separately and generously (200 requests per minute). Over the limit, you get a 429; wait and retry.
Need more volume for a campaign? Talk to us.
Status codes
Errors return JSON with a detail field that explains what went wrong.
Python and JavaScript
import os, time, requests
BASE = "https://veriscore-production.up.railway.app/api/v1"
HEADERS = {"X-Api-Key": os.environ["VERISCORE_API_KEY"]}
def check(platform: str, username: str) -> dict:
r = requests.post(f"{BASE}/analyses", headers=HEADERS,
json={"platform": platform, "username": username})
r.raise_for_status()
analysis_id = r.json()["analysis_id"]
while True:
status = requests.get(f"{BASE}/analyses/{analysis_id}/status",
headers=HEADERS).json()["status"]
if status in ("completed", "failed"):
break
time.sleep(10)
return requests.get(f"{BASE}/analyses/{analysis_id}", headers=HEADERS).json()
result = check("instagram", "natgeo")
print(result["risk_tier"], result["risk_score"])const BASE = "https://veriscore-production.up.railway.app/api/v1";
const headers = { "X-Api-Key": process.env.VERISCORE_API_KEY, "Content-Type": "application/json" };
async function check(platform, username) {
const start = await fetch(`${BASE}/analyses`, {
method: "POST", headers, body: JSON.stringify({ platform, username }),
});
if (!start.ok) throw new Error(`Veriscore ${start.status}`);
const { analysis_id } = await start.json();
for (;;) {
const { status } = await (await fetch(`${BASE}/analyses/${analysis_id}/status`, { headers })).json();
if (status === "completed" || status === "failed") break;
await new Promise((r) => setTimeout(r, 10_000));
}
return (await fetch(`${BASE}/analyses/${analysis_id}`, { headers })).json();
}
const result = await check("instagram", "natgeo");
console.log(result.risk_tier, result.risk_score);Google Sheets template
Built for agencies vetting a shortlist. Paste handles into a sheet, choose Veriscore, Check handles, and the verdict, risk score, and a report link fill in next to each creator. Nothing runs until you choose it from the menu, and you see the maximum credit cost before anything is charged.
- Click Make a copy in Google Sheets and confirm. The copy lands in your own Google Drive with the Veriscore script already inside.
- In your copy, open the Veriscore menu next to Help (reload the sheet if you don't see it). The first time, Google asks you to authorize the script: choose your account, then Advanced, then Go to Veriscore, then Allow.
- Choose Set API key and paste a key from your dashboard. It is stored privately for your Google account only.
- On the Creators tab, put handles in column A (an @handle or a full profile link both work) and pick a platform in column B.
- Choose Check handles. You see the maximum credit cost and your balance first; results appear as checks finish. For long lists, use Refresh pending results or turn on auto-refresh.
Prefer your own spreadsheet?
Add the script to any sheet: open Extensions, Apps Script, delete the placeholder code, paste the script, click Save, and reload the sheet. Then use Veriscore, Set up this sheet to add the columns.
The script talks only to the Veriscore API, and you can read every line before you run it. Large lists pause at the hourly limit; run Check handles again later and it picks up where it stopped.