Documentation
IP Intelligence
Look up any public IP address for geographic location, ASN, reverse DNS, abuse contacts, and threat intelligence.
Authentication
All requests require an API key passed via the X-API-Key header:
X-API-Key: your-api-key-here
Rate Limiting
Requests are rate-limited per API key using a sliding window. Every response includes rate limit headers:
| Header | Description |
|---|---|
X-RateLimit-Limit | Maximum requests per minute for your plan |
X-RateLimit-Remaining | Requests remaining in the current window |
Retry-After | Seconds to wait before retrying (only on 429) |
| Plan | Rate Limit | Max IPs / Request |
|---|---|---|
| Free | 5 req/min | 1 |
| Basic | 30 req/min | 5 |
| Pro | 120 req/min | 20 |
IP Intelligence
Submit one or more IP addresses for concurrent intelligence gathering. Core lookups (geo, ASN, reverse DNS, abuse contact) are available on all plans. Threat intelligence requires a Pro plan.
Request Body
| Field | Type | Plan | Description |
|---|---|---|---|
ips | string[] | All | Array of IPv4 or IPv6 addresses to look up (required) |
threat_intel | bool | Pro | Query VirusTotal, URLhaus, and AlienVault OTX for threat data |
Input Validation
IP addresses are validated and canonicalized using Go's netip.ParseAddr. The following are rejected with a 400 response:
- Invalid IP addresses
- Private/RFC 1918 addresses (10.x, 172.16-31.x, 192.168.x)
- Loopback (127.0.0.1, ::1)
- Link-local (169.254.x, fe80::)
- Multicast, unspecified, and CGNAT (100.64.0.0/10)
Example
curl -X POST https://api.securityaccelerated.com/v1/ip/lookup \
-H 'Content-Type: application/json' \
-H 'X-API-Key: your-api-key' \
-H 'X-Client-Request-ID: req-001' \
-d '{
"ips": ["8.8.8.8", "1.1.1.1"],
"threat_intel": true
}'
import requests
resp = requests.post(
"https://api.securityaccelerated.com/v1/ip/lookup",
headers={
"X-API-Key": "your-api-key",
"X-Client-Request-ID": "req-001",
},
json={"ips": ["8.8.8.8"]},
)
if resp.status_code != 200:
print("Error:", resp.json()["error"])
else:
results = resp.json()
for r in results:
print(r["ip"], r["geo"]["country"], r["asn"]["organization"])
package main
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
)
func main() {
body, _ := json.Marshal(map[string]any{
"ips": []string{"8.8.8.8"},
})
req, _ := http.NewRequest("POST",
"https://api.securityaccelerated.com/v1/ip/lookup",
bytes.NewReader(body))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("X-API-Key", "your-api-key")
req.Header.Set("X-Client-Request-ID", "req-001")
resp, err := http.DefaultClient.Do(req)
if err != nil { panic(err) }
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
var apiErr map[string]string
json.NewDecoder(resp.Body).Decode(&apiErr)
fmt.Println("Error:", apiErr["error"])
return
}
var results []map[string]any
json.NewDecoder(resp.Body).Decode(&results)
fmt.Println(results[0]["ip"], results[0]["geo"])
}
Response Fields
The response is always a JSON array, even for single-IP requests.
geo -- Geographic Location
Location data from MaxMind GeoLite2. Available on all plans.
| Field | Description |
|---|---|
continent / continent_code | Continent name and two-letter code |
country / country_code | Country name and ISO 3166-1 alpha-2 code |
region / region_code | First-level subdivision (state/province) |
city | City name |
postal_code | Postal/ZIP code |
latitude / longitude | Approximate coordinates |
timezone | IANA timezone (e.g. America/New_York) |
accuracy_radius | Accuracy radius in kilometers |
asn -- Autonomous System
Network ownership data from MaxMind GeoLite2 ASN. Available on all plans.
| Field | Description |
|---|---|
asn | Autonomous System Number |
organization | Organization that owns the ASN (e.g. "Google LLC") |
network | CIDR block for the network |
reverse_dns -- PTR Records
Reverse DNS lookup via PTR records. Available on all plans.
| Field | Description |
|---|---|
hostnames | Array of hostnames from PTR records (e.g. ["dns.google"]) |
abuse_contact -- Network Abuse Contact
Abuse contact information from RDAP (Registration Data Access Protocol). Available on all plans.
| Field | Description |
|---|---|
network | IP range (e.g. "8.8.8.0 - 8.8.8.255") |
organization | Network owner organization |
country | Country of the network registration |
email | Abuse contact email address |
threat_intel -- Threat Intelligence Pro
Aggregated threat intelligence from multiple providers. Requires a Pro plan.
| Field | Description |
|---|---|
risk_level | Aggregated risk: none, low, medium, high, critical |
score | Numeric score (0-100) |
categories | Detected categories (e.g. "malicious", "suspicious") |
providers | Per-provider results with individual scores and details |
Providers: VirusTotal (50% weight), URLhaus (30%), AlienVault OTX (20%).
errors -- Partial Failures
If individual lookups fail, they appear here. The rest of the response is still populated.
"errors": [
{ "lookup": "reverse_dns", "message": "ptr lookup: no such host" }
]
Full Response Example
[
{
"ip": "8.8.8.8",
"cache_hit": false,
"geo": {
"continent": "North America",
"continent_code": "NA",
"country": "United States",
"country_code": "US",
"region": "California",
"region_code": "CA",
"city": "Mountain View",
"latitude": 37.386,
"longitude": -122.0838,
"timezone": "America/Los_Angeles",
"accuracy_radius": 1000
},
"asn": {
"asn": 15169,
"organization": "GOOGLE"
},
"reverse_dns": {
"hostnames": ["dns.google"]
},
"abuse_contact": {
"network": "8.8.8.0 - 8.8.8.255",
"organization": "Google LLC",
"country": "US",
"email": "network-abuse@google.com"
},
"errors": []
}
]
Error Handling
| Status | Meaning |
|---|---|
400 Bad Request | Invalid request body, missing ips field, or non-routable IP address |
401 Unauthorized | Missing or invalid API key |
403 Forbidden | Your plan does not include this feature (e.g. threat_intel requires Pro) |
413 Content Too Large | Request body exceeds the 1 MB limit |
429 Too Many Requests | Rate limit exceeded -- check the Retry-After header |
500 Internal Server Error | Server error -- contact support@securityaccelerated.com |
All error responses use this format:
{
"error": "description of the problem"
}
200 OK with successful lookups populated and failures listed in the errors array.Caching
Results are cached for 60 minutes. The cache_hit field on each response indicates whether data was served from cache or fetched live.
Request Correlation
You can pass an optional X-Client-Request-ID header with your own correlation ID for end-to-end tracing. The API echoes it back in the response headers and includes it in server-side logs.
| Header | Direction | Description |
|---|---|---|
X-Client-Request-ID | Request | Your correlation ID (any string up to 128 chars) |
X-Client-Request-ID | Response | Echoed back unchanged |