The Deterministic Trust Layer
Cloudflare Turnstile is for browsers. Sentinel is for APIs.
5-Minute Deployment
Protect any Node.js endpoint in three steps:
npm install api-turnstile
import { sentinel } from 'api-turnstile';
app.use(sentinel({
apiKey: 'sz_live_...',
protect: ['/auth/*', '/payments'],
profile: 'strict'
}));
Sign in to the Sentinel Dashboard to provision your sz_live_
project key instantly.
Sentinel is a high-velocity decision engine designed to render sub-50ms trust decisions for API traffic at the network edge. It replaces user-hostile CAPTCHAs with infrastructure forensics and cryptographic Proof-of-Work, blocking automated attacks without ever interrupting a legitimate user.
Core Architecture
Sentinel operates on a Zero-Friction, Zero-Trust philosophy using three distinct layers of defense:
1. Fast-Path Matrix (< 20ms)
Incoming requests are instantly vetted against a globally distributed in-memory matrix of over 100 known-bad hosting providers, known proxy networks, and datacenter IP blocks. This handles the majority of bot traffic instantly.
2. Behavioral Work Tokens (BWT)
When an IP is identified as "Unstable" (suspicious signals found), Sentinel issues a cryptographic challenge. Legitimate clients solve this in milliseconds via the background SDK engine, while primitive scripts and automated tools fail to generate a valid solution.
3. Infrastructure Forensics
For high-sensitivity endpoints, Sentinel performs real-time forensic signatures on the request environment. We detect headless browsers (Puppeteer, Playwright), automated runtimes, and masking attempts (VPN/Tor) with high confidence.
Agentic Security & AI Governance
Traditional "Human-only" filters are too binary. Sentinel's agentic profile allows you to
categorize traffic into three tiers:
- Verified Human: Full access to high-compute resources.
- Verified Agent: Limited access (cached content, text-only responses, zero-DB access).
- Malicious Bot: Hard rejection.
Global Edge Enforcement
For high-traffic applications, Sentinel offers a specialized Edge Adapter that moves enforcement to the CDN layer. This reduces decision latency from >50ms to **under 5ms** by using local Key-Value caches.
import { sentinelEdge } from 'api-turnstile';
export default {
async fetch(request, env, ctx) {
const shield = sentinelEdge({
apiKey: env.SENTINEL_KEY,
cache: env.SENTINEL_KV, // Cloudflare KV Namespace
protect: ['/v1/*'],
cacheTtl: 300 // 5-minute local cache
});
const blockResponse = await shield(request, ctx);
if (blockResponse) return blockResponse;
return await fetch(request);
}
};
Cloudflare Workers
Native support for Cloudflare KV. Blocks attacks at globally distributed edge nodes before they touch your origin.
Vercel Edge
Leverages Vercel Edge Config for zero-latency lookups. Perfect for Next.js and serverless environments.
Quick Start
Integrate Sentinel in minutes using our official adapter for Express, Fastify, or Next.js.
npm install api-turnstile
Initialize the middleware with your Vector API key and specify the routes you want to protect.
import { sentinel } from 'api-turnstile';
import express from 'express';
const app = express();
app.use(sentinel({
apiKey: process.env.SENTINEL_KEY,
protect: ['/api/auth/*', '/v1/payments'],
profile: 'api'
}));
Framework Integration
Sentinel provides first-class support for popular Node.js frameworks.
Express
Standard middleware support with auto-detection of IP and headers.
Fastify
Native plugin for Fastify's high-performance architecture.
Next.js
Middleware support for both App and Pages router.
Configuration Deep Dive
The SentinelConfig object allows for granular control over enforcement and fallback
strategies.
| Option | Type | Default | Description |
|---|---|---|---|
apiKey |
String | Required | Your unique API key from the Sentinel dashboard. |
protect |
Array | Obj | Required | Paths to secure. Can be an array of patterns or a mapping of patterns to
ProtectionMode.
|
profile |
String | 'api' | The security profile to apply (api, signup, payments, crypto). |
fail |
String | 'closed' | Failure strategy: open (allow on error) or closed (block on
error). |
onBlock |
Function | Default 403 | Custom callback for blocked requests: (req, res, decision) => void. |
Protection Modes
Each protected path can run in one of three modes:
- monitor: Passively logs traffic. Useful for profiling before enforcement.
- balanced: Standard protection. Blocks high-confidence automated threats.
- strict: Zero tolerance. Blocks any suspicious signal including VPNs and datacenters.
Behavioral Work Tokens (BWT)
BWT is our proprietary extension of Proof-of-Work (PoW) that couples cryptographic difficulty with physical human interaction. This ensures that even "smart" bots with GPU clusters cannot scale their attacks because the cost of simulation exceeds the value of the target.
2. Server issues a nonce with a specific difficulty.
3. Client must hold interaction for
N seconds while solving the PoW. 4. Server validates both the PoW solution and the interaction baseline.
Verification Lifecycle
Implementing Sentinel's behavioral gate follows a deterministic three-stage lifecycle. This is standard for all high-security integrations.
Phase 1: Challenge Issuance
The client requests a new challenge from the Sentinel infrastructure. This challenge is unique to the user's IP and session.
POST /v1/challenge/issue
{ "target": "client_ip", "duration": 2.0 }
Phase 2: Intent Demonstration
The client demonstration "Proof of Intent" (via the Widget) while computing the PoW solution in the background. This typically takes 2-4 seconds depending on server requirements.
Phase 3: Verification & Token
The client submits the solved nonce. If valid, Sentinel issues a base64 Trust Token. This token is your cryptographic "passport" for subsequent high-value requests.
POST /v1/challenge/verify
{ "target": "client_ip", "nonce": "SOLVED_NONCE" }
// RESPONSE
{ "success": true, "trust_token": "..." }
Security Profiles
Profiles allow you to tune the engine sensitivity based on the business value of the endpoint.
| Profile | Sensitivity | Typical Targets | Key Checks |
|---|---|---|---|
| api | Balanced | Public Data, Search | ASN, Velocity, Runtimes |
| signup | High | User Registration | Disposable Email, Identity Velocity |
| payments | Strict | Checkout, Wallet | Geo-Mismatch, VPN/Proxy Detection |
| crypto | Zero-Trust | Faucets, Withdrawals | Tor, Known Clusterings, Prior Blocks |
CLI & Forensics
Analyze your traffic and investigate suspicious IPs directly from your terminal.
# Install the CLI npm install -g api-turnstile # Tail live traffic decisions sentinel tail --key YOUR_API_KEY # Forensic audit of an IP sentinel check 1.2.3.4
Frontend Widget
For high-risk interactions like signups or payments, you can add an interactive behavioral challenge to your frontend. The Sentinel Widget requires users to demonstrate "Proof of Intent" through a controlled interaction that bots cannot easily replicate.
1. Implementation
Include the Sentinel client script and add the target element where you want the widget to appear.
Note: This demo uses a testing site-key.
<!-- 1. Add the target element --> <div id="sentinel-widget" data-sitekey="YOUR_PROJECT_KEY"></div> <!-- 2. Include the widget script --> <script src="https://sentinel.risksignal.name.ng/widget.js" async defer></script>
2. Handling Verification
When the user successfully completes the challenge, the widget fires a sentinelSuccess event
and automatically injects a hidden input named sentinel-token if it resides within a form.
document.addEventListener('sentinelSuccess', (event) => {
const { trust_token } = event.detail;
console.log('Verified!', trust_token);
// Optional: Manually submit or enable your submit button
document.getElementById('submit-btn').disabled = false;
});
3. Backend Enforcement
Once the widget generates a sentinel-token, your server must validate it to ensure the
request is legitimate. There are two ways to do this:
Wait, How does it get to the server?
The Sentinel Widget is designed to be zero-config. It will automatically:
- Forms: Search for the nearest
<form>and inject a hidden<input name="sentinel-token">upon success. - AJAX/Fetch: Fire the
sentinelSuccessevent so you can manually add theX-Sentinel-Trustheader to your API calls.
Option A: Express/Node.js Middleware (Pre-built)
If you are using the api-turnstile SDK, simply enable trust token validation in your
middleware config. It will automatically look for the x-sentinel-trust header or the
sentinel-token form field.
app.use(sentinel({
apiKey: process.env.SENTINEL_KEY,
verifyToken: true, // Enable automatic widget token detection
trustTokenField: 'sentinel-token', // Custom field name (Optional)
onBlock: (req, res, decision) => {
return res.status(403).json({ error: "High-risk session. Please complete verification." });
}
}));
Option B: Manual API Validation (Any Language)
If you aren't using the Node.js middleware, you can manually verify the token by calling our verification endpoint from your backend.
# Example: Python / Flask
import requests
def verify_sentinel(token, ip):
res = requests.post(
"https://sentinel.risksignal.name.ng/v1/challenge/verify",
headers={"Authorization": f"Bearer {API_KEY}"},
json={"target": ip, "nonce": token} # Use 'nonce' for token check
)
return res.json().get("success")
API Reference
/v1/check
Render a trust decision for an IP address. This is the primary endpoint used by the Node.js middleware to vet traffic in real-time.
Request Body
{
"target": "185.123.45.6", // Target IP
"profile": "signup", // Security profile
"privacy_mode": "full" // strict | full
}
Response Object
{
"allow": false,
"action": "block",
"risk": "untrusted",
"reason": "vpn_detection_confirmed",
"confidence": 0.99,
"latency_ms": 14,
"remediation": {
"widget_required": true
}
}
Challenge API Reference
The Challenge API powers the interactive behavioral verification system.
/v1/challenge/issue
Request a new behavioral challenge for a target IP.
Request Parameters
| Field | Type | Description |
|---|---|---|
target |
String | Required. The IP address to bind the challenge to. |
duration |
Float | Optional. Required hold duration in seconds (Default: 2.0). |
/v1/challenge/verify
Submit a solved challenge and receive a deterministic Trust Token.
Request Parameters
| Field | Type | Description |
|---|---|---|
target |
String | Required. The IP address the challenge was issued to. |
nonce |
String | Required. The solved cryptographic string. |
Validating the Trust Token
Once your frontend receives a trust_token, send it to your backend. You should verify it
on every subsequent sensitive request using the x-sentinel-trust header.
// Node.js Example
const sentinelToken = req.headers['x-sentinel-trust'];
// The middleware handles this automatically, but for manual validation:
const isValid = await sentinel.verifyToken(sentinelToken, clientIp);
if (!isValid) return res.status(403).send("Behavioral Proof Required");