PureGuard API Documentation
PureGuard is a server-side bot detection engine built for performance media buyers. It analyzes every click through 13+ configurable detection layers and returns a verdict in under 15ms. This documentation covers the REST API, detection engine internals, and integration guides for every major traffic source.
1. Create an account
Register for free to get instant access. Your starter plan includes 100,000 bot checks per month at no cost. No credit card required.
2. Get your API key
After logging in, navigate to Settings to find your API key. The key is a unique
string prefixed with pg_ that authenticates all your requests.
3. Make your first request
curl -X POST https://pureguard.io/api/v1/check \ -H "X-API-Key: pg_your_api_key" \ -H "Content-Type: application/json" \ -d '{ "ip": "1.2.3.4", "ua": "Mozilla/5.0 Chrome/131.0", "url": "https://example.com/offer" }'
The response tells you whether to accept or block the visitor:
{
"verdict": "ACCEPT",
"trust": 7.3,
"confidence": 92,
"signals": ["browser_valid:+bonus", "network:+bonus", "device:+bonus"],
"ms": 2.3
}
Authentication
All API requests (except GET /api/v1/status) require authentication via the
X-API-Key header. Your API key is available on the
Settings page of your dashboard.
Example authenticated request:
curl -H "X-API-Key: pg_abc123def456" \
https://pureguard.io/api/v1/stats
Requests without a valid key receive a 401 Unauthorized response. Requests that exceed
your plan's monthly quota receive 429 Too Many Requests.
API Reference
Base URL: https://pureguard.io/api/v1. All request and response bodies use JSON.
Times are in UTC.
Bot Check
Evaluate a single visitor. Send the visitor's IP address, user-agent string, and optionally their HTTP headers for maximum detection accuracy. The engine runs all enabled layers and returns a verdict within milliseconds.
Request Body
Full Example
POST /api/v1/check HTTP/1.1
Host: pureguard.io
X-API-Key: pg_abc123def456
Content-Type: application/json
{
"ip": "203.0.113.42",
"ua": "Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Mobile Safari/537.36",
"url": "https://example.com/offer?s1=zone_1234",
"headers": {
"Sec-Fetch-Site": "cross-site",
"Sec-Fetch-Mode": "navigate",
"Sec-Fetch-Dest": "document",
"Accept-Language": "th-TH,th;q=0.9,en;q=0.8",
"Accept-Encoding": "gzip, deflate, br"
},
"zone": "zone_1234"
}
{
"verdict": "ACCEPT",
"trust": 7.3,
"confidence": 92,
"signals": [
"browser_valid:+bonus",
"network:+bonus",
"device_auth:+bonus",
"protocol:+bonus",
"geo_match:+bonus"
],
"ms": 2.3
}
Response Fields
{"verdict":"BLOCK","trust":0.0,"confidence":99,"signals":["threat_intel:KILL"],"ms":0.8}
Traffic Statistics
Returns aggregated traffic statistics for your account. Includes today's counts and a 7-day historical breakdown for charting.
{
"today": {
"checks": 14832,
"accepts": 8291,
"blocks": 6541,
"rate": 55.9
},
"week": [
{ "date": "2026-03-02", "checks": 12480, "accepts": 7120, "blocks": 5360 },
{ "date": "2026-03-03", "checks": 13105, "accepts": 7402, "blocks": 5703 },
{ "date": "2026-03-04", "checks": 11893, "accepts": 6814, "blocks": 5079 },
{ "date": "2026-03-05", "checks": 14220, "accepts": 7988, "blocks": 6232 },
{ "date": "2026-03-06", "checks": 15010, "accepts": 8201, "blocks": 6809 },
{ "date": "2026-03-07", "checks": 13744, "accepts": 7512, "blocks": 6232 },
{ "date": "2026-03-08", "checks": 14832, "accepts": 8291, "blocks": 6541 }
]
}
Zone Data
Returns zone reputation data for all zones seen in your traffic. Use this to identify high-quality and toxic traffic sources programmatically.
{
"zones": [
{
"id": "zone_1234",
"status": "trusted",
"score": 8.2,
"hits": 4521,
"accept_rate": 87.3,
"webview_rate": 2.1,
"hosting_rate": 0.5,
"deprecated_rate": 1.3,
"pattern_penalty": 0.8,
"ua_monoculture": 12.4,
"trust_stdev": 1.92,
"hugger_rate": 3.2,
"unique_uas": 387
},
{
"id": "zone_5678",
"status": "blocked",
"score": 1.4,
"hits": 892,
"accept_rate": 12.1,
"webview_rate": 38.7,
"hosting_rate": 62.3,
"deprecated_rate": 45.1,
"pattern_penalty": 28.5,
"ua_monoculture": 78.9,
"trust_stdev": 0.41,
"hugger_rate": 67.2,
"unique_uas": 3
},
{
"id": "zone_9012",
"status": "neutral",
"score": 5.0,
"hits": 38,
"accept_rate": 63.2,
"webview_rate": 8.4,
"hosting_rate": 5.2,
"deprecated_rate": 6.1,
"pattern_penalty": 4.2,
"ua_monoculture": 25.0,
"trust_stdev": 1.58,
"hugger_rate": 12.8,
"unique_uas": 14
}
]
}
Zone Statuses
Pattern Intelligence Fields
Each zone includes pattern intelligence signals that reveal bot behavior patterns beyond simple accept/block rates. These fields are computed from traffic analysis and help identify sophisticated bot farms.
System Status
Public endpoint (no authentication required). Returns current engine status, version, and uptime. Use this for health checks and monitoring.
{
"status": "operational",
"engine": "v17.1",
"layers": 13,
"uptime": 99.7
}
Detection Layers
PureGuard's engine evaluates traffic through multiple independent detection layers. Each layer operates in one of three modes:
- Kill -- Instant block. A single confirmed signal is enough to reject the visitor.
- Score -- Adjusts the trust score up or down. Multiple weak signals compound.
- Observe -- Logs the signal for analysis but does not affect the verdict.
All layers are fully configurable through the dashboard. You can enable/disable individual layers and change their mode via the Guard Settings panel.
Hard Kill Layers
These layers terminate evaluation immediately when triggered. A single match means definite bot.
.0.0.0 build numbers, but older Chrome versions with .0.0.0 are spoofed bots impersonating the UA Reduction format.Trust Scoring Layers
These layers adjust the trust score (proprietary base) up or down. Multiple signals compound. The final trust score determines the verdict: below threshold = BLOCK, above = ACCEPT.
Observation Layers
These layers collect signals for analysis and reporting but do not affect the verdict by default. Enable scoring mode on any of them to start using them in decisions.
CF-TLS-Version header. Modern browsers use TLS 1.3. Older TLS versions correlate with outdated or automated clients.Integration Guide
PureGuard integrates into any stack. Below are production-ready examples for the most common languages, plus traffic source and RTB setup instructions.
PHP Integration
Direct server-side integration. Call the API before redirecting the visitor.
<?php function checkBot($ip, $ua, $url, $headers = []) { $ch = curl_init('https://pureguard.io/api/v1/check'); curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 5, CURLOPT_HTTPHEADER => [ 'X-API-Key: pg_your_api_key', 'Content-Type: application/json', ], CURLOPT_POSTFIELDS => json_encode([ 'ip' => $ip, 'ua' => $ua, 'url' => $url, 'headers' => $headers, ]), ]); $response = json_decode(curl_exec($ch), true); curl_close($ch); return $response; } // Usage in your click handler: $result = checkBot( $_SERVER['REMOTE_ADDR'], $_SERVER['HTTP_USER_AGENT'], 'https://example.com/offer' ); if ($result['verdict'] === 'BLOCK') { http_response_code(204); // Bot killed silently exit; } // Clean visitor -- redirect to offer header('Location: https://offer.example.com/lp1'); exit;
Node.js Integration
const checkBot = async (ip, ua, url) => { const res = await fetch('https://pureguard.io/api/v1/check', { method: 'POST', headers: { 'X-API-Key': process.env.PUREGUARD_KEY, 'Content-Type': 'application/json', }, body: JSON.stringify({ ip, ua, url }), }); return res.json(); }; // Express middleware example app.get('/click', async (req, res) => { const guard = await checkBot( req.ip, req.get('User-Agent'), req.originalUrl ); if (guard.verdict === 'BLOCK') { return res.status(204).end(); } res.redirect('https://offer.example.com/lp1'); });
Python Integration
import requests import os API_KEY = os.getenv("PUREGUARD_KEY") API_URL = "https://pureguard.io/api/v1/check" def check_bot(ip: str, ua: str, url: str) -> dict: resp = requests.post( API_URL, json={"ip": ip, "ua": ua, "url": url}, headers={ "X-API-Key": API_KEY, "Content-Type": "application/json", }, timeout=5, ) resp.raise_for_status() return resp.json() # Usage with Flask from flask import Flask, request, redirect, abort app = Flask(__name__) @app.route("/click") def click_handler(): result = check_bot( request.remote_addr, request.user_agent.string, request.url, ) if result["verdict"] == "BLOCK": abort(204) return redirect("https://offer.example.com/lp1")
Traffic Source Setup
For pop/push/native traffic sources, point your campaign URL through PureGuard's click handler. The engine evaluates the visitor inline and redirects clean traffic to your offer.
click.php (Guard evaluates) →
ACCEPT: 302 to your offer URL | BLOCK: 302 to dump URL
Click URL Format
https://pureguard.io/click.php?wk={workspace_key}&s1={zone_id}&s2={click_id}&s3={source}
Source Macro Mapping
RTB / OpenRTB 2.5
PureGuard includes a built-in OpenRTB 2.5 bidder for programmatic traffic. The RTB endpoint
evaluates bid requests through a dedicated Guard RTB pipeline with dozens of signals
optimized for bid-time decisions (no browser headers available).
// SSP sends bid request to: POST https://pureguard.io/bid.php // PureGuard responds with: // BID (above threshold) -> 200 with bid response // NOBID (below threshold) -> 204 No Content // Win notice URL (in bid response): https://pureguard.io/win.php?price=${AUCTION_PRICE}&id={bid_id}
RTB Trust Engine
The RTB pipeline starts at a base trust score and applies multiple penalty/bonus signals. Traffic scoring at bid time does not have access to browser headers (Sec-Fetch, etc.) since the RTB request comes from the SSP server, not the end user. Instead it relies on:
- IP blocklist checks (multiple threat intelligence feeds)
- UA pattern matching (bot signatures, ad-fraud crawlers)
- Device type analysis (connected TV, set-top box penalties)
- Geo verification (cross-check vs declared geo)
- Domain quality (junk domains, IP-as-domain, ad-heavy TLDs)
- Bid floor analysis (scam floors > $3, suspicious zero floors)
- Burst rate limiting (in-memory, per-IP)
Bid Request Format (OpenRTB 2.5)
Send a POST request with a JSON body conforming to OpenRTB 2.5:
{
"id": "request-123",
"imp": [{
"id": "1",
"instl": 1,
"bidfloor": 0.50,
"banner": { "topframe": 1 },
"ext": { "type": "pop" }
}],
"site": {
"domain": "example.com",
"id": "site_456",
"page": "https://example.com/page"
},
"device": {
"ua": "Mozilla/5.0 (Linux; Android 14; ...) Chrome/131.0...",
"ip": "203.0.113.42",
"devicetype": 2,
"os": "Android",
"geo": { "country": "US" }
},
"at": 1,
"cur": ["USD"]
}
Bid Response Format (200 OK)
When Guard accepts the traffic (above acceptance threshold), PureGuard returns a bid:
{
"id": "request-123",
"seatbid": [{
"bid": [{
"id": "bid-abc123",
"impid": "1",
"price": 0.501,
"adm": "https://pureguard.io/click.php?s1={zone}&s3=SSP&...",
"nurl": "https://pureguard.io/win.php?bid=bid-abc123&price=${AUCTION_PRICE}&req=request-123&zone={zone}&ssp=SSP",
"adomain": ["pureguard.io"],
"crid": "pop-1"
}]
}],
"cur": "USD"
}
No-Bid Response (204 No Content)
A 204 response means PureGuard declined to bid. Common reasons:
Win Notice
The nurl field in the bid response contains the win notification URL. The SSP must
call this URL when the auction is won, replacing ${AUCTION_PRICE} with the actual
clearing price (CPM). PureGuard uses this to track daily spend and per-zone win caps.
GET https://pureguard.io/win.php?bid={bid_id}&price={clearing_price_cpm}&req={request_id}&zone={zone}&ssp={ssp_name}
Testing Your Integration
curl -X POST https://pureguard.io/bid.php \
-H "Content-Type: application/json" \
-d '{
"id":"test-1",
"imp":[{"id":"1","instl":1,"bidfloor":0.50,"ext":{"type":"pop"}}],
"site":{"domain":"test.com"},
"device":{"ua":"Mozilla/5.0 Chrome/131.0","geo":{"country":"US"},
"ip":"1.2.3.4","devicetype":2},
"at":1,"cur":["USD"]
}'
# 200 = bid accepted (check response JSON)
# 204 = no bid (check RTB dashboard for reason)
Current SSP Status
Conversion Tracking (Postback)
PureGuard tracks conversions via server-to-server postback URLs. When a user converts on your offer, the smartlink or offer network fires a postback to PureGuard with the conversion details. This lets PureGuard attribute revenue to specific zones and power the zone quality engine.
How It Works
click.php filters and redirects clean traffic to your offer
https://pureguard.io/postback.php?...
Postback URL Parameters
Example Postback URL
https://pureguard.io/postback.php?s2={click_id}&value={payout}&s1={zone}&network=HILLTOPADS&wk=YOUR_WK
Network-Specific Macros
Each ad network uses different macro names. Use the correct macros for your network:
Duplicate Protection
PureGuard automatically deduplicates conversions. If the same click ID (s2) fires a postback
within 5 minutes, the duplicate is rejected. This prevents double-counting from network retries.
Response Format
OK: Fired to HILLTOPADS | HILLTOPADS: HTTP 200. Sentinel Updated.
DUPLICATE: Conversion for token already recorded within 5 minutes.
Rate Limits
Rate limits are enforced per API key at the Nginx level. Exceeding the limit returns
429 Too Many Requests. The response includes a Retry-After
header indicating when to retry.
Error Codes
All error responses include a JSON body with an error field describing the issue.
Error Response Format
{
"error": "Invalid or missing API key",
"code": 401
}
{
"error": "Rate limit exceeded",
"code": 429,
"retry_after": 2
}
Our team can help you set up PureGuard for your specific traffic stack.