{"openapi":"3.1.0","info":{"title":"SofiaStage Agent API","version":"1.7.0","description":"Read-only filtered API for SofiaStage events, venues, titles, stars and extras."},"servers":[{"url":"https://sofiastage.com/api"}],"tags":[{"name":"system","description":"Service metadata and discovery endpoints."},{"name":"events","description":"Event retrieval endpoints."},{"name":"lookup","description":"Aggregated lookup lists for venues, titles, stars and extras."},{"name":"admin","description":"Sync operations."}],"components":{"securitySchemes":{"SyncSecretHeader":{"type":"apiKey","in":"header","name":"x-sync-secret","description":"Sync secret passed as request header."},"BearerSyncSecret":{"type":"http","scheme":"bearer","description":"Sync secret passed as Bearer token."}},"parameters":{"DateFromQuery":{"name":"date_from","in":"query","description":"Lower inclusive date bound in YYYY-MM-DD format. When date_to is also set, date_from must be on or before date_to.","schema":{"type":"string","format":"date","example":"2026-02-23"}},"DateToQuery":{"name":"date_to","in":"query","description":"Upper inclusive date bound in YYYY-MM-DD format. When date_from is also set, date_to must be on or after date_from.","schema":{"type":"string","format":"date","example":"2026-02-25"}},"StartsAfterQuery":{"name":"starts_after","in":"query","description":"Lower inclusive start-time bound. Accepts HH:mm, YYYY-MM-DDTHH:mm (interpreted with tz, default Europe/Sofia), or RFC3339 with offset/Z.","schema":{"type":"string","example":"17:00"}},"StartsBeforeQuery":{"name":"starts_before","in":"query","description":"Upper inclusive start-time bound. Accepts HH:mm, YYYY-MM-DDTHH:mm (interpreted with tz, default Europe/Sofia), or RFC3339 with offset/Z.","schema":{"type":"string","example":"2026-02-23T18:00:00+02:00"}},"TimezoneQuery":{"name":"tz","in":"query","description":"IANA timezone used for starts_after/starts_before when value has no offset (HH:mm or YYYY-MM-DDTHH:mm). Defaults to Europe/Sofia.","schema":{"type":"string","example":"Europe/Sofia"}},"VenueQuery":{"name":"venue","in":"query","description":"Case-insensitive partial match against venue name. For non-ASCII values (for example Cyrillic), URL-encode query parameter values.","schema":{"type":"string","example":"Кино Влайкова"}},"TitleQuery":{"name":"title","in":"query","description":"Case-insensitive partial match against event title. For non-ASCII values (for example Cyrillic), URL-encode query parameter values.","schema":{"type":"string","example":"Баба"}},"StarQuery":{"name":"star","in":"query","description":"Case-insensitive match against linked star names. For non-ASCII values (for example Cyrillic), URL-encode query parameter values.","schema":{"type":"string","example":"Александра Сърчаджиева"}},"ExtraQuery":{"name":"extra","in":"query","description":"Case-insensitive match against linked extras titles. For non-ASCII values (for example Cyrillic), URL-encode query parameter values.","schema":{"type":"string","example":"Sincerely Personal"}},"ExtraIdQuery":{"name":"extra_id","in":"query","description":"Filter events linked to a specific extra ID.","schema":{"type":"integer","minimum":1,"example":16}},"LimitQuery":{"name":"limit","in":"query","description":"Page size. Values above 100 are clamped to 100.","schema":{"type":"integer","minimum":1,"maximum":100,"default":25,"example":25}},"CursorQuery":{"name":"cursor","in":"query","description":"Opaque cursor from a previous page.next_cursor value. Must be reused with the same filters (date_from, date_to, starts_after, starts_before, tz, venue, title, star, extra, extra_id, include).","schema":{"type":"string"}},"IncludeQuery":{"name":"include","in":"query","description":"Optional related entities to include. Supports comma-separated values and repeated parameters.","schema":{"type":"string","example":"stars,extras","enum":["stars","extras","stars,extras","extras,stars"]}},"IdPath":{"name":"id","in":"path","required":true,"description":"Stable event ID (`show_stable_id`).","schema":{"type":"string","example":"sh_v1_6e1f0d4d5cf4c734b7e2d4803d5ff7a4"}},"SlugPath":{"name":"slug","in":"path","required":true,"description":"URL slug (percent-encoded title/name).","schema":{"type":"string","example":"%D0%98%D0%B2%D0%B0%D0%BD%20%D0%98%D0%B2%D0%B0%D0%BD%D0%BE%D0%B2"}},"QQuery":{"name":"q","in":"query","description":"Case-insensitive partial search query. For non-ASCII values (for example Cyrillic), URL-encode query parameter values.","schema":{"type":"string","example":"Театър"}}},"schemas":{"ErrorResponse":{"type":"object","properties":{"error":{"type":"string","example":"bad_request"},"message":{"type":"string","example":"Invalid date_from"}},"required":["error"],"additionalProperties":true},"HealthResponse":{"type":"object","properties":{"ok":{"type":"boolean","example":true},"service":{"type":"string","example":"sofiastage.com/api"},"version":{"type":"string","example":"v1"},"source_base_url":{"type":"string","format":"uri","example":"https://sofiastage.com"}},"required":["ok","service","version","source_base_url"]},"SyncStateItem":{"type":"object","properties":{"value":{},"updated_at":{"type":["string","null"],"example":"2026-02-22 12:17:43"}},"required":["value","updated_at"]},"MetaCounts":{"type":"object","properties":{"events":{"type":"integer","minimum":0,"example":1880},"stars":{"type":"integer","minimum":0,"example":64},"extras":{"type":"integer","minimum":0,"example":16}},"required":["events","stars","extras"]},"SnapshotInfo":{"type":"object","properties":{"active_version":{"type":["string","null"],"example":"v20260224190503_e1d52730f3"},"generated_at":{"type":["string","null"],"format":"date-time","example":"2026-02-24T19:05:03.584Z"},"updated_at":{"type":["string","null"],"format":"date-time","example":"2026-02-24T19:05:03.584Z"},"age_seconds":{"type":["integer","null"],"minimum":0,"example":360}},"required":["active_version","generated_at","updated_at","age_seconds"]},"MetaData":{"type":"object","properties":{"counts":{"$ref":"#/components/schemas/MetaCounts"},"sync_state":{"type":"object","additionalProperties":{"$ref":"#/components/schemas/SyncStateItem"}},"snapshot":{"$ref":"#/components/schemas/SnapshotInfo"}},"required":["counts","sync_state","snapshot"]},"MetaResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/MetaData"}},"required":["data"]},"EventStarReference":{"type":"object","properties":{"id":{"type":"integer","example":142},"name":{"type":"string","example":"Иван Иванов"},"occupation":{"type":["string","null"],"example":"Актьор"},"image_url":{"type":["string","null"],"format":"uri"},"profile_url":{"type":["string","null"],"format":"uri"}},"required":["id","name","occupation","image_url","profile_url"]},"EventExtraReference":{"type":"object","properties":{"id":{"type":"integer","example":16},"title":{"type":"string","example":"Sincerely Personal - ГРУПОВА ИЗЛОЖБА"},"subtitle":{"type":["string","null"]},"image_url":{"type":["string","null"],"format":"uri"},"is_open":{"type":"integer","enum":[0,1],"example":1},"open_label":{"type":["string","null"]},"profile_image_link":{"type":["string","null"],"format":"uri"},"article":{"type":["string","null"],"description":"Top article body in markdown."},"bottom_article":{"type":["string","null"],"description":"Bottom article body in markdown."},"has_top_article":{"type":"integer","enum":[0,1],"example":1},"has_bottom_article":{"type":"integer","enum":[0,1],"example":0},"upcoming_events_count":{"type":"integer","minimum":0,"example":5}},"required":["id","title","subtitle","image_url","is_open","open_label","profile_image_link","article","bottom_article","has_top_article","has_bottom_article","upcoming_events_count"]},"Event":{"type":"object","properties":{"id":{"type":"string","example":"sh_v1_6e1f0d4d5cf4c734b7e2d4803d5ff7a4"},"source_id":{"type":"string","example":"sh_v1_6e1f0d4d5cf4c734b7e2d4803d5ff7a4"},"title":{"type":["string","null"],"example":"Баба"},"venue":{"type":["string","null"],"example":"Топлоцентрала"},"address":{"type":["string","null"],"example":"бул. Витоша 15, София"},"stage":{"type":["string","null"],"example":"Зала 4"},"starts_at":{"type":"string","format":"date-time","example":"2026-02-23T16:00:00+02:00"},"event_date":{"type":"string","format":"date","example":"2026-02-23"},"ticket_url":{"type":["string","null"],"format":"uri","example":"https://payment.toplocentrala.bg/repertoires/193/baba"},"info_url":{"type":["string","null"],"format":"uri","example":"https://toplocentrala.bg/program/performance/baba?day=6"},"image_url":{"type":["string","null"],"format":"uri"},"canonical_url":{"type":["string","null"],"format":"uri"},"venue_url":{"type":["string","null"],"format":"uri"},"stars":{"type":"array","items":{"$ref":"#/components/schemas/EventStarReference"}},"extras":{"type":"array","items":{"$ref":"#/components/schemas/EventExtraReference"}}},"required":["id","source_id","title","venue","address","stage","starts_at","event_date","ticket_url","info_url","image_url","canonical_url","venue_url"]},"EventsPage":{"type":"object","properties":{"limit":{"type":"integer","minimum":1,"maximum":100,"example":25},"has_more":{"type":"boolean","example":true},"next_cursor":{"type":["string","null"]}},"required":["limit","has_more","next_cursor"]},"EventsFilters":{"type":"object","properties":{"date_from":{"type":["string","null"],"format":"date","example":"2026-02-23"},"date_to":{"type":["string","null"],"format":"date","example":"2026-02-23"},"starts_after":{"type":["string","null"],"format":"date-time","description":"Echo of starts_after normalized by the API to RFC3339 UTC (Z).","example":"2026-02-23T16:00:00.000Z"},"starts_before":{"type":["string","null"],"format":"date-time","description":"Echo of starts_before normalized by the API to RFC3339 UTC (Z).","example":"2026-02-23T18:00:00.000Z"},"tz":{"type":["string","null"],"example":"Europe/Sofia"},"venue":{"type":["string","null"],"example":"Топлоцентрала"},"title":{"type":["string","null"],"example":"Баба"},"star":{"type":["string","null"],"example":"Александра Сърчаджиева"},"extra":{"type":["string","null"],"example":"Sincerely Personal"},"extra_id":{"type":["integer","null"],"example":16},"include":{"type":"array","items":{"type":"string","enum":["stars","extras"]},"example":["stars","extras"]}},"required":["date_from","date_to","starts_after","starts_before","tz","venue","title","star","extra","extra_id","include"]},"EventsResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Event"}},"page":{"$ref":"#/components/schemas/EventsPage"},"filters":{"$ref":"#/components/schemas/EventsFilters"}},"required":["data","page","filters"]},"EventResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Event"}},"required":["data"]},"VenueItem":{"type":"object","properties":{"venue":{"type":"string","example":"Кино Влайкова"},"events_count":{"type":"integer","minimum":0,"example":24},"next_event_at":{"type":["string","null"],"format":"date-time","example":"2026-02-23T14:00:00+02:00"}},"required":["venue","events_count","next_event_at"]},"VenueListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/VenueItem"}}},"required":["data"]},"TitleItem":{"type":"object","properties":{"title":{"type":"string","example":"Баба"},"events_count":{"type":"integer","minimum":0,"example":7},"next_event_at":{"type":["string","null"],"format":"date-time","example":"2026-02-23T16:00:00+02:00"}},"required":["title","events_count","next_event_at"]},"TitleListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/TitleItem"}}},"required":["data"]},"PrecomputedEvent":{"type":"object","properties":{"id":{"type":["string","null"],"example":"sh_v1_6e1f0d4d5cf4c734b7e2d4803d5ff7a4"},"source_id":{"type":["integer","string","null"],"example":"sh_v1_6e1f0d4d5cf4c734b7e2d4803d5ff7a4"},"event_uid":{"type":["string","null"],"example":"event_1a2b3c4d"},"title":{"type":["string","null"],"example":"Баба"},"venue":{"type":["string","null"],"example":"Топлоцентрала"},"city":{"type":["string","null"],"example":"Пловдив"},"address":{"type":["string","null"],"example":"бул. Витоша 15, София"},"stage":{"type":["string","null"],"example":"Зала 4"},"starts_at":{"type":["string","null"],"format":"date-time","example":"2026-02-23T16:00:00+02:00"},"event_date":{"type":["string","null"],"format":"date","example":"2026-02-23"},"ticket_url":{"type":["string","null"],"format":"uri","example":"https://payment.toplocentrala.bg/repertoires/193/baba"},"info_url":{"type":["string","null"],"format":"uri","example":"https://toplocentrala.bg/program/performance/baba?day=6"},"image_url":{"type":["string","null"],"format":"uri"},"canonical_url":{"type":["string","null"],"format":"uri"},"venue_url":{"type":["string","null"],"format":"uri"},"timestamp_ms":{"type":["integer","null"],"example":1771855200000},"is_upcoming":{"type":"boolean","example":true}},"required":["id","source_id","event_uid","title","venue","city","address","stage","starts_at","event_date","ticket_url","info_url","image_url","canonical_url","venue_url","timestamp_ms","is_upcoming"]},"StarItem":{"type":"object","properties":{"id":{"type":"integer","example":142},"name":{"type":"string","example":"Иван Иванов"},"occupation":{"type":["string","null"],"example":"Актьор"},"image_url":{"type":["string","null"],"format":"uri"},"profile_url":{"type":["string","null"],"format":"uri","description":"Canonical SofiaStage star profile URL."},"profile_image_link":{"type":["string","null"],"format":"uri","description":"Optional custom URL attached to the star profile image."},"upcoming_events_count":{"type":"integer","minimum":0,"example":12}},"required":["id","name","occupation","image_url","profile_url","profile_image_link","upcoming_events_count"]},"StarListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/StarItem"}}},"required":["data"]},"StarDetailItem":{"type":"object","properties":{"id":{"type":["integer","null"],"example":142},"name":{"type":"string","example":"Иван Иванов"},"slug":{"type":["string","null"],"example":"%D0%98%D0%B2%D0%B0%D0%BD%20%D0%98%D0%B2%D0%B0%D0%BD%D0%BE%D0%B2"},"occupation":{"type":["string","null"],"example":"Актьор"},"image_url":{"type":["string","null"],"format":"uri"},"profile_url":{"type":["string","null"],"format":"uri","description":"Canonical SofiaStage star profile URL."},"profile_image_link":{"type":["string","null"],"format":"uri","description":"Optional custom URL attached to the star profile image."},"shows_raw":{"type":["string","null"]},"upcoming_events_count":{"type":"integer","minimum":0,"example":12},"upcoming_event_uids":{"type":"array","items":{"type":"string"}},"upcoming_events":{"type":"array","items":{"$ref":"#/components/schemas/PrecomputedEvent"}}},"required":["id","name","slug","occupation","image_url","profile_url","profile_image_link","shows_raw","upcoming_events_count","upcoming_event_uids","upcoming_events"]},"StarDetailResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/StarDetailItem"}},"required":["data"]},"ExtraItem":{"type":"object","properties":{"id":{"type":"integer","example":16},"title":{"type":"string","example":"Sincerely Personal - ГРУПОВА ИЗЛОЖБА"},"subtitle":{"type":["string","null"]},"image_url":{"type":["string","null"],"format":"uri"},"is_open":{"type":"integer","enum":[0,1],"example":1},"open_label":{"type":["string","null"]},"profile_image_link":{"type":["string","null"],"format":"uri"},"article":{"type":["string","null"],"description":"Top article body in markdown."},"bottom_article":{"type":["string","null"],"description":"Bottom article body in markdown."},"has_top_article":{"type":"integer","enum":[0,1],"example":1},"has_bottom_article":{"type":"integer","enum":[0,1],"example":0},"upcoming_events_count":{"type":"integer","minimum":0,"example":5}},"required":["id","title","subtitle","image_url","is_open","open_label","profile_image_link","article","bottom_article","has_top_article","has_bottom_article","upcoming_events_count"]},"ExtraListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ExtraItem"}}},"required":["data"]},"ExtraDetailItem":{"type":"object","properties":{"id":{"type":["integer","null"],"example":16},"title":{"type":"string","example":"Sincerely Personal - ГРУПОВА ИЗЛОЖБА"},"slug":{"type":["string","null"],"example":"Sincerely%20Personal%20-%20%D0%93%D0%A0%D0%A3%D0%9F%D0%9E%D0%92%D0%90%20%D0%98%D0%97%D0%9B%D0%9E%D0%96%D0%91%D0%90"},"subtitle":{"type":["string","null"]},"image_url":{"type":["string","null"],"format":"uri"},"shows_raw":{"type":["string","null"]},"is_open":{"type":"integer","enum":[0,1],"example":1},"open_label":{"type":["string","null"]},"profile_image_link":{"type":["string","null"],"format":"uri"},"article":{"type":["string","null"]},"bottom_article":{"type":["string","null"]},"has_top_article":{"type":"integer","enum":[0,1],"example":1},"has_bottom_article":{"type":"integer","enum":[0,1],"example":0},"upcoming_events_count":{"type":"integer","minimum":0,"example":5},"upcoming_event_uids":{"type":"array","items":{"type":"string"}},"upcoming_events":{"type":"array","items":{"$ref":"#/components/schemas/PrecomputedEvent"}}},"required":["id","title","slug","subtitle","image_url","shows_raw","is_open","open_label","profile_image_link","article","bottom_article","has_top_article","has_bottom_article","upcoming_events_count","upcoming_event_uids","upcoming_events"]},"ExtraDetailResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/ExtraDetailItem"}},"required":["data"]},"SyncSummaryCounts":{"type":"object","properties":{"shows_fetched":{"type":"integer","minimum":0},"stars_fetched":{"type":"integer","minimum":0},"extras_fetched":{"type":"integer","minimum":0},"events_inserted":{"type":"integer","minimum":0},"stars_inserted":{"type":"integer","minimum":0},"extras_inserted":{"type":"integer","minimum":0},"event_stars_inserted":{"type":"integer","minimum":0},"event_extras_inserted":{"type":"integer","minimum":0}},"required":["shows_fetched","stars_fetched","extras_fetched","events_inserted","stars_inserted","extras_inserted","event_stars_inserted","event_extras_inserted"]},"SyncSummary":{"type":"object","properties":{"source_base_url":{"type":"string","format":"uri","example":"https://sofiastage.com"},"started_at":{"type":"string","format":"date-time"},"completed_at":{"type":"string","format":"date-time"},"duration_ms":{"type":"integer","minimum":0,"example":9724},"counts":{"$ref":"#/components/schemas/SyncSummaryCounts"}},"required":["source_base_url","started_at","completed_at","duration_ms","counts"]},"SyncSuccessResponse":{"type":"object","properties":{"ok":{"type":"boolean","const":true},"summary":{"$ref":"#/components/schemas/SyncSummary"}},"required":["ok","summary"]},"SyncFailureResponse":{"type":"object","properties":{"ok":{"type":"boolean","const":false},"error":{"type":"string","example":"sync_failed"},"message":{"type":"string"}},"required":["ok","error","message"]}},"responses":{"BadRequest":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"invalid_date":{"summary":"Invalid date parameter","value":{"error":"bad_request","message":"Invalid date_from"}},"cursor_filter_mismatch":{"summary":"Cursor was reused with different filters","value":{"error":"bad_request","message":"Cursor does not match current filters"}}}}}},"NotFound":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"Unauthorized":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"TooManyRequests":{"description":"Too many requests (retry with backoff)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":"too_many_requests","message":"Rate limit exceeded. Retry later."}}}}}},"paths":{"/health":{"get":{"operationId":"getHealth","tags":["system"],"summary":"Health check","responses":{"200":{"description":"Service health details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HealthResponse"},"example":{"ok":true,"service":"sofiastage.com/api","version":"v1","source_base_url":"https://sofiastage.com"}}}},"429":{"$ref":"#/components/responses/TooManyRequests"}}}},"/v1/meta":{"get":{"operationId":"getMeta","tags":["system"],"summary":"Sync and dataset metadata","responses":{"200":{"description":"Dataset counts and sync status metadata","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MetaResponse"},"example":{"data":{"counts":{"events":1880,"stars":64,"extras":16},"snapshot":{"active_version":"v20260224190503_e1d52730f3","generated_at":"2026-02-24T19:05:03.584Z","updated_at":"2026-02-24T19:05:03.584Z","age_seconds":360},"sync_state":{"last_sync_at":{"value":"2026-02-22T12:17:43.897Z","updated_at":"2026-02-22 12:17:43"},"last_sync_status":{"value":"ok","updated_at":"2026-02-22 12:17:44"}}}}}}},"429":{"$ref":"#/components/responses/TooManyRequests"}}}},"/v1/events":{"get":{"operationId":"listEvents","tags":["events"],"summary":"List events","description":"Defaults to tz=Europe/Sofia when interpreting local starts_after/starts_before values. For 'today' queries, use date_from=date_to=<today in tz>. For 'tonight', combine a single-day date range with starts_after (for example 19:30).","parameters":[{"name":"date_from","in":"query","description":"Lower inclusive date bound in YYYY-MM-DD format.","schema":{"type":"string","format":"date"}},{"name":"date_to","in":"query","description":"Upper inclusive date bound in YYYY-MM-DD format.","schema":{"type":"string","format":"date"}},{"name":"starts_after","in":"query","description":"Lower inclusive start-time bound. Supports HH:mm, local YYYY-MM-DDTHH:mm (with tz), or RFC3339 with offset/Z.","schema":{"type":"string"}},{"name":"starts_before","in":"query","description":"Upper inclusive start-time bound. Supports HH:mm, local YYYY-MM-DDTHH:mm (with tz), or RFC3339 with offset/Z.","schema":{"type":"string"}},{"name":"tz","in":"query","description":"IANA timezone for local starts_* values. Defaults to Europe/Sofia.","schema":{"type":"string","example":"Europe/Sofia"}},{"name":"venue","in":"query","description":"Case-insensitive partial match against venue name.","schema":{"type":"string"}},{"name":"title","in":"query","description":"Case-insensitive partial match against event title.","schema":{"type":"string"}},{"name":"star","in":"query","description":"Case-insensitive match against linked star names.","schema":{"type":"string"}},{"name":"extra","in":"query","description":"Case-insensitive match against linked extras titles.","schema":{"type":"string"}},{"name":"extra_id","in":"query","description":"Filter events linked to a specific extra ID.","schema":{"type":"integer","minimum":1}},{"name":"limit","in":"query","description":"Page size. Values above 100 are clamped to 100.","schema":{"type":"integer","minimum":1,"maximum":100,"default":25}},{"name":"cursor","in":"query","description":"Opaque cursor from page.next_cursor. Reuse with the same filters.","schema":{"type":"string"}},{"name":"include","in":"query","description":"Optional related entities. Use comma-separated and/or repeated values. Allowed tokens: stars, extras.","schema":{"type":"string","example":"stars,extras"}}],"responses":{"200":{"description":"Paginated event list","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventsResponse"},"example":{"data":[{"id":"sh_v1_6e1f0d4d5cf4c734b7e2d4803d5ff7a4","source_id":"sh_v1_6e1f0d4d5cf4c734b7e2d4803d5ff7a4","title":"Кино и телевизионна драматургия с Димитър Коцев - Шошо","venue":"Академия за творческо писане и арт тренинги на Яна Борисова","address":"ул. Ангел Кънчев 3, София","stage":"Галерия Артур","starts_at":"2026-02-23T10:00:00+02:00","event_date":"2026-02-23","ticket_url":"https://yanaborisovaacademy.com/kursove/kino-i-televizionna-dramaturgiya-s-dimitar-kocev-shosho/","info_url":"https://www.facebook.com/events/1165566932036846/","image_url":"https://cache-server.sofiastage.com/image?url=https%3A%2F%2Fexample.com%2Fposter.jpg","canonical_url":"https://sofiastage.com/title/%D0%9A%D0%B8%D0%BD%D0%BE%20%D0%B8%20%D1%82%D0%B5%D0%BB%D0%B5%D0%B2%D0%B8%D0%B7%D0%B8%D0%BE%D0%BD%D0%BD%D0%B0%20%D0%B4%D1%80%D0%B0%D0%BC%D0%B0%D1%82%D1%83%D1%80%D0%B3%D0%B8%D1%8F%20%D1%81%20%D0%94%D0%B8%D0%BC%D0%B8%D1%82%D1%8A%D1%80%20%D0%9A%D0%BE%D1%86%D0%B5%D0%B2%20-%20%D0%A8%D0%BE%D1%88%D0%BE","venue_url":"https://sofiastage.com/venue/%D0%90%D0%BA%D0%B0%D0%B4%D0%B5%D0%BC%D0%B8%D1%8F%20%D0%B7%D0%B0%20%D1%82%D0%B2%D0%BE%D1%80%D1%87%D0%B5%D1%81%D0%BA%D0%BE%20%D0%BF%D0%B8%D1%81%D0%B0%D0%BD%D0%B5%20%D0%B8%20%D0%B0%D1%80%D1%82%20%D1%82%D1%80%D0%B5%D0%BD%D0%B8%D0%BD%D0%B3%D0%B8%20%D0%BD%D0%B0%20%D0%AF%D0%BD%D0%B0%20%D0%91%D0%BE%D1%80%D0%B8%D1%81%D0%BE%D0%B2%D0%B0"}],"page":{"limit":25,"has_more":true,"next_cursor":"eyJzdGFydHNfYXQiOiIyMDI2LTAyLTIzVDEwOjAwOjAwKzAyOjAwIiwiaWQiOjI3ODc5MDd9"},"filters":{"date_from":"2026-02-23","date_to":"2026-02-23","starts_after":null,"starts_before":null,"tz":null,"venue":null,"title":null,"star":null,"extra":null,"extra_id":null,"include":[]}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"429":{"$ref":"#/components/responses/TooManyRequests"}}}},"/v1/events/{id}":{"get":{"operationId":"getEventById","tags":["events"],"summary":"Get event by id","parameters":[{"name":"id","in":"path","required":true,"description":"Stable event ID (`show_stable_id`).","schema":{"type":"string"}},{"name":"include","in":"query","description":"Optional related entities. Use comma-separated and/or repeated values. Allowed tokens: stars, extras.","schema":{"type":"string","example":"stars,extras"}}],"responses":{"200":{"description":"Single event payload","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventResponse"},"example":{"data":{"id":"sh_v1_f8f6f0d8bb7deeb4cc63f6bdf0f8b1a2","source_id":"sh_v1_f8f6f0d8bb7deeb4cc63f6bdf0f8b1a2","title":"Баба","venue":"Топлоцентрала","address":"бул. Черни връх 189, София","stage":"Зала 4","starts_at":"2026-02-23T16:00:00+02:00","event_date":"2026-02-23","ticket_url":"https://payment.toplocentrala.bg/repertoires/193/baba","info_url":"https://toplocentrala.bg/program/performance/baba?day=6","image_url":"https://toplocentrala.bg/attachments/Event/1017/main/Baba_thumb-detail.JPG","canonical_url":"https://sofiastage.com/title/%D0%91%D0%B0%D0%B1%D0%B0","venue_url":"https://sofiastage.com/venue/%D0%A2%D0%BE%D0%BF%D0%BB%D0%BE%D1%86%D0%B5%D0%BD%D1%82%D1%80%D0%B0%D0%BB%D0%B0"}}}}},"404":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":"not_found","message":"Event not found"}}}},"429":{"$ref":"#/components/responses/TooManyRequests"}}}},"/v1/venues":{"get":{"operationId":"listVenues","tags":["lookup"],"summary":"List venues","parameters":[{"name":"q","in":"query","description":"Case-insensitive partial search query.","schema":{"type":"string"}},{"name":"limit","in":"query","description":"Page size. Values above 100 are clamped to 100.","schema":{"type":"integer","minimum":1,"maximum":100,"default":25}}],"responses":{"200":{"description":"Venue list with upcoming event counts","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VenueListResponse"},"example":{"data":[{"venue":"Кино Влайкова","events_count":24,"next_event_at":"2026-02-23T14:00:00+02:00"}]}}}},"429":{"$ref":"#/components/responses/TooManyRequests"}}}},"/v1/titles":{"get":{"operationId":"listTitles","tags":["lookup"],"summary":"List titles","parameters":[{"name":"q","in":"query","description":"Case-insensitive partial search query.","schema":{"type":"string"}},{"name":"limit","in":"query","description":"Page size. Values above 100 are clamped to 100.","schema":{"type":"integer","minimum":1,"maximum":100,"default":25}}],"responses":{"200":{"description":"Title list with upcoming event counts","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TitleListResponse"},"example":{"data":[{"title":"Баба","events_count":7,"next_event_at":"2026-02-23T16:00:00+02:00"}]}}}},"429":{"$ref":"#/components/responses/TooManyRequests"}}}},"/v1/stars":{"get":{"operationId":"listStars","tags":["lookup"],"summary":"List stars","parameters":[{"name":"q","in":"query","description":"Case-insensitive partial search query.","schema":{"type":"string"}},{"name":"limit","in":"query","description":"Page size. Values above 100 are clamped to 100.","schema":{"type":"integer","minimum":1,"maximum":100,"default":25}}],"responses":{"200":{"description":"Stars with upcoming event counts","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StarListResponse"},"example":{"data":[{"id":142,"name":"Иван Иванов","occupation":"Актьор","image_url":"https://res.cloudinary.com/example/star.jpg","profile_url":"https://sofiastage.com/star/%D0%98%D0%B2%D0%B0%D0%BD%20%D0%98%D0%B2%D0%B0%D0%BD%D0%BE%D0%B2","profile_image_link":"https://example.com/ivan-ivanov","upcoming_events_count":12}]}}}},"429":{"$ref":"#/components/responses/TooManyRequests"}}}},"/v1/star/{slug}":{"get":{"operationId":"getStarBySlug","tags":["lookup"],"summary":"Get precomputed star detail and upcoming events by slug","parameters":[{"$ref":"#/components/parameters/SlugPath"}],"responses":{"200":{"description":"Star detail payload with precomputed upcoming events","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StarDetailResponse"}}}},"404":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":"not_found","message":"Star not found"}}}},"429":{"$ref":"#/components/responses/TooManyRequests"}}}},"/v1/extras":{"get":{"operationId":"listExtras","tags":["lookup"],"summary":"List extras","parameters":[{"name":"q","in":"query","description":"Case-insensitive partial search query.","schema":{"type":"string"}},{"name":"limit","in":"query","description":"Page size. Values above 100 are clamped to 100.","schema":{"type":"integer","minimum":1,"maximum":100,"default":25}}],"responses":{"200":{"description":"Extras list with markdown article content and upcoming event counts","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExtraListResponse"},"example":{"data":[{"id":16,"title":"Sincerely Personal - ГРУПОВА ИЗЛОЖБА","subtitle":null,"image_url":"https://res.cloudinary.com/example/extra.jpg","is_open":1,"open_label":"Прочети още","profile_image_link":null,"article":"## Intro\n\nMarkdown top article content.","bottom_article":null,"has_top_article":1,"has_bottom_article":0,"upcoming_events_count":5}]}}}},"429":{"$ref":"#/components/responses/TooManyRequests"}}}},"/v1/extra/{slug}":{"get":{"operationId":"getExtraBySlug","tags":["lookup"],"summary":"Get precomputed extra detail and upcoming events by slug","parameters":[{"$ref":"#/components/parameters/SlugPath"}],"responses":{"200":{"description":"Extra detail payload with precomputed upcoming events","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExtraDetailResponse"}}}},"404":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":"not_found","message":"Extra not found"}}}},"429":{"$ref":"#/components/responses/TooManyRequests"}}}},"/v1/admin/sync":{"post":{"operationId":"runSync","tags":["admin"],"summary":"Sync endpoint (disabled)","description":"Worker-side sync is disabled. Sync runs via external service.","security":[{"SyncSecretHeader":[]},{"BearerSyncSecret":[]}],"responses":{"410":{"description":"Sync is disabled on Worker","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":"sync_disabled","message":"Worker sync is disabled; use external sync service."}}}}}}}}}