Test prompt injection models
without the setup.

Try models in the browser playground or integrate via API.
100 free scans/month. Sign up in 30 seconds.

Why test?

The EU AI Act requires prompt injection defenses by August 2, 2026. Companies are scrambling — Lakera was acquired for $300M, Pangea for $260M, both in September 2025. Open source models exist, but setting them up takes an afternoon of downloading weights, configuring tokenizers, and writing glue code.

We host the models so you can evaluate in seconds, not hours.

Read more about the EU AI Act

One call. That's it.

Drop this before your LLM call. Works with any provider.

python
import requests

def scan_input(user_input: str) -> bool:
    response = requests.post(
        "https://api.pinpout.dev/v1/scan",
        headers={"X-API-Key": "pp_live_your_key_here"},
        json={"text": user_input},
    )
    result = response.json()
    return result["is_safe"]

# Use before calling your LLM
if scan_input(user_message):
    # Safe — pass to OpenAI, Anthropic, etc.
    pass
else:
    raise ValueError("Prompt injection detected")

Or try it in the playground in the Dashboard.

How it works

Three steps to protect your app. Then one endpoint to call.

01

Sign up, get API key

Create an account. Get your key instantly — no approval process, no sales call.

02

Try it

Use the playground to test prompts in the browser, or call /v1/scan from your code. One endpoint, that's it.

03

Sleep better

Every prompt injection attempt gets caught before it reaches your model.

Under the hood

Normalize< 1ms

Strips encoding tricks and obfuscation so nothing sneaks past

Classify~15ms

DeBERTa-v3 classifier — fast, accurate, no LLM API calls.

More models coming soon.

API Reference

Base URL: https://api.pinpout.dev

POST/v1/scan

Scan text for prompt injection attacks. Call this before passing user input to your LLM.

Auth: X-API-Key header
Request body
{
  "text": "string",           // required — the text to scan
  "options": {
    "return_normalized": bool  // optional — include normalized text in response
  }
}
Response
{
  "is_safe": true,             // false if injection detected
  "confidence": 0.97,          // model confidence (0–1)
  "scan_id": "a1b2c3d4-..."   // UUID for this scan
}
Errors
401 INVALID_API_KEYMissing or bad X-API-Key
403 QUOTA_EXCEEDED10K monthly limit reached
429 RATE_LIMITED100 req/min limit, includes Retry-After header
GET/v1/keys

Get your current API key info. Returns null if no key exists yet.

Auth: Authorization: Bearer <session-token>
Response
{
  "key": {
    "prefix": "pp_live_XXXX...",
    "created_at": "2026-02-01T00:00:00Z",
    "last_used_at": "2026-02-23T10:00:00Z"
  } | null
}
POST/v1/keys

Create your API key. One key per account. Returns the full secret — save it, it won't be shown again.

Auth: Authorization: Bearer <session-token>
Response
{
  "key": { "prefix": "pp_live_XXXX...", "created_at": "..." },
  "secret": "pp_live_full_key_here"  // shown once
}
Errors
409 KEY_EXISTSA key already exists — rotate or delete it first
POST/v1/keys/rotate

Rotate your API key. Old key is immediately invalidated. Returns the new full secret.

Auth: Authorization: Bearer <session-token>
Response
{
  "key": { "prefix": "pp_live_XXXX...", "created_at": "..." },
  "secret": "pp_live_new_key_here"
}
Errors
404 NOT_FOUNDNo key exists to rotate
DELETE/v1/keys

Delete your API key. The key is immediately revoked.

Auth: Authorization: Bearer <session-token>
Response
{ "deleted": true }
GET/v1/usage

Get your usage for the current month. Resets at UTC midnight on the 1st.

Auth: Authorization: Bearer <session-token>
Response
{
  "scans_total": 847,
  "quota": {
    "limit": 10000,
    "used": 847,
    "remaining": 9153
  }
}

Error format

All errors use the same shape:

{
  "error": {
    "code": "RATE_LIMITED",
    "message": "Rate limit exceeded. Try again in 30 seconds."
  }
}

FAQ