{"openapi":"3.1.0","info":{"title":"Portada Live Events API","version":"1.0.0","summary":"Read the public Portada conference schedule.","description":"Read-only HTTP API for upcoming Portada Live and Portada Next conferences published at joinevent.portada-online.com by Portada (portada-online.com). No authentication is required. The API cannot register an attendee or change event content. Rate limit: 60 requests per 60 seconds per client IP. Responses include RateLimit-Policy, RateLimit, RateLimit-Limit, RateLimit-Remaining, RateLimit-Reset. RateLimit-Policy and RateLimit follow the IETF RateLimit header fields. A 429 response also includes Retry-After, the seconds to wait before retrying. Errors are JSON objects with error.code, error.message, and error.hint."},"servers":[{"url":"https://joinevent.portada-online.com"}],"tags":[{"name":"Events","description":"Published Portada Live and Portada Next conferences."}],"paths":{"/api/v1/events":{"get":{"operationId":"listEvents","tags":["Events"],"summary":"List published Portada conferences","description":"List the upcoming Portada Live and Portada Next conferences published on joinevent.portada-online.com, including city, dates, and the canonical event URL. Use this when you need the current public schedule or a slug to pass to getEvent.","responses":{"200":{"description":"The published conference list.","headers":{"RateLimit-Policy":{"description":"IETF RateLimit policy. q is the request quota and w is the window in seconds.","schema":{"type":"string"},"example":"\"events\";q=60;w=60"},"RateLimit":{"description":"IETF RateLimit status. r is the remaining requests and t is the seconds until the window resets.","schema":{"type":"string"}},"RateLimit-Limit":{"description":"Integer request quota for the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Integer requests remaining in the current window.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Integer seconds until the quota window resets.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventList"}}}},"405":{"$ref":"#/components/responses/MethodNotAllowed"},"429":{"$ref":"#/components/responses/RateLimited"},"503":{"$ref":"#/components/responses/CatalogUnavailable"}}}},"/api/v1/events/{slug}":{"get":{"operationId":"getEvent","tags":["Events"],"summary":"Get one published Portada conference","description":"Fetch one published Portada conference by its URL slug. Use this when you already know the slug, for example portada-miami-2027, and need that event's city, dates, and canonical URL.","parameters":[{"name":"slug","in":"path","required":true,"description":"URL slug of a published conference, as returned by listEvents. Lowercase letters, numbers, and hyphens only.","schema":{"type":"string","pattern":"^[a-z0-9]+(?:-[a-z0-9]+)*$"}}],"responses":{"200":{"description":"The requested conference.","headers":{"RateLimit-Policy":{"description":"IETF RateLimit policy. q is the request quota and w is the window in seconds.","schema":{"type":"string"},"example":"\"events\";q=60;w=60"},"RateLimit":{"description":"IETF RateLimit status. r is the remaining requests and t is the seconds until the window resets.","schema":{"type":"string"}},"RateLimit-Limit":{"description":"Integer request quota for the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Integer requests remaining in the current window.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Integer seconds until the quota window resets.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventResponse"}}}},"404":{"$ref":"#/components/responses/NotFound"},"405":{"$ref":"#/components/responses/MethodNotAllowed"},"429":{"$ref":"#/components/responses/RateLimited"},"503":{"$ref":"#/components/responses/CatalogUnavailable"}}}}},"components":{"schemas":{"Event":{"type":"object","additionalProperties":false,"required":["slug","title","language","city","country","dateStart","dateEnd","url","image"],"properties":{"slug":{"type":"string","pattern":"^[a-z0-9]+(?:-[a-z0-9]+)*$","description":"URL slug used by getEvent and by the public event page."},"title":{"type":"string","description":"Conference name as published on the schedule."},"language":{"type":"string","description":"BCP 47 language tag of the event page, such as en or es."},"city":{"type":"string","description":"City where the conference is held."},"country":{"type":"string","description":"Country or country code published for the venue."},"dateStart":{"type":"string","description":"Published start date or date-time."},"dateEnd":{"type":"string","description":"Published end date or date-time."},"url":{"type":"string","format":"uri","description":"Canonical event page URL."},"image":{"type":["string","null"],"description":"Card or hero image URL, or null when the event has no public image."}}},"EventList":{"type":"object","additionalProperties":false,"required":["events"],"properties":{"events":{"type":"array","items":{"$ref":"#/components/schemas/Event"}}}},"EventResponse":{"type":"object","additionalProperties":false,"required":["event"],"properties":{"event":{"$ref":"#/components/schemas/Event"}}},"Error":{"type":"object","additionalProperties":false,"required":["error"],"properties":{"error":{"type":"object","additionalProperties":false,"required":["code","message","hint"],"properties":{"code":{"type":"string","description":"Stable machine-readable error code.","enum":["not_found","method_not_allowed","rate_limited","catalog_unavailable"]},"message":{"type":"string","description":"What went wrong, in plain language."},"hint":{"type":"string","description":"What the caller should do next."}}}}}},"responses":{"NotFound":{"description":"No published conference uses that slug, or the path is not an operation.","headers":{"RateLimit-Policy":{"description":"IETF RateLimit policy. q is the request quota and w is the window in seconds.","schema":{"type":"string"},"example":"\"events\";q=60;w=60"},"RateLimit":{"description":"IETF RateLimit status. r is the remaining requests and t is the seconds until the window resets.","schema":{"type":"string"}},"RateLimit-Limit":{"description":"Integer request quota for the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Integer requests remaining in the current window.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Integer seconds until the quota window resets.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"MethodNotAllowed":{"description":"Only GET and HEAD are supported.","headers":{"RateLimit-Policy":{"description":"IETF RateLimit policy. q is the request quota and w is the window in seconds.","schema":{"type":"string"},"example":"\"events\";q=60;w=60"},"RateLimit":{"description":"IETF RateLimit status. r is the remaining requests and t is the seconds until the window resets.","schema":{"type":"string"}},"RateLimit-Limit":{"description":"Integer request quota for the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Integer requests remaining in the current window.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Integer seconds until the quota window resets.","schema":{"type":"integer"}},"Allow":{"description":"Methods the operation accepts.","schema":{"type":"string","example":"GET, HEAD"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"RateLimited":{"description":"The client exceeded the events quota for the current window.","headers":{"RateLimit-Policy":{"description":"IETF RateLimit policy. q is the request quota and w is the window in seconds.","schema":{"type":"string"},"example":"\"events\";q=60;w=60"},"RateLimit":{"description":"IETF RateLimit status. r is the remaining requests and t is the seconds until the window resets.","schema":{"type":"string"}},"RateLimit-Limit":{"description":"Integer request quota for the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Integer requests remaining in the current window.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Integer seconds until the quota window resets.","schema":{"type":"integer"}},"Retry-After":{"description":"Seconds to wait before retrying the same request.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"CatalogUnavailable":{"description":"The built conference catalog could not be read.","headers":{"RateLimit-Policy":{"description":"IETF RateLimit policy. q is the request quota and w is the window in seconds.","schema":{"type":"string"},"example":"\"events\";q=60;w=60"},"RateLimit":{"description":"IETF RateLimit status. r is the remaining requests and t is the seconds until the window resets.","schema":{"type":"string"}},"RateLimit-Limit":{"description":"Integer request quota for the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Integer requests remaining in the current window.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Integer seconds until the quota window resets.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}