{
  "openapi": "3.0.1",
  "info": {
    "title": "WHOIS Lookup, DNS Records Scraper - DMARC, SPF, DKIM Checker",
    "description": "Bulk domain lookup in one run: WHOIS and RDAP registrar with registration and expiry dates, DNS records including A, AAAA, MX, NS, TXT, CAA, and the SSL certificate issuer with days until expiry. Email security reads SPF, DKIM and DMARC. 1200 zones over RDAP plus 238 more over WHOIS port 43.",
    "version": "0.1",
    "x-build-id": "as2c20cgkHhYqqj8n"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/snow_leo_data~whois-dns-lookup/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-snow_leo_data-whois-dns-lookup",
        "x-openai-isConsequential": false,
        "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
        "tags": [
          "Run Actor"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/inputSchema"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Enter your Apify token here"
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/acts/snow_leo_data~whois-dns-lookup/runs": {
      "post": {
        "operationId": "runs-sync-snow_leo_data-whois-dns-lookup",
        "x-openai-isConsequential": false,
        "summary": "Executes an Actor and returns information about the initiated run in response.",
        "tags": [
          "Run Actor"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/inputSchema"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Enter your Apify token here"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/runsResponseSchema"
                }
              }
            }
          }
        }
      }
    },
    "/acts/snow_leo_data~whois-dns-lookup/run-sync": {
      "post": {
        "operationId": "run-sync-snow_leo_data-whois-dns-lookup",
        "x-openai-isConsequential": false,
        "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
        "tags": [
          "Run Actor"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/inputSchema"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Enter your Apify token here"
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "inputSchema": {
        "type": "object",
        "properties": {
          "domains": {
            "title": "🌐 Domains",
            "type": "array",
            "description": "One domain per line. URLs and email addresses are accepted and cleaned automatically: https://www.example.co.uk/pricing and sales@example.co.uk both become example.co.uk. Duplicates are removed before anything is charged.",
            "items": {
              "type": "string"
            }
          },
          "maxItems": {
            "title": "Maximum domains",
            "minimum": 0,
            "type": "integer",
            "description": "Hard stop on how many domains are checked. 0 means every domain in the list. Leaving the list empty runs a 10-domain sample instead of a full job.",
            "default": 0
          },
          "includeRegistration": {
            "title": "Registration data (RDAP + WHOIS)",
            "type": "boolean",
            "description": "Registrar, creation and expiry dates, registry status codes, transfer lock and registry nameservers. RDAP covers 1200 TLDs; the other 238 in the IANA root (.de, .io, .co, .ch, .it, .eu, .ru, .jp, .cn, .se, .es, .kz and more) fall back to WHOIS on port 43. Registrant names, emails, phones and addresses are never collected.",
            "default": true
          },
          "includeDkim": {
            "title": "Probe DKIM selectors",
            "type": "boolean",
            "description": "DKIM selector names cannot be listed from DNS — only guessed. Measured on Tranco top-120: probing 35 selectors found a key for 53 domains (44%). Zones that answer every name with a wildcard are detected and reported instead of producing dozens of fake selectors.",
            "default": true
          },
          "dkimSelectorSet": {
            "title": "Selector list",
            "enum": [
              "common",
              "full"
            ],
            "type": "string",
            "description": "Common = 15 selectors that produced almost all hits in the measurement. Full = 46 selectors, roughly three times slower for a few percent more.",
            "default": "common"
          },
          "dkimSelectors": {
            "title": "Your own selectors",
            "type": "array",
            "description": "Overrides the list above. Use this when you already know the selector, for example from a signed message header.",
            "default": [],
            "items": {
              "type": "string"
            }
          },
          "includeDnssec": {
            "title": "DNSSEC check",
            "type": "boolean",
            "description": "Looks for a DS delegation at the parent as well as the resolver's authenticated-data flag. The flag alone only says the resolver validated something, not that the zone is signed.",
            "default": true
          },
          "includeTlsCertificate": {
            "title": "TLS certificate",
            "type": "boolean",
            "description": "Opens a TLS handshake on port 443 and reads the certificate: issuer, validity window, days left and how many SANs it covers. A certificate that exists but fails validation (expired, self-signed, issued for another name) is reported as a finding, not as missing data.",
            "default": true
          },
          "includeReverseDns": {
            "title": "Reverse DNS (PTR)",
            "type": "boolean",
            "description": "PTR records for up to 4 IPv4 addresses of the domain. Shows whose hardware the site sits on; on shared hosting hundreds of domains return the same name. Off by default because it costs an extra query per address.",
            "default": false
          },
          "requestTimeoutSecs": {
            "title": "Timeout per request",
            "minimum": 3,
            "maximum": 60,
            "type": "integer",
            "description": "Seconds to wait for one DNS, WHOIS or TLS request before giving up on it. The run continues; the field it would have filled stays empty.",
            "default": 8
          },
          "onlyChanged": {
            "title": "🔁 Monitor mode — only what changed since the last run",
            "type": "boolean",
            "description": "Remembers 20 fields per domain in a named key-value store and returns only domains where one of them moved: new MX, weakened DMARC, changed nameservers, a new registrar, a closer expiry date. Every row carries change_type (NEW / UPDATED / UNCHANGED) and changed_fields. Unchanged domains are not written, so you are not charged for them twice.",
            "default": false
          },
          "emitUnchanged": {
            "title": "Include unchanged domains too",
            "type": "boolean",
            "description": "Writes UNCHANGED rows as well. Off by default because you would pay for the same data on every run.",
            "default": false
          },
          "watchAddressRecords": {
            "title": "Also treat changed A/AAAA records as a change",
            "type": "boolean",
            "description": "Off by default, and that is a measurement, not a guess: four snapshots ten seconds apart of the ten prefill domains showed a different address set for three of them (apify.com on AAAA, stripe.com and vercel.com on A), while MX, NS, TXT and CAA did not move for a single domain out of the Tranco top 100. Address rotation is load balancing, not a zone edit, and watching it makes you pay for CDN-backed domains every single run.",
            "default": false
          },
          "onlyWithFindings": {
            "title": "Only domains with at least one finding",
            "type": "boolean",
            "description": "All filters here run before rows are written, so filtered-out domains are never charged.",
            "default": false
          },
          "maxPostureScore": {
            "title": "Maximum posture score",
            "minimum": 0,
            "maximum": 100,
            "type": "integer",
            "description": "Keep only domains scoring at or below this. 0 turns the filter off. The score starts at 100 and every finding subtracts its published weight; the full table is in the README.",
            "default": 0
          },
          "minSeverity": {
            "title": "Minimum severity",
            "enum": [
              "any",
              "low",
              "medium",
              "high",
              "critical"
            ],
            "type": "string",
            "description": "Keep only domains whose worst finding is at least this severe.",
            "default": "any"
          },
          "findingCodes": {
            "title": "Only these findings",
            "type": "array",
            "description": "Keep only domains carrying one of the chosen findings. Choosing a registration or DKIM finding switches the matching section on automatically, so the filter cannot silently return nothing.",
            "items": {
              "type": "string",
              "enum": [
                "spf-missing",
                "spf-lookup-limit",
                "spf-multiple-records",
                "spf-all-pass",
                "spf-all-neutral",
                "spf-all-softfail",
                "spf-include-broken",
                "dmarc-missing",
                "dmarc-policy-none",
                "dmarc-policy-quarantine",
                "dmarc-partial-pct",
                "dmarc-no-reports",
                "dkim-none-found",
                "dnssec-unsigned",
                "mta-sts-missing",
                "mta-sts-no-policy",
                "mta-sts-testing",
                "caa-missing",
                "mx-missing",
                "expiry-soon",
                "expiry-past",
                "transfer-unlocked",
                "nameserver-mismatch",
                "tls-expiry-soon",
                "tls-invalid"
              ],
              "enumTitles": [
                "SPF missing",
                "SPF over the 10-lookup limit",
                "More than one SPF record",
                "SPF ends in +all",
                "SPF ends in ?all",
                "SPF ends in ~all",
                "SPF include with no record",
                "DMARC missing",
                "DMARC p=none",
                "DMARC p=quarantine",
                "DMARC pct below 100",
                "DMARC with no reports",
                "No DKIM key found",
                "Zone not signed (DNSSEC)",
                "No MTA-STS",
                "MTA-STS announced but policy does not load",
                "MTA-STS in testing mode",
                "No CAA record",
                "No MX record",
                "Expires within 30 days",
                "Expiry date already passed",
                "No transfer lock",
                "Nameserver mismatch",
                "TLS certificate expires within 14 days",
                "TLS certificate does not validate"
              ]
            },
            "default": []
          },
          "onlySpoofable": {
            "title": "Only spoofable domains",
            "type": "boolean",
            "description": "A domain counts as spoofable when DMARC does not enforce: no record, p=none, or a policy applied to less than 100% of mail. SPF alone does not stop From: spoofing.",
            "default": false
          },
          "expiringWithinDays": {
            "title": "Expiring within N days",
            "minimum": 0,
            "type": "integer",
            "description": "Keep only registrations expiring inside this window. 0 turns it off. Domains whose expiry date is genuinely unknown are kept and counted separately in the run report — dropping them would claim they are safe.",
            "default": 0
          },
          "onlyResolved": {
            "title": "Only domains that resolve",
            "type": "boolean",
            "description": "Drops names that answer NXDOMAIN and have no MX, NS or TXT records.",
            "default": false
          },
          "compactOutput": {
            "title": "Compact output",
            "type": "boolean",
            "description": "22 decision fields instead of 60. Built for AI agents and spreadsheets that choke on wide rows.",
            "default": false
          },
          "excludeEmptyFields": {
            "title": "Drop empty fields",
            "type": "boolean",
            "description": "Removes null and empty values from each row. Smaller JSON, but columns appear and disappear between rows.",
            "default": false
          }
        }
      },
      "runsResponseSchema": {
        "type": "object",
        "properties": {
          "data": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "actId": {
                "type": "string"
              },
              "userId": {
                "type": "string"
              },
              "startedAt": {
                "type": "string",
                "format": "date-time",
                "example": "2025-01-08T00:00:00.000Z"
              },
              "finishedAt": {
                "type": "string",
                "format": "date-time",
                "example": "2025-01-08T00:00:00.000Z"
              },
              "status": {
                "type": "string",
                "example": "READY"
              },
              "meta": {
                "type": "object",
                "properties": {
                  "origin": {
                    "type": "string",
                    "example": "API"
                  },
                  "userAgent": {
                    "type": "string"
                  }
                }
              },
              "stats": {
                "type": "object",
                "properties": {
                  "inputBodyLen": {
                    "type": "integer",
                    "example": 2000
                  },
                  "rebootCount": {
                    "type": "integer",
                    "example": 0
                  },
                  "restartCount": {
                    "type": "integer",
                    "example": 0
                  },
                  "resurrectCount": {
                    "type": "integer",
                    "example": 0
                  },
                  "computeUnits": {
                    "type": "integer",
                    "example": 0
                  }
                }
              },
              "options": {
                "type": "object",
                "properties": {
                  "build": {
                    "type": "string",
                    "example": "latest"
                  },
                  "timeoutSecs": {
                    "type": "integer",
                    "example": 300
                  },
                  "memoryMbytes": {
                    "type": "integer",
                    "example": 1024
                  },
                  "diskMbytes": {
                    "type": "integer",
                    "example": 2048
                  }
                }
              },
              "buildId": {
                "type": "string"
              },
              "defaultKeyValueStoreId": {
                "type": "string"
              },
              "defaultDatasetId": {
                "type": "string"
              },
              "defaultRequestQueueId": {
                "type": "string"
              },
              "buildNumber": {
                "type": "string",
                "example": "1.0.0"
              },
              "containerUrl": {
                "type": "string"
              },
              "usage": {
                "type": "object",
                "properties": {
                  "ACTOR_COMPUTE_UNITS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_WRITES": {
                    "type": "integer",
                    "example": 1
                  },
                  "KEY_VALUE_STORE_LISTS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_INTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_EXTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_SERPS": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_UNBLOCKER_UNITS": {
                    "type": "integer",
                    "example": 0
                  }
                }
              },
              "usageTotalUsd": {
                "type": "number",
                "example": 0.00005
              },
              "usageUsd": {
                "type": "object",
                "properties": {
                  "ACTOR_COMPUTE_UNITS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_WRITES": {
                    "type": "number",
                    "example": 0.00005
                  },
                  "KEY_VALUE_STORE_LISTS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_INTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_EXTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_SERPS": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_UNBLOCKER_UNITS": {
                    "type": "integer",
                    "example": 0
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}