API Documentation

Authentication

All write endpoints require an API key in the request header:

X-API-Key: your-api-key

If the key is missing or invalid, the API returns 401 Unauthorized.

POST /api/iocs

Submit a single IOC (Indicator of Compromise). Send one JSON object per request. IOCs are upserted by indicator + type + source (your API key): repeated submissions update the same row (last seen, hit count). Comments are stored in a history table (at most one per day per source).

Required fields:

  • indicator — the IOC value (e.g. IP, URL, hash, hostname)
  • type — one of: ip, url, hash, host
  • tag — tag/category

Optional:

  • comment — string, max 255 characters (stored in comment history; at most one per calendar day per source)
  • timestamp — client-submitted datetime; stored for reference only. Server uses its own time for first_seen/last_seen.

Response:

  • status, inserted (0 or 1), updated (0 or 1)

Example:

{
  "indicator": "192.0.2.1",
  "type": "ip",
  "tag": "malware",
  "comment": "Observed in campaign XYZ"
}

curl:

curl -X POST "https://ctidao.com/api/iocs" \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"indicator":"192.0.2.1","type":"ip","tag":"malware","comment":"Observed in campaign XYZ"}'

GET /api/blocklist

Export IOCs as a blocklist (plain text, one indicator per line, or JSON). No API key required. Only IOCs with last_seen within the given time window are included (TTL-style).

Query parameters (all optional):

  • type — filter by IOC type (e.g. ip)
  • tag — filter by tag
  • hours or ttl — time window in hours (default: 24); only rows with last_seen ≥ now − hours
  • formattext (default) or json

Examples:

curl "https://ctidao.com/api/blocklist?type=ip&hours=24"
curl "https://ctidao.com/api/blocklist?type=ip&tag=malware&hours=48&format=json"

POST /api/pdns

Submit one or more passive DNS records. Send a single object or an array. You supply host, ip, record, and timestamp; the system sets first seen, last seen, and hit count (new record: firstseen = lastseen = timestamp, hits = 1; existing host+ip: lastseen = timestamp, hits incremented).

Required fields:

  • host — hostname
  • ip — IP address

Optional (with defaults):

  • record — record type (default: A; only A is supported for now)
  • timestamp — datetime string (default: current server time)

Example:

{
  "host": "sub.example.com",
  "ip": "203.0.113.10",
  "record": "A",
  "timestamp": "2026-02-22 12:00:00"
}

curl:

curl -X POST "https://ctidao.com/api/pdns" \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"host":"sub.example.com","ip":"203.0.113.10","record":"A","timestamp":"2026-02-22 12:00:00"}'