Anonymous, no key required. Current limits: 10,000 characters per scan, 20 scans/hour per IP (6 with the model signal). API keys with higher limits arrive with accounts.
The body can be JSON, a form field, or just raw text. The quickest taste, straight from a file, with a human-readable answer:
# pipe any file in, get the report back as plain text: curl -s --data-binary @draft.txt "https://scanforai.com/api/scan?format=text"
JSON for programs (a JSON body overrides the query-param knobs):
curl -s https://scanforai.com/api/scan \
-H 'Content-Type: application/json' \
-d '{"text": "...", "use_model": true, "include_fixes": true, "background": false}'
Set "background": true for batch/scripted scans: they queue
behind interactive web scans on the model worker (heuristics are instant
either way), in exchange for a much longer queue-wait allowance.
File upload (multipart; .txt, .md, .html, .docx — text is extracted server-side, 1 MB max):
curl -s -F "[email protected]" https://scanforai.com/api/scan
Response (fields are stable; new ones may be added):
{
"score": 68.4, // 0..100 tell density — NOT a probability
"band": "elevated", // low | moderate | elevated | high
"label": "strong AI tells",
"model_used": true, // was the local perplexity signal in the mix
"word_count": 1240,
"coverage": {"active_signals": 9, "total_signals": 11, "words": 1240},
"signals": [ {"name": "burstiness", "score": 0.82, "weight": 3.0,
"detail": "sentence-length CV=0.24 (human ~0.5-0.9, ...)",
"value": 0.24}, ... ],
"fixes": ["burstiness: ...", ...],
"scan_id": null, // anonymous scans are never stored
"disclaimer": "AI-tell density, not a verdict. ..."
}
Errors: 413 over the character cap, 429 rate-limited
(message includes retry seconds), 422 empty text. If the model worker
is briefly unavailable the scan still succeeds heuristics-only, with
"model_used": false and a "degraded" note.
Model-queue state, for showing a wait estimate:
{"queued_interactive": 3, "queued_background": 12, "workers": 2,
"capacity": 4, "model_loaded": true, "avg_scan_seconds": 2.4,
"eta_interactive_seconds": 4.3, "eta_background_seconds": 11.9}
— workers is live worker processes, capacity their
combined inference threads.
The limits for your tier — what the landing-page counter uses.
{"ok": true, "version": "0.1.0", "model_worker": true}
POST /api/scans/{id}/share returns an expiring public URL
(https://scanforai.com/s/<token>, 7 days) showing the
RESULT only — the original text never leaves your account.
DELETE /api/scans/{id}/share revokes all links for that scan;
deleting the scan or your account revokes them too.
A free account (dashboard) raises the per-scan limit to
50,000 characters, saves scan history with revision comparison, and issues
API keys. Keys are sent the same way as the examples above:
Authorization: Bearer at_sk_…. Key scopes: full, or
read (may scan and read history, cannot modify anything).
Authenticated scans are saved by default — pass "save": false to
opt out; anonymous scans are never stored.
Please don't wrap this in a product that presents scores as verdicts about
people. The response's disclaimer field exists to be shown.