Async Deep Scans
Use async scans, polling, and webhooks for deep image and PDF review.
Goal
Run deeper scans without blocking a user request.
Async scans are for image and PDF workflows where depth matters more than immediate completion.
Requirements
async=truemode=comprehensivecontent_type=imageorcontent_type=pdf- Optional
webhook_url
Architecture
- Submit the image or PDF with
async=true. - Store the returned
scan_id. - Show a pending review state to the user or workflow.
- Receive the webhook or poll
GET /v1/scan/{scan_id}. - Route the final result.
Submit An Async Scan
curl -X POST https://gateway.trymighty.ai/v1/scan \
-H "Authorization: Bearer $MIGHTY_API_KEY" \
-F "file=@./claim-packet.pdf" \
-F "content_type=pdf" \
-F "scan_phase=input" \
-F "mode=comprehensive" \
-F "focus=all" \
-F "async=true" \
-F "webhook_url=https://example.com/api/mighty/webhook"Poll For Completion
curl https://gateway.trymighty.ai/v1/scan/c178225b-1ee2-4c60-bab3-41f1ad32d532 \
-H "Authorization: Bearer $MIGHTY_API_KEY"preliminary: true on the initial response means the heuristic verdict is in but the deep scan is still running — do not treat preliminary as final. Each item in threats is an object with category, confidence, an optional evidence excerpt, and a human-readable reason.
Webhook Handler Shape
export async function POST(request: Request) {
const scan = await request.json();
await saveMightyScanResult({
scanId: scan.scan_id,
scanGroupId: scan.scan_group_id,
action: scan.action,
riskScore: scan.risk_score,
status: scan.scan_status,
threats: scan.threats ?? [],
});
await routeFinalScanResult(scan);
return Response.json({ ok: true });
}Validate webhook authenticity according to your deployment policy. At minimum, use HTTPS, strict routing, request logs, replay protection, and a secret value in your own webhook path or headers when available.
Routing Logic
export function routeAsyncStatus(scan: { scan_status?: string; action?: string }) {
if (scan.scan_status === "pending") return "keep_pending";
if (scan.scan_status === "failed") return "manual_review";
if (scan.action === "ALLOW") return "continue";
if (scan.action === "WARN") return "manual_review";
return "stop";
}Common Mistakes
- Setting
async=truewithmode=secure. Async requiresmode=comprehensive. - Using async for text. Async deep scan is for image and PDF.
- Letting the workflow continue before final routing.
- Treating a preliminary response as the final answer.
Production Checklist
- Store pending state with
scan_id. - Retry polling with backoff.
- Make webhook handling idempotent.
- Re-route if the final result differs from the preliminary route.
- Add monitoring for stuck pending scans.
- Use manual review as the safe fallback for failed deep scans.
Ready to scan real traffic?
Create an API key, keep it on your server, then wire Mighty into the workflow that handles untrusted material.
AI-Agent Prompt
Paste this into Cursor, Codex, Claude Code, or Windsurf.
Add Mighty async deep scans for high-risk PDF or image workflows.
Requirements:
- Submit file scans with async=true and mode=comprehensive.
- Only use async for content_type=image or content_type=pdf.
- Store scan_id, scan_group_id, preliminary, scan_status, and action.
- Add a pending state in the workflow.
- Implement GET /v1/scan/{scan_id} polling with backoff.
- Implement webhook receiving if the app has a public HTTPS endpoint.
- Make webhook updates idempotent.
- Route complete ALLOW, WARN, BLOCK.
- Route failed or stuck pending scans to manual review.
Acceptance criteria:
- Tests cover pending, complete, failed, webhook duplicate, and polling retry.
- The workflow does not treat preliminary as final.
- Logs include scan_id and request_id.