API Integration Guide
Learn how to integrate Have I Been Squatted’s Enterprise API into your security workflows.
Authentication
Enterprise API access requires an API key. Contact us at hello@haveibeensquatted.com to get started.
Making Requests
We currently expose two endpoints:
https://api.haveibeensquatted.com/v1/squat
- Lookup a single domain for squattinghttps://api.haveibeensquatted.com/v1/nxdomain
- Lookup a single domain for unregistered domains (NXDOMAIN)
Request Format
curl -N https://api.haveibeensquatted.com/v1/squat/$domain \ -H "Authorization: Bearer YOUR_API_KEY"
Handling Streaming Responses
Our API uses HTTP/2 streaming to provide real-time results. Here are examples of how to handle the streamed JSON responses:
import httpximport json
async def lookup_domain(domain: str, api_key: str): async with httpx.AsyncClient() as client: url = f"https://api.haveibeensquatted.com/v1/squat/{domain}" headers = {"Authorization": f"Bearer {api_key}"}
async with client.stream("GET", url, headers=headers) as response: async for line in response.aiter_lines(): if line.strip(): result = json.loads(line) # Handle each result as it arrives if result["op"] == "Meta": print(f"Progress: {result['data']['data'][0]}/{result['data']['data'][1]}") elif result["op"] == "GeoIp": print(f"Found IP in {result['data']['country']['iso_code']}")
async function lookupDomain(domain, apiKey) { const response = await fetch(`https://api.haveibeensquatted.com/v1/squat/${domain}`, { method: 'GET', headers: { 'Authorization': `Bearer ${apiKey}`, }, });
const reader = response.body.getReader(); const decoder = new TextDecoder(); let buffer = '';
while (true) { const { done, value } = await reader.read(); if (done) break;
buffer += decoder.decode(value, { stream: true }); const lines = buffer.split('\n'); buffer = lines.pop() || '';
for (const line of lines) { if (line.trim()) { const result = JSON.parse(line); // Handle each result as it arrives if (result.op === 'Meta') { console.log(`Progress: ${result.data.data[0]}/${result.data.data[1]}`); } } } }}
package main
import ( "bufio" "encoding/json" "fmt" "net/http")
func lookupDomain(domain, apiKey string) error { url := fmt.Sprintf("https://api.haveibeensquatted.com/v1/squat/%s", domain) req, err := http.NewRequest("GET", url, nil) if err != nil { return err }
req.Header.Add("Authorization", "Bearer "+apiKey)
resp, err := http.DefaultClient.Do(req) if err != nil { return err } defer resp.Body.Close()
scanner := bufio.NewScanner(resp.Body) for scanner.Scan() { line := scanner.Text() if line == "" { continue }
var result map[string]interface{} if err := json.Unmarshal([]byte(line), &result); err != nil { return err }
// Handle each result as it arrives if result["op"] == "Meta" { data := result["data"].(map[string]interface{}) progress := data["data"].([]interface{}) fmt.Printf("Progress: %v/%v\n", progress[0], progress[1]) } }
return scanner.Err()}
Processing Results
Here are some examples of processing the JSON output using jq:
# Find domains hosted on specific ASNsjq '.[] | select(.ips[].asn.number == 16509)' results.json
# List domains with suspicious hosting locationsjq '.[] | select(.ips[].country.iso_code != "US")' results.json
# Extract all unique ASNsjq '.[] | .ips[].asn.organization' results.json | sort | uniq
For the complete JSON schema reference, see our JSON Schema Documentation.