factlens
v6.7.1
Published
Official Node.js, TypeScript SDK, and CLI for the FactLens verification API
Maintainers
Readme
FactLens SDK & CLI
The official Node.js, TypeScript SDK, and command-line interface for the FactLens verification API.
FactLens exposes a focused runtime: Verify. Transcription, evidence retrieval, safety checks, and AI analysis remain internal verification stages rather than standalone provider commands.
Current package: 6.7.0
Runtime: Node.js 18+
Install
npm install factlensThe same package contains the CLI:
npx factlens --help
npx factlens verify "Earth orbits the Sun."For a global command:
npm install -g factlens
factlens --helpCredentials
Open https://api.factlens.pro/dashboard.
| Credential | Used for | |---|---| | Project API key | Verify and runtime usage | | Developer token | Account, projects, keys, key customization, logs, request inspection |
The SDK reads these environment variables automatically:
FACTLENS_API_KEY=fl_live_YOUR_KEY
FACTLENS_DEVELOPER_TOKEN=fldev_live_YOUR_TOKENThe CLI can store them in the operating-system user configuration directory:
factlens configure
factlens config show
factlens doctorconfig show masks secrets. Environment variables override saved CLI credentials.
v6.7.0 runtime metadata
Ordinary SDK calls remain source-compatible:
const result = await factlens.verify({ mode: "text", claim: "Earth orbits the Sun." });Use the additive detailed path when you need transport/runtime diagnostics:
const { data, meta } = await factlens.verifyDetailed({ mode: "text", claim: "Earth orbits the Sun." });
console.log(meta.serverTiming.coreMs, meta.serverTiming.edgeMs, meta.gatewayNetworkMs);CLI
Text verification
factlens verify "The Eiffel Tower is in Paris."
factlens verify --file claim.txtA passage may contain multiple claims. Human output renders every successful claim separately and reports failed_claims independently when only part of a multi-claim request fails.
Image/post verification
factlens verify --image screenshot.png
factlens verify --image screenshot.webp --claim "Optional focus or guidance"Supported image files are PNG, JPEG, WebP, HEIC, and HEIF. The image claim is optional because FactLens can isolate the primary checkable claim from the image itself.
Audio/video and transcripts
factlens verify --audio interview.mp3
factlens verify --audio clip.m4a --speaker "Jane Doe" --language auto
factlens verify --audio-url https://example.com/interview.mp3
factlens verify --transcript "Transcript text"
factlens verify --transcript-file transcript.txtThe CLI streams local audio through FactLens's resumable upload path. Audio is limited to 3 hours and is billed at one API credit per 10 minutes or part thereof. Direct transcript input includes the first 100,000 transcript characters in the normal one-credit charge and then adds one credit for each additional 30,000 transcript characters or part thereof.
Forward-only progress
Interactive terminals use a forward-only animated phase rail. It never runs backward:
FactLens TEXT 1.842s [✓] Sent ━━━ [◐] Verifying ━━━ [ ] ResultCompleted phases stay green, the active spinner/rail stays cyan, waiting/retry states use warning colors, and the final verdict uses the exact API-provided verdictColor. Audio upload uses a real byte-derived percentage because the resumable uploader knows the acknowledged offset; text and image verification deliberately do not invent percentages.
When stdout is not a TTY, FactLens avoids animation frames. --json remains clean for automation. NO_COLOR disables ANSI color.
Local jobs:
factlens list
factlens kill REQUEST_ID
factlens kill allSource preferences and advanced Verify controls
Trusted and blocked domains can be saved as defaults for each API key. A request that omits a list uses the saved list. Supplying a list overrides the matching saved list for that request only. An explicit empty array in the SDK, or the matching CLI --no-* flag, temporarily clears that saved list without rewriting dashboard configuration. Blocked domains win if a domain is present in both lists.
factlens verify "A claim" \
--trusted-domains reuters.com,apnews.com \
--blocked-domains example.com \
--instructions "Prefer direct primary evidence." \
--search-query "custom research query" \
--results-per-search 10Explicitly ignore saved lists for one request:
factlens verify "A claim" --no-trusted-domains --no-blocked-domainsRequest-scoped verdict definitions, including colors, can be supplied from JSON:
[
{
"id": "custom:11111111-1111-4111-8111-111111111111",
"name": "CONFIRMED",
"color": "#16a34a",
"rule": "Choose when the supplied evidence directly establishes the claim."
}
]factlens verify "A claim" --verdicts-file verdicts.jsonTiming
The old millisecond option remains backward compatible:
factlens verify "A claim" --timeout 90000v6.7.0 continues to accept seconds:
factlens verify "A claim" --timeout-seconds 90Do not pass both timeout forms together. Human output can choose its display unit:
factlens verify "A claim" --time-unit auto
factlens verify "A claim" --time-unit ms
factlens verify "A claim" --time-unit sv6.7.0 consumes the API's additive Server-Timing contract. Default output shows total client wall time and core verification time. --verbose adds Auth/Config/Core/Post/Edge plus the approximate outside-network remainder; --trace adds safe HTTP/retry diagnostics. response_time_ms remains core verification time and is never relabeled as total server time.
Output modes
factlens verify "A claim" --quiet
factlens verify "A claim" --verbose
factlens verify "A claim" --json--quiet: verdict IDs only.- default: readable claim/verdict/evidence/source summary.
--verbose: full source URLs and runtime breakdown.--trace: full safe transport/runtime diagnostics.--json: machine-readable API response with additivetimingmetadata for Verify.
If the API returns verdictColor, human output uses that exact #RRGGBB color. With ANSI disabled, the hex value remains visible.
Management and API-key customization
Management commands require a developer token:
factlens account
factlens projects list
factlens projects create "Production"
factlens projects update PROJECT_ID "Production API"
factlens projects select PROJECT_ID
factlens projects delete PROJECT_ID --yes
factlens keys list
factlens keys create "Backend"
factlens keys revoke KEY_ID --yes
factlens usage --account
factlens logs --limit 50 --endpoint verify
factlens request REQUEST_IDv6.7.0 preserves the API-key customization contract through the public developer-token management API:
factlens keys customization get KEY_ID --project PROJECT_ID
factlens keys customization preferences KEY_ID \
--project PROJECT_ID \
--trusted-domains reuters.com,apnews.com \
--blocked-domains example.com
factlens keys customization prompt save KEY_ID \
--project PROJECT_ID \
--mode text \
--stage claim_extraction \
--instruction-file claim-prompt.txt \
--input-budget 8000 \
--prompt-mode guided
factlens keys customization prompt reset KEY_ID \
--project PROJECT_ID \
--mode text \
--stage claim_extraction
factlens keys customization verdicts save KEY_ID \
--project PROJECT_ID \
--file verdict-config.json
factlens keys customization verdicts reset KEY_ID \
--project PROJECT_ID \
--yesCustomization modes are text, audio, and image. Saved prompt budgets are stage-specific: default 8,000, minimum 2,000, maximum 20,000, in 100-token increments.
SDK
import FactLens from "factlens";
const factlens = new FactLens();
const result = await factlens.verify({
mode: "text",
claim: "The Eiffel Tower is in Paris.",
});
console.log(result.verdictId);
console.log(result.verdictColor);
console.log(result.explanation);
console.log(result.sources);Pass credentials explicitly if preferred:
const factlens = new FactLens({
apiKey: process.env.FACTLENS_API_KEY,
developerToken: process.env.FACTLENS_DEVELOPER_TOKEN,
});Verify inputs
Text:
const result = await factlens.verify({
mode: "text",
text: "A passage containing one or more factual claims.",
trusted_domains: ["reuters.com"],
blocked_domains: [],
instructions: "Prefer primary sources.",
search_query: "optional query override",
results_per_search: 10,
});Image/post:
const result = await factlens.verify({
mode: "image_post",
image_base64: imageBase64,
content_type: "image/png",
});Audio/video or an existing transcript:
const mediaResult = await factlens.verify({
mode: "audio_video",
audio_url: "https://example.com/interview.mp3",
speaker: "Jane Doe",
language: "auto",
});
const transcriptResult = await factlens.verify({
mode: "audio_video",
transcript: existingTranscript,
});Request-scoped verdict colors
const result = await factlens.verify({
mode: "text",
claim: "A claim",
verdicts: [
{
id: "custom:11111111-1111-4111-8111-111111111111",
name: "CONFIRMED",
color: "#16a34a",
rule: "Choose when the supplied evidence directly establishes the claim.",
},
],
});
console.log(result.verdictId);
console.log(result.verdictColor);For multi-claim responses, result.results contains independently verified results and each result can include its own verdictColor. result.failed_claims contains per-claim failures when other claims still succeed.
Manage saved key customization
The SDK uses the developer token and the same per-key storage/contracts as the FactLens dashboard:
factlens.projects.select("PROJECT_ID");
const state = await factlens.keys.customization.get({
keyId: "KEY_ID",
});
await factlens.keys.customization.updatePreferences({
keyId: "KEY_ID",
trustedDomains: ["reuters.com", "apnews.com"],
blockedDomains: ["example.com"],
});
await factlens.keys.customization.savePrompt({
keyId: "KEY_ID",
mode: "text",
stage: "claim_extraction",
instruction: "Extract only explicit, complete claims.",
inputBudgetTokens: 8000,
promptMode: "guided",
enabled: true,
});
await factlens.keys.customization.saveVerdicts({
keyId: "KEY_ID",
config: verdictConfigV3,
});Reset methods delete only the selected key's saved customization:
await factlens.keys.customization.resetPrompt({
keyId: "KEY_ID",
mode: "text",
stage: "claim_extraction",
});
await factlens.keys.customization.resetVerdicts({ keyId: "KEY_ID" });Request control and timing
await factlens.verify(
{ mode: "text", claim: "..." },
{
timeoutSeconds: 90,
maxRetries: 2,
onProgress(progress) {
console.log(progress.state, progress.elapsedMs, progress.elapsedSeconds);
},
},
);timeout remains milliseconds. timeoutSeconds is the seconds alternative. Supplying both is a configuration error. Progress timing uses a monotonic clock, so wall-clock adjustments cannot make elapsed time run backward.
Verify automatically receives an X-Request-ID when one is not supplied. Automatic retries and REQUEST_IN_PROGRESS polling reuse it so an idempotent request is not executed twice.
SDK management
const account = await factlens.account.get();
const projects = await factlens.projects.list();
const project = await factlens.projects.create({ name: "Production" });
factlens.projects.select(project.id);
const createdKey = await factlens.keys.create({ label: "Backend" });
console.log(createdKey.api_key); // shown once
const accountUsage = await factlens.usage.getAccount();
const logs = await factlens.logs.list({ limit: 50 });
const request = await factlens.logs.get("REQUEST_ID");projects.select() changes only the default project for management calls. Runtime project identity remains bound to the project API key.
Errors
import FactLens, { FactLensError } from "factlens";
try {
await factlens.verify({ mode: "text", claim: "..." });
} catch (error) {
if (error instanceof FactLensError) {
console.error(error.code);
console.error(error.status);
console.error(error.requestId);
console.error(error.retryable);
console.error(error.stage);
console.error(error.details);
console.error(error.helpUrl);
}
}409 REQUEST_IN_PROGRESS remains recoverable within the configured timeout. Ordinary validation/authentication/quota/billing/ownership/request-ID-conflict errors are not retried. Retryable network errors, 408, 429, and retryable 5xx responses use the bounded retry budget.
See Errors and retries.
Browser safety
Secret API keys and developer tokens belong on the server. The SDK refuses secret credentials in browser-like environments by default. dangerouslyAllowBrowser: true is an explicit escape hatch and should not be used with production secrets.
Usage and limits
Eligible free accounts receive 30 shared requests per UTC day. Paid API credits use the current rate: $1 funds 30 API checks.
| | Free | Paid | |---|---:|---:| | Projects | 3 | 100 | | Active keys per project | 1 | 10 | | Daily free requests | 30 shared | 0 | | Throughput | 20/min shared | 60/min shared | | Purchased balance | — | Shared across all projects |
Keys, logs, requests, and metrics remain project-attributed. Existing unused paid balances are migrated by the API backend; the SDK reads the resulting request-credit balance and does not perform local money conversion.
See Usage and limits.
Documentation
- Getting started
- Authentication
- Runtime API
- Projects and keys
- Usage and limits
- Errors and retries
- TypeScript
- Publishing
- Full HTTP documentation:
https://api.factlens.pro/docs
Security
See SECURITY.md. Never put live API keys, developer tokens, or sensitive request payloads in public issues.
License
MIT
6.5.0 → 6.7.0
No change is required for ordinary client.verify() callers. v6.7.0 adds verifyDetailed(), runtime timing metadata, conservative one-retry behavior for read-only GETs, AbortSignal support, richer safe errors, CLI --trace, and non-billable factlens doctor. Billable Verify POSTs and mutations are not automatically retried.
