{
  "openapi": "3.1.0",
  "info": {
    "title": "Ciolvra Whois API",
    "version": "1.1.0",
    "description": "WHOIS lookups for domains and IP addresses. 25 requests are allowed in a row per IP address. Once they are used up, a cooldown of one minute applies before the quota is available again."
  },
  "servers": [
    {
      "url": "https://ciolvrawhois.de"
    }
  ],
  "tags": [
    {
      "name": "Whois",
      "description": "Look up registration data."
    },
    {
      "name": "Service",
      "description": "Limit and service status."
    }
  ],
  "paths": {
    "/request": {
      "post": {
        "operationId": "lookup",
        "tags": [
          "Whois"
        ],
        "summary": "Look up WHOIS data",
        "description": "Send the query as a JSON body.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/LookupRequest"
              },
              "examples": {
                "plain": {
                  "summary": "Raw WHOIS text",
                  "value": {
                    "query": "domain.tld"
                  }
                },
                "parsed": {
                  "summary": "With structured fields",
                  "value": {
                    "query": "domain.tld",
                    "parse": true
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "WHOIS data was fetched.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LookupResponse"
                }
              }
            }
          },
          "400": {
            "description": "The body is missing or contains an invalid query or parse value.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "No WHOIS data exists for this query.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "405": {
            "description": "Wrong HTTP method.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "All requests are used up. Wait for the cooldown to finish.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "502": {
            "description": "The WHOIS service is currently unavailable.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "get": {
        "operationId": "lookupGet",
        "tags": [
          "Whois"
        ],
        "summary": "Look up WHOIS data with GET",
        "description": "Same as POST for clients that can send a body with GET, for example curl. Browsers cannot send a body with GET, use POST there.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/LookupRequest"
              },
              "examples": {
                "plain": {
                  "summary": "Raw WHOIS text",
                  "value": {
                    "query": "domain.tld"
                  }
                },
                "parsed": {
                  "summary": "With structured fields",
                  "value": {
                    "query": "domain.tld",
                    "parse": true
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "WHOIS data was fetched.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LookupResponse"
                }
              }
            }
          },
          "400": {
            "description": "The body is missing or contains an invalid query or parse value.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "No WHOIS data exists for this query.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "405": {
            "description": "Wrong HTTP method.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "All requests are used up. Wait for the cooldown to finish.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "502": {
            "description": "The WHOIS service is currently unavailable.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/limit": {
      "get": {
        "operationId": "limit",
        "tags": [
          "Service"
        ],
        "summary": "Get the current limit status",
        "description": "Does not count as a request.",
        "responses": {
          "200": {
            "description": "Current limit status for the calling client.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LimitResponse"
                }
              }
            }
          }
        }
      }
    },
    "/health": {
      "get": {
        "operationId": "health",
        "tags": [
          "Service"
        ],
        "summary": "Get the service status",
        "responses": {
          "200": {
            "description": "The service is running.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HealthResponse"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "headers": {
      "XRateLimitLimit": {
        "description": "Allowed requests in a row.",
        "schema": {
          "type": "integer"
        }
      },
      "XRateLimitRemaining": {
        "description": "Remaining requests. Used requests are available again only after all requests were used and the cooldown finished.",
        "schema": {
          "type": "integer"
        }
      },
      "RetryAfter": {
        "description": "Seconds until the next request is allowed.",
        "schema": {
          "type": "integer"
        }
      }
    },
    "schemas": {
      "LookupRequest": {
        "type": "object",
        "required": [
          "query"
        ],
        "properties": {
          "query": {
            "type": "string",
            "maxLength": 253,
            "description": "Domain name or IP address (IPv4 or IPv6).",
            "examples": [
              "domain.tld"
            ]
          },
          "parse": {
            "type": "boolean",
            "default": false,
            "description": "Adds structured fields in data.parsed."
          }
        }
      },
      "ParsedWhois": {
        "type": "object",
        "properties": {
          "registrar": {
            "type": [
              "string",
              "null"
            ]
          },
          "organisation": {
            "type": [
              "string",
              "null"
            ]
          },
          "country": {
            "type": [
              "string",
              "null"
            ]
          },
          "created": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "expires": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "updated": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "status": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "nameservers": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "LookupData": {
        "type": "object",
        "required": [
          "query",
          "type",
          "whois"
        ],
        "properties": {
          "query": {
            "type": "string"
          },
          "type": {
            "type": "string",
            "enum": [
              "domain",
              "ip"
            ]
          },
          "whois": {
            "type": "string",
            "description": "Raw WHOIS text."
          },
          "parsed": {
            "$ref": "#/components/schemas/ParsedWhois"
          }
        }
      },
      "LookupResponse": {
        "type": "object",
        "required": [
          "response",
          "state",
          "data"
        ],
        "properties": {
          "response": {
            "type": "string"
          },
          "state": {
            "type": "string",
            "enum": [
              "success"
            ]
          },
          "data": {
            "$ref": "#/components/schemas/LookupData"
          }
        }
      },
      "ErrorResponse": {
        "type": "object",
        "required": [
          "response",
          "state"
        ],
        "properties": {
          "response": {
            "type": "string"
          },
          "state": {
            "type": "string",
            "enum": [
              "error"
            ]
          },
          "retry_after": {
            "type": "integer",
            "description": "Only present with status 429."
          }
        }
      },
      "LimitResponse": {
        "type": "object",
        "required": [
          "response",
          "state",
          "data"
        ],
        "properties": {
          "response": {
            "type": "string"
          },
          "state": {
            "type": "string",
            "enum": [
              "success"
            ]
          },
          "data": {
            "type": "object",
            "required": [
              "limit",
              "window",
              "used",
              "remaining",
              "locked",
              "cooldown"
            ],
            "properties": {
              "limit": {
                "type": "integer"
              },
              "window": {
                "type": "integer",
                "description": "Cooldown length in seconds."
              },
              "used": {
                "type": "integer"
              },
              "remaining": {
                "type": "integer"
              },
              "locked": {
                "type": "boolean"
              },
              "cooldown": {
                "type": "number",
                "description": "Seconds until the quota is available again."
              }
            }
          }
        }
      },
      "HealthResponse": {
        "type": "object",
        "required": [
          "response",
          "state",
          "data"
        ],
        "properties": {
          "response": {
            "type": "string"
          },
          "state": {
            "type": "string",
            "enum": [
              "success"
            ]
          },
          "data": {
            "type": "object",
            "required": [
              "version",
              "time"
            ],
            "properties": {
              "version": {
                "type": "string"
              },
              "time": {
                "type": "string",
                "format": "date-time"
              }
            }
          }
        }
      }
    }
  }
}
