Introduction
In most acquisitions, the domain portfolio is listed as a line item: the company owns the brand, the websites, and the customer login domain. In practice, domain assets drift. Marketing buys ccTLDs through agencies. Engineers register product domains on personal accounts. A registrar transfer happens during a rebrand. A renewal date quietly moves into the first 90 days after close.
The failure mode is predictable: a post-close outage, a legal scramble over who controls the registrar account, or a domain that cannot be consolidated because an unexpected EPP lock blocks transfer. A focused, API-backed domain due diligence pass can be done in under an hour and produces timestamped evidence legal and technical teams can attach to the deal record.
This article is the deep dive for use case 6 in the WHOIS API use cases guide. It is not a general domain inventory tutorial and not a long-term monitoring playbook.
What Is M&A Domain Due Diligence?
M&A domain due diligence is a structured review of a target's externally visible domain signals before signing: registrar, registrant context when available, expiration dates, EPP status codes, nameserver delegation, and — for customer-facing domains — SSL certificate health.
WhoisJSON supplies the lookup layer through documented REST endpoints. Your diligence system stores the normalized output with a timestamp so legal, IT, and integration teams can triage blockers before Day 0.
Why Pre-Close Domain Audits Fail Without API Evidence
Deal teams often rely on a domain list from the seller, a registrar export, or screenshots from a WHOIS website. Those sources are slow to reconcile, hard to timestamp, and easy to misread across TLDs. An API workflow makes the audit reproducible: the same domain list produces the same JSON structure every time the check is rerun.
Ownership drift
Domains registered to employees, agencies, or former subsidiaries block clean registrar consolidation after close.
Transfer blockers
Unexpected EPP locks and holds can delay registrar moves when you need them most. See the EPP status codes reference.
Renewal cliffs
Expiry inside the integration window creates outage risk during the most fragile operating period. See domain expiry lifecycle detection.
DNS control mismatch
WHOIS/RDAP nameservers that do not match live NS records suggest the zone is controlled elsewhere than expected.
Red Flags to Track Before Signing
A useful diligence pass focuses on issues that can block transfers, break continuity, or create immediate operational risk — not on generic security posture scoring.
| Red flag | Endpoint | Fields to read | Why it matters |
|---|---|---|---|
| Registrant org does not match target entity | /whois | contacts, registrar | Ownership disputes delay transfers and renewals. |
| Expiration inside 90–180 days post-close | /whois | expires, expiration.daysLeft | Renewals during integration are a common outage source. |
| Unexpected transfer lock or hold | /whois | status, statusAnalysis | Locks can block registrar consolidation or emergency response. |
| WHOIS nameservers ≠ live DNS delegation | /whois + /nslookup | nameserver, NS, nsAnalysis | The zone may be controlled by an unknown DNS provider. |
| Customer-facing domain with invalid or near-expiry SSL | /ssl-cert-check | valid, valid_to, issuer | Certificate incidents become revenue and trust incidents. |
Which WhoisJSON Endpoints to Use
The workflow below uses only documented endpoints from the WhoisJSON OpenAPI specification. Authenticate every request with Authorization: TOKEN=YOUR_API_KEY and use the production base URL https://whoisjson.com/api/v1.
| Diligence signal | Endpoint | Fields to read | Use |
|---|---|---|---|
| Registrar and ownership context | /whois | registrar, contacts, created | Confirm administrative control and entity alignment. |
| Expiry and transfer readiness | /whois | expires, expiration, status, statusAnalysis | Flag renewal cliffs and transfer blockers. |
| Live DNS delegation | /nslookup | NS, SOA | Compare against WHOIS nameservers and expected provider. |
| Production HTTPS posture | /ssl-cert-check | valid, valid_to, issuer, details | Check login, app, and customer-facing endpoints only. |
For field-level semantics, see the WHOIS API JSON response reference. For registrar-specific workflows, see the registrar lookup API guide.
Pre-Close Workflow in Four Steps
Treat diligence like evidence collection, not like security scanning. Each step produces fields you can attach to the deal record.
Step 1 — Collect the domain list
Start from the seller's asset schedule, public product links, OAuth callback domains, support email domains, ccTLDs, redirect domains, and any domain referenced in contracts or marketing materials. If the list is large, use the a(href="/blog/bulk-whois-api-multiple-domains") bulk WHOIS lookup guide | to pace parallel requests within your plan.
Step 2 — Query WHOIS/RDAP for every domain
Capture registrar, created and expires dates, EPP status, nameserver fields, and registrant organization when visible. Compare registrant organization against the target legal entity name. Flag domains expiring inside your integration window using code expiration.daysLeft | when available.
Step 3 — Confirm DNS delegation
Query /nslookup and compare NS against WHOIS/RDAP nameservers. A mismatch does not always mean fraud, but it should be documented before close. For ongoing delegation monitoring after close, see nameserver monitoring.
Step 4 — Check SSL on customer-facing domains only
Use /ssl-cert-check for login, app, API, and marketing domains where a certificate incident would be visible to users. Skip parked or redirect-only names unless they terminate HTTPS.
Example Diligence Report Schema
Legal teams need a list of issues. Technical teams need evidence. Store raw responses if required, but normalize each domain into one row you can sort, filter, and export.
{
"domain": "example.com",
"checked_at": "2026-07-09T09:00:00Z",
"registrar": "Example Registrar, Inc.",
"created": "2014-03-21 00:00:00",
"expires": "2026-09-02 00:00:00",
"days_left": 55,
"epp_status": ["clientTransferProhibited"],
"risk": {
"level": "medium",
"reasons": [
"expires_in_integration_window",
"transfer_lock_present"
]
},
"delegation": {
"dns_ns": ["ns1.dns-provider.com", "ns2.dns-provider.com"],
"whois_ns": ["ns1.dns-provider.com", "ns2.dns-provider.com"],
"matches": true
},
"ssl": {
"checked": true,
"valid": true,
"issuer": "DigiCert Inc",
"valid_to": "2026-12-10T23:59:59.000Z"
}
}Add an internal code criticality | field from your deal team — SSO, email, production web, redirect only — so renewal and SSL findings are prioritized correctly.
Basic Requests
A minimum viable diligence pass usually starts with two calls per domain. Add SSL only where user-facing HTTPS matters.
curl "https://whoisjson.com/api/v1/whois?domain=example.com" \
-H "Authorization: TOKEN=YOUR_API_KEY"curl "https://whoisjson.com/api/v1/nslookup?domain=example.com" \
-H "Authorization: TOKEN=YOUR_API_KEY"curl "https://whoisjson.com/api/v1/ssl-cert-check?domain=example.com" \
-H "Authorization: TOKEN=YOUR_API_KEY"
Python Example: Audit a Domain List Before Close
This example reads a target domain list, fetches WHOIS and DNS evidence for every name, optionally checks SSL for customer-facing domains, and returns normalized diligence rows. In production, persist results and add retry/backoff for 429 responses.
import json
import requests
from datetime import datetime, timezone
API_KEY = "YOUR_API_KEY"
BASE_URL = "https://whoisjson.com/api/v1"
HEADERS = {"Authorization": f"TOKEN={API_KEY}"}
def get_json(path, domain):
response = requests.get(
f"{BASE_URL}/{path}",
headers=HEADERS,
params={"domain": domain},
timeout=20,
)
response.raise_for_status()
return response.json()
def normalize_domain(domain, ssl_check=False, integration_window_days=90):
whois = get_json("whois", domain)
dns = get_json("nslookup", domain)
registrar = (whois.get("registrar") or {}).get("name")
expiration = whois.get("expiration") or {}
days_left = expiration.get("daysLeft")
status = whois.get("status") or []
dns_ns = dns.get("NS") or []
whois_ns = whois.get("nameserver") or []
ns_matches = sorted([x.lower() for x in dns_ns]) == sorted([x.lower() for x in whois_ns])
reasons = []
if days_left is not None and days_left <= integration_window_days:
reasons.append("expires_in_integration_window")
if any("transferprohibited" in s.lower() for s in status):
reasons.append("transfer_lock_present")
if dns_ns and whois_ns and not ns_matches:
reasons.append("whois_dns_delegation_mismatch")
level = "low"
if "whois_dns_delegation_mismatch" in reasons:
level = "high"
elif reasons:
level = "medium"
row = {
"domain": domain,
"checked_at": datetime.now(timezone.utc).isoformat(),
"registrar": registrar,
"created": whois.get("created"),
"expires": whois.get("expires"),
"days_left": days_left,
"epp_status": status,
"risk": {"level": level, "reasons": reasons},
"delegation": {
"dns_ns": dns_ns,
"whois_ns": whois_ns,
"matches": ns_matches,
},
"ssl": {"checked": False},
}
if ssl_check:
ssl = get_json("ssl-cert-check", domain)
issuer = ssl.get("issuer") or {}
row["ssl"] = {
"checked": True,
"valid": ssl.get("valid"),
"issuer": issuer.get("O") or issuer.get("CN"),
"valid_to": ssl.get("valid_to"),
}
return row
domains = ["example.com", "example.org"]
report = [normalize_domain(d, ssl_check=True) for d in domains]
print(json.dumps(report, indent=2))Every response includes the Remaining-Requests header. For larger target portfolios, use the rate limits and retries guide.
Node.js Example: Export a Due Diligence JSON Report
The same normalization pattern works in Node.js when your diligence tooling already runs in JavaScript.
const API_KEY = "YOUR_API_KEY";
const BASE_URL = "https://whoisjson.com/api/v1";
async function getJson(path, domain) {
const url = new URL(`${BASE_URL}/${path}`);
url.searchParams.set("domain", domain);
const response = await fetch(url, {
headers: { Authorization: `TOKEN=${API_KEY}` },
});
if (!response.ok) {
throw new Error(`${path} failed with ${response.status}`);
}
return response.json();
}
function sorted(values) {
return [...new Set((values || []).map((v) => String(v).toLowerCase()))].sort();
}
async function auditDomain(domain, { sslCheck = false } = {}) {
const whois = await getJson("whois", domain);
const dns = await getJson("nslookup", domain);
const status = whois.status || [];
const dnsNs = dns.NS || [];
const whoisNs = whois.nameserver || [];
const nsMatches = JSON.stringify(sorted(dnsNs)) === JSON.stringify(sorted(whoisNs));
const reasons = [];
if ((whois.expiration?.daysLeft ?? 999) <= 90) {
reasons.push("expires_in_integration_window");
}
if (status.some((s) => String(s).toLowerCase().includes("transferprohibited"))) {
reasons.push("transfer_lock_present");
}
if (dnsNs.length && whoisNs.length && !nsMatches) {
reasons.push("whois_dns_delegation_mismatch");
}
const row = {
domain,
checked_at: new Date().toISOString(),
registrar: whois?.registrar?.name || null,
expires: whois?.expires || null,
days_left: whois?.expiration?.daysLeft ?? null,
epp_status: status,
delegation: { dns_ns: dnsNs, whois_ns: whoisNs, matches: nsMatches },
risk: {
level: reasons.includes("whois_dns_delegation_mismatch") ? "high" : reasons.length ? "medium" : "low",
reasons,
},
ssl: { checked: false },
};
if (sslCheck) {
const ssl = await getJson("ssl-cert-check", domain);
row.ssl = {
checked: true,
valid: ssl?.valid,
issuer: ssl?.issuer?.O || ssl?.issuer?.CN || null,
valid_to: ssl?.valid_to || null,
};
}
return row;
}
async function main() {
const domains = ["example.com", "example.org"];
const report = [];
for (const domain of domains) {
report.push(await auditDomain(domain, { sslCheck: true }));
}
console.log(JSON.stringify(report, null, 2));
}
main().catch(console.error);
Turn Findings Into Day 0 Actions
The best diligence output is not a static PDF. It is a task list with owners and deadlines aligned to the integration plan.
- Transfer blockers: escalate EPP locks and registrar account access to the seller before close. Fixing these post-close is slower and riskier.
- Renewal cliffs: renew critical domains pre-close or negotiate an escrow process so renewals cannot be missed during transition.
- DNS ownership: document the authoritative DNS provider for Day 0 and capture nameserver management access as a deliverable.
- Customer-facing SSL risk: ensure certificate issuance and renewal are not tied to an employee mailbox or abandoned vendor account.
After close, move from diligence snapshots to continuous monitoring with Domain Monitoring and the domain portfolio management workflow.
Limits and Non-Goals
A good diligence workflow is explicit about what public domain data can and cannot prove.
- WHOIS/RDAP provides administrative evidence, not legal title. Treat it as operational proof of who controls renewal and DNS today.
- This article does not replace legal review, IP assignment checks, or registrar account access validation.
- Lookup endpoints return current data. Store your own snapshots if the deal timeline spans weeks.
- SSL checks inspect the certificate currently served on supported HTTPS ports; they do not audit internal infrastructure.
- Vendor-facing third-party risk reviews are a different workflow. See the vendor domain security audit checklist when evaluating SaaS suppliers rather than acquisition targets.
Where This Fits in the Domain Intelligence Cluster
Treat this article as the pre-close spoke in your operations and business-use-case cluster. The surrounding guides cover the steady-state workflows that begin after the deal closes.
- WHOIS API use cases — parent hub for business applications.
- Domain inventory API — build the first normalized dataset from a domain list.
- Domain portfolio management — ongoing renewal, DNS and SSL operations.
- EPP status codes — transfer locks, holds, and lifecycle states.
- Domain expiry detection — grace period, redemption, and pending delete.
- Bulk WHOIS lookup — parallel requests for large target portfolios.
FAQ
What domains should be included in an M&A domain audit?
Include brand domains, customer login and SSO domains, API and documentation domains, redirect and marketing campaign domains, and any ccTLDs. If a domain appears in product links, customer emails, OAuth callbacks, or legal notices, it belongs in the diligence list.
Can WHOIS and RDAP data prove ownership?
WHOIS/RDAP provides strong administrative evidence such as registrar, dates, status codes, and nameservers, and sometimes registrant details. Treat it as operational evidence of who controls renewal and DNS today, not as a legal deed.
How often should diligence checks run?
Pre-close diligence is usually a snapshot. If signing is delayed, rerun the audit weekly on critical domains and daily on anything expiring inside 30 days.
What is the fastest minimum viable audit?
Start with registrar, expiry date, and EPP status from /whois, then confirm DNS delegation via /nslookup. Add /ssl-cert-check only for customer-facing domains and login endpoints where certificate incidents would be visible to users.
How many API calls does a diligence pass need?
A minimum pass uses two calls per domain for WHOIS and DNS. Adding SSL for customer-facing domains brings the total to three calls per domain. For 50 domains, that is 100 to 150 API calls depending on SSL coverage.
Conclusion
Domain assets are business-critical infrastructure, but they are often treated as paperwork until something breaks after close. A lightweight API-based diligence pass turns them into evidence: who controls the registrar, what can block a transfer, what can expire during integration, and whether DNS delegation matches the operating model you are buying.
Start with the seller's domain list, normalize WHOIS and DNS evidence into one report row per domain, escalate blockers before signing, then hand the portfolio to monitoring and portfolio management workflows on Day 0.
Run a pre-close domain audit
Query WHOIS, DNS and SSL evidence as structured JSON. Export a report, assign owners, and remove transfer and renewal risk before close.
Start freeBulk WHOIS guide