@raid_ai/sdk
v0.1.2
Published
Official TypeScript SDK for the Raid AI detection API — detect AI-generated and manipulated media, and fact-check claims.
Downloads
355
Readme
@raid_ai/sdk
Official TypeScript/JavaScript SDK for the Raid AI detection API — detect AI-generated and manipulated media (images, audio, video) and fact-check media against the public record.
Works in Node 18+ and the browser. Full API reference: https://docs.raidxai.com.
Install
npm install @raid_ai/sdkAuthentication
Every request uses a developer token. Create one in the Raid AI dashboard (Settings → API keys) and keep it server-side — never ship it in client code.
import { RaidClient } from "@raid_ai/sdk";
const raid = new RaidClient({
apiKey: process.env.RAID_API_KEY!, // your API key
baseUrl: process.env.RAID_API_BASE_URL!, // required — the Raid AI API base URL
// timeoutMs: 60_000,
// maxRetries: 2,
// authHeader: "bearer", // or "x-api-key"
});Each API key carries scopes (image, audio, video, fact-check) — a call to a modality
your key isn't scoped for returns a typed 403 (api_key.scope_missing).
Usage
Images (synchronous)
import { readFileSync } from "node:fs";
const res = await raid.images.process({
data: readFileSync("suspect.jpg"),
fileName: "suspect.jpg",
contentType: "image/jpeg",
});
console.log(res.images[0]?.verdict, res.images[0]?.confidence);
// …or from a URL:
await raid.images.processFromUrl("https://example.com/photo.jpg");Audio (synchronous)
import { VoiceWorkflow } from "@raid_ai/sdk";
const res = await raid.audio.process(
{ data: readFileSync("clip.mp3"), fileName: "clip.mp3", contentType: "audio/mpeg" },
{ workflowType: VoiceWorkflow.AiDetectionOnly },
);
console.log(res.isAiDetected, res.detectionConfidence);Video (asynchronous — submit then poll)
// One-liner: submit and wait for the terminal verdict.
const job = await raid.video.submitAndWait(
{ data: readFileSync("clip.mp4"), fileName: "clip.mp4", contentType: "video/mp4" },
{ clientDurationSeconds: 42, intervalMs: 3000, timeoutMs: 300_000 },
);
console.log(job.status, job.result?.verdict);
// …or drive it yourself:
const { jobId } = await raid.video.submit(file, { clientDurationSeconds: 42 });
const state = await raid.video.getJob(jobId);Fact-checking (asynchronous)
const job = await raid.factChecking.submitAndWait(
{ data: readFileSync("photo.jpg"), fileName: "photo.jpg", contentType: "image/jpeg" },
"image",
{ userContext: "Claimed to be from the 2024 election." },
);
console.log(job.result?.summary, job.result?.provenance);Errors
Non-2xx responses throw RaidApiError with status, code, message, and body. Transient
429/5xx responses are retried automatically with exponential backoff (configurable via maxRetries).
import { RaidApiError, RaidTimeoutError } from "@raid_ai/sdk";
try {
await raid.images.process(file);
} catch (err) {
if (err instanceof RaidApiError) {
if (err.isAuth) console.error("bad or unscoped token:", err.code);
else if (err.isPaymentRequired) console.error("out of credits:", err.code);
else console.error(err.status, err.code, err.message);
} else if (err instanceof RaidTimeoutError) {
console.error("job did not finish in time; last status:", err.lastStatus);
}
}Types
All response and enum types are exported (ImageForensicsResponse, VideoJob, Verdict,
JobStatus, …). They are generated from the API's OpenAPI spec, so they track the server contract.
Development
npm install
npm run generate:types # regenerate src/generated/openapi.ts from ../spec/openapi.yaml
npm run typecheck
npm run build # ESM + CJS + .d.ts via tsup
npm test # vitest (fetch mocked)Run the live smoke test against a real tier:
RAID_API_KEY=<your-api-key> RAID_API_BASE_URL=<raid-ai-api-url> npm test