Documentation
Secure every LLM interaction with one guardrail call. This guide walks through the production setup end to end.
1. Overview
Axiom sits between the user and your language model. Scan first, then decide whether to forward the request.
Request flow
- Your backend calls
POST /api/v1/scanwith the user prompt. - Axiom returns a verdict:
allowed: true | falseplus metadata. - If
allowedis false, block, sanitize, or log the attempt. - If
allowedis true, send the prompt to your LLM (Azure OpenAI, OpenAI, etc.).
Why it's simple
- No SDKs or local agents, only HTTPS calls.
- Drop-in compatible with any existing LLM stack.
- Only two environment variables are needed.
2. Get an Axiom API key
Generate a key in the dashboard and keep it server-side only.
- Open the Axiom dashboard and select Generate API key.
- Copy the token (format:
sk_ax_XXXXXXXXXXXXXXXXXXXXXXXX). - Store it securely in your environment variables.
- Never expose your API key to the client or browser.
# .env AXIOM_API_KEY=sk_ax_XXXXXXXXXXXXXXXXXXXXXXXX AXIOM_API_BASE=https://axiom-api-heg8gxfrg7a2bef9.eastus-01.azurewebsites.net # These are the ONLY Axiom variables you ever need. # Axiom handles all internal connections and scanning automatically.
3. Call Axiom
Send text, images, PDFs, or any combination to /api/v1/scan. Axiom supports multiple input formats.
Text Input (JSON)
POST {AXIOM_API_BASE}/api/v1/scan
Authorization: Bearer sk_ax_...
Content-Type: application/json
{ "prompt": "user input goes here" }Use text as an alias for prompt (backward compatible).
Images via Base64 (JSON)
POST {AXIOM_API_BASE}/api/v1/scan
Authorization: Bearer sk_ax_...
Content-Type: application/json
{
"prompt": "Review this image",
"images": [
"data:image/jpeg;base64,/9j/4AAQSkZJRg...",
"data:image/png;base64,iVBORw0KGgo..."
]
}Supports JPEG, PNG, GIF, WebP. Max 20MB per image.
File Uploads (Multipart)
POST {AXIOM_API_BASE}/api/v1/scan
Authorization: Bearer sk_ax_...
Content-Type: multipart/form-data
prompt: "optional text"
file: [image or PDF file]
file: [additional files...]Images: 20MB max. PDFs: 10MB max. Text extracted from PDFs.
Mixed Content
{
"prompt": "Analyze these",
"images": ["data:image/jpeg;base64,..."]
}
// Or combine text + images + PDFs via multipartAny blocked content blocks the entire request.
4. Choose your code based on input type
Pick the code example that matches what you're scanning. Use before sending to your LLM.
For TEXT prompts only
Use this when scanning text input from users.
const AXIOM_API_BASE = process.env.AXIOM_API_BASE!;
const AXIOM_API_KEY = process.env.AXIOM_API_KEY!;
async function scanText(prompt) {
const res = await fetch(`${AXIOM_API_BASE}/api/v1/scan`, {
method: "POST",
headers: {
Authorization: `Bearer ${AXIOM_API_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({ prompt })
});
if (!res.ok) throw new Error("Axiom scan failed");
const verdict = await res.json();
if (!verdict.allowed) throw new Error(`Blocked: ${verdict.reason}`);
return verdict;
}
// Usage
await scanText("user input here");For IMAGES (base64)
Use this when scanning images. Convert files to base64 first.
import fs from "fs";
async function scanImages(images, prompt = "") {
const res = await fetch(`${AXIOM_API_BASE}/api/v1/scan`, {
method: "POST",
headers: {
Authorization: `Bearer ${AXIOM_API_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({ prompt, images })
});
if (!res.ok) throw new Error("Axiom scan failed");
const verdict = await res.json();
if (!verdict.allowed) throw new Error(`Blocked: ${verdict.reason}`);
return verdict;
}
// Convert file to base64
const fileBuffer = await fs.readFile("image.jpg");
const base64 = fileBuffer.toString("base64");
const dataUrl = `data:image/jpeg;base64,${base64}`;
// Usage
await scanImages([dataUrl], "Review this image");For FILE UPLOADS (images or PDFs)
Use this when uploading files directly. Supports images (20MB) and PDFs (10MB).
import FormData from "form-data";
import fs from "fs";
async function scanFiles(files, prompt = "") {
const formData = new FormData();
if (prompt) formData.append("prompt", prompt);
files.forEach(file => formData.append("file", file));
const res = await fetch(`${AXIOM_API_BASE}/api/v1/scan`, {
method: "POST",
headers: {
Authorization: `Bearer ${AXIOM_API_KEY}`,
...formData.getHeaders()
},
body: formData
});
if (!res.ok) throw new Error("Axiom scan failed");
const verdict = await res.json();
if (!verdict.allowed) throw new Error(`Blocked: ${verdict.reason}`);
return verdict;
}
// Usage
const files = [
fs.createReadStream("image.jpg"),
fs.createReadStream("document.pdf")
];
await scanFiles(files, "Optional text prompt");For MIXED content (text + images)
Use this when combining text prompts with images in one request.
// Same as image scanning, just include both prompt and images
await scanImages(
["data:image/jpeg;base64,..."],
"Analyze this image and explain what you see"
);
// Or use multipart for text + files
const formData = new FormData();
formData.append("prompt", "Analyze these files");
formData.append("file", fs.createReadStream("image.jpg"));
formData.append("file", fs.createReadStream("doc.pdf"));Response handling (same for all types):
Check allowed in the response. If false, block the request. If true, proceed to your LLM.
5. Why this design
Axiom was built to be as secure and effortless as possible.
- Isolation: You never touch Axiom’s internal configuration. Your key and base URL are the only requirements.
- Simplicity: The integration works with any backend stack through one HTTP call.
- Security: Because the API key never leaves the server, Axiom cannot be misused or leaked by frontend code.
- Self-contained: All analytics, scanning, and AI evaluation logic happen inside Axiom’s backend environment, just like Azure or Supabase variables.
6. Mental model
- 1. Get your keyStore
AXIOM_API_KEYandAXIOM_API_BASEin your environment. - 2. Scan every promptCall
POST /api/v1/scanbefore any LLM request. - 3. Respect the verdictIf
allowedis false, block and respond safely. Otherwise, continue normally.