Mighty
Why MightyCitadel
Use cases
LendingIncome files before you fundInsuranceAppraisals to claim photosClaimsPhotos and estimates at first noticeAll use cases
SecurityDocsLog in
See it on your files

Docs

Direct SaaS purchase is no longer offered

New commercial terms are enterprise or custom, scoped on a call.

See it on your files
Browse docs
Start Here
Citadel Docs5-Minute QuickstartMighty PlatformUse CasesFAQ
Core Concepts
How Citadel WorksModalities And AttacksModes And ToleranceChoose Scan SettingsGlossarySessions And Scan GroupsDriftBilling, SCU, And Limits
Integration Guides
Integration GuidesMultimodal SupportScan Text And OCR OutputScan File UploadsDamage Photo AI Fraud ReviewScan Model OutputAsync Deep ScansError Handling
Frameworks
Framework Integration MapVercel AI SDK Chat GuardrailNext.js Upload GuardrailBackend API HelpersDocument Processing PipelineLangChain + LangGraph Guardrail
Workflows
Workflow Playbooks
API Reference
POST /v1/scan
Use With AI
Use With AI
Start Here
Citadel Docs5-Minute QuickstartMighty PlatformUse CasesFAQ
Core Concepts
How Citadel WorksModalities And AttacksModes And ToleranceChoose Scan SettingsGlossarySessions And Scan GroupsDriftBilling, SCU, And Limits
Integration Guides
Integration GuidesMultimodal SupportScan Text And OCR OutputScan File UploadsDamage Photo AI Fraud ReviewScan Model OutputAsync Deep ScansError Handling
Frameworks
Framework Integration MapVercel AI SDK Chat GuardrailNext.js Upload GuardrailBackend API HelpersDocument Processing PipelineLangChain + LangGraph Guardrail
Workflows
Workflow Playbooks
API Reference
POST /v1/scan
Use With AI
Use With AI
Loading docs…
Mighty

Citadel is Mighty's product. It finds generated or AI-edited fakes in customer files.

See it on your files

Platform

  • For Lending
  • For Insurance
  • For Claims
  • Product
  • Use Cases
  • Contact
  • Docs

Company

  • Why Mighty
  • Blog

Trust

  • Security
  • Status
  • Privacy
  • Terms
© 2026 Nine Suns Inc. All rights reserved.Citadel, from Mighty

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.

You can request async processing explicitly. Citadel may also automatically offload an eligible PDF when completing it inside the synchronous budget would risk a timeout. Every PDF client must therefore handle 202 Accepted, even when it did not set async=true.

Explicit Async Requirements

  • async=true
  • mode=comprehensive
  • content_type=image or content_type=pdf
  • Optional webhook_url

Automatic PDF offload does not require these request fields. It uses the same 202 and polling contract when Citadel needs to protect a bounded synchronous request.

Architecture

  1. Submit the image or PDF with async=true.
  2. On 202 Accepted, store the returned scan_id and Location header.
  3. Show a pending review state to the user or workflow.
  4. Wait at least the Retry-After interval, then receive the webhook or poll Location.
  5. 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 scan is still running — do not treat its action or threats as final. Each item in threats is an object with category, confidence, an optional evidence excerpt, and a human-readable reason.

Webhook Handler Shape

Webhook delivery is at least once, not exactly once. A receiver can commit a request and lose its HTTP response, so Citadel may send the same event again. Every retry carries the same X-Citadel-Event-Id and Idempotency-Key; persist that value with a unique constraint before applying downstream effects. The X-Citadel-Scan-Id header remains the scan correlation ID.

export async function POST(request: Request) {
  const scan = await request.json();

  await saveCitadelScanResult({
    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 === "REVIEW") return "manual_review";
  if (scan.action === "WARN") return "manual_review";
  return "stop";
}

Common Mistakes

  • Setting async=true with mode=secure. Async requires mode=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.
  • Poll the returned Location and honor Retry-After before every retry.
  • Make webhook handling idempotent.
  • Deduplicate webhook retries by X-Citadel-Event-Id or Idempotency-Key; do not assume one delivery.
  • 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.
  • Treat 429 as capacity backpressure and 503 as an unavailable job store; neither is an accepted scan.
Next step

Ready to scan real traffic?

Book a working session on your files. Starting October 1, 2026, new commercial terms are enterprise or custom.

See it on your filesHandle errors

AI-Agent Prompt

AI-ready prompt
Add async deep scans

Paste this into Cursor, Codex, Claude Code, or Windsurf.

Add Citadel 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.

On this page

GoalExplicit Async RequirementsArchitectureSubmit An Async ScanPoll For CompletionWebhook Handler ShapeRouting LogicCommon MistakesProduction ChecklistAI-Agent Prompt