Quick Start Guide

Get SafePrompt integrated into your LLM application in 5 minutes.

1. Get Your API Key

Sign up and 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.

npm install safeprompt
import SafePrompt from 'safeprompt';

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

const result = await sp.check(userInput, { userIP: clientIP });
if (!result.safe) {
  throw new Error(`Blocked: ${result.threats?.[0] || 'Security threat detected'}`);
}

Or use the HTTP API directly — same endpoint, no package required.

3. Validate User Prompts

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 })
});

const result = await response.json();
if (!result.safe) {
  throw new Error(`Blocked: ${result.threats?.[0] || 'Security threat detected'}`);
}

4. Understanding the Response

The API returns a JSON object with these key fields:

  • safe (boolean): true if the prompt is safe, false if it's a threat
  • confidence (float, 0-1): How certain we are about the verdict (0.9+ is very high confidence)
  • threats (array): List of detected threat types (e.g., "prompt_injection", "jailbreak")
  • processingTime (number): Response time in milliseconds
{
  "safe": false,
  "confidence": 0.95,
  "threats": ["prompt_injection"],
  "processingTime": 245,
  "sessionId": "sess_abc123"
}

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.

How to get the end user's IP:

  • Express.js: req.headers['x-forwarded-for'] || req.connection.remoteAddress
  • Flask/Django: request.headers.get('X-Forwarded-For', request.remote_addr)
  • Next.js: req.headers['x-forwarded-for'] || req.socket.remoteAddress
  • PHP: $_SERVER['HTTP_X_FORWARDED_FOR'] ?? $_SERVER['REMOTE_ADDR']

For testing and development:

When the end user's IP is unavailable (testing, batch processing, or privacy requirements), use a placeholder IP from the RFC 5737 TEST-NET-3 range:

# Use TEST-NET-3 addresses (203.0.113.0/24) for testing
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: Tracks actual attackers vs. legitimate API callers
  • IP reputation: Identifies patterns of malicious behavior
  • Network defense: Protects all SafePrompt customers from coordinated attacks

6. Best Practices

Fail-Open Strategy

If the SafePrompt API is unreachable or times out, allow the request to proceed rather than blocking legitimate users:

try {
  const result = await validatePrompt(userInput);
  if (!result.safe) {
    return { error: 'Invalid request' };
  }
} catch (error) {
  // Fail open: Allow request if validation service is down
  console.error('SafePrompt validation failed:', error);
}

Caching (Optional)

For high-traffic applications, consider caching validation results:

const cache = new Map();
const CACHE_TTL = 60000; // 1 minute
const MAX_CACHE_SIZE = 1000;

// Simple hash function for caching (use crypto.createHash in production)
function hashPrompt(prompt) {
  return prompt.toLowerCase().trim();
}

async function validateWithCache(prompt) {
  const hash = hashPrompt(prompt);
  const cached = cache.get(hash);

  if (cached && Date.now() - cached.timestamp < CACHE_TTL) {
    return cached.result;
  }

  const result = await validatePrompt(prompt);

  // Prevent cache from growing unbounded
  if (cache.size >= MAX_CACHE_SIZE) {
    const firstKey = cache.keys().next().value;
    cache.delete(firstKey);
  }

  cache.set(hash, { result, timestamp: Date.now() });
  return result;
}

Multi-Turn Protection

For conversational AI, track session tokens to detect multi-turn attacks:

let sessionToken = null;

async function validateConversationTurn(userInput, clientIP) {
  const requestBody = {
    prompt: userInput
  };

  // Include session_token for multi-turn tracking (if we have one)
  if (sessionToken) {
    requestBody.session_token = sessionToken;
  }

  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)
  });

  const data = await result.json();
  sessionToken = data.session_token;  // Store for next turn
  return data;
}

Next Steps