{
 "$schema": "https://json-schema.org/draft/2020-12/schema",
 "$id": "https://philadelphia.whatsupin.ai/data/event.schema.json",
 "title": "Philadelphia Events event",
 "type": "object",
 "description": "One upcoming event in data/events.json (and data/events_rest.json). Fields marked optional are absent when unknown.",
 "required": [
  "id",
  "title",
  "date",
  "link"
 ],
 "properties": {
  "id": {
   "type": "string",
   "pattern": "^[0-9a-f]{12}$",
   "description": "Stable public id. Kept while the event stays listed: a retitle, reschedule or new link by the source does not change it. Ids are never reused for a different event."
  },
  "title": {
   "type": "string"
  },
  "date": {
   "type": "string",
   "format": "date",
   "description": "Local start date (site time zone)."
  },
  "start_time": {
   "type": [
    "string",
    "null"
   ],
   "format": "date-time",
   "description": "Local start with UTC offset; null for all-day or untimed."
  },
  "end_time": {
   "type": [
    "string",
    "null"
   ],
   "format": "date-time"
  },
  "location": {
   "type": [
    "string",
    "null"
   ]
  },
  "ll": {
   "type": "array",
   "items": {
    "type": "number"
   },
   "minItems": 2,
   "maxItems": 2,
   "description": "[lat, lon] of the venue (optional)."
  },
  "price": {
   "type": [
    "string",
    "null"
   ],
   "description": "Only an all-in price or \"Free\". When the source does not state the all-in total there is no number; see tix."
  },
  "free": {
   "type": "boolean",
   "description": "Optional. True when the listing is free."
  },
  "tix": {
   "type": "boolean",
   "description": "Optional. Paid event; the source does not state an all-in price, so none is shown."
  },
  "categories": {
   "type": "array",
   "items": {
    "type": "string"
   }
  },
  "tags": {
   "type": "array",
   "items": {
    "type": "string"
   },
   "description": "topic/<name> tags and others."
  },
  "performers": {
   "type": "array",
   "items": {
    "type": "string"
   },
   "description": "Optional."
  },
  "link": {
   "type": [
    "string",
    "null"
   ],
   "format": "uri",
   "description": "The original listing. Link to it when you use the event."
  },
  "srcs": {
   "type": "array",
   "items": {
    "type": "string"
   },
   "description": "Every source that lists the event (MCP calls this `sources`)."
  },
  "org": {
   "type": "array",
   "items": {
    "type": "string"
   },
   "description": "Organizer per source, aligned with srcs (optional)."
  },
  "fs": {
   "type": "string",
   "format": "date",
   "description": "first_seen: first day a fetch of the source listed this event."
  },
  "ls": {
   "type": "string",
   "format": "date",
   "description": "last_seen: latest day a fetch of the source listed it. Older than ft means the source has stopped listing it."
  },
  "ft": {
   "type": "string",
   "format": "date",
   "description": "last_fetched: the day the source was last fetched."
  },
  "dup_count": {
   "type": "integer",
   "description": "Optional. Number of sources merged into this card."
  },
  "rv": {
   "type": "string",
   "description": "Provenance fingerprint (keyed by us). Keep it if you copy the record."
  }
 }
}
