API Documentation

REST API for Infrastructure Analysis and IOC Lookup

Overview

The PREDICT Community Edition API provides programmatic access to malware infrastructure analysis and IOC lookup capabilities.

Community Edition:

All users have unlimited API access at no cost. No subscription tiers or payment required.

Base URL: https://predict.pyosec.com/api

Content-Type: application/json

Response Format: JSON

Authentication: Required via API Key (see Authentication section)

Database: PostgreSQL with Redis caching for high performance

Quick Start Example:
# Get your API key from /account, then:
export PREDICT_API_KEY="predict_your_api_key_here"

# Test it out:
curl -H "X-API-Key: $PREDICT_API_KEY" \
     "https://predict.pyosec.com/api/ioc/lookup/8.8.8.8"
Supported IOC Types:
  • IP Addresses (IPv4/IPv6)
  • Domain Names
  • CIDR Blocks
  • URLs
  • Hashes (MD5, SHA1, SHA256)
  • Nameservers

Authentication

All API requests require authentication via API key. Web interface access uses session-based authentication.

Getting Your API Key:
  1. Log in to your account
  2. Navigate to Account Settings
  3. Click "New Key" in the API Keys section
  4. Copy and securely store your API key
Authentication Methods:
Method 1: X-API-Key Header (Recommended)
curl -H "X-API-Key: predict_your_api_key_here" \
     -H "Content-Type: application/json" \
     "https://predict.pyosec.com/api/ioc/lookup/213.199.53.152"
Method 2: Authorization Bearer Header
curl -H "Authorization: Bearer predict_your_api_key_here" \
     -H "Content-Type: application/json" \
     "https://predict.pyosec.com/api/ioc/lookup/213.199.53.152"
Python Example:
import requests

api_key = "predict_your_api_key_here"
headers = {
    "X-API-Key": api_key,
    "Content-Type": "application/json"
}

response = requests.get(
    "https://predict.pyosec.com/api/ioc/lookup/213.199.53.152",
    headers=headers
)

if response.status_code == 200:
    data = response.json()
    print(f"Risk Level: {data['risk_assessment']['risk_level']}")
elif response.status_code == 401:
    print("Invalid or missing API key")
elif response.status_code == 429:
    print("Rate limit exceeded")
else:
    print(f"Error: {response.status_code}")
Security Notes:
  • Never share your API key or commit it to version control
  • Store API keys in environment variables or secure configuration
  • Rotate API keys regularly
  • Revoke API keys immediately if compromised
API Key Management:
  • Generate New Key: Create multiple API keys for different applications
  • View Keys: See masked versions of your active keys
  • Revoke Key: Immediately invalidate a key if compromised
  • Unlimited Usage: No limits on API requests in Community Edition

IOC Lookup Endpoints

Single IOC Lookup

GET /api/ioc/lookup/{ioc}

Look up a single Indicator of Compromise (IOC) in the infrastructure database.

Parameters:
  • ioc (path parameter): The IOC to lookup (IP, domain, hash, etc.)
Example Requests:
cURL with API Key:
# Using X-API-Key header (recommended)
curl -H "X-API-Key: predict_your_api_key_here" \
     "https://predict.pyosec.com/api/ioc/lookup/213.199.53.152"

# Using Authorization Bearer header
curl -H "Authorization: Bearer predict_your_api_key_here" \
     "https://predict.pyosec.com/api/ioc/lookup/213.199.53.152"

# Domain lookup with API key
curl -H "X-API-Key: predict_your_api_key_here" \
     "https://predict.pyosec.com/api/ioc/lookup/jonkerdd.nl"

# IP with better formatting
curl -s -H "X-API-Key: predict_your_api_key_here" \
     "https://predict.pyosec.com/api/ioc/lookup/43.159.45.212" | jq '.risk_assessment'
Python with API Key:
import requests

# Set your API key
api_key = "predict_your_api_key_here"
headers = {"X-API-Key": api_key}

# Single IOC lookup
response = requests.get(
    'https://predict.pyosec.com/api/ioc/lookup/213.199.53.152',
    headers=headers
)

if response.status_code == 200:
    data = response.json()
    print(f"IOC: {data['ioc']}")
    if data['found']:
        risk = data['risk_assessment']
        print(f"Risk Level: {risk['risk_level']}")
        print(f"Risk Score: {risk['risk_score']}")
        print(f"Malware Families: {risk['malware_families']}")
    else:
        print("IOC not found in database")
elif response.status_code == 401:
    print("Invalid or missing API key")
elif response.status_code == 429:
    print("Rate limit exceeded")
else:
    print(f"Error: {response.status_code}")
Response:
{
  "ioc": "213.199.53.152",
  "normalized_ioc": "213.199.53.152",
  "ioc_type": "ip",
  "found": true,
  "total_matches": 1,
  "results": [
    {
      "date": "2025-09-12 20:03:01",
      "ioc_input": "213.199.53.152:4321",
      "ioc_type": "ip",
      "ip": "213.199.53.152",
      "as_owner": "Contabo GmbH",
      "label": "AdaptixC2",
      "country": "DE",
      "result": "malicious"
    }
  ],
  "risk_assessment": {
    "risk_level": "high",
    "risk_score": 95.0,
    "confidence": "medium",
    "reason": "1 malicious infrastructure matches",
    "malicious_matches": 1,
    "harmless_matches": 0,
    "malware_families": ["AdaptixC2"]
  },
  "timestamp": "2025-09-22T11:30:00Z"
}

Bulk IOC Lookup

POST /api/ioc/bulk

Look up multiple IOCs in a single request (max 100).

Request Body:
{
  "iocs": ["213.199.53.152", "example.com", "10.0.0.0/24"],
  "max_iocs": 100
}
Example Requests:
cURL with API Key:
# Bulk IOC lookup
curl -X POST "https://predict.pyosec.com/api/ioc/bulk" \
     -H "X-API-Key: predict_your_api_key_here" \
     -H "Content-Type: application/json" \
     -d '{
       "iocs": ["43.159.45.212", "jonkerdd.nl", "213.199.53.152"],
       "max_iocs": 100
     }'

# With jq formatting
curl -X POST "https://predict.pyosec.com/api/ioc/bulk" \
     -H "X-API-Key: predict_your_api_key_here" \
     -H "Content-Type: application/json" \
     -d '{"iocs": ["43.159.45.212", "jonkerdd.nl"]}' | jq '.summary'
Python with API Key:
import requests
import json

# Set your API key
api_key = "predict_your_api_key_here"
headers = {
    "X-API-Key": api_key,
    "Content-Type": "application/json"
}

# Bulk IOC lookup
bulk_data = {
    "iocs": ["43.159.45.212", "jonkerdd.nl", "213.199.53.152"],
    "max_iocs": 100
}

response = requests.post(
    'https://predict.pyosec.com/api/ioc/bulk',
    headers=headers,
    json=bulk_data
)

if response.status_code == 200:
    results = response.json()
    print(f"Total IOCs: {results['summary']['total_iocs']}")
    print(f"Found: {results['summary']['found_iocs']}")
    print(f"Malicious: {results['summary']['malicious_iocs']}")

    for result in results['results']:
        if result['found']:
            risk = result['risk_assessment']
            print(f"{result['ioc']}: {risk['risk_level']} ({risk['risk_score']})")
elif response.status_code == 401:
    print("Invalid or missing API key")
elif response.status_code == 429:
    print("Rate limit exceeded")
else:
    print(f"Error: {response.status_code}")
Response:
{
  "results": [
    {
      "ioc": "213.199.53.152",
      "normalized_ioc": "213.199.53.152",
      "ioc_type": "ip",
      "found": true,
      "total_matches": 1,
      "risk_assessment": { ... }
    }
  ],
  "summary": {
    "total_iocs": 3,
    "found_iocs": 1,
    "malicious_iocs": 1,
    "success_rate": "33.3%"
  },
  "timestamp": "2025-09-22T11:30:00Z"
}

IOC Database Statistics

GET /api/ioc/stats

Get overall statistics about the IOC database.

Related Infrastructure Analysis

GET /api/ioc/related/{ioc}

Find infrastructure related to the given IOC (same network, similar domains, etc.).

Example Requests:
cURL with API Key:
# Get related infrastructure
curl -H "X-API-Key: predict_your_api_key_here" \
     "https://predict.pyosec.com/api/ioc/related/43.159.45.212"

# Format risk summary
curl -s -H "X-API-Key: predict_your_api_key_here" \
     "https://predict.pyosec.com/api/ioc/related/43.159.45.212" | jq '.risk_summary'

# Get related domains
curl -H "X-API-Key: predict_your_api_key_here" \
     "https://predict.pyosec.com/api/ioc/related/jonkerdd.nl"
Python with API Key:
import requests

# Set your API key
api_key = "predict_your_api_key_here"
headers = {"X-API-Key": api_key}

# Get related infrastructure
response = requests.get(
    'https://predict.pyosec.com/api/ioc/related/43.159.45.212',
    headers=headers
)

if response.status_code == 200:
    data = response.json()
    close_rel = data['related_infrastructure']['close_relationships']
    print(f"Close relationships: {close_rel['count']}")

    for item in close_rel['items'][:3]:  # Show first 3
        print(f"  {item['ip']}: {item['result']} ({item['network_relationship']})")

    risk_summary = data['risk_summary']
    print(f"Risk Summary: {risk_summary['close_malicious']} close malicious")
elif response.status_code == 401:
    print("Invalid or missing API key")
elif response.status_code == 429:
    print("Rate limit exceeded")
else:
    print(f"Error: {response.status_code}")
Response:
{
  "ioc": "43.159.45.212",
  "ioc_type": "ip",
  "related_infrastructure": {
    "close_relationships": {
      "description": "Same subnet (/24) or direct domain relationships",
      "count": 3,
      "items": [
        {
          "ip": "43.159.45.210",
          "result": "malicious",
          "label": "AdaptixC2",
          "network_relationship": "same_subnet",
          "relationship_distance": 1
        }
      ]
    },
    "broader_relationships": {
      "description": "Same network (/16) or extended domain relationships",
      "count": 12,
      "items": [...]
    }
  },
  "risk_summary": {
    "close_malicious": 2,
    "broader_malicious": 5,
    "total_related": 15
  }
}

Analysis Endpoints

Infrastructure Summary

GET /api/analysis/summary

Get a summary of infrastructure analysis.

Search Infrastructure

GET /api/analysis/search?q={query}&type={type}

Search infrastructure by query string.

Parameters:
  • q: Search query
  • type (optional): Infrastructure type filter
Example Requests:
cURL with API Key:
# Search for specific IP
curl -H "X-API-Key: predict_your_api_key_here" \
     "https://predict.pyosec.com/api/analysis/search?q=43.159.45.212"

# Search ASNs containing "contabo"
curl -H "X-API-Key: predict_your_api_key_here" \
     "https://predict.pyosec.com/api/analysis/search?q=contabo&type=asns"

# Search domains
curl -H "X-API-Key: predict_your_api_key_here" \
     "https://predict.pyosec.com/api/analysis/search?q=jonkerdd.nl&type=domains"

# Format results
curl -s -H "X-API-Key: predict_your_api_key_here" \
     "https://predict.pyosec.com/api/analysis/search?q=contabo" | jq '.[].identifier'
Python with API Key:
import requests

# Set your API key
api_key = "predict_your_api_key_here"
headers = {"X-API-Key": api_key}

# Search infrastructure
params = {'q': 'contabo', 'type': 'asns'}
response = requests.get(
    'https://predict.pyosec.com/api/analysis/search',
    params=params,
    headers=headers
)

if response.status_code == 200:
    results = response.json()
    print(f"Found {len(results)} infrastructure items")

    for item in results[:5]:  # Show first 5
        print(f"{item['identifier']} ({item['type']}) - Risk: {item.get('risk_score', 'N/A')}")
elif response.status_code == 401:
    print("Invalid or missing API key")
elif response.status_code == 429:
    print("Rate limit exceeded")
else:
    print(f"Error: {response.status_code}")

PREDICT Matrix Data

GET /api/analysis/matrix

Get PREDICT framework matrix data for visualization.

Prediction Endpoints

Infrastructure Prediction

GET /api/predictions/infrastructure/{type}/{identifier}

Get reuse probability prediction for specific infrastructure.

Batch Predictions

POST /api/predictions/batch

Get predictions for multiple infrastructure items.

Code Examples

Complete Python Example

import requests
import json

# Configure your API key
API_KEY = "predict_your_api_key_here"
BASE_URL = "https://predict.pyosec.com"

# Headers with API key
headers = {
    "X-API-Key": API_KEY,
    "Content-Type": "application/json"
}

# Single IOC lookup
response = requests.get(
    f"{BASE_URL}/api/ioc/lookup/213.199.53.152",
    headers=headers
)

if response.status_code == 200:
    data = response.json()
    print(f"IOC: {data['ioc']}")
    print(f"Risk Level: {data['risk_assessment']['risk_level']}")
    print(f"Risk Score: {data['risk_assessment']['risk_score']}")
elif response.status_code == 401:
    print("Error: Invalid API key")
elif response.status_code == 429:
    print("Error: Rate limit exceeded")

# Bulk IOC lookup
bulk_data = {
    "iocs": ["213.199.53.152", "example.com", "10.0.0.0/24"]
}

response = requests.post(
    f"{BASE_URL}/api/ioc/bulk",
    headers=headers,
    json=bulk_data
)

if response.status_code == 200:
    bulk_results = response.json()
    print(f"Success Rate: {bulk_results['summary']['success_rate']}")

Complete cURL Examples

# Set your API key as environment variable (recommended)
export PREDICT_API_KEY="predict_your_api_key_here"

# Single IOC lookup
curl -H "X-API-Key: $PREDICT_API_KEY" \
     "https://predict.pyosec.com/api/ioc/lookup/213.199.53.152"

# Bulk IOC lookup
curl -X POST "https://predict.pyosec.com/api/ioc/bulk" \
  -H "X-API-Key: $PREDICT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"iocs": ["213.199.53.152", "example.com"]}'

# Search infrastructure
curl -H "X-API-Key: $PREDICT_API_KEY" \
     "https://predict.pyosec.com/api/analysis/search?q=contabo&type=asns"

# Get IOC statistics
curl -H "X-API-Key: $PREDICT_API_KEY" \
     "https://predict.pyosec.com/api/ioc/stats"

Rate Limits & Usage

PREDICT Community Edition - Unlimited Access:
Feature Limit Notes
Web Interface Requests Unlimited No restrictions on web-based queries
API Requests Unlimited Programmatic access with no daily limits
Bulk IOC Lookup 100 IOCs per request Technical limit for optimal performance
API Keys Unlimited Create as many keys as needed
Price Free Open-source community edition
Important Notes:
  • No Subscription Required: This is the Community Edition - all features are free and unlimited
  • Fair Use: Please use the API responsibly to ensure good performance for all users
  • Bulk Limits: The 100 IOC limit per bulk request is for performance optimization, not usage restriction
  • Open Source: This is an open-source project available on GitHub
Monitoring Your Usage:

Track your API usage for informational purposes:

  • Visit your Account Settings page
  • View the "Usage Statistics" section
  • See separate tracking for web and API requests
  • Monitor your total usage (informational only, no limits)
Best Practices:
  • Use Bulk Endpoints: Process multiple IOCs efficiently in a single request (up to 100)
  • Cache Results: Store and reuse results when appropriate to reduce redundant queries
  • Handle Errors: Implement proper error handling for network issues and server errors
  • Monitor Performance: Track your usage statistics in the account dashboard
  • Responsible Use: Use the API efficiently to ensure good performance for all community users
Error Handling:

The API returns standard HTTP status codes:

200 Success
400 Bad Request - Invalid parameters
401 Unauthorized - Missing or invalid API key
403 Forbidden - Insufficient permissions
404 Not Found - Resource doesn't exist
429 Too Many Requests - Server is temporarily overloaded, retry after a short delay
500 Internal Server Error
Error Response Example:
{
  "error": "Error message",
  "ioc": "requested_ioc",
  "timestamp": "2025-01-28T12:00:00Z"
}