{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://artifacts.apis.io/cheapest-domains/json-schema/cheapest-domains-prices-schema.json",
  "title": "Prices",
  "x-generated": "2026-11-04",
  "x-method": "derived",
  "x-generator": "derive-json-schema.py",
  "x-source": "openapi/cheapest-domains-openapi.json#/components/schemas/Prices",
  "allOf": [
    {
      "$ref": "#/$defs/Envelope"
    },
    {
      "type": "object",
      "required": [
        "comparison",
        "offers",
        "query",
        "pagination"
      ],
      "properties": {
        "comparison": {
          "$ref": "#/$defs/Comparison"
        },
        "offers": {
          "type": "array",
          "maxItems": 200,
          "items": {
            "$ref": "#/$defs/Offer"
          }
        },
        "favoriteOffers": {
          "type": "array",
          "maxItems": 400,
          "description": "Only requested favorites for this page’s extensions, independent of filters. Missing offers are absent; stale offers remain labeled.",
          "items": {
            "allOf": [
              {
                "$ref": "#/$defs/Offer"
              },
              {
                "type": "object",
                "properties": {
                  "differenceFromCheapestCents": {
                    "type": [
                      "integer",
                      "null"
                    ],
                    "description": "Selected metric minus the lowest fresh quote across all connected registrars. Null for stale/unpriced quotes or absent fresh baseline; never claim savings from stale data."
                  }
                }
              }
            ]
          }
        },
        "favoriteBaselines": {
          "type": "array",
          "maxItems": 200,
          "items": {
            "$ref": "#/$defs/Offer"
          },
          "description": "Lowest fresh saved quote per returned extension for the selected metric, independent of filters. Omitted where no fresh priced baseline exists."
        },
        "query": {
          "type": "object"
        },
        "pagination": {
          "type": "object",
          "required": [
            "limit",
            "offset",
            "total",
            "next"
          ],
          "properties": {
            "limit": {
              "type": "integer"
            },
            "offset": {
              "type": "integer"
            },
            "total": {
              "type": "integer"
            },
            "next": {
              "type": [
                "string",
                "null"
              ]
            }
          }
        }
      }
    }
  ],
  "$defs": {
    "Comparison": {
      "type": "object",
      "required": [
        "url",
        "omittedParameters"
      ],
      "description": "Revisit current standard prices with supported website filters. Omits proposed names and API pagination; does not save prices or availability.",
      "properties": {
        "url": {
          "type": "string",
          "format": "uri"
        },
        "omittedParameters": {
          "type": "array",
          "items": {
            "enum": [
              "years",
              "favorites"
            ]
          },
          "description": "Estimate horizons outside 2, 3, 5 and 10 years use the website default. Favorites are browser-local preferences and are never written by a link. Disclose omitted settings."
        }
      }
    },
    "Coverage": {
      "type": "object",
      "required": [
        "scope",
        "totalOffers",
        "freshOffers",
        "sources",
        "notCompared",
        "partial"
      ],
      "properties": {
        "scope": {
          "type": "string"
        },
        "totalOffers": {
          "type": "integer"
        },
        "freshOffers": {
          "type": "integer"
        },
        "partial": {
          "type": "boolean"
        },
        "error": {
          "type": [
            "string",
            "null"
          ]
        },
        "sources": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/Source"
          }
        },
        "notCompared": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "name": {
                "type": "string"
              },
              "url": {
                "type": "string"
              },
              "reason": {
                "type": "string"
              }
            }
          }
        }
      }
    },
    "Destination": {
      "type": "object",
      "required": [
        "href",
        "mode",
        "domain"
      ],
      "properties": {
        "href": {
          "type": "string",
          "format": "uri"
        },
        "mode": {
          "type": "string",
          "enum": [
            "search",
            "copy",
            "pricing"
          ]
        },
        "domain": {
          "type": "string"
        }
      }
    },
    "Envelope": {
      "type": "object",
      "required": [
        "service",
        "apiVersion",
        "generatedAt",
        "currency",
        "coverage",
        "limits"
      ],
      "properties": {
        "service": {
          "$ref": "#/$defs/ServiceInformation"
        },
        "apiVersion": {
          "type": "string"
        },
        "generatedAt": {
          "type": "string",
          "format": "date-time"
        },
        "currency": {
          "const": "USD"
        },
        "availability": {
          "const": "not_checked"
        },
        "coverage": {
          "$ref": "#/$defs/Coverage"
        },
        "limits": {
          "type": "array",
          "items": {
            "type": "string"
          }
        }
      }
    },
    "Offer": {
      "type": "object",
      "required": [
        "tld",
        "registrarId",
        "registrarName",
        "currency",
        "registrationCents",
        "renewalCents",
        "minimumTermYears",
        "stale",
        "estimatedTotalCents",
        "estimateYears",
        "availability",
        "pageUrl",
        "sourceUrl",
        "registrarSearch"
      ],
      "properties": {
        "tld": {
          "type": "string"
        },
        "registrarId": {
          "type": "string"
        },
        "registrarName": {
          "type": "string"
        },
        "currency": {
          "const": "USD"
        },
        "registrationCents": {
          "type": "integer",
          "minimum": 0,
          "description": "Integer USD cents; 1000 = USD 10."
        },
        "renewalCents": {
          "type": "integer",
          "minimum": 0,
          "description": "Integer USD cents; 1000 = USD 10."
        },
        "minimumTermYears": {
          "type": "integer",
          "minimum": 1
        },
        "countryCode": {
          "type": "boolean"
        },
        "sourceUrl": {
          "type": "string",
          "format": "uri"
        },
        "fetchedAt": {
          "type": [
            "string",
            "null"
          ]
        },
        "nextRefreshAt": {
          "type": [
            "string",
            "null"
          ],
          "description": "When the saved catalog is due for its next scheduled refresh; not an expiry of its prices."
        },
        "stale": {
          "type": "boolean",
          "description": "True when the source’s last refresh failed and its saved catalog is at least 24 hours old. Passing nextRefreshAt alone does not make prices stale; a scheduled refresh every 15 minutes replaces due catalogs."
        },
        "estimatedTotalCents": {
          "type": [
            "integer",
            "null"
          ],
          "description": "Null for multi-year minimum terms; not zero."
        },
        "estimateYears": {
          "type": "integer",
          "minimum": 1,
          "maximum": 10,
          "default": 3,
          "description": "Planning horizon in years, including initial registration."
        },
        "availability": {
          "const": "not_checked"
        },
        "pageUrl": {
          "type": "string",
          "format": "uri"
        },
        "registrarSearch": {
          "$ref": "#/$defs/Destination"
        },
        "futureRenewalCents": {
          "type": "integer",
          "minimum": 0,
          "description": "Integer USD cents; 1000 = USD 10."
        },
        "futureRenewalDate": {
          "type": "string"
        },
        "regularRenewalCents": {
          "type": "integer",
          "minimum": 0,
          "description": "Integer USD cents; 1000 = USD 10."
        },
        "regularRegistrationCents": {
          "type": "integer",
          "minimum": 0,
          "description": "Integer USD cents; 1000 = USD 10."
        },
        "transferCents": {
          "type": "integer",
          "minimum": 0,
          "description": "Integer USD cents; 1000 = USD 10."
        },
        "registrationTermCents": {
          "type": "integer",
          "minimum": 0,
          "description": "Integer USD cents; 1000 = USD 10."
        },
        "renewalTermCents": {
          "type": "integer",
          "minimum": 0,
          "description": "Integer USD cents; 1000 = USD 10."
        },
        "pricingBasis": {
          "type": "string",
          "enum": [
            "sampled_standard",
            "sampled_api"
          ],
          "description": "Absent for published price lists. sampled_standard: standard-tier prices sampled from registrar search results (Cloudflare). sampled_api (API 1.9.0): registrar API purchase and auto-renewal rates sampled with a synthetic name (GoDaddy); the registrar website and manual renewals can charge more. Both have limited coverage and are not exact-name quotes. Preserve this distinction when displaying or reusing prices."
        },
        "originalCurrency": {
          "type": "string"
        },
        "originalRegistrationCents": {
          "type": "integer"
        },
        "originalRenewalCents": {
          "type": "integer"
        },
        "exchangeRate": {
          "type": "number"
        },
        "exchangeRateDate": {
          "type": "string"
        },
        "exchangeRateSourceUrl": {
          "type": "string"
        },
        "billingCountry": {
          "type": "string"
        },
        "taxExcluded": {
          "type": "boolean"
        },
        "priceValidUntil": {
          "type": "string",
          "format": "date-time",
          "description": "When a scheduled price change takes effect or the exchange rate behind a converted price expires; recheck after this time."
        },
        "renewalSince": {
          "type": "string",
          "format": "date-time",
          "description": "API 1.12.0: when this renewal price (with its regular price) was first seen; unchanged since. Absent when not yet dated. See renewalSinceFirstRecord and the price history endpoint."
        },
        "renewalSinceFirstRecord": {
          "type": "boolean",
          "description": "True when renewalSince is our earliest record of this price, so the price may be older. Say \"unchanged since at least\" that date."
        }
      }
    },
    "ServiceInformation": {
      "type": "object",
      "required": [
        "name",
        "url",
        "setupUrl",
        "pluginUrl"
      ],
      "description": "Cheapest Domains identity and optional setup links, separate from upstream evidence. Does not establish client installation or provider health.",
      "properties": {
        "name": {
          "const": "Cheapest Domains"
        },
        "url": {
          "type": "string",
          "format": "uri"
        },
        "setupUrl": {
          "type": "string",
          "format": "uri"
        },
        "pluginUrl": {
          "type": "string",
          "format": "uri"
        }
      }
    },
    "Source": {
      "type": "object",
      "required": [
        "id",
        "name",
        "url",
        "offerCount",
        "freshOfferCount",
        "stale",
        "refreshing"
      ],
      "properties": {
        "id": {
          "type": "string"
        },
        "name": {
          "type": "string"
        },
        "url": {
          "type": "string",
          "format": "uri"
        },
        "note": {
          "type": "string"
        },
        "offerCount": {
          "type": "integer"
        },
        "freshOfferCount": {
          "type": "integer"
        },
        "fetchedAt": {
          "type": [
            "string",
            "null"
          ]
        },
        "nextRefreshAt": {
          "type": [
            "string",
            "null"
          ],
          "description": "When the saved catalog is due for its next scheduled refresh; not an expiry of its prices."
        },
        "stale": {
          "type": "boolean",
          "description": "True when the source’s last refresh failed and its saved catalog is at least 24 hours old. Passing nextRefreshAt alone does not make prices stale; a scheduled refresh every 15 minutes replaces due catalogs."
        },
        "refreshing": {
          "type": "boolean"
        },
        "error": {
          "type": [
            "string",
            "null"
          ]
        },
        "refresh": {
          "type": "object",
          "required": [
            "phase",
            "completed",
            "total",
            "startedAt",
            "resumeAt"
          ],
          "description": "Progress of a staged catalog refresh, when one exists. Saved prices remain usable meanwhile.",
          "properties": {
            "phase": {
              "enum": [
                "queued",
                "running",
                "waiting",
                "paused",
                "complete"
              ]
            },
            "completed": {
              "type": "integer",
              "minimum": 0
            },
            "total": {
              "type": "integer",
              "minimum": 0
            },
            "startedAt": {
              "type": "integer",
              "description": "Unix time in milliseconds."
            },
            "resumeAt": {
              "type": "integer",
              "description": "Unix time in milliseconds."
            }
          }
        }
      }
    }
  }
}