HomeAPI & DocsBlogContact
Log InGet Started
Developer Resources

Integrations & SDKs

Add fraud detection to any stack in under 5 minutes. Works with any language that can make HTTP requests — no proprietary SDK required.

< 40ms
Average global response time
Any lang
REST API works with any HTTP client
No SDK
Plain HTTP POST, zero dependencies

One endpoint. Full signal set.

A single POST request returns a risk score, verdict, and all detection signals. No pagination, no setup, no webhooks required to get started.

Endpoint
Method POST
URL https://api.sntlhq.com/v1/check
Auth Authorization: Bearer YOUR_API_KEY
Request { "ip": "1.2.3.4", "user_agent": "...", "headers": {} }
Response { "risk_score": 94, "verdict": "block", "signals": { "vpn": true, "proxy": false, "tor": false, "datacenter": false, "residential_proxy": true, "headless": false }, "country": "US", "latency_ms": 28 }

Pick your language

Copy-paste ready examples for the most common server-side languages. All examples show the full request/response flow with a block-or-pass pattern.

Node.js / JavaScript
const response = await fetch('https://api.sntlhq.com/v1/check', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    ip: req.ip,
    user_agent: req.headers['user-agent'],
    headers: req.headers
  })
});
const result = await response.json();

if (result.verdict === 'block') {
  return res.status(403).json({ error: 'Access denied' });
}
Python
import requests

response = requests.post(
    'https://api.sntlhq.com/v1/check',
    headers={
        'Authorization': 'Bearer YOUR_API_KEY',
        'Content-Type': 'application/json'
    },
    json={
        'ip': request.remote_addr,
        'user_agent': request.headers.get('User-Agent'),
        'headers': dict(request.headers)
    }
)
result = response.json()

if result['verdict'] == 'block':
    return jsonify({'error': 'Access denied'}), 403
PHP
$response = file_get_contents('https://api.sntlhq.com/v1/check', false, stream_context_create([
    'http' => [
        'method'  => 'POST',
        'header'  => "Authorization: Bearer YOUR_API_KEY\r\nContent-Type: application/json\r\n",
        'content' => json_encode([
            'ip'         => $_SERVER['REMOTE_ADDR'],
            'user_agent' => $_SERVER['HTTP_USER_AGENT'],
            'headers'    => getallheaders()
        ])
    ]
]));
$result = json_decode($response, true);

if ($result['verdict'] === 'block') {
    http_response_code(403);
    echo json_encode(['error' => 'Access denied']);
    exit;
}
Go
type CheckRequest struct {
    IP        string            `json:"ip"`
    UserAgent string            `json:"user_agent"`
    Headers   map[string]string `json:"headers"`
}

func checkIP(ip, userAgent string) (*SentinelResult, error) {
    body, _ := json.Marshal(CheckRequest{IP: ip, UserAgent: userAgent})
    req, _ := http.NewRequest("POST", "https://api.sntlhq.com/v1/check", bytes.NewReader(body))
    req.Header.Set("Authorization", "Bearer YOUR_API_KEY")
    req.Header.Set("Content-Type", "application/json")

    resp, err := http.DefaultClient.Do(req)
    if err != nil { return nil, err }
    defer resp.Body.Close()

    var result SentinelResult
    json.NewDecoder(resp.Body).Decode(&result)
    return &result, nil
}
Ruby
require 'net/http'
require 'json'

uri  = URI('https://api.sntlhq.com/v1/check')
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true

request = Net::HTTP::Post.new(uri.path)
request['Authorization'] = 'Bearer YOUR_API_KEY'
request['Content-Type']  = 'application/json'
request.body = {
  ip:         request.remote_ip,
  user_agent: request.user_agent,
  headers:    request.headers.to_h
}.to_json

response = http.request(request)
result   = JSON.parse(response.body)

render json: { error: 'Access denied' }, status: 403 if result['verdict'] == 'block'
Java
HttpClient client = HttpClient.newHttpClient();
String body = String.format(
    "{\"ip\":\"%s\",\"user_agent\":\"%s\"}",
    request.getRemoteAddr(),
    request.getHeader("User-Agent")
);

HttpRequest httpRequest = HttpRequest.newBuilder()
    .uri(URI.create("https://api.sntlhq.com/v1/check"))
    .header("Authorization", "Bearer YOUR_API_KEY")
    .header("Content-Type", "application/json")
    .POST(HttpRequest.BodyPublishers.ofString(body))
    .build();

HttpResponse<String> response = client.send(httpRequest,
    HttpResponse.BodyHandlers.ofString());
JSONObject result = new JSONObject(response.body());

if ("block".equals(result.getString("verdict"))) {
    response.setStatus(403);
    return Map.of("error", "Access denied");
}

Works with every framework

If your framework can make an outbound HTTP request, Sentinel works. No middleware, no plugins, no vendor lock-in.

NX
Next.js
Node / React
EX
Express.js
Node
FY
Fastify
Node
NS
NestJS
Node / TS
DJ
Django
Python
FA
FastAPI
Python
FL
Flask
Python
LV
Laravel
PHP
SF
Symfony
PHP
RR
Rails
Ruby
SB
Spring Boot
Java
GN
Gin
Go
EC
Echo
Go

Get your free API key

10,000 requests/month free. No credit card required. Up and running in under 5 minutes.