{
  "openapi": "3.1.0",
  "info": {
    "title": "DechoNet API",
    "version": "2026-10-10",
    "description": "Read-only domain security checks observed from outside. No key is needed; with a key, rate limits are counted per key instead of per IP. Free use is non-commercial (terms). The same checks are available as MCP tools at /mcp.",
    "termsOfService": "https://dechonet.com/terms",
    "contact": {
      "email": "support@dechonet.com"
    }
  },
  "servers": [
    {
      "url": "https://dechonet.com"
    }
  ],
  "security": [
    {},
    {
      "apiKey": []
    }
  ],
  "components": {
    "securitySchemes": {
      "apiKey": {
        "type": "http",
        "scheme": "bearer",
        "description": "Key from the monitoring account page (dn_…)."
      }
    },
    "schemas": {
      "Envelope": {
        "type": "object",
        "required": [
          "ok",
          "requestId",
          "cached",
          "data",
          "error"
        ],
        "properties": {
          "ok": {
            "type": "boolean"
          },
          "requestId": {
            "type": "string"
          },
          "cached": {
            "type": "boolean",
            "description": "True when a recent stored result was returned."
          },
          "updatedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the result was produced."
          },
          "data": {
            "description": "Tool result. Most tools return `raw` (what was observed) and `interpretation` (status, KPIs, issues with severity, cause and action)."
          },
          "error": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "code": {
                "type": "string",
                "enum": [
                  "INVALID_INPUT",
                  "NOT_FOUND",
                  "RATE_LIMITED",
                  "UPSTREAM_ERROR",
                  "UPSTREAM_TIMEOUT",
                  "INVALID_API_KEY",
                  "API_KEY_REQUIRED"
                ]
              },
              "message": {
                "type": "string"
              },
              "retryAfter": {
                "type": [
                  "integer",
                  "null"
                ]
              },
              "reason": {
                "type": "string"
              }
            }
          },
          "previousSnapshot": {
            "type": "object",
            "description": "The previous stored result for the same target, when there is one."
          }
        }
      }
    }
  },
  "paths": {
    "/api/util/dns": {
      "get": {
        "operationId": "dns_lookup",
        "summary": "DNS Lookup",
        "description": "Query DNS records (A, AAAA, MX, TXT, NS, SOA, CAA) for a domain and validate email-related records, including DNSSEC presence and SPF/DMARC syntax, returning severity-rated diagnostics.",
        "parameters": [
          {
            "name": "query",
            "in": "query",
            "required": true,
            "description": "Registrable domain or hostname to query, without scheme or path (e.g., 'example.com' or 'mail.example.com'). Do not include 'http://' or a trailing slash.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "lang",
            "in": "query",
            "required": false,
            "description": "Language of the interpretation text.",
            "schema": {
              "type": "string",
              "enum": [
                "en",
                "ko"
              ],
              "default": "en"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Result",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          },
          "400": {
            "description": "Invalid input",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          },
          "401": {
            "description": "Wrong or revoked API key, or a key is required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited — see the Retry-After header",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          },
          "503": {
            "description": "An upstream source failed or timed out",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/util/ssl": {
      "get": {
        "operationId": "ssl_check",
        "summary": "SSL Certificate Check",
        "description": "Inspect a host's served TLS/SSL certificate and connection: expiry date, issuer, SAN list, chain integrity, revocation (OCSP, then CRL; unknown when neither answers — not graded unless revoked), TLS version, and HSTS, returning an A+ to F grade weighted by certificate validity (40%), TLS version (25%), chain trust (15%), and HSTS (20%).",
        "parameters": [
          {
            "name": "host",
            "in": "query",
            "required": true,
            "description": "Hostname to inspect, without scheme (e.g., 'example.com'). The host portion of a pasted URL is also accepted.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "port",
            "in": "query",
            "required": false,
            "description": "TCP port for the TLS handshake. Defaults to 443 (standard HTTPS); set this only for a non-standard HTTPS port such as 8443.",
            "schema": {
              "type": "number",
              "default": 443
            }
          },
          {
            "name": "lang",
            "in": "query",
            "required": false,
            "description": "Language of the interpretation text.",
            "schema": {
              "type": "string",
              "enum": [
                "en",
                "ko"
              ],
              "default": "en"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Result",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          },
          "400": {
            "description": "Invalid input",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          },
          "401": {
            "description": "Wrong or revoked API key, or a key is required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited — see the Retry-After header",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          },
          "503": {
            "description": "An upstream source failed or timed out",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/util/http": {
      "get": {
        "operationId": "http_security",
        "summary": "HTTP Security Headers Audit",
        "description": "Follow a URL's HTTP redirect chain and audit response security headers (CSP, HSTS, X-Frame-Options, COOP, CORP, COEP, Permissions-Policy), grading A+ to F on the six core headers (CSP, HSTS, X-Frame-Options, X-Content-Type-Options, Referrer-Policy, Permissions-Policy; COOP/CORP/COEP are reported but not graded) and flagging information leaks such as server-version disclosure.",
        "parameters": [
          {
            "name": "url",
            "in": "query",
            "required": true,
            "description": "Full URL including scheme (e.g., 'https://example.com/path'). If the scheme is omitted, https:// is assumed. Redirects are followed starting from this URL.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "lang",
            "in": "query",
            "required": false,
            "description": "Language of the interpretation text.",
            "schema": {
              "type": "string",
              "enum": [
                "en",
                "ko"
              ],
              "default": "en"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Result",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          },
          "400": {
            "description": "Invalid input",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          },
          "401": {
            "description": "Wrong or revoked API key, or a key is required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited — see the Retry-After header",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          },
          "503": {
            "description": "An upstream source failed or timed out",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/util/email": {
      "get": {
        "operationId": "email_auth",
        "summary": "Email Authentication Check",
        "description": "Assess a domain's email authentication and deliverability posture: MX records, SPF, DMARC, DKIM (probes 15 common selectors), BIMI, MTA-STS, TLS-RPT, and DANE, plus a blacklist check across all MX hosts, returning a 0-100 deliverability score.",
        "parameters": [
          {
            "name": "query",
            "in": "query",
            "required": true,
            "description": "Email domain to assess — the part after '@' (e.g., 'example.com'). An IP address is also accepted for reverse/PTR-based checks.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "lang",
            "in": "query",
            "required": false,
            "description": "Language of the interpretation text.",
            "schema": {
              "type": "string",
              "enum": [
                "en",
                "ko"
              ],
              "default": "en"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Result",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          },
          "400": {
            "description": "Invalid input",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          },
          "401": {
            "description": "Wrong or revoked API key, or a key is required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited — see the Retry-After header",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          },
          "503": {
            "description": "An upstream source failed or timed out",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/util/port": {
      "get": {
        "operationId": "port_scan",
        "summary": "Open Port Scan",
        "description": "Probe a host for a fixed set of common TCP ports (HTTP, HTTPS, SSH, FTP, SMTP, DNS, and common databases) and report which are open, the service name, and the response time.",
        "parameters": [
          {
            "name": "host",
            "in": "query",
            "required": true,
            "description": "Hostname or IP to probe (e.g., 'example.com' or '203.0.113.10'). A 'host:port' form is accepted to hint a specific port. Only supply targets you own or are authorized to test.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "lang",
            "in": "query",
            "required": false,
            "description": "Language of the interpretation text.",
            "schema": {
              "type": "string",
              "enum": [
                "en",
                "ko"
              ],
              "default": "en"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Result",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          },
          "400": {
            "description": "Invalid input",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          },
          "401": {
            "description": "Wrong or revoked API key, or a key is required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited — see the Retry-After header",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          },
          "503": {
            "description": "An upstream source failed or timed out",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/util/propagation": {
      "get": {
        "operationId": "dns_propagation",
        "summary": "DNS Propagation Check",
        "description": "Query one DNS record across 8+ global public resolvers (Google, Cloudflare, Quad9, OpenDNS, and more) simultaneously and report which resolvers return stale versus updated values.",
        "parameters": [
          {
            "name": "domain",
            "in": "query",
            "required": true,
            "description": "Domain whose record to compare across resolvers (e.g., 'example.com'), without scheme or path.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "type",
            "in": "query",
            "required": false,
            "description": "DNS record type to compare across resolvers. Defaults to A (IPv4 address), the most common propagation check.",
            "schema": {
              "type": "string",
              "enum": [
                "A",
                "AAAA",
                "MX",
                "CNAME",
                "TXT",
                "NS"
              ],
              "default": "A"
            }
          },
          {
            "name": "lang",
            "in": "query",
            "required": false,
            "description": "Language of the interpretation text.",
            "schema": {
              "type": "string",
              "enum": [
                "en",
                "ko"
              ],
              "default": "en"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Result",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          },
          "400": {
            "description": "Invalid input",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          },
          "401": {
            "description": "Wrong or revoked API key, or a key is required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited — see the Retry-After header",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          },
          "503": {
            "description": "An upstream source failed or timed out",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/util/reverse-dns": {
      "get": {
        "operationId": "reverse_dns",
        "summary": "Reverse DNS (PTR) Lookup",
        "description": "Resolve the PTR (reverse DNS) record for an IPv4 or IPv6 address and verify forward-confirmed reverse DNS (FCrDNS) by checking that the PTR hostname resolves back to the same IP.",
        "parameters": [
          {
            "name": "query",
            "in": "query",
            "required": true,
            "description": "IP address to reverse-resolve, IPv4 or IPv6 (e.g., '8.8.8.8' or '2001:4860:4860::8888'). Must be an IP, not a hostname.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "lang",
            "in": "query",
            "required": false,
            "description": "Language of the interpretation text.",
            "schema": {
              "type": "string",
              "enum": [
                "en",
                "ko"
              ],
              "default": "en"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Result",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          },
          "400": {
            "description": "Invalid input",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          },
          "401": {
            "description": "Wrong or revoked API key, or a key is required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited — see the Retry-After header",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          },
          "503": {
            "description": "An upstream source failed or timed out",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/util/asn": {
      "get": {
        "operationId": "asn_lookup",
        "summary": "ASN / BGP Lookup",
        "description": "Look up Autonomous System (ASN) / BGP information for an IP address or AS number: the network operator, announced prefixes, abuse contact, and a classification (cloud, CDN, ISP, hosting, or enterprise).",
        "parameters": [
          {
            "name": "query",
            "in": "query",
            "required": true,
            "description": "An IP address (e.g., '1.1.1.1') or an AS number in 'AS####' form (e.g., 'AS13335').",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "lang",
            "in": "query",
            "required": false,
            "description": "Language of the interpretation text.",
            "schema": {
              "type": "string",
              "enum": [
                "en",
                "ko"
              ],
              "default": "en"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Result",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          },
          "400": {
            "description": "Invalid input",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          },
          "401": {
            "description": "Wrong or revoked API key, or a key is required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited — see the Retry-After header",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          },
          "503": {
            "description": "An upstream source failed or timed out",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/util/rdap": {
      "get": {
        "operationId": "whois_lookup",
        "summary": "WHOIS / RDAP Domain Lookup",
        "description": "Retrieve domain registration data via RDAP (with WHOIS fallback): registrar, creation/expiry/update dates, nameservers, and EPP status flags, highlighting risk states such as clientHold and pendingDelete.",
        "parameters": [
          {
            "name": "query",
            "in": "query",
            "required": true,
            "description": "Registered domain name to look up (e.g., 'example.com'). A subdomain is normalized to its registrable domain.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "lang",
            "in": "query",
            "required": false,
            "description": "Language of the interpretation text.",
            "schema": {
              "type": "string",
              "enum": [
                "en",
                "ko"
              ],
              "default": "en"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Result",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          },
          "400": {
            "description": "Invalid input",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          },
          "401": {
            "description": "Wrong or revoked API key, or a key is required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited — see the Retry-After header",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          },
          "503": {
            "description": "An upstream source failed or timed out",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/util/subdomains": {
      "get": {
        "operationId": "subdomain_discovery",
        "summary": "Subdomain Discovery",
        "description": "Enumerate the subdomains of a domain from Certificate Transparency logs — fully passive (no packets are sent to the target; CT logs are public records of every TLS certificate ever issued).",
        "parameters": [
          {
            "name": "query",
            "in": "query",
            "required": true,
            "description": "Registrable domain to enumerate (e.g., 'example.com'), without scheme or path. Subdomains found in CT logs for this domain are returned.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "lang",
            "in": "query",
            "required": false,
            "description": "Language of the interpretation text.",
            "schema": {
              "type": "string",
              "enum": [
                "en",
                "ko"
              ],
              "default": "en"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Result",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          },
          "400": {
            "description": "Invalid input",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          },
          "401": {
            "description": "Wrong or revoked API key, or a key is required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited — see the Retry-After header",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          },
          "503": {
            "description": "An upstream source failed or timed out",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/util/lookalike": {
      "get": {
        "operationId": "lookalike_domains",
        "summary": "Lookalike Domain Check",
        "description": "Generate the typosquat/lookalike variants of a domain that phishers actually register — homoglyph swaps (l→1, o→0, rn→m), TLD swaps (.com→.co), character omissions, transpositions, repetitions, hyphenations — and check which of them are currently registered (live NS delegation via DoH).",
        "parameters": [
          {
            "name": "query",
            "in": "query",
            "required": true,
            "description": "Domain to protect (e.g., 'example.com'), without scheme or path. Variants of its label and TLD are generated and checked.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "lang",
            "in": "query",
            "required": false,
            "description": "Language of the interpretation text.",
            "schema": {
              "type": "string",
              "enum": [
                "en",
                "ko"
              ],
              "default": "en"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Result",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          },
          "400": {
            "description": "Invalid input",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          },
          "401": {
            "description": "Wrong or revoked API key, or a key is required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited — see the Retry-After header",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          },
          "503": {
            "description": "An upstream source failed or timed out",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/util/ip": {
      "get": {
        "operationId": "ip_info",
        "summary": "My IP Info",
        "description": "Report information about the caller's own public IP as seen by the server: IPv4/IPv6 address, ISP, ASN, approximate geolocation, and proxy/VPN heuristics.",
        "parameters": [
          {
            "name": "lang",
            "in": "query",
            "required": false,
            "description": "Language of the interpretation text.",
            "schema": {
              "type": "string",
              "enum": [
                "en",
                "ko"
              ],
              "default": "en"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Result",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          },
          "400": {
            "description": "Invalid input",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          },
          "401": {
            "description": "Wrong or revoked API key, or a key is required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited — see the Retry-After header",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          },
          "503": {
            "description": "An upstream source failed or timed out",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/util/email-header": {
      "post": {
        "operationId": "email_header_analysis",
        "summary": "Email Header Analysis",
        "description": "Parse raw email headers to reconstruct the delivery path (each Received hop in order), extract SPF/DKIM/DMARC authentication results, measure per-hop delays, and flag unencrypted (non-TLS) hops.",
        "parameters": [
          {
            "name": "lang",
            "in": "query",
            "required": false,
            "description": "Language of the interpretation text.",
            "schema": {
              "type": "string",
              "enum": [
                "en",
                "ko"
              ],
              "default": "en"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "headers"
                ],
                "properties": {
                  "headers": {
                    "type": "string",
                    "description": "The complete raw email header block, copied verbatim — every line from the first 'Received:'/'From:' down to the blank line before the body. Paste as-is, including folded continuation lines; do not include the message body."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Result",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          },
          "400": {
            "description": "Invalid input",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          },
          "401": {
            "description": "Wrong or revoked API key, or a key is required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited — see the Retry-After header",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          },
          "503": {
            "description": "An upstream source failed or timed out",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/util/owasp": {
      "get": {
        "operationId": "owasp_check",
        "summary": "OWASP Security Checkup",
        "description": "Assess a domain's OWASP posture from EXTERNAL OBSERVATION only: the OWASP Secure Headers Project plus the externally observable Top 10 subset — A02 Cryptographic Failures (TLS/cert), A05 Security Misconfiguration (header/info leaks), and A06 Vulnerable & Outdated Components (version disclosure) — returning an A+ to F grade.",
        "parameters": [
          {
            "name": "host",
            "in": "query",
            "required": true,
            "description": "Hostname to assess, without scheme (e.g., 'example.com'). The host portion of a pasted URL is also accepted.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "lang",
            "in": "query",
            "required": false,
            "description": "Language of the interpretation text.",
            "schema": {
              "type": "string",
              "enum": [
                "en",
                "ko"
              ],
              "default": "en"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Result",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          },
          "400": {
            "description": "Invalid input",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          },
          "401": {
            "description": "Wrong or revoked API key, or a key is required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited — see the Retry-After header",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          },
          "503": {
            "description": "An upstream source failed or timed out",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/util/impersonation": {
      "get": {
        "operationId": "impersonation_exposure",
        "summary": "Brand Impersonation Exposure",
        "description": "Assess how exposed a domain is to brand impersonation and phishing, PASSIVELY: live typosquat/lookalike domains (homoglyph, omission, transposition, TLD swap) that actually resolve, operational subdomains (dev/staging/admin) exposed in CT logs, and whether a wildcard certificate exists — returning an A+ (low exposure) to F (high exposure) grade.",
        "parameters": [
          {
            "name": "query",
            "in": "query",
            "required": true,
            "description": "Registrable domain to assess for impersonation exposure (e.g., 'example.com'). Scheme and path are stripped.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "lang",
            "in": "query",
            "required": false,
            "description": "Language of the interpretation text.",
            "schema": {
              "type": "string",
              "enum": [
                "en",
                "ko"
              ],
              "default": "en"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Result",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          },
          "400": {
            "description": "Invalid input",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          },
          "401": {
            "description": "Wrong or revoked API key, or a key is required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited — see the Retry-After header",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          },
          "503": {
            "description": "An upstream source failed or timed out",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/util/changes": {
      "get": {
        "operationId": "domain_changes",
        "summary": "Domain Change History",
        "description": "Report what has changed for a domain over time — the security regressions and drift that DechoNet's daily monitoring has recorded across every watch on the domain (SSL grade, headers, DNS, OWASP posture, impersonation exposure, etc.).",
        "parameters": [
          {
            "name": "query",
            "in": "query",
            "required": true,
            "description": "Domain whose recorded change history to fetch (e.g., 'example.com'). Scheme and path are stripped.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "lang",
            "in": "query",
            "required": false,
            "description": "Language of the interpretation text.",
            "schema": {
              "type": "string",
              "enum": [
                "en",
                "ko"
              ],
              "default": "en"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Result",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          },
          "400": {
            "description": "Invalid input",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          },
          "401": {
            "description": "Wrong or revoked API key, or a key is required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited — see the Retry-After header",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          },
          "503": {
            "description": "An upstream source failed or timed out",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/util/history": {
      "get": {
        "operationId": "domain_history",
        "summary": "Infrastructure History",
        "description": "Show how a domain's (or IPv4 address's) infrastructure has changed over time from DechoNet's stored observations: nameservers, A/AAAA, MX, CNAME, certificate issuer, registrar, RDAP nameservers and status, and for an IP its ASN and PTR — each value with when it was first and last seen.",
        "parameters": [
          {
            "name": "target",
            "in": "query",
            "required": true,
            "description": "Domain (e.g., 'example.com') or IPv4 address. Scheme, path and a leading www. are stripped.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "lang",
            "in": "query",
            "required": false,
            "description": "Language of the interpretation text.",
            "schema": {
              "type": "string",
              "enum": [
                "en",
                "ko"
              ],
              "default": "en"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Result",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          },
          "400": {
            "description": "Invalid input",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          },
          "401": {
            "description": "Wrong or revoked API key, or a key is required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited — see the Retry-After header",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          },
          "503": {
            "description": "An upstream source failed or timed out",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/util/pivot": {
      "get": {
        "operationId": "infrastructure_pivot",
        "summary": "Infrastructure Pivot",
        "description": "Find other domains DechoNet has seen with the same infrastructure value — a nameserver, IP address, MX host, certificate issuer or registrar — with first and last seen, to map related infrastructure (e.g.",
        "parameters": [
          {
            "name": "kind",
            "in": "query",
            "required": true,
            "description": "Which kind of value to pivot on.",
            "schema": {
              "type": "string",
              "enum": [
                "dns:a",
                "dns:aaaa",
                "dns:ns",
                "dns:mx",
                "ssl:issuer",
                "rdap:registrar",
                "rdap:ns"
              ]
            }
          },
          {
            "name": "value",
            "in": "query",
            "required": true,
            "description": "The value itself, e.g. 'ns1.example-dns.net' or '203.0.113.9'.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "lang",
            "in": "query",
            "required": false,
            "description": "Language of the interpretation text.",
            "schema": {
              "type": "string",
              "enum": [
                "en",
                "ko"
              ],
              "default": "en"
            }
          }
        ],
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "Result",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          },
          "400": {
            "description": "Invalid input",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          },
          "401": {
            "description": "Wrong or revoked API key, or a key is required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited — see the Retry-After header",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          },
          "503": {
            "description": "An upstream source failed or timed out",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/util/golive": {
      "get": {
        "operationId": "golive_check",
        "summary": "Go-Live Readiness Checklist",
        "description": "Check whether a domain is ready to launch or migrate — a go/no-go verdict over five essentials: DNS resolves to an IP, has propagated consistently across global resolvers, SSL/TLS is ready, the site is reachable over HTTPS, and the domain registration is not about to expire.",
        "parameters": [
          {
            "name": "query",
            "in": "query",
            "required": true,
            "description": "Domain to check for launch/migration readiness (e.g., 'example.com'). Scheme and path are stripped.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "lang",
            "in": "query",
            "required": false,
            "description": "Language of the interpretation text.",
            "schema": {
              "type": "string",
              "enum": [
                "en",
                "ko"
              ],
              "default": "en"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Result",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          },
          "400": {
            "description": "Invalid input",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          },
          "401": {
            "description": "Wrong or revoked API key, or a key is required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited — see the Retry-After header",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          },
          "503": {
            "description": "An upstream source failed or timed out",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/util/pqc": {
      "get": {
        "operationId": "pqc_readiness",
        "summary": "Post-Quantum TLS Readiness",
        "description": "Check whether a website's public TLS endpoint is ready for post-quantum cryptography: does it complete a TLS 1.3 handshake that offers only the hybrid X25519MLKEM768 key exchange (ML-KEM), and does the organisation's own server provide it or a CDN edge in front of it.",
        "parameters": [
          {
            "name": "host",
            "in": "query",
            "required": true,
            "description": "Domain whose HTTPS endpoint to check (e.g., 'example.com'). Scheme and path are stripped.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "lang",
            "in": "query",
            "required": false,
            "description": "Language of the interpretation text.",
            "schema": {
              "type": "string",
              "enum": [
                "en",
                "ko"
              ],
              "default": "en"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Result",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          },
          "400": {
            "description": "Invalid input",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          },
          "401": {
            "description": "Wrong or revoked API key, or a key is required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited — see the Retry-After header",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          },
          "503": {
            "description": "An upstream source failed or timed out",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/util/phishing": {
      "post": {
        "operationId": "phishing_link_check",
        "summary": "Phishing / Smishing Link Check",
        "description": "Check the links in a suspicious text message (smishing) or e-mail before anyone taps them.",
        "parameters": [
          {
            "name": "lang",
            "in": "query",
            "required": false,
            "description": "Language of the interpretation text.",
            "schema": {
              "type": "string",
              "enum": [
                "en",
                "ko"
              ],
              "default": "en"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "text"
                ],
                "properties": {
                  "text": {
                    "type": "string",
                    "description": "The suspicious message exactly as received (any language), or just the URL. Up to 5 links are checked."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Result",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          },
          "400": {
            "description": "Invalid input",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          },
          "401": {
            "description": "Wrong or revoked API key, or a key is required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited — see the Retry-After header",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          },
          "503": {
            "description": "An upstream source failed or timed out",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/util/exposure": {
      "get": {
        "operationId": "exposure_map",
        "summary": "Exposed Admin Page Check",
        "description": "Map what an organisation exposes to the internet beyond its home page: subdomains from Certificate Transparency logs (plus hosts DechoNet has already observed), each opened once from outside and sorted into developer/ops tools, directory listings, admin screens, VPN/remote-access logins, staging servers, default install pages, login pages and so on — the forgotten assets AI-driven attack tools look for first.",
        "parameters": [
          {
            "name": "domain",
            "in": "query",
            "required": true,
            "description": "The organisation's domain (e.g., 'example.co.kr'). Scheme, path and a leading www. are stripped.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "lang",
            "in": "query",
            "required": false,
            "description": "Language of the interpretation text.",
            "schema": {
              "type": "string",
              "enum": [
                "en",
                "ko"
              ],
              "default": "en"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Result",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          },
          "400": {
            "description": "Invalid input",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          },
          "401": {
            "description": "Wrong or revoked API key, or a key is required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited — see the Retry-After header",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          },
          "503": {
            "description": "An upstream source failed or timed out",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/util/gate": {
      "get": {
        "operationId": "dechonet_gate__GitHub_Action_",
        "summary": "Pre-deploy gate",
        "description": "Runs the SSL and HTTP checks against a deployed URL and answers pass or fail per check, for failing a CI build.",
        "parameters": [
          {
            "name": "url",
            "in": "query",
            "required": true,
            "description": "Deployed URL (https:// is assumed when the scheme is missing).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "min_ssl",
            "in": "query",
            "required": false,
            "description": "Lowest acceptable SSL grade.",
            "schema": {
              "type": "string",
              "enum": [
                "A+",
                "A",
                "B",
                "C",
                "D",
                "E",
                "F"
              ],
              "default": "B"
            }
          },
          {
            "name": "min_headers",
            "in": "query",
            "required": false,
            "description": "Lowest acceptable security-header grade.",
            "schema": {
              "type": "string",
              "enum": [
                "A+",
                "A",
                "B",
                "C",
                "D",
                "E",
                "F"
              ],
              "default": "C"
            }
          },
          {
            "name": "min_days",
            "in": "query",
            "required": false,
            "description": "Fewest days the certificate must still be valid (0–365).",
            "schema": {
              "type": "integer",
              "default": 14
            }
          },
          {
            "name": "require_https",
            "in": "query",
            "required": false,
            "description": "Set 0 to allow a site that does not redirect to HTTPS.",
            "schema": {
              "type": "string",
              "enum": [
                "0",
                "1"
              ],
              "default": "1"
            }
          },
          {
            "name": "lang",
            "in": "query",
            "required": false,
            "description": "Language of the interpretation text.",
            "schema": {
              "type": "string",
              "enum": [
                "en",
                "ko"
              ],
              "default": "en"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Result",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          },
          "400": {
            "description": "Invalid input",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          },
          "401": {
            "description": "Wrong or revoked API key, or a key is required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited — see the Retry-After header",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          },
          "503": {
            "description": "An upstream source failed or timed out",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          }
        }
      }
    }
  }
}