Discovery Scan API
The Discovery Scan API lets you run Chainara's discovery scanners on demand
and get back actionable indicators — crypto wallet addresses and URLs
(IOCs) — plus a per-source scam verdict. You submit a scan for a module
(e.g. youtube, telegram) with your existing API key; the scan runs
asynchronously and you retrieve results by polling or via a signed webhook.
It's the same scanning engine that powers Chainara's automated discovery jobs, exposed per request so you can point it at your own search terms or channels.
Available modules
| Module | What it scans | Module-specific input |
|---|---|---|
youtube | Live/recent YouTube videos for crypto-scam overlays, QR codes, and links (vision analysis) | queries[] or video_url, optional max_streams_per_query |
telegram | Recent messages in public Telegram channels | channels[], optional max_messages_per_channel |
meta-ads | Meta (Facebook/Instagram) Ad Library for crypto-scam ads — returns destination domains + impersonated handles | queries[], optional max_ads_per_query, countries[] |
bluesky | Bluesky (AT Protocol) posts matching your search queries | queries[], optional limit |
bing-ads | Microsoft Bing Ad Library (EU/EEA) for crypto recovery/broker-scam ads — returns destination URLs | queries[], optional max_ads_per_query |
Call GET /api/v2/discovery/modules for the live list and an example body for each.
The module list grows over time. Always discover capabilities programmatically
via /discovery/modules rather than hard-coding the set.
Authentication
All endpoints use your standard API key (see API & Integration):
Authorization: Bearer <your-api-key>
Endpoints
| Method | Path | Purpose |
|---|---|---|
GET | /api/v2/discovery/modules | List modules + example body for each |
POST | /api/v2/discovery/{module}/scan | Submit a scan → 202 with jobId |
GET | /api/v2/discovery/{module}/scan/{jobId} | Poll status + IOCs + findings |
GET | /api/v2/discovery/scans | List your recent scans (?module=, ?limit=) |
Submit a scan
The request body is module-specific plus two common blocks — filters
(optional) and callback_url (optional).
# YouTube
curl -X POST https://api.chainara.io/api/v2/discovery/youtube/scan \
-H "Authorization: Bearer $CHAINARA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"queries": ["Brad Garlinghouse live giveaway", "XRP airdrop confirmed"],
"max_streams_per_query": 10,
"filters": { "scams_only": true },
"callback_url": "https://you.example.com/webhooks/chainara"
}'
# Telegram
curl -X POST https://api.chainara.io/api/v2/discovery/telegram/scan \
-H "Authorization: Bearer $CHAINARA_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "channels": ["@investigations"], "max_messages_per_channel": 60 }'
# Meta Ads (Facebook / Instagram Ad Library)
curl -X POST https://api.chainara.io/api/v2/discovery/meta-ads/scan \
-H "Authorization: Bearer $CHAINARA_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "queries": ["xrp giveaway", "ripple airdrop"], "max_ads_per_query": 30, "countries": ["US"] }'
// 202 Accepted
{
"jobId": "855a022b-c7e6-4b7e-bf59-0fe57a46efb0",
"module": "youtube",
"status": "scanning",
"statusUrl": "/api/v2/discovery/youtube/scan/855a022b-…",
"webhook": { "url": "https://you.example.com/…", "signed": true }
}
Poll for results
curl https://api.chainara.io/api/v2/discovery/youtube/scan/855a022b-… \
-H "Authorization: Bearer $CHAINARA_API_KEY"
{
"jobId": "855a022b-…",
"module": "youtube",
"status": "completed",
"summary": { "itemsScanned": 14, "hitsConfirmed": 3, "iocCount": 5 },
"iocs": {
"wallets": [ { "chain": "xrp", "address": "rXxx…", "foundIn": ["abc123"] } ],
"urls": [ { "url": "https://giftsaylor.us", "domain": "giftsaylor.us", "foundIn": ["abc123"] } ]
},
"findings": [
{
"sourceId": "abc123",
"sourceUrl": "https://www.youtube.com/watch?v=abc123",
"verdict": "scam",
"confidence": 0.85,
"signals": ["impersonation", "qr_code", "scam_language"],
"wallets": [ /* … */ ],
"urls": [ /* … */ ],
"extra": { "streamLayout": "scam_overlay" }
}
]
}
status is one of queued · scanning · completed · partial · failed.
The iocs block is the de-duplicated rollup across all findings — usually
the only part you need to action. Each finding's verdict is scam, benign,
or unknown, with a confidence of 0–1.
YouTube scans take ~2–5 minutes (video capture + vision analysis). Telegram
scans typically finish in under a minute. Poll every ~15 seconds, or use a
callback_url webhook to avoid polling.
Filters (all modules)
| Field | Effect |
|---|---|
scams_only | Return only findings with verdict: scam |
min_confidence | Drop findings below this confidence (0–1) |
require_iocs | Drop findings with no wallet/URL |
Webhooks
If you supply callback_url, Chainara POSTs the completed result to that URL
with an HMAC signature so you can verify authenticity:
X-Chainara-Event: discovery-scan.completed
X-Chainara-Timestamp: 1748396843
X-Chainara-Signature: sha256=<hmac>
The signature is HMAC-SHA256(secret, "{timestamp}.{rawBody}"). Verify in Node:
import crypto from "crypto";
function verify(req, secret) {
const ts = req.headers["x-chainara-timestamp"];
const expected =
"sha256=" + crypto.createHmac("sha256", secret)
.update(`${ts}.${req.rawBody}`).digest("hex");
const got = req.headers["x-chainara-signature"];
return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(got));
}
The webhook body mirrors the poll response (jobId, module, status,
summary, iocs, findings) plus an event field. Your per-job signing secret
is shown in the API Keys area of the dashboard.
Errors
| Status | Meaning |
|---|---|
400 | Invalid request body (e.g. missing module params) |
401 | Missing or invalid API key |
404 | Unknown module, or job not found / not yours |
502 | Could not queue the scan — retry |
Try it
Use the interactive Discovery section of the API Explorer to send live requests with your key.