# Backend API Helpers

Use these server-side helper patterns when your backend is Node, Python, Express, FastAPI, Flask, Django, or a custom API.

Source URL: https://trymighty.ai/docs/frameworks/node-python

Use this page when you are not using a special framework guide.

This page proves the minimum backend contract:

```text
server receives untrusted material -> server calls Mighty -> server routes ALLOW, WARN, BLOCK
```

Node and Python are here because most teams wire Mighty 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 Upload Guardrail](/docs/frameworks/next-file-upload). If you are using Vercel AI SDK chat, use [Vercel AI SDK Chat Guardrail](/docs/frameworks/vercel-ai-sdk).

## Backend Helper Shape

Every backend helper should do five things:

1. Read `MIGHTY_API_KEY` from server environment.
2. Call `POST https://gateway.trymighty.ai/v1/scan`.
3. Send `scan_phase`, `content_type`, `mode`, and `focus`.
4. Return the parsed scan result.
5. Preserve IDs so the app can route and audit.

## Node Text Helper

Use this in a server route, worker, queue consumer, or agent backend.

```ts
type MightyScanOptions = {
  scanPhase?: "input" | "output";
  scanGroupId?: string;
  sessionId?: string;
  dataSensitivity?: "standard" | "tolerant" | "strict";
};

export async function scanTextWithMighty(
  content: string,
  options: MightyScanOptions = {},
) {
  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: "both",
      data_sensitivity: options.dataSensitivity ?? "standard",
    }),
  });

  if (!response.ok) {
    throw new Error(`Mighty scan failed with ${response.status}`);
  }

  return response.json();
}
```

## Python Text Helper

Use this in FastAPI, Flask, Django, Celery, or a document processing job.

```py
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": "both",
            "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.

```py
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": "both",
                "data_sensitivity": "tolerant",
            },
            timeout=60,
        )

    response.raise_for_status()
    return response.json()
```

## Routing Helper

Do not collapse `WARN` and `BLOCK` into one generic failure. They mean different product routes.

```ts
type MightyAction = "ALLOW" | "WARN" | "BLOCK";

export function routeMightyAction(scan: {
  action: MightyAction;
  scan_id: string;
  redacted_output?: string;
}) {
  if (scan.action === "ALLOW") {
    return { type: "continue" as const };
  }

  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

The model call is not the trust boundary. The trust boundaries are before input reaches the model and before output reaches the user or workflow.

```ts
const inputScan = await scanTextWithMighty(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 scanTextWithMighty(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`, `WARN`, and `BLOCK` route differently.
- Output scans reuse the related `scan_group_id`.
- Logs include `scan_id`, `request_id`, `scan_group_id`, and `session_id`.

## AI-Agent Prompt

### Add Mighty backend helpers

```text
Add Mighty 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=both.
- 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, WARN, and BLOCK separately.
- Handle 400, 402, 409, 413, 429, and network errors.

Acceptance criteria:
- Tests cover ALLOW, 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.
```
