API Documentation

Everything you need to integrate Auspex Verus™ IP classification into your application.

Quick Start

1. Get Your API Credentials

Sign up for an Auspex Verus™ account and generate your API key and secret from the portal.

API Key:    alk_1234567890abcdef
API Secret: als_abcdefghijklmnopqrstuvwxyz1234567890

Important: Keep your API secret secure. It is used to sign requests and should never be transmitted directly.

2. Make Your First Request

Requests are authenticated using HMAC-SHA256 signatures. Each request requires:

  • X-Amz-Date: Current timestamp in ISO 8601 basic format
  • Authorization: HMAC-SHA256 signature header
# Example signed request (see code examples below for signature generation)
curl -X POST https://api.auspex-labs.com/verus/classify \
  -H "Content-Type: application/json" \
  -H "X-Amz-Date: 20250115T103000Z" \
  -H "Authorization: HMAC-SHA256 Credential=alk_xxx/20250115/verus/aws4_request, SignedHeaders=x-amz-date, Signature=abc123..." \
  -d '{"ipAddress": "8.8.8.8"}'

3. Handle the Response

The API returns a JSON response with classification results.

{
  "human": false,
  "certainty": 100
}

API Reference

Endpoint

POST https://api.auspex-labs.com/verus/classify

Request Headers

Header Required Description
Content-Type Yes Must be application/json
X-Amz-Date Yes Request timestamp in ISO 8601 basic format (YYYYMMDDTHHMMSSZ)
Authorization Yes HMAC-SHA256 signature (see Authentication section below)

Authentication

Auspex Verus™ uses HMAC-SHA256 request signing. The Authorization header format is:

HMAC-SHA256 Credential={keyId}/{date}/verus/aws4_request, SignedHeaders={headers}, Signature={signature}
Component Description
keyId Your API key (starts with alk_)
date Date in YYYYMMDD format (must match X-Amz-Date)
SignedHeaders Semicolon-separated lowercase header names: x-amz-date
Signature Hex-encoded HMAC-SHA256 signature

Request timestamps must be within 5 minutes of server time. Requests with expired timestamps will be rejected.

Request Body

Field Type Required Description
ipAddress string Yes IPv4 or IPv6 address to classify

Response Fields

Field Type Description
human boolean true if likely human user, false if likely bot/automated traffic
certainty integer Confidence score from 0-100. Higher values indicate stronger confidence.

Code Examples

Python

import hashlib
import hmac
import json
from datetime import datetime, timezone

import requests

API_KEY = "alk_1234567890abcdef"
API_SECRET = "als_abcdefghijklmnopqrstuvwxyz1234567890"

def sign_request(method, uri, body):
    """Generate HMAC-SHA256 signature for API request."""
    amz_date = datetime.now(timezone.utc).strftime("%Y%m%dT%H%M%SZ")
    date_stamp = amz_date[:8]

    # Derive signing key
    k_date = hmac.new(f"AWS4{API_SECRET}".encode(), date_stamp.encode(), hashlib.sha256).digest()
    k_service = hmac.new(k_date, b"verus", hashlib.sha256).digest()
    k_signing = hmac.new(k_service, b"aws4_request", hashlib.sha256).digest()

    # Create canonical request
    signed_headers = "x-amz-date"
    payload_hash = hashlib.sha256(body.encode()).hexdigest()
    canonical_headers = f"x-amz-date:{amz_date}\n"
    canonical_request = f"{method}\n{uri}\n\n{canonical_headers}\n{signed_headers}\n{payload_hash}"

    # Create string to sign
    credential_scope = f"{date_stamp}/verus/aws4_request"
    request_hash = hashlib.sha256(canonical_request.encode()).hexdigest()
    string_to_sign = f"HMAC-SHA256\n{amz_date}\n{credential_scope}\n{request_hash}"

    # Compute signature
    signature = hmac.new(k_signing, string_to_sign.encode(), hashlib.sha256).hexdigest()
    authorization = f"HMAC-SHA256 Credential={API_KEY}/{credential_scope}, SignedHeaders={signed_headers}, Signature={signature}"

    return {"Content-Type": "application/json", "X-Amz-Date": amz_date, "Authorization": authorization}

# Make request
body = json.dumps({"ipAddress": "8.8.8.8"})
headers = sign_request("POST", "/verus/classify", body)

response = requests.post("https://api.auspex-labs.com/verus/classify", headers=headers, data=body)
result = response.json()
print(f"Human: {result['human']}, Certainty: {result['certainty']}%")

JavaScript (Node.js)

const crypto = require('crypto');

const API_KEY = 'alk_1234567890abcdef';
const API_SECRET = 'als_abcdefghijklmnopqrstuvwxyz1234567890';

function signRequest(method, uri, body) {
    const amzDate = new Date().toISOString().replace(/[-:]/g, '').split('.')[0] + 'Z';
    const dateStamp = amzDate.slice(0, 8);

    // Derive signing key
    const kDate = crypto.createHmac('sha256', 'AWS4' + API_SECRET).update(dateStamp).digest();
    const kService = crypto.createHmac('sha256', kDate).update('verus').digest();
    const kSigning = crypto.createHmac('sha256', kService).update('aws4_request').digest();

    // Create canonical request
    const signedHeaders = 'x-amz-date';
    const payloadHash = crypto.createHash('sha256').update(body).digest('hex');
    const canonicalHeaders = `x-amz-date:${amzDate}\n`;
    const canonicalRequest = `${method}\n${uri}\n\n${canonicalHeaders}\n${signedHeaders}\n${payloadHash}`;

    // Create string to sign
    const credentialScope = `${dateStamp}/verus/aws4_request`;
    const requestHash = crypto.createHash('sha256').update(canonicalRequest).digest('hex');
    const stringToSign = `HMAC-SHA256\n${amzDate}\n${credentialScope}\n${requestHash}`;

    // Compute signature
    const signature = crypto.createHmac('sha256', kSigning).update(stringToSign).digest('hex');
    const authorization = `HMAC-SHA256 Credential=${API_KEY}/${credentialScope}, SignedHeaders=${signedHeaders}, Signature=${signature}`;

    return { amzDate, authorization };
}

async function classifyIP(ipAddress) {
    const body = JSON.stringify({ ipAddress });
    const { amzDate, authorization } = signRequest('POST', '/verus/classify', body);

    const response = await fetch('https://api.auspex-labs.com/verus/classify', {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
            'X-Amz-Date': amzDate,
            'Authorization': authorization
        },
        body
    });

    const result = await response.json();
    console.log(`Human: ${result.human}, Certainty: ${result.certainty}%`);
    return result;
}

classifyIP('8.8.8.8');

PHP

<?php
$apiKey = 'alk_1234567890abcdef';
$apiSecret = 'als_abcdefghijklmnopqrstuvwxyz1234567890';
$uri = '/verus/classify';

function signRequest($method, $uri, $body, $apiKey, $apiSecret) {
    $amzDate = gmdate('Ymd\THis\Z');
    $dateStamp = substr($amzDate, 0, 8);

    // Derive signing key
    $kDate = hash_hmac('sha256', $dateStamp, 'AWS4' . $apiSecret, true);
    $kService = hash_hmac('sha256', 'verus', $kDate, true);
    $kSigning = hash_hmac('sha256', 'aws4_request', $kService, true);

    // Create canonical request
    $signedHeaders = 'x-amz-date';
    $payloadHash = hash('sha256', $body);
    $canonicalHeaders = "x-amz-date:$amzDate\n";
    $canonicalRequest = "$method\n$uri\n\n$canonicalHeaders\n$signedHeaders\n$payloadHash";

    // Create string to sign
    $credentialScope = "$dateStamp/verus/aws4_request";
    $requestHash = hash('sha256', $canonicalRequest);
    $stringToSign = "HMAC-SHA256\n$amzDate\n$credentialScope\n$requestHash";

    // Compute signature
    $signature = hash_hmac('sha256', $stringToSign, $kSigning);
    $authorization = "HMAC-SHA256 Credential=$apiKey/$credentialScope, SignedHeaders=$signedHeaders, Signature=$signature";

    return ['amzDate' => $amzDate, 'authorization' => $authorization];
}

$body = json_encode(['ipAddress' => '8.8.8.8']);
$sig = signRequest('POST', $uri, $body, $apiKey, $apiSecret);

$ch = curl_init("https://api.auspex-labs.com$uri");
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    'Content-Type: application/json',
    'X-Amz-Date: ' . $sig['amzDate'],
    'Authorization: ' . $sig['authorization']
]);
curl_setopt($ch, CURLOPT_POSTFIELDS, $body);

$response = curl_exec($ch);
$result = json_decode($response, true);
echo "Human: " . ($result['human'] ? 'true' : 'false') . ", Certainty: " . $result['certainty'] . "%\n";
curl_close($ch);

C#

using System.Security.Cryptography;
using System.Text;
using System.Text.Json;

const string ApiKey = "alk_1234567890abcdef";
const string ApiSecret = "als_abcdefghijklmnopqrstuvwxyz1234567890";
const string Uri = "/verus/classify";

(string amzDate, string authorization) SignRequest(string method, string uri, string body)
{
    var amzDate = DateTime.UtcNow.ToString("yyyyMMddTHHmmssZ");
    var dateStamp = amzDate[..8];

    // Derive signing key
    var kDate = HmacSha256(Encoding.UTF8.GetBytes("AWS4" + ApiSecret), Encoding.UTF8.GetBytes(dateStamp));
    var kService = HmacSha256(kDate, Encoding.UTF8.GetBytes("verus"));
    var kSigning = HmacSha256(kService, Encoding.UTF8.GetBytes("aws4_request"));

    // Create canonical request
    var signedHeaders = "x-amz-date";
    var payloadHash = Sha256Hex(body);
    var canonicalHeaders = $"x-amz-date:{amzDate}\n";
    var canonicalRequest = $"{method}\n{uri}\n\n{canonicalHeaders}\n{signedHeaders}\n{payloadHash}";

    // Create string to sign
    var credentialScope = $"{dateStamp}/verus/aws4_request";
    var requestHash = Sha256Hex(canonicalRequest);
    var stringToSign = $"HMAC-SHA256\n{amzDate}\n{credentialScope}\n{requestHash}";

    // Compute signature
    var signature = Convert.ToHexString(HmacSha256(kSigning, Encoding.UTF8.GetBytes(stringToSign))).ToLower();
    var authorization = $"HMAC-SHA256 Credential={ApiKey}/{credentialScope}, SignedHeaders={signedHeaders}, Signature={signature}";

    return (amzDate, authorization);
}

byte[] HmacSha256(byte[] key, byte[] data)
{
    using var hmac = new HMACSHA256(key);
    return hmac.ComputeHash(data);
}

string Sha256Hex(string data)
{
    var hash = SHA256.HashData(Encoding.UTF8.GetBytes(data));
    return Convert.ToHexString(hash).ToLower();
}

// Make request
var body = JsonSerializer.Serialize(new { ipAddress = "8.8.8.8" });
var (amzDate, authorization) = SignRequest("POST", Uri, body);

using var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Post, $"https://api.auspex-labs.com{Uri}");
request.Content = new StringContent(body, Encoding.UTF8, "application/json");
request.Headers.Add("X-Amz-Date", amzDate);
request.Headers.Add("Authorization", authorization);

var response = await client.SendAsync(request);
var result = await JsonSerializer.DeserializeAsync<JsonElement>(await response.Content.ReadAsStreamAsync());
Console.WriteLine($"Human: {result.GetProperty("human")}, Certainty: {result.GetProperty("certainty")}%");

Go

package main

import (
    "bytes"
    "crypto/hmac"
    "crypto/sha256"
    "encoding/hex"
    "encoding/json"
    "fmt"
    "net/http"
    "time"
)

const (
    apiKey    = "alk_1234567890abcdef"
    apiSecret = "als_abcdefghijklmnopqrstuvwxyz1234567890"
)

func signRequest(method, uri, body string) (string, string) {
    amzDate := time.Now().UTC().Format("20060102T150405Z")
    dateStamp := amzDate[:8]

    // Derive signing key
    kDate := hmacSHA256([]byte("AWS4"+apiSecret), []byte(dateStamp))
    kService := hmacSHA256(kDate, []byte("verus"))
    kSigning := hmacSHA256(kService, []byte("aws4_request"))

    // Create canonical request
    signedHeaders := "x-amz-date"
    payloadHash := sha256Hex([]byte(body))
    canonicalHeaders := fmt.Sprintf("x-amz-date:%s\n", amzDate)
    canonicalRequest := fmt.Sprintf("%s\n%s\n\n%s\n%s\n%s", method, uri, canonicalHeaders, signedHeaders, payloadHash)

    // Create string to sign
    credentialScope := fmt.Sprintf("%s/verus/aws4_request", dateStamp)
    requestHash := sha256Hex([]byte(canonicalRequest))
    stringToSign := fmt.Sprintf("HMAC-SHA256\n%s\n%s\n%s", amzDate, credentialScope, requestHash)

    // Compute signature
    signature := hex.EncodeToString(hmacSHA256(kSigning, []byte(stringToSign)))
    authorization := fmt.Sprintf("HMAC-SHA256 Credential=%s/%s, SignedHeaders=%s, Signature=%s",
        apiKey, credentialScope, signedHeaders, signature)

    return amzDate, authorization
}

func hmacSHA256(key, data []byte) []byte {
    h := hmac.New(sha256.New, key)
    h.Write(data)
    return h.Sum(nil)
}

func sha256Hex(data []byte) string {
    hash := sha256.Sum256(data)
    return hex.EncodeToString(hash[:])
}

func main() {
    body, _ := json.Marshal(map[string]string{"ipAddress": "8.8.8.8"})
    amzDate, authorization := signRequest("POST", "/verus/classify", string(body))

    req, _ := http.NewRequest("POST", "https://api.auspex-labs.com/verus/classify", bytes.NewBuffer(body))
    req.Header.Set("Content-Type", "application/json")
    req.Header.Set("X-Amz-Date", amzDate)
    req.Header.Set("Authorization", authorization)

    resp, _ := (&http.Client{}).Do(req)
    defer resp.Body.Close()

    var result map[string]interface{}
    json.NewDecoder(resp.Body).Decode(&result)
    fmt.Printf("Human: %v, Certainty: %.0f%%\n", result["human"], result["certainty"])
}

Bash (with OpenSSL)

#!/bin/bash
API_KEY="alk_1234567890abcdef"
API_SECRET="als_abcdefghijklmnopqrstuvwxyz1234567890"
URI="/verus/classify"
BODY='{"ipAddress": "8.8.8.8"}'

# Generate timestamp
AMZ_DATE=$(date -u +"%Y%m%dT%H%M%SZ")
DATE_STAMP=${AMZ_DATE:0:8}

# Helper function for HMAC-SHA256
hmac_sha256() {
    local key="$1"
    local data="$2"
    echo -n "$data" | openssl dgst -sha256 -mac HMAC -macopt "$key" -binary
}

# Derive signing key
K_DATE=$(hmac_sha256 "key:AWS4${API_SECRET}" "$DATE_STAMP")
K_SERVICE=$(echo -n "verus" | openssl dgst -sha256 -mac HMAC -macopt "hexkey:$(echo -n "$K_DATE" | xxd -p -c 256)" -binary)
K_SIGNING=$(echo -n "aws4_request" | openssl dgst -sha256 -mac HMAC -macopt "hexkey:$(echo -n "$K_SERVICE" | xxd -p -c 256)" -binary)
K_SIGNING_HEX=$(echo -n "$K_SIGNING" | xxd -p -c 256)

# Create canonical request
SIGNED_HEADERS="x-amz-date"
PAYLOAD_HASH=$(echo -n "$BODY" | openssl dgst -sha256 | awk '{print $2}')
CANONICAL_HEADERS="x-amz-date:${AMZ_DATE}\n"
CANONICAL_REQUEST="POST\n${URI}\n\n${CANONICAL_HEADERS}\n${SIGNED_HEADERS}\n${PAYLOAD_HASH}"
REQUEST_HASH=$(echo -ne "$CANONICAL_REQUEST" | openssl dgst -sha256 | awk '{print $2}')

# Create string to sign
CREDENTIAL_SCOPE="${DATE_STAMP}/verus/aws4_request"
STRING_TO_SIGN="HMAC-SHA256\n${AMZ_DATE}\n${CREDENTIAL_SCOPE}\n${REQUEST_HASH}"

# Compute signature
SIGNATURE=$(echo -ne "$STRING_TO_SIGN" | openssl dgst -sha256 -mac HMAC -macopt "hexkey:${K_SIGNING_HEX}" | awk '{print $2}')

# Build authorization header
AUTHORIZATION="HMAC-SHA256 Credential=${API_KEY}/${CREDENTIAL_SCOPE}, SignedHeaders=${SIGNED_HEADERS}, Signature=${SIGNATURE}"

# Make request
curl -X POST "https://api.auspex-labs.com${URI}" \
  -H "Content-Type: application/json" \
  -H "X-Amz-Date: ${AMZ_DATE}" \
  -H "Authorization: ${AUTHORIZATION}" \
  -d "$BODY"

Error Handling

HTTP Status Codes

Status Meaning Description
200 Success Classification completed successfully
400 Bad Request Invalid IP address format or missing required fields
401 Unauthorized Invalid or missing API credentials
500 Server Error Internal server error, contact support if persists

Error Response Format

{
  "error": "Invalid IP address format",
  "statusCode": 400
}

Best Practices

Cache Results

Cache classification results for frequently seen IPs to reduce API calls and improve response times.

Use Certainty Scores

Don't just check human/bot - use certainty scores to implement nuanced policies (block high certainty bots, challenge medium certainty).

Secure Your Credentials

Never expose API keys in client-side code. Always make API calls from your backend server.

Monitor Usage

Track your API usage through the portal to avoid unexpected overage charges and optimize your plan.

Understanding Results

Interpreting Classifications

Human vs Bot

  • human: true - IP is likely residential, mobile, or office network (legitimate user)
  • human: false - IP is from hosting provider, datacenter, VPN, proxy, or known bot network

Certainty Levels

  • 75-100 - High confidence, strong signal (act with confidence)
  • 50-74 - Medium confidence, good signal (reasonable to act)
  • 25-49 - Low confidence, weak signal (consider additional verification)
  • 0-24 - Very low confidence, minimal signal (treat with caution)

Special Cases

  • Private IPs - RFC 1918 (10.x, 172.16.x, 192.168.x) and RFC 6598 (100.64.x) always return {human: true, certainty: 0}
  • Certainty: 0 - Unable to classify with confidence (private IP or insufficient data)

Recommended Actions

Classification Certainty Recommended Action
Bot 75-100 Block or present CAPTCHA
Bot 50-74 Challenge with CAPTCHA or additional verification
Bot 0-49 Allow with monitoring, apply rate limits
Human Any Allow with normal rate limits

Support & Resources

Need Help?

Contact our support team for integration assistance, technical questions, or account issues.
Email: support@auspex-labs.com

Contact Support

Try It Out

Test the Auspex Verus™ API with real IP addresses using our interactive demo interface.

Try Demo

View Pricing

Choose a plan that fits your needs with transparent, predictable pricing.

See Pricing

GitHub

Explore our open-source tools, report issues, and connect with other developers using Auspex Verus™.

View on GitHub

Ready to Try Auspex Verus™?

Experience real-time IP classification in action. Test our demo or get in touch to learn more.