Built against OWASP LLM01Benchmark re-run every 6 hoursOpen-source SDK · MIT

Quick Start Guide

Check one input, enforce the verdict, then test failures before connecting your model.

1. Get Your API Key

Sign up, confirm your email, then get your API key from dashboard.safeprompt.dev

2. Install the SDK (Optional)

Use the official npm package for a typed client, or call the HTTP API directly. The published JavaScript SDK sends no sensitivity, so your account default applies.

npm install safeprompt
import SafePrompt from 'safeprompt';

const sp = new SafePrompt({ apiKey: 'YOUR_API_KEY' });

const result = await sp.check(userInput, { userIP: clientIP });
if (typeof result.safe !== 'boolean' || !result.safe) {
  throw new Error('Unsafe or invalid verdict');
}
// Only now add this checked input to model context.

The SDK forwards the userIP you supply. Keep the key on your server. The raw HTTP helper gives you a configurable request deadline without a package.

3. Validate User Prompts

async function validatePrompt(userInput, clientIpAddress, timeoutMs) {
  const response = await fetch('https://api.safeprompt.dev/api/v1/validate', {
  method: 'POST',
  headers: {
    'X-API-Key': 'YOUR_API_KEY',
    'X-User-IP': clientIpAddress, // End user's IP address
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({ prompt: userInput }),
  signal: AbortSignal.timeout(timeoutMs)
});

if (!response.ok) throw new Error('Validation HTTP error');
const result = await response.json();
if (typeof result.safe !== 'boolean' || !result.safe) {
  throw new Error('Unsafe or invalid verdict');
}
return result; // Forward the same checked input only after this resolves.
}

4. Understanding the Response

The following is an illustrative response shape, not an observed attack result. Require successful HTTP status and a boolean safe before using any verdict.

  • safe (boolean): true is a passing verdict for submitted text; false tells your app to stop it
  • confidence (float, 0-1): Detector confidence, not a calibrated attack probability or permission grant
  • threats (array): List of detected threat types (e.g., "jailbreak_instruction_override", "jailbreak")
  • processingTime (number): Response time in milliseconds
{
  "safe": false,
  "confidence": 0.95,
  "threats": ["jailbreak_instruction_override"],
  "reasoning": "Illustrative instruction-override verdict",
  "sessionToken": null
}

5. Important: End User IP Address

Always pass the end user's IP address via the X-User-IP header, not your server's IP.

Derive the address through trusted server configuration:

  • Express.js: use req.ip after configuring trust proxy for your actual proxy topology
  • Flask/Django: use the framework's client address after configuring trusted proxies
  • Next.js: use the client address supplied by your trusted deployment platform
  • PHP: use the verified client address supplied by your trusted server or proxy

For testing and development:

Use documentation addresses only in local mocks. In production, supply the actual end user address; a server address or test placeholder does not meet that requirement. The request below shows the shape and is not a recommendation to send a fabricated address to the live API.

# Documentation placeholder; replace with the actual end user IP before live use
curl -X POST https://api.safeprompt.dev/api/v1/validate \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "X-User-IP: 203.0.113.45" \
  -H "Content-Type: application/json" \
  -d '{"prompt": "Hello world"}'

Why X-User-IP is required:

  • Threat intelligence: Supplies correlation signals from submitted requests
  • IP reputation: Identifies patterns of malicious behavior
  • Network defense: Supplies correlation signals; a verdict does not guarantee protection elsewhere

6. Best Practices

Stop Unavailable Checks

Use the validatePrompt HTTP helper in the JavaScript tab above. If a check fails, keep the input out of model context. Retry or return an error. Continuing without a verdict explicitly bypasses screening. The snippets use a timeout budget you configure for your application; compare it with the published latency percentiles.

async function checkedInput(userInput, clientIP, timeoutMs) {
  const result = await validatePrompt(userInput, clientIP, timeoutMs);
  if (typeof result.safe !== 'boolean' || !result.safe) {
    throw new Error('Unsafe or invalid verdict');
  }
  return userInput; // Add to context only after this resolves.
}

Keep the Exact Input

Submit the same representation your model receives, including source labels. Avoid reusing a verdict keyed only by lowercased or trimmed text: IP, conversation context, sensitivity and detector changes can alter its meaning.

async function checkRetrievedText(extractedText, clientIP, timeoutMs) {
  // Include source labels here if the model will receive them too.
  const verdict = await validatePrompt(extractedText, clientIP, timeoutMs);
  if (typeof verdict.safe !== 'boolean' || !verdict.safe) {
    throw new Error('Unsafe or invalid verdict');
  }
  return extractedText; // Forward these same bytes, not another extraction.
}

Conversation Context

SafePrompt checks each request on its own and does not track sessions. A session_token in the request has no effect. To have several turns judged together, send them in one check. Keep conversation state and authorization in your application.

// Server-side: send the recent turns you want judged together in one check.
// Keep the joined text under the 50,000-character request limit.
async function validateConversationTurns(turns, clientIP, timeoutMs) {
  const requestBody = {
    // Join the turns in the order your model sees them.
    prompt: turns.map((t) => t.role + ': ' + t.text).join('\n')
  };

  const result = await fetch('https://api.safeprompt.dev/api/v1/validate', {
    method: 'POST',
    headers: {
      'X-API-Key': 'YOUR_API_KEY',
      'X-User-IP': clientIP,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify(requestBody),
    signal: AbortSignal.timeout(timeoutMs)
  });

  if (!result.ok) throw new Error('Validation HTTP error');
  const data = await result.json();
  if (typeof data.safe !== 'boolean' || !data.safe) {
    throw new Error('Unsafe or invalid verdict');
  }
  return data;
}

Next Steps