Backend API Helpers
Use these server-side helper patterns when your backend is Node, Python, Express, FastAPI, Flask, Django, or a custom API.
Use this page when you are not using a special framework guide.
This page proves the minimum backend contract:
server receives untrusted material -> server calls Citadel -> server routes ALLOW, REVIEW, WARN, BLOCKNode and Python are here because most teams wire Citadel from a backend service. The language does not matter. The important part is that the scan call happens server-side before your app trusts the material.
When To Use This
| Backend | Use this helper for |
|---|---|
| Node, Express, Fastify, Hono | API routes, workers, upload services, OCR services, agent backends. |
| Python, FastAPI, Flask, Django | Claim intake, document processing, OCR or IDP jobs, review queues. |
| OpenAI SDK service | Prompt scanning before the model and output scanning after generation. |
| LangChain or LlamaIndex | Input, retrieved content, tool output, and final answer scans. |
If you are using Next.js file uploads, use Next.js File Upload Integration. If you are using Vercel AI SDK chat, use Vercel AI SDK Chat Integration.
Backend Helper Shape
Every backend helper should do five things:
- Read
MIGHTY_API_KEYfrom server environment. - Call
POST https://gateway.trymighty.ai/v1/scan. - Send
scan_phase,content_type,mode, andfocus. - Return the parsed scan result.
- Preserve IDs so the app can route and audit.
Node Text Helper
Use this in a server route, worker, queue consumer, or agent backend.
type CitadelScanOptions = {
scanPhase?: "input" | "output";
scanGroupId?: string;
sessionId?: string;
dataSensitivity?: "standard" | "tolerant" | "strict";
};
export async function scanTextWithCitadel(
content: string,
options: CitadelScanOptions = {},
) {
const response = await fetch("https://gateway.trymighty.ai/v1/scan", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.MIGHTY_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
content,
content_type: "text",
scan_phase: options.scanPhase ?? "input",
scan_group_id: options.scanGroupId,
session_id: options.sessionId,
mode: "secure",
focus: "steg",
data_sensitivity: options.dataSensitivity ?? "standard",
}),
});
if (!response.ok) {
throw new Error(`Citadel scan failed with ${response.status}`);
}
return response.json();
}Python Text Helper
Use this in FastAPI, Flask, Django, Celery, or a document processing job.
import os
import requests
def scan_text_with_mighty(
content: str,
scan_phase: str = "input",
scan_group_id: str | None = None,
session_id: str | None = None,
data_sensitivity: str = "standard",
) -> dict:
response = requests.post(
"https://gateway.trymighty.ai/v1/scan",
headers={
"Authorization": f"Bearer {os.environ['MIGHTY_API_KEY']}",
"Content-Type": "application/json",
},
json={
"content": content,
"content_type": "text",
"scan_phase": scan_phase,
"scan_group_id": scan_group_id,
"session_id": session_id,
"mode": "secure",
"focus": "steg",
"data_sensitivity": data_sensitivity,
},
timeout=20,
)
response.raise_for_status()
return response.json()Python File Helper
Use this when a Python service receives files before OCR, extraction, or review.
import os
import requests
def scan_file_with_mighty(path: str, content_type: str = "auto") -> dict:
with open(path, "rb") as file:
response = requests.post(
"https://gateway.trymighty.ai/v1/scan",
headers={"Authorization": f"Bearer {os.environ['MIGHTY_API_KEY']}"},
files={"file": file},
data={
"content_type": content_type,
"scan_phase": "input",
"mode": "secure",
"focus": "steg",
"data_sensitivity": "tolerant",
},
timeout=60,
)
response.raise_for_status()
return response.json()Routing Helper
Keep all four actions separate. REVIEW pauses the item; WARN means suspicious evidence.
type CitadelAction = "ALLOW" | "REVIEW" | "WARN" | "BLOCK";
export function routeCitadelAction(scan: {
action: CitadelAction;
scan_id: string;
redacted_output?: string;
}) {
if (scan.action === "ALLOW") {
return { type: "continue" as const };
}
if (scan.action === "REVIEW") {
return { type: "pause" as const, scanId: scan.scan_id };
}
if (scan.action === "WARN") {
return { type: "review" as const, scanId: scan.scan_id };
}
if (scan.redacted_output) {
return { type: "show_redacted" as const, text: scan.redacted_output };
}
return { type: "block" as const, scanId: scan.scan_id };
}OpenAI SDK Pattern
Scan the prompt before the model runs. Scan the answer before the user or workflow sees it.
const inputScan = await scanTextWithCitadel(userPrompt, {
scanPhase: "input",
sessionId: chatId,
});
if (inputScan.action !== "ALLOW") {
return { status: "review", scan_id: inputScan.scan_id };
}
const completion = await openai.responses.create({
model: process.env.OPENAI_MODEL,
input: userPrompt,
});
const outputScan = await scanTextWithCitadel(completion.output_text, {
scanPhase: "output",
scanGroupId: inputScan.scan_group_id,
sessionId: chatId,
dataSensitivity: "strict",
});LangChain And LlamaIndex Pattern
Use the same helper around the places where untrusted material enters or leaves the chain.
| Chain surface | Scan phase | Why |
|---|---|---|
| User query | input | Stop risky prompt input before retrieval or agent execution. |
| Retrieved document text | output | Keep poisoned documents out of model context. |
| Tool result | output | Keep unsafe tool output out of the next step. |
| Final answer | output | Scan before user display or workflow automation. |
Acceptance Criteria
- API key is never used in browser code.
- The helper handles non-2xx errors.
- ALLOW, REVIEW, WARN, and BLOCK route differently.
- Output scans reuse the related
scan_group_id. - Logs include
scan_id,request_id,scan_group_id, andsession_id.
Ready to scan real traffic?
Book a working session on your files. Starting October 1, 2026, new commercial terms are enterprise or custom.
AI-Agent Prompt
Paste this into Cursor, Codex, Claude Code, or Windsurf.
Add Citadel backend helpers to this codebase.
Use this guide when the app is a Node, Python, Express, FastAPI, Flask, Django, worker, queue, or custom API service.
Requirements:
- Keep MIGHTY_API_KEY on the server.
- Add a text scan helper for POST https://gateway.trymighty.ai/v1/scan.
- Add a file scan helper if the app accepts files.
- Use content_type=text for text.
- Use multipart form data for files.
- Default to scan_phase=input, mode=secure, focus=steg. Use focus=all only for known image/PDF evidence that needs authenticity or edit review.
- Add scan_phase=output support for model output, OCR output, extraction output, and tool output.
- Reuse scan_group_id for derived output from the same item.
- Route ALLOW, REVIEW, WARN, and BLOCK separately.
- Handle 400, 402, 409, 413, 429, and network errors.
Acceptance criteria:
- Tests cover ALLOW, REVIEW, WARN, BLOCK, error responses, and scan failure.
- API key never appears in client code.
- Logs include scan_id, request_id, scan_group_id, and session_id.