{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://parpass.example/schema/pass.schema.json",
  "title": "ParPass pass / card row",
  "description": "One golf season pass, discount card, prepaid bundle or loyalty pass. Unknown values MUST be null, never guessed. Every row needs source_url + last_verified.",
  "type": "object",
  "required": [
    "id",
    "city",
    "state",
    "name",
    "issuer",
    "pass_type",
    "price",
    "included",
    "eligibility",
    "rate_scenarios",
    "source_url",
    "last_verified"
  ],
  "additionalProperties": false,
  "properties": {
    "id": {
      "type": "string",
      "pattern": "^[a-z0-9-]+$",
      "description": "URL slug, unique site-wide"
    },
    "city": {
      "type": "string"
    },
    "state": {
      "type": "string",
      "pattern": "^[A-Z]{2}$"
    },
    "name": {
      "type": "string",
      "description": "Pass/card name as the issuer writes it"
    },
    "issuer": {
      "type": "string",
      "description": "Who sells it (city parks dept, course operator)"
    },
    "pass_type": {
      "enum": [
        "unlimited_pass",
        "discount_card",
        "prepaid_bundle",
        "loyalty_points",
        "resident_id_card"
      ]
    },
    "courses": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "description": "Courses where it is valid"
    },
    "price": {
      "type": "object",
      "required": [
        "amount"
      ],
      "additionalProperties": false,
      "properties": {
        "amount": {
          "type": [
            "number",
            "null"
          ],
          "description": "Headline price in USD for the eligible/resident buyer"
        },
        "nonresident_amount": {
          "type": [
            "number",
            "null"
          ]
        },
        "renewal_amount": {
          "type": [
            "number",
            "null"
          ]
        },
        "variants": {
          "type": "array",
          "items": {
            "type": "object",
            "required": [
              "label",
              "amount"
            ],
            "additionalProperties": false,
            "properties": {
              "label": {
                "type": "string"
              },
              "amount": {
                "type": [
                  "number",
                  "null"
                ]
              }
            }
          }
        },
        "tax_note": {
          "type": [
            "string",
            "null"
          ]
        },
        "nonresident_breakeven": {
          "type": [
            "boolean",
            "null"
          ],
          "description": "Set false when the non-resident price is known but the issuer does not publish a separate non-resident card rate, so break-even is not computed for it."
        }
      }
    },
    "validity": {
      "type": [
        "string",
        "null"
      ],
      "description": "Term, e.g. '12 months from purchase' or 'through Dec 31, 2026'"
    },
    "included": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "description": "What the pass includes, as stated by the issuer"
    },
    "eligibility": {
      "type": "object",
      "required": [
        "resident_rules",
        "nonresident_rules"
      ],
      "additionalProperties": false,
      "properties": {
        "resident_only": {
          "type": [
            "boolean",
            "null"
          ]
        },
        "resident_rules": {
          "type": [
            "string",
            "null"
          ]
        },
        "nonresident_rules": {
          "type": [
            "string",
            "null"
          ]
        }
      }
    },
    "benefit_model": {
      "type": "object",
      "additionalProperties": false,
      "description": "How savings are computed when it is not 'with-pass rate vs without-pass rate'.",
      "properties": {
        "discount_pct": {
          "type": [
            "number",
            "null"
          ],
          "description": "Percent discount off green fees (0.10 = 10%). Use the issuer's maximum if stated 'up to'."
        },
        "discount_is_maximum": {
          "type": [
            "boolean",
            "null"
          ]
        },
        "rebate_pct": {
          "type": [
            "number",
            "null"
          ],
          "description": "Effective rebate from loyalty points (0.10 = 10%)"
        },
        "rounds_included": {
          "type": [
            "integer",
            "null"
          ],
          "description": "For prepaid bundles: number of rounds in the bundle"
        },
        "bonus_rounds": {
          "type": [
            "integer",
            "null"
          ],
          "description": "Complimentary rounds mentioned by issuer (not netted out of break-even)"
        }
      }
    },
    "rate_scenarios": {
      "type": "array",
      "description": "Per-round rates. First entry is the 'typical' headline scenario. Use an empty array only if the issuer publishes no usable rate.",
      "items": {
        "type": "object",
        "required": [
          "label",
          "without_pass",
          "with_pass",
          "basis"
        ],
        "additionalProperties": false,
        "properties": {
          "label": {
            "type": "string"
          },
          "without_pass": {
            "type": [
              "number",
              "null"
            ],
            "description": "USD per round if you do NOT have the pass (public/non-card/non-resident rate as stated)"
          },
          "with_pass": {
            "type": [
              "number",
              "null"
            ],
            "description": "USD per round WITH the pass (0 for unlimited green fees)"
          },
          "includes_cart": {
            "type": [
              "boolean",
              "null"
            ]
          },
          "basis": {
            "type": "string",
            "description": "Which rate sheet / assumptions the numbers come from"
          },
          "source_url": {
            "type": [
              "string",
              "null"
            ],
            "format": "uri"
          }
        }
      }
    },
    "affiliate_url": {
      "type": [
        "string",
        "null"
      ],
      "description": "PLACEHOLDER: fill with tracked affiliate link later. Null = link straight to source_url, no sponsored rel."
    },
    "sponsored": {
      "type": "boolean",
      "description": "True once a paid listing; drives a 'Sponsored' label"
    },
    "data_notes": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "description": "Discrepancies, caveats, open questions"
    },
    "confidence": {
      "enum": [
        "high",
        "medium",
        "low"
      ],
      "description": "high = official page read directly; medium = dynamic/sampled rates or minor conflicts"
    },
    "source_url": {
      "type": "string",
      "format": "uri",
      "description": "Official page for the pass itself"
    },
    "additional_sources": {
      "type": "array",
      "items": {
        "type": "string",
        "format": "uri"
      }
    },
    "last_verified": {
      "type": "string",
      "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
    },
    "short_name": {
      "type": "string",
      "maxLength": 40,
      "description": "Short name for page titles / SEO (no parentheses)."
    }
  }
}