{"openapi":"3.1.0","info":{"title":"Live Sports Hula Data API","version":"1.0.0","summary":"Sports schedules with where-to-watch (channel/streaming service) and free/paid availability.","description":"Times are ISO 8601 UTC. Countries are ISO 3166-1 alpha-2. Languages are BCP 47. Ids are stable URNs (lsh:<type>:<UUID v5>). Errors are RFC 9457 problem+json. Use `updated_since` for incremental sync."},"servers":[{"url":"https://nexlitflow.com/live-sports-hula/api/v1"}],"security":[{"bearer":[]}],"paths":{"/events":{"get":{"summary":"List events","description":"Default window: from 12 hours ago, for 8 days. With `updated_since`, returns every event changed after that instant (ordered by updated_at, deleted events included) for incremental sync.","parameters":[{"name":"from","in":"query","required":false,"description":"Start of window (ISO 8601).","schema":{"type":"string","format":"date-time"}},{"name":"to","in":"query","required":false,"description":"End of window, exclusive (ISO 8601).","schema":{"type":"string","format":"date-time"}},{"name":"updated_since","in":"query","required":false,"description":"Delta feed: events changed after this instant.","schema":{"type":"string","format":"date-time"}},{"name":"sport","in":"query","required":false,"description":"Sport id or slug.","schema":{"type":"string"}},{"name":"competition","in":"query","required":false,"description":"Competition id or slug.","schema":{"type":"string"}},{"name":"team","in":"query","required":false,"description":"Team id.","schema":{"type":"string"}},{"name":"region","in":"query","required":false,"description":"Keep only airings for this audience country (ISO 3166-1 alpha-2).","schema":{"type":"string","pattern":"^[A-Z]{2}$"}},{"name":"access","in":"query","required":false,"description":"Only events with a free airing, or only paid ones.","schema":{"enum":["free","paid"]}},{"name":"q","in":"query","required":false,"description":"Search title, teams, competition, venue and service names.","schema":{"type":"string"}},{"name":"ids","in":"query","required":false,"description":"Comma-separated event ids.","schema":{"type":"string"}},{"name":"include_deleted","in":"query","required":false,"description":"Include events the source stopped listing.","schema":{"type":"boolean"}},{"name":"cursor","in":"query","required":false,"description":"Opaque cursor from meta.next_cursor.","schema":{"type":"string"}},{"name":"limit","in":"query","required":false,"description":"Page size (1-1000).","schema":{"type":"integer","default":100}}],"responses":{"200":{"description":"OK","headers":{"ETag":{"schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Event"}},"meta":{"$ref":"#/components/schemas/Meta"}}}}}},"304":{"description":"Not modified (If-None-Match matched)"},"400":{"$ref":"#/components/responses/Problem"},"401":{"$ref":"#/components/responses/Problem"},"429":{"$ref":"#/components/responses/Problem"}}}},"/events/{id}":{"get":{"summary":"Get an event with its change history","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","pattern":"^lsh:event:[0-9a-f-]{36}$","description":"Stable public id (lsh:event:<UUID v5>)."}}],"responses":{"200":{"description":"OK","headers":{"ETag":{"schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Event"},"history":{"type":"array","items":{"type":"object","properties":{"at":{"type":"string","format":"date-time"},"change":{"enum":["created","updated","airings","deleted","restored"]},"fields":{"type":["object","null"]}}}}}}}}},"304":{"description":"Not modified (If-None-Match matched)"},"400":{"$ref":"#/components/responses/Problem"},"401":{"$ref":"#/components/responses/Problem"},"404":{"$ref":"#/components/responses/Problem"},"429":{"$ref":"#/components/responses/Problem"}}}},"/sports":{"get":{"summary":"List sports","responses":{"200":{"description":"OK","headers":{"ETag":{"schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Sport"}},"meta":{"$ref":"#/components/schemas/Meta"}}}}}},"304":{"description":"Not modified (If-None-Match matched)"},"400":{"$ref":"#/components/responses/Problem"},"401":{"$ref":"#/components/responses/Problem"},"429":{"$ref":"#/components/responses/Problem"}}}},"/competitions":{"get":{"summary":"List competitions","parameters":[{"name":"sport","in":"query","required":false,"description":"Sport id or slug.","schema":{"type":"string"}}],"responses":{"200":{"description":"OK","headers":{"ETag":{"schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Competition"}},"meta":{"$ref":"#/components/schemas/Meta"}}}}}},"304":{"description":"Not modified (If-None-Match matched)"},"400":{"$ref":"#/components/responses/Problem"},"401":{"$ref":"#/components/responses/Problem"},"429":{"$ref":"#/components/responses/Problem"}}}},"/teams":{"get":{"summary":"List teams","parameters":[{"name":"sport","in":"query","required":false,"description":"Sport id or slug.","schema":{"type":"string"}},{"name":"q","in":"query","required":false,"description":"Search by name or abbreviation.","schema":{"type":"string"}},{"name":"cursor","in":"query","required":false,"description":"Opaque cursor from meta.next_cursor.","schema":{"type":"string"}},{"name":"limit","in":"query","required":false,"description":"Page size (1-1000).","schema":{"type":"integer","default":100}}],"responses":{"200":{"description":"OK","headers":{"ETag":{"schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Team"}},"meta":{"$ref":"#/components/schemas/Meta"}}}}}},"304":{"description":"Not modified (If-None-Match matched)"},"400":{"$ref":"#/components/responses/Problem"},"401":{"$ref":"#/components/responses/Problem"},"429":{"$ref":"#/components/responses/Problem"}}}},"/services":{"get":{"summary":"List services (channels and streaming services)","parameters":[{"name":"region","in":"query","required":false,"description":"Audience country.","schema":{"type":"string","pattern":"^[A-Z]{2}$"}}],"responses":{"200":{"description":"OK","headers":{"ETag":{"schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Service"}},"meta":{"$ref":"#/components/schemas/Meta"}}}}}},"304":{"description":"Not modified (If-None-Match matched)"},"400":{"$ref":"#/components/responses/Problem"},"401":{"$ref":"#/components/responses/Problem"},"429":{"$ref":"#/components/responses/Problem"}}}},"/epg.xml":{"get":{"summary":"Airings as XMLTV","description":"One <channel> per service and one <programme> per airing. stop= is estimated from the sport's typical duration. Only confirmed airings unless include_rights=true.","parameters":[{"name":"from","in":"query","required":false,"description":"Start of window.","schema":{"type":"string","format":"date-time"}},{"name":"to","in":"query","required":false,"description":"End of window.","schema":{"type":"string","format":"date-time"}},{"name":"region","in":"query","required":false,"description":"Audience country.","schema":{"type":"string","pattern":"^[A-Z]{2}$"}},{"name":"sport","in":"query","required":false,"description":"Sport id or slug.","schema":{"type":"string"}},{"name":"competition","in":"query","required":false,"description":"Competition id or slug.","schema":{"type":"string"}},{"name":"platform","in":"query","required":false,"description":"linear or ott.","schema":{"enum":["linear","ott"]}},{"name":"include_rights","in":"query","required":false,"description":"Also include expected (rights-holder) airings.","schema":{"type":"boolean"}}],"responses":{"200":{"description":"OK","headers":{"ETag":{"schema":{"type":"string"}}},"content":{"application/xml":{"schema":{"type":"string"}}}},"304":{"description":"Not modified (If-None-Match matched)"},"400":{"$ref":"#/components/responses/Problem"},"401":{"$ref":"#/components/responses/Problem"},"429":{"$ref":"#/components/responses/Problem"}}}},"/status":{"get":{"summary":"Data freshness per source (public)","security":[],"responses":{"200":{"description":"All sources fresh"},"503":{"description":"A source is stale"}}}},"/openapi.json":{"get":{"summary":"This document (public)","security":[],"responses":{"200":{"description":"OK"}}}}},"components":{"securitySchemes":{"bearer":{"type":"http","scheme":"bearer","description":"API key issued by Live Sports Hula."}},"responses":{"Problem":{"description":"RFC 9457 problem details","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}},"schemas":{"Meta":{"type":"object","properties":{"count":{"type":"integer"},"next_cursor":{"anyOf":[{"type":"string"},{"type":"null"}]},"api_version":{"type":"string"}}},"Problem":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"}}},"Sport":{"type":"object","required":["id","slug","names"],"properties":{"id":{"type":"string","pattern":"^lsh:sport:[0-9a-f-]{36}$","description":"Stable public id (lsh:sport:<UUID v5>)."},"slug":{"type":"string"},"names":{"type":"object","additionalProperties":{"type":"string"},"description":"Localized names keyed by BCP 47 tag; `en` is always present.","example":{"en":"Soccer","ko":"축구"}}}},"Competition":{"type":"object","properties":{"id":{"type":"string","pattern":"^lsh:competition:[0-9a-f-]{36}$","description":"Stable public id (lsh:competition:<UUID v5>)."},"slug":{"type":"string"},"name":{"type":"string"},"names":{"type":"object","additionalProperties":{"type":"string"},"description":"Localized names keyed by BCP 47 tag; `en` is always present.","example":{"en":"Soccer","ko":"축구"}},"short_name":{"anyOf":[{"type":"string"},{"type":"null"}]},"country":{"anyOf":[{"type":"string","description":"ISO 3166-1 alpha-2, or EU / ASIA"},{"type":"null"}]},"sport":{"$ref":"#/components/schemas/Sport"}}},"Team":{"type":"object","properties":{"id":{"type":"string","pattern":"^lsh:team:[0-9a-f-]{36}$","description":"Stable public id (lsh:team:<UUID v5>)."},"name":{"type":"string"},"short_name":{"anyOf":[{"type":"string"},{"type":"null"}]},"abbreviation":{"anyOf":[{"type":"string"},{"type":"null"}]},"color":{"anyOf":[{"type":"string","pattern":"^[0-9a-fA-F]{6}$"},{"type":"null"}]},"lang":{"anyOf":[{"type":"string"},{"type":"null"}]},"external_ids":{"type":"object","additionalProperties":{"type":"string"}}}},"Service":{"type":"object","properties":{"id":{"type":"string","pattern":"^lsh:service:[0-9a-f-]{36}$","description":"Stable public id (lsh:service:<UUID v5>)."},"name":{"type":"string"},"region":{"type":"string","pattern":"^[A-Z]{2}$"},"platform":{"enum":["linear","ott"]},"monetization":{"enum":["fta","avod","svod","pay_tv","ppv","unknown"],"description":"fta/avod = free; svod/pay_tv/ppv = paid"},"url":{"anyOf":[{"type":"string"},{"type":"null"}]}}},"Airing":{"type":"object","properties":{"service":{"$ref":"#/components/schemas/Service"},"access":{"enum":["free","paid","unknown"]},"note":{"anyOf":[{"type":"string"},{"type":"null"}]},"basis":{"enum":["listed","rights"],"description":"listed: named by the source for this event; rights: competition rights holder"},"confidence":{"enum":["confirmed","expected"]},"market":{"anyOf":[{"enum":["national","home","away"]},{"type":"null"}]}}},"Event":{"type":"object","properties":{"id":{"type":"string","pattern":"^lsh:event:[0-9a-f-]{36}$","description":"Stable public id (lsh:event:<UUID v5>)."},"sport":{"$ref":"#/components/schemas/Sport"},"competition":{"$ref":"#/components/schemas/Competition"},"title":{"type":"string"},"stage":{"anyOf":[{"type":"string"},{"type":"null"}]},"start_time":{"type":"string","format":"date-time"},"status":{"enum":["scheduled","live","final","postponed","canceled"]},"status_detail":{"anyOf":[{"type":"string"},{"type":"null"}]},"venue":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","pattern":"^lsh:venue:[0-9a-f-]{36}$","description":"Stable public id (lsh:venue:<UUID v5>)."},"name":{"type":"string"},"city":{"anyOf":[{"type":"string"},{"type":"null"}]},"country":{"anyOf":[{"type":"string","pattern":"^[A-Z]{2}$","description":"ISO 3166-1 alpha-2 (geocoded)"},{"type":"null"}]},"lat":{"anyOf":[{"type":"number","description":"WGS 84 latitude"},{"type":"null"}]},"lng":{"anyOf":[{"type":"number","description":"WGS 84 longitude"},{"type":"null"}]},"geo_precision":{"anyOf":[{"enum":["venue","approximate","city"],"description":"venue: the venue itself; approximate: a nearby feature named after it; city: city centre only"},{"type":"null"}]}}},{"type":"null"}]},"competitors":{"type":"array","items":{"type":"object","properties":{"qualifier":{"enum":["home","away"]},"team":{"anyOf":[{"$ref":"#/components/schemas/Team"},{"type":"null"}]},"name":{"anyOf":[{"type":"string"},{"type":"null"}]},"score":{"anyOf":[{"type":"string"},{"type":"null"}]}}}},"airings":{"type":"array","items":{"$ref":"#/components/schemas/Airing"}},"external_ids":{"type":"object","additionalProperties":{"type":"string"},"example":{"espn":"s:600~l:700~e:401879248"}},"source":{"type":"object","properties":{"provider":{"type":"string"},"url":{"anyOf":[{"type":"string"},{"type":"null"}]}}},"updated_at":{"type":"string","format":"date-time"},"deleted":{"type":"boolean"}}}}}}