API Documentation
REST API for Infrastructure Analysis and IOC Lookup
Quick Navigation
Quick Links
Overview
The PREDICT Community Edition API provides programmatic access to malware infrastructure analysis and IOC lookup capabilities.
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
# 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"
- 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.
- Log in to your account
- Navigate to Account Settings
- Click "New Key" in the API Keys section
- 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}")
- 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 querytype(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"
}