{
  "openapi": "3.0.3",
  "info": {
    "title": "DomainCrust Sales API",
    "description": "Machine-readable contract for the DomainCrust domain sales research API. Read operations are public and rate limited. Write operations require an X-API-Key with write permission. Responses include RateLimit-Limit, RateLimit-Remaining, and RateLimit-Reset (seconds until reset); 429 responses include Retry-After (seconds to wait). Legacy X-RateLimit-* aliases use a Unix timestamp for reset.",
    "version": "1.0.0",
    "contact": {
      "name": "DomainCrust Support",
      "email": "api@domaincrust.com"
    }
  },
  "servers": [
    {
      "url": "https://domaincrust.com/api/v1",
      "description": "Production server"
    }
  ],
  "externalDocs": {
    "description": "DomainCrust API versioning and deprecation policy",
    "url": "https://domaincrust.com/api-versioning"
  },
  "tags": [
    {
      "name": "System",
      "description": "API availability and service metadata"
    },
    {
      "name": "Sales",
      "description": "Historical domain sale records"
    },
    {
      "name": "Statistics",
      "description": "Aggregated domain market statistics"
    },
    {
      "name": "Admin",
      "description": "Protected data-management operations"
    }
  ],
  "paths": {
    "/health": {
      "get": {
        "operationId": "getApiHealth",
        "summary": "Health Check",
        "description": "Check whether the DomainCrust Sales API is available.",
        "tags": ["System"],
        "responses": {
          "200": {
            "description": "API is healthy.",
            "content": {
              "application/json": {
                "schema": {"$ref": "#/components/schemas/HealthResponse"}
              }
            }
          }
        }
      }
    },
    "/sales/search": {
      "get": {
        "operationId": "searchDomainSales",
        "summary": "Search Domain Sales",
        "description": "Search historical domain sales using optional domain, TLD, price, date, platform, quality, and pagination filters.",
        "tags": ["Sales"],
        "parameters": [
          {"name": "domain", "in": "query", "description": "Partial or full domain-name search.", "schema": {"type": "string"}},
          {"name": "tld", "in": "query", "description": "Top-level domain filter, such as com or ai.", "schema": {"type": "string"}},
          {"name": "min_price", "in": "query", "description": "Minimum sale price in USD.", "schema": {"type": "integer", "minimum": 0}},
          {"name": "max_price", "in": "query", "description": "Maximum sale price in USD.", "schema": {"type": "integer", "minimum": 0}},
          {"name": "date_from", "in": "query", "description": "Include sales on or after this ISO-8601 date.", "schema": {"type": "string", "format": "date"}},
          {"name": "date_to", "in": "query", "description": "Include sales on or before this ISO-8601 date.", "schema": {"type": "string", "format": "date"}},
          {"name": "platform", "in": "query", "description": "Sales platform or venue filter.", "schema": {"type": "string"}},
          {"name": "min_score", "in": "query", "description": "Minimum domain quality score from 0 to 100.", "schema": {"type": "integer", "minimum": 0, "maximum": 100}},
          {"name": "word_count", "in": "query", "description": "Exact number of words in the domain.", "schema": {"type": "integer", "minimum": 0}},
          {"name": "has_numbers", "in": "query", "description": "Filter for domains that contain numbers.", "schema": {"type": "boolean"}},
          {"name": "has_hyphen", "in": "query", "description": "Filter for domains that contain a hyphen.", "schema": {"type": "boolean"}},
          {"name": "sort_by", "in": "query", "description": "Result field used for sorting.", "schema": {"type": "string", "enum": ["name", "sale_price", "sale_date", "platform", "domain_score", "word_count"], "default": "sale_date"}},
          {"name": "sort_order", "in": "query", "description": "Sort direction.", "schema": {"type": "string", "enum": ["ASC", "DESC"], "default": "DESC"}},
          {"name": "page", "in": "query", "description": "One-based result page.", "schema": {"type": "integer", "minimum": 1, "default": 1}},
          {"name": "limit", "in": "query", "description": "Results per page, capped at 100.", "schema": {"type": "integer", "minimum": 1, "maximum": 100, "default": 50}}
        ],
        "responses": {
          "200": {"description": "Matching sales and pagination.", "headers": {"RateLimit-Limit": {"$ref": "#/components/headers/RateLimitLimit"}, "RateLimit-Remaining": {"$ref": "#/components/headers/RateLimitRemaining"}, "RateLimit-Reset": {"$ref": "#/components/headers/RateLimitReset"}}, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/SalesSearchResponse"}}}},
          "429": {"description": "Rate limit exceeded.", "headers": {"RateLimit-Limit": {"$ref": "#/components/headers/RateLimitLimit"}, "RateLimit-Remaining": {"$ref": "#/components/headers/RateLimitRemaining"}, "RateLimit-Reset": {"$ref": "#/components/headers/RateLimitReset"}, "Retry-After": {"$ref": "#/components/headers/RetryAfter"}}, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ErrorResponse"}}}}
        }
      }
    },
    "/sales/domain/{domain}": {
      "get": {
        "operationId": "getDomainSalesHistory",
        "summary": "Get Domain Sales History",
        "description": "Return all recorded historical sales for one full domain name.",
        "tags": ["Sales"],
        "parameters": [
          {"name": "domain", "in": "path", "required": true, "description": "Full domain name, such as example.com.", "schema": {"type": "string", "minLength": 1}}
        ],
        "responses": {
          "200": {"description": "Domain sales history.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/DomainHistoryResponse"}}}},
          "404": {"description": "Domain history was not found.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ErrorResponse"}}}}
        }
      }
    },
    "/sales/stats": {
      "get": {
        "operationId": "getMarketStatistics",
        "summary": "Market Statistics",
        "description": "Return aggregate market statistics, price distribution, and daily trend data.",
        "tags": ["Statistics"],
        "parameters": [
          {"name": "date_from", "in": "query", "description": "Include sales on or after this ISO-8601 date.", "schema": {"type": "string", "format": "date"}},
          {"name": "date_to", "in": "query", "description": "Include sales on or before this ISO-8601 date.", "schema": {"type": "string", "format": "date"}},
          {"name": "tld", "in": "query", "description": "Filter statistics to one top-level domain.", "schema": {"type": "string"}}
        ],
        "responses": {
          "200": {"description": "Market statistics.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/MarketStatsResponse"}}}}
        }
      }
    },
    "/sales/tlds": {
      "get": {
        "operationId": "getTldStatistics",
        "summary": "TLD Statistics",
        "description": "Return sales performance grouped by top-level domain.",
        "tags": ["Statistics"],
        "parameters": [
          {"name": "date_from", "in": "query", "description": "Include sales on or after this ISO-8601 date.", "schema": {"type": "string", "format": "date"}},
          {"name": "date_to", "in": "query", "description": "Include sales on or before this ISO-8601 date.", "schema": {"type": "string", "format": "date"}}
        ],
        "responses": {
          "200": {"description": "TLD statistics.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/TldStatsResponse"}}}}
        }
      }
    },
    "/sales/platforms": {
      "get": {
        "operationId": "getPlatformStatistics",
        "summary": "Platform Statistics",
        "description": "Return sales performance grouped by marketplace or sales platform.",
        "tags": ["Statistics"],
        "parameters": [
          {"name": "date_from", "in": "query", "description": "Include sales on or after this ISO-8601 date.", "schema": {"type": "string", "format": "date"}},
          {"name": "date_to", "in": "query", "description": "Include sales on or before this ISO-8601 date.", "schema": {"type": "string", "format": "date"}}
        ],
        "responses": {
          "200": {"description": "Platform statistics.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/PlatformStatsResponse"}}}}
        }
      }
    },
    "/sales/top": {
      "get": {
        "operationId": "getTopDomainSales",
        "summary": "Top Sales",
        "description": "Return the highest-priced recorded domain sales, optionally filtered by date and TLD.",
        "tags": ["Sales"],
        "parameters": [
          {"name": "limit", "in": "query", "description": "Number of results, capped at 500.", "schema": {"type": "integer", "minimum": 1, "maximum": 500, "default": 100}},
          {"name": "date_from", "in": "query", "description": "Include sales on or after this ISO-8601 date.", "schema": {"type": "string", "format": "date"}},
          {"name": "date_to", "in": "query", "description": "Include sales on or before this ISO-8601 date.", "schema": {"type": "string", "format": "date"}},
          {"name": "tld", "in": "query", "description": "Filter results to a single top-level domain.", "schema": {"type": "string"}}
        ],
        "responses": {
          "200": {"description": "Top domain sales.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/TopSalesResponse"}}}}
        }
      }
    },
    "/sales/upsert": {
      "post": {
        "operationId": "upsertDomainSale",
        "summary": "Create or Update Sale",
        "description": "Create or update one domain sale record. Requires an API key with write permission.",
        "tags": ["Admin"],
        "security": [{"ApiKeyAuth": []}],
        "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/UpsertRequest"}}}},
        "responses": {
          "200": {"description": "Sale created or updated.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/UpsertResponse"}}}},
          "401": {"description": "API key missing or invalid.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ErrorResponse"}}}},
          "403": {"description": "API key lacks write permission.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ErrorResponse"}}}}
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "ApiKeyAuth": {"type": "apiKey", "in": "header", "name": "X-API-Key", "description": "API key issued by DomainCrust."}
    },
    "headers": {
      "RateLimitLimit": {"description": "Maximum requests allowed in the active rate-limit window.", "schema": {"type": "integer", "minimum": 0}},
      "RateLimitRemaining": {"description": "Requests remaining in the active rate-limit window.", "schema": {"type": "integer", "minimum": 0}},
      "RateLimitReset": {"description": "Seconds until the active rate-limit window resets.", "schema": {"type": "integer", "minimum": 0}},
      "RetryAfter": {"description": "Seconds the client should wait before retrying a throttled request.", "schema": {"type": "integer", "minimum": 1}}
    },
    "schemas": {
      "DomainSale": {
        "type": "object",
        "description": "A recorded domain sale.",
        "properties": {
          "id": {"type": "integer"}, "name": {"type": "string"}, "tld": {"type": "string"}, "sale_price": {"type": "integer"}, "sale_date": {"type": "string", "format": "date"}, "platform": {"type": "string"}, "domain_score": {"type": "integer", "minimum": 0, "maximum": 100}, "phrase_words": {"type": "string"}, "word_count": {"type": "integer"}, "has_numbers": {"type": "boolean"}, "has_hyphen": {"type": "boolean"}, "registration_date": {"type": "string", "format": "date"}, "domain_age_years": {"type": "integer"}
        }
      },
      "Pagination": {
        "type": "object",
        "properties": {"page": {"type": "integer"}, "limit": {"type": "integer"}, "total": {"type": "integer"}, "pages": {"type": "integer"}}
      },
      "HealthResponse": {
        "type": "object",
        "required": ["success", "data"],
        "properties": {"success": {"type": "boolean"}, "data": {"type": "object", "properties": {"status": {"type": "string"}, "version": {"type": "string"}, "timestamp": {"type": "string", "format": "date-time"}}}}
      },
      "SalesSearchResponse": {
        "type": "object",
        "required": ["success", "data"],
        "properties": {"success": {"type": "boolean"}, "data": {"type": "object", "properties": {"sales": {"type": "array", "items": {"$ref": "#/components/schemas/DomainSale"}}, "pagination": {"$ref": "#/components/schemas/Pagination"}}}, "meta": {"$ref": "#/components/schemas/Meta"}}
      },
      "DomainHistoryResponse": {
        "type": "object",
        "required": ["success", "data"],
        "properties": {"success": {"type": "boolean"}, "data": {"type": "object", "properties": {"domain": {"type": "string"}, "sales_count": {"type": "integer"}, "sales": {"type": "array", "items": {"$ref": "#/components/schemas/DomainSale"}}}}, "meta": {"$ref": "#/components/schemas/Meta"}}
      },
      "MarketStats": {
        "type": "object",
        "properties": {"total_sales": {"type": "integer"}, "unique_domains": {"type": "integer"}, "total_volume": {"type": "number"}, "avg_price": {"type": "number"}, "min_price": {"type": "integer"}, "max_price": {"type": "integer"}, "avg_score": {"type": "number"}}
      },
      "MarketStatsResponse": {
        "type": "object",
        "required": ["success", "data"],
        "properties": {"success": {"type": "boolean"}, "data": {"type": "object", "properties": {"summary": {"$ref": "#/components/schemas/MarketStats"}, "price_distribution": {"type": "array", "items": {"type": "object", "additionalProperties": true}}, "daily_trend": {"type": "array", "items": {"type": "object", "additionalProperties": true}}}}, "meta": {"$ref": "#/components/schemas/Meta"}}
      },
      "TldStats": {"type": "object", "properties": {"tld": {"type": "string"}, "sales_count": {"type": "integer"}, "unique_domains": {"type": "integer"}, "total_volume": {"type": "number"}, "avg_price": {"type": "number"}, "min_price": {"type": "integer"}, "max_price": {"type": "integer"}, "avg_score": {"type": "number"}}},
      "TldStatsResponse": {"type": "object", "required": ["success", "data"], "properties": {"success": {"type": "boolean"}, "data": {"type": "object", "properties": {"tlds": {"type": "array", "items": {"$ref": "#/components/schemas/TldStats"}}}}, "meta": {"$ref": "#/components/schemas/Meta"}}},
      "PlatformStats": {"type": "object", "properties": {"platform": {"type": "string"}, "sales_count": {"type": "integer"}, "total_volume": {"type": "number"}, "avg_price": {"type": "number"}, "min_price": {"type": "integer"}, "max_price": {"type": "integer"}}},
      "PlatformStatsResponse": {"type": "object", "required": ["success", "data"], "properties": {"success": {"type": "boolean"}, "data": {"type": "object", "properties": {"platforms": {"type": "array", "items": {"$ref": "#/components/schemas/PlatformStats"}}}}, "meta": {"$ref": "#/components/schemas/Meta"}}},
      "TopSalesResponse": {"type": "object", "required": ["success", "data"], "properties": {"success": {"type": "boolean"}, "data": {"type": "object", "properties": {"sales": {"type": "array", "items": {"$ref": "#/components/schemas/DomainSale"}}}}, "meta": {"$ref": "#/components/schemas/Meta"}}},
      "UpsertRequest": {"type": "object", "required": ["name", "tld", "sale_price", "sale_date"], "properties": {"name": {"type": "string"}, "tld": {"type": "string"}, "sale_price": {"type": "integer", "minimum": 0}, "sale_date": {"type": "string", "format": "date"}, "platform": {"type": "string"}, "domain_score": {"type": "integer", "minimum": 0, "maximum": 100}, "phrase_words": {"type": "string"}, "word_count": {"type": "integer"}, "has_numbers": {"type": "boolean"}, "has_hyphen": {"type": "boolean"}, "registration_date": {"type": "string", "format": "date"}, "domain_age_years": {"type": "integer"}}},
      "UpsertResponse": {"type": "object", "required": ["success", "data"], "properties": {"success": {"type": "boolean"}, "data": {"type": "object", "properties": {"bulk": {"type": "boolean"}, "result": {"type": "object", "properties": {"id": {"type": "integer"}, "action": {"type": "string", "enum": ["created", "updated"]}}}}}, "meta": {"$ref": "#/components/schemas/Meta"}}},
      "Meta": {"type": "object", "properties": {"request_id": {"type": "string"}, "timestamp": {"type": "string", "format": "date-time"}}},
      "ErrorResponse": {"type": "object", "required": ["success", "error"], "properties": {"success": {"type": "boolean", "example": false}, "error": {"type": "object", "properties": {"code": {"type": "string"}, "message": {"type": "string"}, "details": {"type": "object", "additionalProperties": true}}}, "meta": {"$ref": "#/components/schemas/Meta"}}}
    }
  }
}
