{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://artifacts.apis.io/craftingeventfinder-com/json-schema/craftingeventfinder-com-event-detail-schema.json",
  "title": "EventDetail",
  "x-generated": "2026-11-10",
  "x-method": "derived",
  "x-generator": "derive-json-schema.py",
  "x-source": "openapi/craftingeventfinder-com-events-api-openapi.yml#/components/schemas/EventDetail",
  "allOf": [
    {
      "$ref": "#/$defs/Event"
    },
    {
      "type": "object",
      "properties": {
        "upcoming_dates": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "start": {
                "type": "string"
              },
              "end": {
                "type": "string"
              }
            },
            "required": [
              "start",
              "end"
            ]
          }
        },
        "recurrence_label": {
          "type": [
            "string",
            "null"
          ]
        },
        "owned": {
          "type": "boolean",
          "description": "An organizer manages this event (it can't be claimed)"
        },
        "managedBy": {
          "allOf": [
            {
              "$ref": "#/$defs/EventManager"
            },
            {
              "type": [
                "object",
                "null"
              ],
              "description": "The managing organizer when their profile is public, else null (also null when owned is false)"
            }
          ]
        }
      },
      "required": [
        "upcoming_dates",
        "recurrence_label",
        "owned",
        "managedBy"
      ]
    }
  ],
  "$defs": {
    "Event": {
      "type": "object",
      "properties": {
        "id": {
          "type": "string"
        },
        "slug": {
          "type": "string"
        },
        "title": {
          "type": "string"
        },
        "description": {
          "type": [
            "string",
            "null"
          ]
        },
        "summary": {
          "type": [
            "string",
            "null"
          ]
        },
        "start_date": {
          "type": "string"
        },
        "end_date": {
          "type": [
            "string",
            "null"
          ]
        },
        "start_time": {
          "type": [
            "string",
            "null"
          ]
        },
        "end_time": {
          "type": [
            "string",
            "null"
          ]
        },
        "timezone": {
          "type": [
            "string",
            "null"
          ]
        },
        "city": {
          "type": "string"
        },
        "state": {
          "type": "string"
        },
        "venue": {
          "type": [
            "string",
            "null"
          ]
        },
        "location_kind": {
          "type": "string",
          "enum": [
            "venue",
            "online",
            "hybrid",
            "multi"
          ],
          "description": "venue, online, hybrid (one place and online at once) or multi (several places)"
        },
        "street_address": {
          "type": [
            "string",
            "null"
          ]
        },
        "postal_code": {
          "type": [
            "string",
            "null"
          ]
        },
        "signup_note": {
          "type": [
            "string",
            "null"
          ]
        },
        "craft_types": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "event_type": {
          "type": [
            "string",
            "null"
          ]
        },
        "tags": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "url": {
          "type": [
            "string",
            "null"
          ]
        },
        "source_url": {
          "type": [
            "string",
            "null"
          ]
        },
        "organizer_name": {
          "type": [
            "string",
            "null"
          ]
        },
        "lat": {
          "type": [
            "number",
            "null"
          ]
        },
        "lng": {
          "type": [
            "number",
            "null"
          ]
        },
        "price_note": {
          "type": [
            "string",
            "null"
          ]
        },
        "is_free": {
          "type": [
            "boolean",
            "null"
          ]
        },
        "published_at": {
          "type": [
            "string",
            "null"
          ]
        },
        "languages": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "description": "The languages it is held in, as BCP 47 codes (en, es); empty when unknown"
        },
        "hosted_by": {
          "type": [
            "string",
            "null"
          ],
          "description": "The group or shop hosting an online or hybrid event, when given"
        },
        "hasJoinDetails": {
          "type": "boolean",
          "description": "An online or hybrid event with join details (link, meeting ID, passcode or dial-in); get them from GET /api/events/{slug}/join"
        },
        "joinPlatform": {
          "type": [
            "string",
            "null"
          ],
          "enum": [
            "zoom",
            "meet",
            "teams",
            "webex",
            "facebook",
            "youtube",
            "other",
            null
          ],
          "description": "The online meeting platform, for online events"
        },
        "contactName": {
          "type": [
            "string",
            "null"
          ],
          "description": "The organizer's contact person"
        },
        "hasContactDetails": {
          "type": "boolean",
          "description": "A contact email or phone exists; get them from GET /api/events/{slug}/contact"
        },
        "isNew": {
          "type": "boolean",
          "description": "Published within the last 7 days"
        },
        "updatedRecently": {
          "type": "boolean",
          "description": "Its date, time, place or price changed within the last 7 days"
        },
        "changedFields": {
          "type": "array",
          "items": {
            "type": "string",
            "enum": [
              "date",
              "time",
              "place",
              "price"
            ]
          },
          "description": "What changed (date, time, place, price); empty unless updatedRecently"
        },
        "contentChangedAt": {
          "type": [
            "string",
            "null"
          ],
          "description": "When its date, time, place or price last changed; null if never"
        },
        "cancelled": {
          "type": "boolean",
          "description": "A cancelled event (only GET /api/events/{slug} returns one, until its dates pass); lists never include it"
        },
        "scheduleChange": {
          "type": [
            "string",
            "null"
          ],
          "enum": [
            "postponed",
            "rescheduled",
            "moved_online",
            null
          ],
          "description": "postponed (new date to come), rescheduled or moved_online; null when it runs as listed"
        },
        "previousStartDate": {
          "type": [
            "string",
            "null"
          ],
          "description": "The start date a rescheduled event had before (YYYY-MM-DD); null otherwise"
        },
        "images": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/PublicEventImage"
          },
          "description": "The organizer's pictures in order, at most 6; the first is the cover. Empty when there are none"
        }
      },
      "required": [
        "id",
        "slug",
        "title",
        "description",
        "summary",
        "start_date",
        "end_date",
        "start_time",
        "end_time",
        "timezone",
        "city",
        "state",
        "venue",
        "location_kind",
        "street_address",
        "postal_code",
        "signup_note",
        "craft_types",
        "event_type",
        "tags",
        "url",
        "source_url",
        "organizer_name",
        "lat",
        "lng",
        "price_note",
        "is_free",
        "published_at",
        "languages",
        "hosted_by",
        "hasJoinDetails",
        "joinPlatform",
        "contactName",
        "hasContactDetails",
        "isNew",
        "updatedRecently",
        "changedFields",
        "contentChangedAt",
        "cancelled",
        "scheduleChange",
        "previousStartDate",
        "images"
      ]
    },
    "EventManager": {
      "type": "object",
      "properties": {
        "slug": {
          "type": "string",
          "description": "Their public page: /organizers/{slug} (GET /api/organizers/{slug})"
        },
        "displayName": {
          "type": "string"
        },
        "avatarUrl": {
          "type": [
            "string",
            "null"
          ],
          "description": "The 512px picture, or null when the default badge shows"
        },
        "avatarSmallUrl": {
          "type": [
            "string",
            "null"
          ],
          "description": "The 96px picture"
        },
        "defaultAvatar": {
          "type": "string",
          "description": "The built-in badge, '<craft icon>-<color 1-6>'"
        }
      },
      "required": [
        "slug",
        "displayName",
        "avatarUrl",
        "avatarSmallUrl",
        "defaultAvatar"
      ]
    },
    "PublicEventImage": {
      "type": "object",
      "properties": {
        "url": {
          "type": "string",
          "description": "The picture at most 1600px wide (WebP)"
        },
        "cardUrl": {
          "type": "string",
          "description": "The picture at most 600px wide (WebP), for cards"
        },
        "alt": {
          "type": "string",
          "description": "The description read to people who can't see the picture"
        },
        "width": {
          "type": "integer"
        },
        "height": {
          "type": "integer"
        },
        "focusX": {
          "type": "number",
          "description": "The focus point across, 0 (left) to 1 (right), kept in view when the picture is cropped"
        },
        "focusY": {
          "type": "number",
          "description": "The focus point down, 0 (top) to 1 (bottom)"
        }
      },
      "required": [
        "url",
        "cardUrl",
        "alt",
        "width",
        "height",
        "focusX",
        "focusY"
      ]
    }
  }
}