Public Events API (v1)
Last updated: April 23, 2026
Overview
The Hedliner Public Events API lets a venue expose its upcoming shows to any website, mobile app, AI agent, or third-party integration. The API is read-first: GET endpoints are fully implemented; create, update, and delete endpoints are reserved for future use and currently return 501 Not Implemented with the correct scope enforcement already in place.
Base URL: https://hedliner.com/api/v1
All endpoints return JSON. Every request must include a valid API key. Each key is scoped to a single venue — the API will only ever return events owned by that venue.
Getting an API key
- Sign in as a venue user at https://hedliner.com/login.
- Go to /settings and scroll to the API Keys section.
- If you manage multiple venues, pick the venue you want the key scoped to.
- Click Generate key, give it a label (e.g.
website production), and select scopes. The default isevents:read. - Copy the plaintext token immediately. It is shown exactly once. Hedliner only stores a SHA-256 hash — if you lose the token you must revoke it and generate a new one.
Tokens look like hdlr_live_ followed by 22 URL-safe random characters (128 bits of entropy). Example: hdlr_live_J89bZfJGeWgAZoarSZOBFw.
Authentication
Send the token on every request using one of two headers:
Authorization: Bearer hdlr_live_YOUR_TOKEN_HERE # or x-api-key: hdlr_live_YOUR_TOKEN_HERE
The Authorization header takes precedence if both are present. Tokens are case-sensitive.
Scopes
A key carries one or more scopes. The API enforces the scope required by each endpoint; a request with an insufficient scope returns 403.
events:read— read events for the venue. Required by allGETendpoints.events:write— create or update events. Required byPOSTandPATCH(currently501 Not Implemented).events:delete— delete events. Required byDELETE(currently501 Not Implemented).
Revocation
Revoke a key by clicking Revoke next to it on the settings page. Revocation is immediate — the next request with that token returns 401. Revocation is a soft delete (the hash is retained with a revokedAt timestamp), so you cannot resurrect a revoked token. Generate a new one instead.
Endpoints
GET /api/v1/events
List upcoming events for the venue the key is scoped to.
Query parameters
| Name | Type | Default | Description |
|---|---|---|---|
from | ISO date YYYY-MM-DD | today (UTC) | Earliest show date (inclusive). |
to | ISO date YYYY-MM-DD | today + 90 days | Latest show date (inclusive). |
status | open | filled | cancelled | reserved | any except cancelled | Filter by slot status. |
recurring | exclude | include | only | exclude | Control whether slots generated from a recurring template (e.g. a weekly dance class) are returned. Default hides them so you see only one-off bookings. |
limit | integer 1–100 | 50 | Max events to return. |
cursor | uuid | — | Opaque pagination cursor. Pass the meta.nextCursor from the previous response. |
Example request
curl -H "Authorization: Bearer hdlr_live_YOUR_TOKEN_HERE" \ "https://hedliner.com/api/v1/events?from=2026-05-01&to=2026-06-30&limit=20"
Example response (200)
{
"data": [
{
"id": "e2b1c4f8-....",
"date": "2026-05-14",
"doorsOpenTime": "20:00",
"setStartTime": "21:00",
"setEndTime": "23:00",
"setLengthMinutes": 120,
"status": "filled",
"eventName": "Les Trois Accords — Spring Tour",
"posterUrl": "https://.../poster.jpg",
"producerName": null,
"notes": null,
"venue": {
"id": "v1-uuid",
"name": "Nash",
"slug": "nash",
"city": "Nashville",
"stateProvince": "TN",
"country": "US",
"timezone": "America/Chicago",
"capacity": 300
},
"performers": [
{
"name": "Les Trois Accords",
"role": "headliner",
"bandSlug": "les-trois-accords",
"bandBannerUrl": "https://.../banner.jpg"
}
],
"pricing": {
"online": "25.00",
"door": "30.00",
"doorSellerName": null
},
"links": {
"ticketing": "https://tickets.example/abc",
"facebookEvent": null,
"website": null
}
}
],
"meta": {
"count": 1,
"nextCursor": null,
"venueId": "v1-uuid"
}
}GET /api/v1/events/[id]
Fetch a single event by its UUID. Returns the same object shape as one entry in the list endpoint's data array. Returns 404 if the event does not exist or is not owned by the venue the key is scoped to.
Write endpoints (reserved)
These endpoints are wired up with scope enforcement but intentionally return 501 Not Implemented. They will be enabled in a future release, primarily for AI-driven integrations. You can request keys with these scopes today so you don't need a new token later.
POST /api/v1/events— requiresevents:write.PATCH /api/v1/events/[id]— requiresevents:write.DELETE /api/v1/events/[id]— requiresevents:delete.
Field reference
Every event object in data has the following fields.
| Field | Type | Description |
|---|---|---|
id | uuid | Stable event identifier. Use as the cursor value. |
date | ISO date | Show date in the venue's local calendar. |
doorsOpenTime | string HH:MM | null | Local time the doors open. |
setStartTime | string HH:MM | null | Local time the headliner starts. |
setEndTime | string HH:MM | null | Local time the show ends. |
setLengthMinutes | integer | null | Total set length. |
status | enum | open | filled | cancelled | reserved. |
eventName | string | null | Override name for the show (tour title, themed night, etc.). |
posterUrl | URL | null | Poster image. |
producerName | string | null | Producer/promoter if external. |
notes | string | null | Public-facing notes from the venue. |
venue | object | Venue profile: id, name, slug, city, stateProvince, country, timezone, capacity. timezone is an IANA zone (e.g. America/Chicago) and should be used to interpret the time fields. |
performers | array | Ordered list of performers. Each has name, role (headliner | support | opener), bandSlug (null if the performer is not a Hedliner band profile), and bandBannerUrl. |
pricing | object | online and door are decimal strings (e.g. "25.00") or null; doorSellerName is a free-text string or null. |
links | object | ticketing, facebookEvent, website — URLs or null. |
meta
count— number of events indata.nextCursor— uuid to pass as?cursor=on the next request, ornullif there are no more results.venueId— the venue the key is scoped to. Handy as an assertion in client code.
Pagination
Pagination is cursor-based and sorted by (showDate, setStartTime, id) ascending. To walk the full result set:
- Call with your desired filters and no cursor.
- If
meta.nextCursoris not null, call again with the same filters plus?cursor=<nextCursor>. - Stop when
meta.nextCursoris null.
Errors
All errors are JSON with an error string and an HTTP status code.
| Status | Meaning |
|---|---|
400 | Invalid query parameter (bad date format, out-of-range limit, etc.). The response includes details from Zod. |
401 | Missing, malformed, or revoked token. Also returned if the token does not match any stored key. |
403 | Token is valid but lacks the scope required by this endpoint. |
404 | The requested event does not exist or is not owned by the key's venue. |
501 | Write endpoint not yet implemented. |
Security notes
- Treat tokens like passwords. Never commit them to git, bundle them into a browser build, or paste them into chat. Use a server-side proxy or your framework's secret store.
- A leaked key exposes only that venue's event data and only the scopes you granted. Revoke and rotate immediately if a key is exposed.
- All traffic is HTTPS only. Hedliner stores only a SHA-256 hash of the token, so we cannot recover it for you.
- Use a separate key per deployment (production, staging, local dev) so you can revoke one without disrupting the others.
Guidance for AI agents
If you are an autonomous agent acting on behalf of a venue owner, follow these rules verbatim:
- Never hardcode or store a token the user has not explicitly provided. Always read it from a secure environment variable the operator has set.
- Send the token in the
Authorization: Bearerheader. Do not log the token. - Default to
GET /api/v1/eventswith no filters — this returns the next 90 days of non-recurring events for the venue. - To page through everything, loop until
meta.nextCursorisnull. Cap your loops at a reasonable number (e.g. 20 pages) to avoid accidental infinite pagination. - The canonical ordering is
(date, setStartTime, id)ascending. Do not re-sort client-side unless the consumer explicitly asks for a different order. - Interpret
date,doorsOpenTime,setStartTime, andsetEndTimeinvenue.timezone. They are not UTC. - Treat any field typed as
| nullas genuinely optional. Do not invent placeholder values. - Write operations (
POST,PATCH,DELETE) currently return501. Do not retry; surface the status to the caller and stop. - On
401or403, do not retry with a different key or header — instead report the failure to the operator so they can rotate the key or grant a scope.
Rate limits
There is no enforced per-key rate limit at this time. Please be reasonable — cache responses for at least a minute on the client and back off on errors. Abusive traffic will be rate-limited without notice.
Versioning
The URL carries a major version (/v1). Breaking changes will ship under /v2; additive changes (new optional fields, new optional query params) may land in /v1 without notice.
Support
Questions, bug reports, or requests for write access? Email support@hedliner.com.