{"openapi":"3.1.0","info":{"title":"Austin Happy Hour Database Public API","version":"1.0.0","description":"Credential-free, read-only discovery API for published Austin happy-hour listings. The API is a sanitized public projection; it does not expose Payload CMS records, drafts, review state, or authoring timestamps. All schedule times use America/Chicago."},"servers":[{"url":"https://austinhappyhourdatabase.com","description":"Production public website and API"}],"externalDocs":{"description":"Agent and usage guidance","url":"https://austinhappyhourdatabase.com/AGENTS.md"},"security":[],"tags":[{"name":"Metadata","description":"Dataset identity and API capabilities."},{"name":"Happy hours","description":"Published happy-hour discovery resources."},{"name":"Discovery","description":"Machine-readable API and agent discovery documents."}],"paths":{"/api/v1/meta":{"get":{"tags":["Metadata"],"operationId":"getPublicApiMeta","summary":"Get dataset metadata","responses":{"200":{"description":"Current public dataset identity and supported capabilities.","headers":{"ETag":{"$ref":"#/components/headers/ETag"},"X-HHDB-API-Version":{"$ref":"#/components/headers/ApiVersion"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MetaResponse"}}}},"304":{"$ref":"#/components/responses/NotModified"},"502":{"$ref":"#/components/responses/BadGateway"},"503":{"$ref":"#/components/responses/Unavailable"}}},"head":{"tags":["Metadata"],"operationId":"headPublicApiMeta","summary":"Inspect dataset metadata headers","responses":{"200":{"$ref":"#/components/responses/HeadSuccess"},"502":{"$ref":"#/components/responses/HeadUpstreamFailure"},"503":{"$ref":"#/components/responses/HeadUpstreamFailure"}}}},"/api/v1/happy-hours":{"get":{"tags":["Happy hours"],"operationId":"listHappyHours","summary":"Search and list happy hours","description":"Returns at most 50 published listings. Follow page.nextCursor with the exact same query until it is null. A cursor is signed, expires after 15 minutes, and returns 409 if the published dataset changes during pagination.","parameters":[{"$ref":"#/components/parameters/Query"},{"$ref":"#/components/parameters/Category"},{"$ref":"#/components/parameters/CategoryMode"},{"$ref":"#/components/parameters/Day"},{"$ref":"#/components/parameters/Time"},{"$ref":"#/components/parameters/At"},{"$ref":"#/components/parameters/Intent"},{"$ref":"#/components/parameters/Availability"},{"$ref":"#/components/parameters/Near"},{"$ref":"#/components/parameters/RadiusMeters"},{"$ref":"#/components/parameters/BoundingBox"},{"$ref":"#/components/parameters/Sort"},{"$ref":"#/components/parameters/Seed"},{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/Cursor"}],"responses":{"200":{"description":"A stable cursor page of matching published listings.","headers":{"ETag":{"$ref":"#/components/headers/ETag"},"X-HHDB-API-Version":{"$ref":"#/components/headers/ApiVersion"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HappyHourListResponse"}}}},"304":{"$ref":"#/components/responses/NotModified"},"400":{"$ref":"#/components/responses/BadRequest"},"409":{"$ref":"#/components/responses/Conflict"},"502":{"$ref":"#/components/responses/BadGateway"},"503":{"$ref":"#/components/responses/Unavailable"}}},"head":{"tags":["Happy hours"],"operationId":"headHappyHours","summary":"Inspect list response headers","parameters":[{"$ref":"#/components/parameters/Query"},{"$ref":"#/components/parameters/Category"},{"$ref":"#/components/parameters/CategoryMode"},{"$ref":"#/components/parameters/Day"},{"$ref":"#/components/parameters/Time"},{"$ref":"#/components/parameters/At"},{"$ref":"#/components/parameters/Intent"},{"$ref":"#/components/parameters/Availability"},{"$ref":"#/components/parameters/Near"},{"$ref":"#/components/parameters/RadiusMeters"},{"$ref":"#/components/parameters/BoundingBox"},{"$ref":"#/components/parameters/Sort"},{"$ref":"#/components/parameters/Seed"},{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/Cursor"}],"responses":{"200":{"$ref":"#/components/responses/HeadSuccess"},"304":{"$ref":"#/components/responses/NotModified"},"400":{"$ref":"#/components/responses/HeadClientFailure"},"409":{"$ref":"#/components/responses/HeadClientFailure"},"502":{"$ref":"#/components/responses/HeadUpstreamFailure"},"503":{"$ref":"#/components/responses/HeadUpstreamFailure"}}}},"/api/v1/happy-hours/{idOrSlug}":{"parameters":[{"$ref":"#/components/parameters/IdOrSlug"}],"get":{"tags":["Happy hours"],"operationId":"getHappyHour","summary":"Get one happy hour","description":"Looks up a published listing by opaque public ID, canonical slug, or retained slug alias. Alias responses identify the canonical slug in response headers.","responses":{"200":{"description":"One published listing.","headers":{"Content-Location":{"$ref":"#/components/headers/ContentLocation"},"ETag":{"$ref":"#/components/headers/ETag"},"X-HHDB-API-Version":{"$ref":"#/components/headers/ApiVersion"},"X-HHDB-Canonical-Slug":{"$ref":"#/components/headers/CanonicalSlug"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HappyHourDetailResponse"}}}},"304":{"$ref":"#/components/responses/NotModified"},"404":{"$ref":"#/components/responses/NotFound"},"502":{"$ref":"#/components/responses/BadGateway"},"503":{"$ref":"#/components/responses/Unavailable"}}},"head":{"tags":["Happy hours"],"operationId":"headHappyHour","summary":"Inspect detail response headers","responses":{"200":{"$ref":"#/components/responses/HeadSuccess"},"304":{"$ref":"#/components/responses/NotModified"},"404":{"$ref":"#/components/responses/HeadClientFailure"},"502":{"$ref":"#/components/responses/HeadUpstreamFailure"},"503":{"$ref":"#/components/responses/HeadUpstreamFailure"}}}},"/api/v1/happy-hours/map":{"get":{"tags":["Happy hours"],"operationId":"getHappyHourMap","summary":"Get map points","description":"Returns lightweight points for all matching listings that have public coordinates. Pagination parameters are intentionally not used on this resource.","parameters":[{"$ref":"#/components/parameters/Query"},{"$ref":"#/components/parameters/Category"},{"$ref":"#/components/parameters/CategoryMode"},{"$ref":"#/components/parameters/Day"},{"$ref":"#/components/parameters/Time"},{"$ref":"#/components/parameters/At"},{"$ref":"#/components/parameters/Intent"},{"$ref":"#/components/parameters/Availability"},{"$ref":"#/components/parameters/Near"},{"$ref":"#/components/parameters/RadiusMeters"},{"$ref":"#/components/parameters/BoundingBox"}],"responses":{"200":{"description":"Matching geocoded listings.","headers":{"ETag":{"$ref":"#/components/headers/ETag"},"X-HHDB-API-Version":{"$ref":"#/components/headers/ApiVersion"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MapResponse"}}}},"304":{"$ref":"#/components/responses/NotModified"},"400":{"$ref":"#/components/responses/BadRequest"},"502":{"$ref":"#/components/responses/BadGateway"},"503":{"$ref":"#/components/responses/Unavailable"}}},"head":{"tags":["Happy hours"],"operationId":"headHappyHourMap","summary":"Inspect map response headers","parameters":[{"$ref":"#/components/parameters/Query"},{"$ref":"#/components/parameters/Category"},{"$ref":"#/components/parameters/CategoryMode"},{"$ref":"#/components/parameters/Day"},{"$ref":"#/components/parameters/Time"},{"$ref":"#/components/parameters/At"},{"$ref":"#/components/parameters/Intent"},{"$ref":"#/components/parameters/Availability"},{"$ref":"#/components/parameters/Near"},{"$ref":"#/components/parameters/RadiusMeters"},{"$ref":"#/components/parameters/BoundingBox"}],"responses":{"200":{"$ref":"#/components/responses/HeadSuccess"},"502":{"$ref":"#/components/responses/HeadUpstreamFailure"},"503":{"$ref":"#/components/responses/HeadUpstreamFailure"}}}},"/api/v1/happy-hours/facets":{"get":{"tags":["Happy hours"],"operationId":"getHappyHourFacets","summary":"Get discovery facet counts","description":"Returns day and category counts after applying the supplied discovery filters. Pagination parameters are intentionally not used on this resource.","parameters":[{"$ref":"#/components/parameters/Query"},{"$ref":"#/components/parameters/Category"},{"$ref":"#/components/parameters/CategoryMode"},{"$ref":"#/components/parameters/Day"},{"$ref":"#/components/parameters/Time"},{"$ref":"#/components/parameters/At"},{"$ref":"#/components/parameters/Intent"},{"$ref":"#/components/parameters/Availability"},{"$ref":"#/components/parameters/Near"},{"$ref":"#/components/parameters/RadiusMeters"},{"$ref":"#/components/parameters/BoundingBox"}],"responses":{"200":{"description":"Counts for the filtered dataset.","headers":{"ETag":{"$ref":"#/components/headers/ETag"},"X-HHDB-API-Version":{"$ref":"#/components/headers/ApiVersion"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FacetsResponse"}}}},"304":{"$ref":"#/components/responses/NotModified"},"400":{"$ref":"#/components/responses/BadRequest"},"502":{"$ref":"#/components/responses/BadGateway"},"503":{"$ref":"#/components/responses/Unavailable"}}},"head":{"tags":["Happy hours"],"operationId":"headHappyHourFacets","summary":"Inspect facet response headers","parameters":[{"$ref":"#/components/parameters/Query"},{"$ref":"#/components/parameters/Category"},{"$ref":"#/components/parameters/CategoryMode"},{"$ref":"#/components/parameters/Day"},{"$ref":"#/components/parameters/Time"},{"$ref":"#/components/parameters/At"},{"$ref":"#/components/parameters/Intent"},{"$ref":"#/components/parameters/Availability"},{"$ref":"#/components/parameters/Near"},{"$ref":"#/components/parameters/RadiusMeters"},{"$ref":"#/components/parameters/BoundingBox"}],"responses":{"200":{"$ref":"#/components/responses/HeadSuccess"},"502":{"$ref":"#/components/responses/HeadUpstreamFailure"},"503":{"$ref":"#/components/responses/HeadUpstreamFailure"}}}},"/api/v1/openapi.json":{"get":{"tags":["Discovery"],"operationId":"getOpenApiDocument","summary":"Get this OpenAPI document","responses":{"200":{"description":"OpenAPI 3.1 JSON document.","content":{"application/json":{"schema":{"type":"object"}}}}}},"head":{"tags":["Discovery"],"operationId":"headOpenApiDocument","summary":"Inspect OpenAPI document headers","responses":{"200":{"$ref":"#/components/responses/HeadDocumentSuccess"}}}},"/openapi.json":{"get":{"tags":["Discovery"],"operationId":"getCanonicalOpenApiDocument","summary":"Get the canonical OpenAPI document","responses":{"200":{"description":"OpenAPI 3.1 JSON document.","content":{"application/json":{"schema":{"type":"object"}}}}}}}},"components":{"headers":{"ApiVersion":{"description":"Public contract version.","schema":{"type":"string","const":"1"}},"CanonicalSlug":{"description":"Canonical public slug for a detail lookup.","schema":{"type":"string"}},"ContentLocation":{"description":"Canonical internal producer location for the resource.","schema":{"type":"string"}},"ETag":{"description":"Strong representation ETag. Send it in If-None-Match for conditional GET or HEAD.","schema":{"type":"string"}}},"parameters":{"At":{"name":"at","in":"query","description":"RFC 3339 instant converted to America/Chicago. Cannot be combined with intent, day, or time.","schema":{"type":"string","format":"date-time"}},"Availability":{"name":"availability","in":"query","description":"Time-window behavior. Requires a resolved day and time. active is the default when time is supplied; ending-after includes any program that ends later, including ones not yet started.","schema":{"type":"string","enum":["active","ending-after"]}},"BoundingBox":{"name":"bbox","in":"query","description":"Coordinate bounds as west,south,east,north. Mutually exclusive with near.","schema":{"type":"string","pattern":"^-?[0-9]+(?:\\.[0-9]+)?,-?[0-9]+(?:\\.[0-9]+)?,-?[0-9]+(?:\\.[0-9]+)?,-?[0-9]+(?:\\.[0-9]+)?$"},"example":"-97.80,30.20,-97.68,30.34"},"Category":{"name":"category","in":"query","description":"Offer categories. Repeat the parameter or use comma-separated values.","style":"form","explode":true,"schema":{"type":"array","items":{"$ref":"#/components/schemas/Category"}}},"CategoryMode":{"name":"categoryMode","in":"query","description":"Whether a listing must contain every selected category or any selected category.","schema":{"type":"string","enum":["all","any"],"default":"all"}},"Cursor":{"name":"cursor","in":"query","description":"Opaque nextCursor from the prior page. Reuse it with the exact same filters and sort.","schema":{"type":"string","maxLength":1000}},"Day":{"name":"day","in":"query","description":"Austin local weekday. Required when time is supplied directly.","schema":{"$ref":"#/components/schemas/Day"}},"IdOrSlug":{"name":"idOrSlug","in":"path","required":true,"description":"Opaque hh_ ID, canonical slug, or retained slug alias.","schema":{"type":"string","minLength":1,"maxLength":160}},"Intent":{"name":"intent","in":"query","description":"Resolve the current Austin day and time on the server. Cannot be combined with at, day, or time.","schema":{"type":"string","enum":["now"]}},"Limit":{"name":"limit","in":"query","description":"Maximum listings in one page.","schema":{"type":"integer","minimum":1,"maximum":50,"default":20}},"Near":{"name":"near","in":"query","description":"Origin as latitude,longitude. Enables distance sorting and defaults radiusMeters to 50000. Mutually exclusive with bbox.","schema":{"type":"string","pattern":"^-?[0-9]+(?:\\.[0-9]+)?,-?[0-9]+(?:\\.[0-9]+)?$"},"example":"30.2672,-97.7431"},"Query":{"name":"q","in":"query","description":"Case- and accent-insensitive text search across venue names, restrictions, offers, and prices.","schema":{"type":"string","maxLength":120}},"RadiusMeters":{"name":"radiusMeters","in":"query","description":"Radius around near. Requires near.","schema":{"type":"integer","minimum":1,"maximum":50000,"default":50000}},"Seed":{"name":"seed","in":"query","description":"Stable seed for random ordering.","schema":{"type":"string","maxLength":64,"default":"0"}},"Sort":{"name":"sort","in":"query","description":"Ordering. distance requires near; relevance requires q. Defaults to distance with near, relevance with q, otherwise name.","schema":{"type":"string","enum":["distance","name","random","relevance"]}},"Time":{"name":"time","in":"query","description":"Austin local 24-hour time. Requires day; use at or intent as alternatives when the client should not supply both fields.","schema":{"type":"string","pattern":"^([01][0-9]|2[0-3]):[0-5][0-9]$"},"example":"17:30"}},"responses":{"BadGateway":{"description":"The private producer returned a response outside the frozen public contract.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"BadRequest":{"description":"Invalid, conflicting, unsupported, or cursor-bound query parameters.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"Conflict":{"description":"The cursor is stale because the published dataset changed. Restart without a cursor.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"HeadClientFailure":{"description":"Client error. HEAD responses contain headers only."},"HeadDocumentSuccess":{"description":"Document is available. No response body."},"HeadSuccess":{"description":"Resource is available. No response body.","headers":{"ETag":{"$ref":"#/components/headers/ETag"},"X-HHDB-API-Version":{"$ref":"#/components/headers/ApiVersion"}}},"HeadUpstreamFailure":{"description":"Public data is unavailable. HEAD responses contain headers only."},"NotFound":{"description":"No published listing matches the identifier. Missing and unpublished records are indistinguishable.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"NotModified":{"description":"The If-None-Match value matches the current representation.","headers":{"ETag":{"$ref":"#/components/headers/ETag"},"X-HHDB-API-Version":{"$ref":"#/components/headers/ApiVersion"}}},"Unavailable":{"description":"The public data service is temporarily unavailable.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}},"schemas":{"Category":{"type":"string","enum":["beer","wine","spirit","food"]},"Day":{"type":"string","enum":["sunday","monday","tuesday","wednesday","thursday","friday","saturday"]},"Envelope":{"type":"object","required":["apiVersion","dataVersion","generatedAt"],"properties":{"apiVersion":{"type":"string","const":"1"},"dataVersion":{"type":"string","pattern":"^[a-f0-9]{64}$","description":"Content-derived identity of the entire published dataset."},"generatedAt":{"type":"string","format":"date-time","description":"Projection generation time. This is not a venue verification or freshness claim."}}},"FacetsResponse":{"allOf":[{"$ref":"#/components/schemas/Envelope"},{"type":"object","required":["categories","days","total"],"properties":{"categories":{"type":"array","items":{"type":"object","required":["count","value"],"properties":{"count":{"type":"integer","minimum":0},"value":{"$ref":"#/components/schemas/Category"}}}},"days":{"type":"array","items":{"type":"object","required":["count","value"],"properties":{"count":{"type":"integer","minimum":0},"value":{"$ref":"#/components/schemas/Day"}}}},"total":{"type":"integer","minimum":0}}}]},"HappyHour":{"type":"object","additionalProperties":false,"required":["aliases","facets","id","links","location","name","path","programs","revision","slug","timezone"],"properties":{"aliases":{"type":"array","items":{"type":"string","minLength":1}},"facets":{"type":"object","additionalProperties":false,"required":["categories","days"],"properties":{"categories":{"type":"array","items":{"$ref":"#/components/schemas/Category"}},"days":{"type":"array","items":{"$ref":"#/components/schemas/Day"}}}},"id":{"$ref":"#/components/schemas/HappyHourId"},"links":{"$ref":"#/components/schemas/PublicLinks"},"location":{"oneOf":[{"$ref":"#/components/schemas/Location"},{"type":"null"}]},"name":{"type":"string","minLength":1},"path":{"type":"string","pattern":"^/happy-hour/"},"programs":{"type":"array","minItems":1,"items":{"$ref":"#/components/schemas/Program"}},"revision":{"type":"string","pattern":"^[a-f0-9]{64}$","description":"Content-derived identity for this public listing."},"slug":{"type":"string","minLength":1,"maxLength":160},"timezone":{"type":"string","const":"America/Chicago"}}},"HappyHourDetailResponse":{"allOf":[{"$ref":"#/components/schemas/Envelope"},{"type":"object","required":["item"],"properties":{"item":{"$ref":"#/components/schemas/HappyHour"}}}]},"HappyHourId":{"type":"string","pattern":"^hh_[a-f0-9]{24}$"},"HappyHourListResponse":{"allOf":[{"$ref":"#/components/schemas/Envelope"},{"type":"object","required":["items","page"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/HappyHour"}},"page":{"type":"object","additionalProperties":false,"required":["hasMore","limit","nextCursor","total"],"properties":{"hasMore":{"type":"boolean"},"limit":{"type":"integer","minimum":1,"maximum":50},"nextCursor":{"type":["string","null"]},"total":{"type":"integer","minimum":0}}}}}]},"Location":{"type":"object","additionalProperties":false,"required":["latitude","longitude"],"properties":{"latitude":{"type":"number","minimum":-90,"maximum":90},"longitude":{"type":"number","minimum":-180,"maximum":180}}},"MapPoint":{"type":"object","additionalProperties":false,"required":["categories","days","id","latitude","longitude","name","slug"],"properties":{"categories":{"type":"array","items":{"$ref":"#/components/schemas/Category"}},"days":{"type":"array","items":{"$ref":"#/components/schemas/Day"}},"id":{"$ref":"#/components/schemas/HappyHourId"},"latitude":{"type":"number","minimum":-90,"maximum":90},"longitude":{"type":"number","minimum":-180,"maximum":180},"name":{"type":"string","minLength":1},"slug":{"type":"string","minLength":1,"maxLength":160}}},"MapResponse":{"allOf":[{"$ref":"#/components/schemas/Envelope"},{"type":"object","required":["items","total"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/MapPoint"}},"total":{"type":"integer","minimum":0}}}]},"MetaResponse":{"allOf":[{"$ref":"#/components/schemas/Envelope"},{"type":"object","required":["capabilities","listingCount","maxPageSize"],"properties":{"capabilities":{"type":"object","additionalProperties":false,"required":["categoryFilter","cursorPagination","geoFilter","map","overnightSchedules","textSearch","timeFilter"],"properties":{"categoryFilter":{"type":"boolean","const":true},"cursorPagination":{"type":"boolean","const":true},"geoFilter":{"type":"boolean","const":true},"map":{"type":"boolean","const":true},"overnightSchedules":{"type":"boolean","const":true},"textSearch":{"type":"boolean","const":true},"timeFilter":{"type":"boolean","const":true}}},"listingCount":{"type":"integer","minimum":0},"maxPageSize":{"type":"integer","minimum":1,"maximum":50}}}]},"Offer":{"type":"object","additionalProperties":false,"required":["category","id"],"properties":{"category":{"oneOf":[{"$ref":"#/components/schemas/Category"},{"type":"null"}]},"description":{"type":"string","minLength":1},"id":{"type":"string","pattern":"^off_[a-f0-9]{24}$"},"price":{"type":"string","minLength":1}}},"Problem":{"type":"object","additionalProperties":false,"required":["apiVersion","code","detail","requestId","status","title","type"],"properties":{"apiVersion":{"type":"string","const":"1"},"code":{"type":"string","minLength":1},"detail":{"type":"string","minLength":1},"requestId":{"type":"string","minLength":1},"status":{"type":"integer","minimum":400,"maximum":599},"title":{"type":"string","minLength":1},"type":{"type":"string","format":"uri"}}},"Program":{"type":"object","additionalProperties":false,"required":["id","offers","schedule"],"properties":{"id":{"type":"string","pattern":"^prog_[a-f0-9]{24}$"},"offers":{"type":"array","items":{"$ref":"#/components/schemas/Offer"}},"restrictions":{"type":"string","minLength":1},"schedule":{"type":"array","minItems":1,"items":{"$ref":"#/components/schemas/ScheduleWindow"}}}},"PublicLinks":{"type":"object","additionalProperties":false,"properties":{"directions":{"type":"string","format":"uri"},"happyHour":{"type":"string","format":"uri"},"website":{"type":"string","format":"uri"}}},"ScheduleWindow":{"type":"object","additionalProperties":false,"required":["day","endMinute","endTime","endsNextDay","id","startMinute","startTime"],"properties":{"day":{"$ref":"#/components/schemas/Day"},"endMinute":{"type":"integer","minimum":0,"maximum":1439},"endTime":{"type":"string","pattern":"^([01][0-9]|2[0-3]):[0-5][0-9]$"},"endsNextDay":{"type":"boolean","description":"True when endMinute is less than or equal to startMinute. Starts are inclusive and ends are exclusive."},"id":{"type":"string","pattern":"^win_[a-f0-9]{24}$"},"startMinute":{"type":"integer","minimum":0,"maximum":1439},"startTime":{"type":"string","pattern":"^([01][0-9]|2[0-3]):[0-5][0-9]$"}}}}},"x-hhdb-contract":{"apiVersion":"1","canonicalDocumentation":"https://austinhappyhourdatabase.com/api/v1/openapi.json","cors":"Access-Control-Allow-Origin: *","readOnly":true,"timeZone":"America/Chicago","privateProducer":"The Payload CMS origin and /api/public/v1 producer require a scoped server credential and are not public client surfaces.","freshnessBoundary":"generatedAt and revision identify projected content; neither claims that a venue offer was recently verified."}}