Back to IOC Enrichment

Enrich Indicators

POST/api/v1/enrichment/lookup

Enrich up to 10 indicators of compromise per request against 14 threat intelligence providers. Each indicator costs 3 credits. Returns per-provider verdicts, aggregated scores, and a summary classification for each indicator.

Permission

enrichment:read

Credits

3 per indicator

Plans

All plans

Timeout

60 seconds

Supported Indicator Types

TypeExampleNotes
ip185.220.101.42IPv4 addresses
domainevil-domain.comDomain names without protocol
urlhttps://malware.example.com/payloadFull URLs (SSRF-protected)
hash44d88612fea8a8f36de82e1278abb02fMD5, SHA-1, or SHA-256
emailattacker@phishing.comEmail addresses

Request Body

{
  "indicators": [
    { "type": "ip", "value": "185.220.101.42" },
    { "type": "domain", "value": "evil-domain.com" },
    { "type": "hash", "value": "44d88612fea8a8f36de82e1278abb02f" }
  ]
}
FieldTypeRequiredDescription
indicatorsobject[]YesArray of 1–10 indicator objects to enrich
indicators[].typestringYesOne of "ip", "domain", "url", "hash", "email"
indicators[].valuestringYesThe indicator value. Max 2048 characters.

Response

{
  "data": {
    "results": [
      {
        "indicator": { "type": "ip", "value": "185.220.101.42" },
        "verdict": "malicious",
        "score": 85,
        "providers": {
          "virustotal": {
            "verdict": "malicious",
            "score": 90,
            "details": {
              "positives": 12,
              "total": 94,
              "as_owner": "Tor Exit Node"
            }
          },
          "abuseipdb": {
            "verdict": "suspicious",
            "score": 75,
            "details": {
              "total_reports": 342,
              "confidence_score": 75,
              "categories": ["SSH Brute-Force", "Port Scan"]
            }
          },
          "shodan": {
            "verdict": "suspicious",
            "score": 60,
            "details": {
              "ports": [22, 80, 443],
              "org": "Tor Network",
              "os": "Linux"
            }
          }
        },
        "enriched_at": "2026-03-24T12:34:56.789Z"
      },
      {
        "indicator": { "type": "domain", "value": "evil-domain.com" },
        "verdict": "suspicious",
        "score": 45,
        "providers": {
          "virustotal": {
            "verdict": "suspicious",
            "score": 45,
            "details": {
              "positives": 3,
              "total": 94
            }
          },
          "urlscan": {
            "verdict": "clean",
            "score": 10,
            "details": {
              "malicious": false,
              "categories": []
            }
          }
        },
        "enriched_at": "2026-03-24T12:34:57.123Z"
      },
      {
        "indicator": { "type": "hash", "value": "44d88612fea8a8f36de82e1278abb02f" },
        "verdict": "unknown",
        "score": 0,
        "providers": {},
        "enriched_at": "2026-03-24T12:34:57.456Z"
      }
    ],
    "summary": {
      "total": 3,
      "malicious": 1,
      "suspicious": 1,
      "clean": 0,
      "unknown": 1
    }
  },
  "meta": {
    "request_id": "req_abc123def456",
    "credits_used": 9,
    "credits_remaining": 91,
    "processing_time_ms": 3450
  }
}
FieldTypeDescription
data.resultsarrayArray of enrichment results, one per indicator submitted
data.results[].indicatorobjectThe original indicator (type and value) that was enriched
data.results[].verdictstring"malicious", "suspicious", "clean", or "unknown"
data.results[].scorenumberAggregated threat score from 0 (clean) to 100 (malicious)
data.results[].providersobjectPer-provider results keyed by provider name, each with verdict, score, and details
data.results[].enriched_atstringISO 8601 timestamp of when the enrichment was performed
data.summaryobjectCounts of indicators by verdict: total, malicious, suspicious, clean, unknown
meta.request_idstringUnique request identifier for support and debugging
meta.credits_usednumberCredits consumed by this request
meta.credits_remainingnumberRemaining credit balance after this request
meta.processing_time_msnumberServer-side processing time in milliseconds

Scoring & Verdicts

Each indicator is enriched against all applicable providers in parallel. The aggregated score is a weighted average of scores from providers that found the indicator. The verdict is derived from the score:

Score RangeVerdict
70 – 100malicious
30 – 69suspicious
0 – 29clean
No dataunknown

Individual provider failures are handled gracefully. If a provider times out or errors, the remaining providers still contribute to the verdict. The failed provider is omitted from the providers object.

Credit Pricing

IOC Enrichment is billed per indicator submitted in the request. Each indicator is enriched against up to 14 threat intelligence providers in parallel.

IndicatorsCostExample
1 indicator3 creditsSingle IP reputation check
3 indicators9 creditsIP + domain + hash from an incident
5 indicators15 creditsIOCs extracted from a phishing email
10 indicators30 creditsFull batch enrichment (max per request)

Credits are deducted before enrichment begins. If your balance is insufficient for the number of indicators submitted, the request returns 402 Insufficient Credits and no indicators are processed.

Phishing sub-tool pricing differs. When IOC enrichment is called as part of the Phishing Analysis workflow via /api/v1/phishing/enrich, the cost is 2 credits flat (regardless of indicator count) since it serves as a lightweight follow-up to email analysis.

Threat Intelligence Providers

Each indicator is queried against all providers that support its type. Not all providers support all indicator types — see the “Supported Types” column for which types each provider handles.

ProviderSupported TypesData Collected
VirusTotalip, domain, url, hashMulti-engine antivirus scan results, detection ratios, and community reputation
AbuseIPDBipCrowd-sourced IP abuse reports, confidence scoring, ISP and usage type classification
Shodanip, domainOpen ports, service banners, known CVEs, OS fingerprinting, and organization data
AlienVault OTXip, domain, url, hashCommunity threat intelligence pulses, tags, and indicator correlation
urlscan.ioip, domain, urlURL analysis with scan history, malicious verdicts, community tags, and contacted infrastructure
URLhausip, domain, url, hashMalware URL database — active/offline status, payload tracking, and threat type classification
ThreatFoxip, domain, url, hashIOC sharing platform — malware family association, threat types, and reporter context
MalwareBazaarhashMalware sample repository — file metadata, signature matches, and delivery method tracking
Hybrid Analysisip, domain, url, hashSandbox analysis results, behavioral indicators, and threat scoring
GreyNoiseipInternet noise classification — distinguishes mass scanners from targeted attacks, RIOT benign service detection
CensysipInternet-wide scan data for host discovery, certificate analysis, and service enumeration
Pulsediveip, domain, urlThreat intelligence aggregation with risk scoring, linked indicators, and feed correlation
OpenPhishurl, domainAutomated phishing URL detection — checks against known active phishing campaigns
IPVoid DNSBLipDNS-based blackhole list checks across multiple blocklist providers

Caching

Enrichment results are cached for 24 hours per indicator and source. Subsequent requests for the same indicator within the cache window return cached provider results without re-querying the upstream provider.

Cached results are still aggregated fresh on each request, so the verdict and score reflect the latest scoring logic. Credits are charged at 3 credits per indicator regardless of cache status.

Code Examples

cURL
curl -X POST https://api.dfir-lab.ch/v1/enrichment/lookup \
  -H "Authorization: Bearer sk-dfir-your-key-here" \
  -H "Content-Type: application/json" \
  -d '{
    "indicators": [
      { "type": "ip", "value": "185.220.101.42" },
      { "type": "domain", "value": "evil-domain.com" },
      { "type": "hash", "value": "44d88612fea8a8f36de82e1278abb02f" }
    ]
  }'
Python
import requests

response = requests.post(
    "https://api.dfir-lab.ch/v1/enrichment/lookup",
    headers={
        "Authorization": "Bearer sk-dfir-your-key-here",
        "Content-Type": "application/json",
    },
    json={
        "indicators": [
            {"type": "ip", "value": "185.220.101.42"},
            {"type": "domain", "value": "evil-domain.com"},
            {"type": "hash", "value": "44d88612fea8a8f36de82e1278abb02f"},
        ]
    },
)

data = response.json()
for result in data["data"]["results"]:
    ioc = result["indicator"]
    verdict = result["verdict"]
    score = result["score"]
    print(f"{ioc['type']}:{ioc['value']} -> {verdict} (score: {score})")

summary = data["data"]["summary"]
print(f"\nSummary: {summary['malicious']} malicious, "
      f"{summary['suspicious']} suspicious, {summary['clean']} clean")
TypeScript
const response = await fetch("https://api.dfir-lab.ch/v1/enrichment/lookup", {
  method: "POST",
  headers: {
    Authorization: "Bearer sk-dfir-your-key-here",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    indicators: [
      { type: "ip", value: "185.220.101.42" },
      { type: "domain", value: "evil-domain.com" },
      { type: "hash", value: "44d88612fea8a8f36de82e1278abb02f" },
    ],
  }),
});

const { data, meta } = await response.json();

for (const result of data.results) {
  console.log(
    `${result.indicator.type}:${result.indicator.value} -> ` +
    `${result.verdict} (score: ${result.score})`
  );
}

console.log(`Credits used: ${meta.credits_used}, remaining: ${meta.credits_remaining}`);

Important Notes

  • Maximum 10 indicators per request. For larger batches, split across multiple requests.
  • URL-type indicators have SSRF protection. URLs pointing to private or internal IP ranges (10.x.x.x, 192.168.x.x, 172.16-31.x.x, 127.0.0.1) are rejected with a 400 Bad Request.
  • Enrichment queries all applicable providers in parallel. Requests typically complete in 2–10 seconds depending on provider response times. The 60-second timeout covers worst-case scenarios.
  • Indicator values have a maximum length of 2048 characters.
  • The enrichment:read permission scope is required. API keys with phishing:read scope also have enrichment access automatically.