{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://splitclubapp.com/schemas/v1/availability.json",
  "title": "Availability",
  "description": "When an offering can be bought: explicit slots and/or recurring rules, minus blackout dates.",
  "x-doc": "schema-availability",
  "type": "object",
  "additionalProperties": false,
  "properties": {
    "timezone": {
      "type": "string",
      "maxLength": 64,
      "pattern": "^[A-Za-z_]+(/[A-Za-z0-9_+-]+){0,2}$",
      "x-expected": "an IANA time zone (e.g. \"America/New_York\")",
      "examples": [
        "America/New_York"
      ]
    },
    "slots": {
      "type": "array",
      "maxItems": 1000,
      "items": {
        "$ref": "#/$defs/slot"
      }
    },
    "recurring": {
      "type": "array",
      "maxItems": 20,
      "items": {
        "$ref": "#/$defs/rule"
      }
    },
    "blackout_dates": {
      "type": "array",
      "maxItems": 366,
      "uniqueItems": true,
      "items": {
        "type": "string",
        "format": "date"
      }
    },
    "lead_time_minutes": {
      "type": "integer",
      "minimum": 0,
      "maximum": 525600,
      "description": "How long before a slot it can still be booked.",
      "examples": [
        60
      ]
    },
    "cutoff_minutes": {
      "type": "integer",
      "minimum": 0,
      "maximum": 525600,
      "description": "How long before a slot the party must be fully paid (the checkout's pay_by default).",
      "examples": [
        120
      ]
    }
  },
  "$defs": {
    "slot": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "starts_at"
      ],
      "properties": {
        "external_id": {
          "type": "string",
          "minLength": 1,
          "maxLength": 128,
          "pattern": "^[^\\s]+$",
          "description": "Your system's id for this object. Sending the same external_id again updates or replays it; it never makes a second one.",
          "x-expected": "your own id for it, 1–128 characters, no spaces",
          "examples": [
            "tee-sheet-4471"
          ]
        },
        "starts_at": {
          "type": "string",
          "format": "date-time",
          "examples": [
            "2026-11-07T08:00:00-05:00"
          ]
        },
        "ends_at": {
          "type": "string",
          "format": "date-time",
          "examples": [
            "2026-11-07T12:30:00-05:00"
          ]
        },
        "capacity": {
          "type": "integer",
          "minimum": 1,
          "maximum": 5000,
          "examples": [
            4
          ]
        },
        "tier_overrides": {
          "type": "array",
          "maxItems": 20,
          "items": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "tier",
              "amount"
            ],
            "properties": {
              "tier": {
                "type": "string",
                "minLength": 1,
                "maxLength": 128,
                "description": "The tier's external_id (or label)."
              },
              "amount": {
                "type": "integer",
                "minimum": 0,
                "maximum": 100000000,
                "description": "Money in integer minor units (cents for usd): 14500 is $145.00.",
                "x-expected": "an integer in minor units (e.g. 14500 for $145.00)",
                "examples": [
                  14500
                ]
              }
            }
          }
        }
      },
      "examples": [
        {
          "starts_at": "2026-11-07T08:00:00-05:00",
          "capacity": 4
        }
      ]
    },
    "rule": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "rrule",
        "starts_at"
      ],
      "properties": {
        "rrule": {
          "type": "string",
          "maxLength": 500,
          "pattern": "^(RRULE:)?FREQ=(DAILY|WEEKLY|MONTHLY|YEARLY)(;[A-Z]+=[A-Za-z0-9,:+-]+)*$",
          "x-expected": "an RFC 5545 RRULE (e.g. \"FREQ=DAILY;BYHOUR=7,8,9;BYMINUTE=0,10,20,30,40,50\")",
          "examples": [
            "FREQ=DAILY;BYHOUR=7,8,9;BYMINUTE=0,10,20,30,40,50"
          ]
        },
        "starts_at": {
          "type": "string",
          "format": "date-time",
          "examples": [
            "2026-11-07T08:00:00-05:00"
          ],
          "description": "DTSTART: the first occurrence."
        },
        "until": {
          "type": "string",
          "format": "date"
        },
        "duration_minutes": {
          "type": "integer",
          "minimum": 5,
          "maximum": 1440,
          "examples": [
            270
          ]
        },
        "capacity": {
          "type": "integer",
          "minimum": 1,
          "maximum": 5000,
          "examples": [
            4
          ]
        }
      }
    }
  },
  "examples": [
    {
      "timezone": "America/New_York",
      "recurring": [
        {
          "rrule": "FREQ=DAILY;BYHOUR=7,8,9;BYMINUTE=0,10,20,30,40,50",
          "starts_at": "2026-11-01T07:00:00-05:00",
          "duration_minutes": 270,
          "capacity": 4
        }
      ],
      "blackout_dates": [
        "2026-11-26"
      ],
      "lead_time_minutes": 60
    }
  ]
}
