{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://caribescout.com/standard/rees/v0.1/schema.json",
  "title": "REES feed",
  "description": "Real Estate Exchange Standard v0.1: one publisher, its listings and developments.",
  "type": "object",
  "required": [
    "rees",
    "publisher",
    "generated_at",
    "listings"
  ],
  "additionalProperties": false,
  "properties": {
    "rees": {
      "const": "0.1",
      "description": "Spec version this feed follows."
    },
    "publisher": {
      "$ref": "#/$defs/Publisher"
    },
    "generated_at": {
      "type": "string",
      "format": "date-time",
      "description": "When this feed was produced (ISO 8601, with timezone)."
    },
    "license": {
      "$ref": "#/$defs/License"
    },
    "listings": {
      "type": "array",
      "items": {
        "$ref": "#/$defs/Listing"
      },
      "description": "All current listings, or only changes when `since` is set."
    },
    "developments": {
      "type": "array",
      "items": {
        "$ref": "#/$defs/Development"
      }
    },
    "since": {
      "type": "string",
      "format": "date-time",
      "description": "Set when this is a delta feed: only records updated after this instant."
    },
    "next": {
      "type": "string",
      "format": "uri",
      "description": "URL of the next page, for large feeds."
    }
  },
  "$defs": {
    "LocalizedText": {
      "type": "object",
      "description": "Text by language, keyed by ISO 639-1 code: {\"en\": \"...\", \"es\": \"...\"}. At least one language.",
      "minProperties": 1,
      "additionalProperties": {
        "type": "string"
      },
      "propertyNames": {
        "pattern": "^[a-z]{2}(-[A-Z]{2})?$",
        "x-hint": "a language code such as en, es or pt-BR"
      }
    },
    "Money": {
      "type": "object",
      "description": "An amount, its currency and what it is a price OF. Never a bare number.",
      "required": [
        "currency",
        "basis"
      ],
      "additionalProperties": false,
      "properties": {
        "amount": {
          "type": "number",
          "minimum": 0,
          "description": "Required unless basis is on_request. For a range, the low end."
        },
        "max": {
          "type": "number",
          "minimum": 0,
          "description": "High end of a range (basis \"range\")."
        },
        "currency": {
          "type": "string",
          "pattern": "^[A-Z]{3}$",
          "x-hint": "a 3-letter ISO currency code such as USD or DOP, not a symbol",
          "description": "ISO 4217 code: USD, DOP, EUR, JMD… Never a symbol."
        },
        "basis": {
          "enum": [
            "total",
            "per_m2",
            "from",
            "range",
            "per_month",
            "per_week",
            "per_night",
            "per_year",
            "on_request"
          ],
          "description": "total = the whole property; per_m2 = rate × area; from = lowest unit in a development; range = amount…max."
        },
        "includes": {
          "type": "array",
          "items": {
            "enum": [
              "furniture",
              "hoa",
              "utilities",
              "vat",
              "transfer_tax"
            ]
          },
          "description": "What the amount includes, when it is not bare."
        },
        "provenance": {
          "$ref": "#/$defs/Provenance"
        }
      }
    },
    "Measure": {
      "type": "object",
      "required": [
        "value",
        "unit"
      ],
      "additionalProperties": false,
      "properties": {
        "value": {
          "type": "number",
          "exclusiveMinimum": 0
        },
        "unit": {
          "enum": [
            "m2",
            "ft2",
            "ha",
            "acre"
          ],
          "description": "Always stated. No default unit exists."
        },
        "provenance": {
          "$ref": "#/$defs/Provenance"
        }
      }
    },
    "Geo": {
      "type": "object",
      "required": [
        "lat",
        "lng",
        "precision"
      ],
      "additionalProperties": false,
      "properties": {
        "lat": {
          "type": "number",
          "minimum": -90,
          "maximum": 90
        },
        "lng": {
          "type": "number",
          "minimum": -180,
          "maximum": 180
        },
        "precision": {
          "enum": [
            "exact",
            "street",
            "neighbourhood",
            "approximate"
          ],
          "description": "How close the point is to the property. Use \"approximate\" for a deliberately blurred pin."
        },
        "provenance": {
          "$ref": "#/$defs/Provenance"
        }
      }
    },
    "Provenance": {
      "type": "object",
      "description": "Where a value came from. Optional everywhere; required on price and area for the Verified level.",
      "required": [
        "source"
      ],
      "additionalProperties": false,
      "properties": {
        "source": {
          "enum": [
            "owner",
            "agent",
            "developer",
            "survey",
            "registry",
            "appraisal",
            "estimate"
          ]
        },
        "date": {
          "type": "string",
          "format": "date"
        },
        "confidence": {
          "enum": [
            "verified",
            "stated",
            "estimated"
          ],
          "description": "verified = checked against a document; stated = as told; estimated = derived."
        },
        "note": {
          "type": "string"
        }
      }
    },
    "Contact": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "name": {
          "type": "string",
          "minLength": 1
        },
        "email": {
          "type": "string",
          "format": "email"
        },
        "phone": {
          "type": "string",
          "pattern": "^\\+[0-9 ()-]{7,20}$",
          "x-hint": "an international number starting with +, e.g. +1 809 555 0100",
          "description": "E.164-style with country code: +1 809 555 0100."
        },
        "whatsapp": {
          "type": "string",
          "pattern": "^\\+[0-9 ()-]{7,20}$",
          "x-hint": "an international number starting with +"
        }
      }
    },
    "License": {
      "type": "object",
      "description": "What a receiver may do with the data. Set once on the feed; override per listing.",
      "required": [
        "use"
      ],
      "additionalProperties": false,
      "properties": {
        "use": {
          "enum": [
            "republish-with-credit",
            "display-only",
            "idx-personal-use",
            "no-republish"
          ],
          "description": "idx-personal-use = MLS/IDX data a portal may NOT republish; no-republish = analysis only."
        },
        "credit_required": {
          "type": "boolean"
        },
        "backlink_required": {
          "type": "boolean"
        },
        "url": {
          "type": "string",
          "format": "uri",
          "description": "The publisher's terms, if any."
        }
      }
    },
    "Publisher": {
      "type": "object",
      "required": [
        "id",
        "name",
        "website"
      ],
      "additionalProperties": false,
      "properties": {
        "id": {
          "type": "string",
          "pattern": "^[a-z0-9][a-z0-9-]{1,62}$",
          "x-hint": "lowercase letters, digits and hyphens, e.g. \"example-realty\"",
          "description": "Stable slug for the publisher, chosen once: \"cabarete-real-estate\"."
        },
        "name": {
          "type": "string",
          "minLength": 1
        },
        "kind": {
          "enum": [
            "agency",
            "developer",
            "owner",
            "mls",
            "portal"
          ]
        },
        "website": {
          "type": "string",
          "format": "uri"
        },
        "country": {
          "type": "string",
          "pattern": "^[A-Z]{2}$",
          "x-hint": "a 2-letter ISO country code such as DO"
        },
        "contact": {
          "$ref": "#/$defs/Contact"
        },
        "license_number": {
          "type": "string",
          "description": "Local broker licence or registry number, where one exists."
        }
      }
    },
    "Listing": {
      "type": "object",
      "required": [
        "id",
        "url",
        "status",
        "updated_at",
        "operation",
        "property_type",
        "title",
        "price",
        "location"
      ],
      "additionalProperties": false,
      "properties": {
        "id": {
          "type": "string",
          "minLength": 1,
          "maxLength": 128,
          "description": "Stable within the publisher. Never reuse; never change when the listing is edited."
        },
        "url": {
          "type": "string",
          "format": "uri",
          "description": "The listing's canonical page on the publisher's site. Receivers link back here."
        },
        "status": {
          "enum": [
            "active",
            "reserved",
            "sold",
            "rented",
            "withdrawn"
          ]
        },
        "updated_at": {
          "type": "string",
          "format": "date-time"
        },
        "listed_at": {
          "type": "string",
          "format": "date"
        },
        "operation": {
          "enum": [
            "sale",
            "rent_long",
            "rent_mid",
            "rent_short"
          ],
          "description": "rent_mid = monthly, 1–11 months; rent_short = nightly/weekly."
        },
        "property_type": {
          "enum": [
            "apartment",
            "penthouse",
            "villa",
            "house",
            "townhouse",
            "land",
            "commercial",
            "hotel",
            "building",
            "other"
          ]
        },
        "development_id": {
          "type": "string",
          "description": "The development this unit belongs to, when there is one in `developments`."
        },
        "unit": {
          "type": "string",
          "description": "Unit label inside a building or development: \"A-402\"."
        },
        "title": {
          "$ref": "#/$defs/LocalizedText"
        },
        "description": {
          "$ref": "#/$defs/LocalizedText"
        },
        "price": {
          "$ref": "#/$defs/Money"
        },
        "area": {
          "type": "object",
          "additionalProperties": false,
          "properties": {
            "built": {
              "$ref": "#/$defs/Measure",
              "description": "Interior living area."
            },
            "terrace": {
              "$ref": "#/$defs/Measure"
            },
            "plot": {
              "$ref": "#/$defs/Measure",
              "description": "Land. For property_type \"land\", this is the size."
            }
          }
        },
        "rooms": {
          "type": "object",
          "additionalProperties": false,
          "properties": {
            "bedrooms": {
              "type": "integer",
              "minimum": 0,
              "description": "0 = studio."
            },
            "bathrooms": {
              "type": "number",
              "minimum": 0,
              "description": "Half baths as .5."
            },
            "parking": {
              "type": "integer",
              "minimum": 0
            }
          }
        },
        "location": {
          "type": "object",
          "required": [
            "country",
            "city"
          ],
          "additionalProperties": false,
          "properties": {
            "country": {
              "type": "string",
              "pattern": "^[A-Z]{2}$",
              "x-hint": "a 2-letter ISO country code such as DO",
              "description": "ISO 3166-1 alpha-2."
            },
            "region": {
              "type": "string",
              "description": "Province / parish / state."
            },
            "city": {
              "type": "string",
              "minLength": 1
            },
            "area": {
              "type": "string",
              "description": "Neighbourhood, sector or resort: \"Cap Cana\", \"Los Corales\"."
            },
            "address": {
              "type": "string",
              "description": "Omit when the publisher does not disclose it."
            },
            "postal_code": {
              "type": "string"
            },
            "geo": {
              "$ref": "#/$defs/Geo"
            }
          }
        },
        "delivery": {
          "type": "object",
          "required": [
            "status"
          ],
          "additionalProperties": false,
          "properties": {
            "status": {
              "enum": [
                "built",
                "under_construction",
                "off_plan"
              ]
            },
            "year_built": {
              "type": "integer",
              "minimum": 1800,
              "maximum": 2100
            },
            "expected": {
              "type": "string",
              "pattern": "^[0-9]{4}(-Q[1-4]|-[01][0-9])?$",
              "x-hint": "a year, quarter or month: 2027, 2027-Q2 or 2027-06",
              "description": "Handover: \"2027\", \"2027-Q2\" or \"2027-06\"."
            }
          }
        },
        "features": {
          "type": "array",
          "items": {
            "type": "string",
            "pattern": "^[a-z0-9_]+$",
            "x-hint": "lowercase with underscores, e.g. ocean_view"
          },
          "description": "Controlled vocabulary (see the field reference): pool, private_pool, beachfront, ocean_view, gated, furnished, generator, cistern…"
        },
        "media": {
          "type": "array",
          "items": {
            "type": "object",
            "required": [
              "url",
              "type"
            ],
            "additionalProperties": false,
            "properties": {
              "url": {
                "type": "string",
                "format": "uri"
              },
              "type": {
                "enum": [
                  "photo",
                  "floorplan",
                  "video",
                  "tour",
                  "document"
                ]
              },
              "caption": {
                "$ref": "#/$defs/LocalizedText"
              },
              "order": {
                "type": "integer",
                "minimum": 0
              }
            }
          }
        },
        "costs": {
          "type": "object",
          "additionalProperties": false,
          "properties": {
            "hoa": {
              "$ref": "#/$defs/Money",
              "description": "Condominium / maintenance fee. basis MUST be a period (per_month, per_year) or per_m2 with a period in note."
            },
            "property_tax": {
              "$ref": "#/$defs/Money"
            },
            "transfer_tax_pct": {
              "type": "number",
              "minimum": 0,
              "maximum": 30
            }
          }
        },
        "legal": {
          "type": "object",
          "additionalProperties": false,
          "properties": {
            "title_status": {
              "enum": [
                "titled",
                "titled_individual",
                "in_process",
                "untitled",
                "unknown"
              ],
              "description": "titled_individual = its own certificate (in the DR, after deslinde)."
            },
            "survey_done": {
              "type": "boolean",
              "description": "Boundary survey registered (deslinde in the DR)."
            },
            "tax_exemption": {
              "type": "object",
              "required": [
                "scheme"
              ],
              "additionalProperties": false,
              "properties": {
                "scheme": {
                  "type": "string",
                  "description": "e.g. \"CONFOTUR\"."
                },
                "until_year": {
                  "type": "integer",
                  "minimum": 2000,
                  "maximum": 2100
                },
                "provenance": {
                  "$ref": "#/$defs/Provenance"
                }
              }
            },
            "foreign_buyers": {
              "enum": [
                "allowed",
                "restricted",
                "not_allowed",
                "unknown"
              ]
            }
          }
        },
        "agent": {
          "$ref": "#/$defs/Contact"
        },
        "listing_office": {
          "type": "object",
          "required": [
            "name"
          ],
          "additionalProperties": false,
          "description": "The office that holds the listing, when it is not the publisher (co-brokerage, MLS).",
          "properties": {
            "name": {
              "type": "string",
              "minLength": 1
            },
            "id": {
              "type": "string"
            },
            "website": {
              "type": "string",
              "format": "uri"
            }
          }
        },
        "license": {
          "$ref": "#/$defs/License"
        }
      }
    },
    "Development": {
      "type": "object",
      "required": [
        "id",
        "name",
        "url",
        "location",
        "delivery"
      ],
      "additionalProperties": false,
      "properties": {
        "id": {
          "type": "string",
          "minLength": 1,
          "maxLength": 128
        },
        "name": {
          "type": "string",
          "minLength": 1
        },
        "url": {
          "type": "string",
          "format": "uri"
        },
        "developer": {
          "type": "string"
        },
        "location": {
          "$ref": "#/$defs/Listing/properties/location"
        },
        "delivery": {
          "$ref": "#/$defs/Listing/properties/delivery"
        },
        "units_total": {
          "type": "integer",
          "minimum": 1
        },
        "units_available": {
          "type": "integer",
          "minimum": 0
        },
        "price_from": {
          "$ref": "#/$defs/Money"
        },
        "description": {
          "$ref": "#/$defs/LocalizedText"
        },
        "media": {
          "$ref": "#/$defs/Listing/properties/media"
        },
        "features": {
          "$ref": "#/$defs/Listing/properties/features"
        }
      }
    }
  }
}