{
  "openapi": "3.1.0",
  "info": {
    "title": "Subdomains by Jsmon API",
    "version": "1.1.0",
    "description": "Subdomain lookup API with 5.4 billion+ subdomains from certificate transparency logs, DNS records, web crawling and other OSINT sources. Updated daily, average response under 100ms. Two ways to query: an API key (/api/domain/{domain}, free tier available) or pay-per-query with the Machine Payments Protocol (/api/mpp/domain/{domain}, $0.50 per lookup, no account).",
    "contact": {
      "name": "Jsmon Inc.",
      "email": "support@jsmon.sh",
      "url": "https://jsmon.sh"
    },
    "termsOfService": "https://jsmon.sh/terms"
  },
  "servers": [
    {
      "url": "https://subdomains.jsmon.sh"
    }
  ],
  "tags": [
    {
      "name": "API key",
      "description": "Standard access with an Api-Key header. Free tier: 3 queries/day, 100 results/query."
    },
    {
      "name": "Pay per query (MPP)",
      "description": "No account. $0.50 per lookup via the Machine Payments Protocol."
    }
  ],
  "paths": {
    "/api/domain/{domain}": {
      "get": {
        "tags": [
          "API key"
        ],
        "operationId": "getSubdomainsWithApiKey",
        "summary": "List subdomains for a domain (API key)",
        "description": "Returns subdomains observed for a root domain. JSON results are paginated with the page parameter. With mode=txt (Pro and Max), every subdomain is returned as plain text in one response, consuming one query.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/Domain"
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "description": "Page number for paginated JSON results. Increment until a page returns no subdomains.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "default": 1
            }
          },
          {
            "name": "mode",
            "in": "query",
            "required": false,
            "description": "Set to txt for plain text, one subdomain per line, no pagination (Pro and Max).",
            "schema": {
              "type": "string",
              "enum": [
                "txt"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Subdomains returned.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SubdomainPage"
                }
              },
              "text/plain": {
                "schema": {
                  "type": "string"
                },
                "example": "api.example.com\nmail.example.com\n"
              }
            }
          },
          "400": {
            "description": "Invalid domain format.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Plan restriction — feature not available (e.g. mode=txt on Free), email not verified, or query quota exceeded.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No subdomains known for this domain.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotFound"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited (Free plan: one request per 10 seconds).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/mpp/domain/{domain}": {
      "get": {
        "tags": [
          "Pay per query (MPP)"
        ],
        "operationId": "getSubdomains",
        "summary": "List subdomains for a domain (pay per query)",
        "description": "Returns up to 10,000 subdomains, sorted alphabetically, for one $0.50 payment. Unauthenticated calls return 402 with an MPP challenge. The domain is checked before payment, so unknown domains return 404 without a charge.",
        "security": [
          {},
          {
            "MppPayment": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/Domain"
          },
          {
            "name": "mode",
            "in": "query",
            "required": false,
            "description": "Set to txt for plain text, one subdomain per line. Total count is in the X-Total-Count header.",
            "schema": {
              "type": "string",
              "enum": [
                "txt"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Subdomains returned.",
            "headers": {
              "Payment-Receipt": {
                "description": "MPP payment receipt.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Total-Count": {
                "description": "Total known subdomains (mode=txt only).",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SubdomainResult"
                }
              },
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "Invalid domain format.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "Payment required. The WWW-Authenticate header carries the MPP challenge.",
            "headers": {
              "WWW-Authenticate": {
                "description": "MPP payment challenge.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "No known subdomains. Not charged.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotFound"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "parameters": {
      "Domain": {
        "name": "domain",
        "in": "path",
        "required": true,
        "description": "Root domain to look up, e.g. example.com. Case-insensitive.",
        "schema": {
          "type": "string",
          "pattern": "^(?=.{1,253}$)([a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\\.)+[a-zA-Z]{2,63}$"
        },
        "example": "example.com"
      }
    },
    "securitySchemes": {
      "ApiKeyAuth": {
        "type": "apiKey",
        "in": "header",
        "name": "Api-Key",
        "description": "Get a free key at https://subdomains.jsmon.sh/signup"
      },
      "MppPayment": {
        "type": "http",
        "scheme": "Payment",
        "description": "Credential obtained by paying the 402 MPP challenge, sent in the Authorization header."
      }
    },
    "schemas": {
      "SubdomainPage": {
        "type": "object",
        "required": [
          "domain",
          "total",
          "page",
          "per_page",
          "total_pages",
          "subdomains"
        ],
        "properties": {
          "domain": {
            "type": "string",
            "example": "tesla.com"
          },
          "total": {
            "type": "integer",
            "description": "Total known subdomains for the domain.",
            "example": 4521
          },
          "page": {
            "type": "integer",
            "description": "Current page number.",
            "example": 1
          },
          "per_page": {
            "type": "integer",
            "description": "Results per page.",
            "example": 100
          },
          "total_pages": {
            "type": "integer",
            "description": "Total number of pages.",
            "example": 46
          },
          "subdomains": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Fully qualified subdomains.",
            "example": [
              "api.tesla.com",
              "mail.tesla.com"
            ]
          }
        }
      },
      "SubdomainResult": {
        "type": "object",
        "required": [
          "domain",
          "total",
          "returned",
          "is_truncated",
          "subdomains"
        ],
        "properties": {
          "domain": {
            "type": "string",
            "description": "Looked-up domain, lowercased."
          },
          "total": {
            "type": "integer",
            "description": "Total known subdomains."
          },
          "returned": {
            "type": "integer",
            "maximum": 10000,
            "description": "Subdomains in this response."
          },
          "is_truncated": {
            "type": "boolean",
            "description": "True when total exceeds returned."
          },
          "subdomains": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Fully qualified subdomains, sorted alphabetically."
          }
        },
        "example": {
          "domain": "example.com",
          "total": 1547,
          "returned": 1547,
          "is_truncated": false,
          "subdomains": [
            "a.example.com",
            "b.example.com"
          ]
        }
      },
      "Error": {
        "type": "object",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "string"
          }
        }
      },
      "NotFound": {
        "type": "object",
        "required": [
          "error",
          "domain"
        ],
        "properties": {
          "error": {
            "type": "string"
          },
          "domain": {
            "type": "string"
          }
        }
      }
    }
  }
}