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

  1. Sign in as a venue user at https://hedliner.com/login.
  2. Go to /settings and scroll to the API Keys section.
  3. If you manage multiple venues, pick the venue you want the key scoped to.
  4. Click Generate key, give it a label (e.g. website production), and select scopes. The default is events:read.
  5. 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 all GET endpoints.
  • events:write — create or update events. Required by POST and PATCH (currently 501 Not Implemented).
  • events:delete — delete events. Required by DELETE (currently 501 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

NameTypeDefaultDescription
fromISO date YYYY-MM-DDtoday (UTC)Earliest show date (inclusive).
toISO date YYYY-MM-DDtoday + 90 daysLatest show date (inclusive).
statusopen | filled | cancelled | reservedany except cancelledFilter by slot status.
recurringexclude | include | onlyexcludeControl 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.
limitinteger 1–10050Max events to return.
cursoruuidOpaque 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 — requires events:write.
  • PATCH /api/v1/events/[id] — requires events:write.
  • DELETE /api/v1/events/[id] — requires events:delete.

Field reference

Every event object in data has the following fields.

FieldTypeDescription
iduuidStable event identifier. Use as the cursor value.
dateISO dateShow date in the venue's local calendar.
doorsOpenTimestring HH:MM | nullLocal time the doors open.
setStartTimestring HH:MM | nullLocal time the headliner starts.
setEndTimestring HH:MM | nullLocal time the show ends.
setLengthMinutesinteger | nullTotal set length.
statusenumopen | filled | cancelled | reserved.
eventNamestring | nullOverride name for the show (tour title, themed night, etc.).
posterUrlURL | nullPoster image.
producerNamestring | nullProducer/promoter if external.
notesstring | nullPublic-facing notes from the venue.
venueobjectVenue 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.
performersarrayOrdered list of performers. Each has name, role (headliner | support | opener), bandSlug (null if the performer is not a Hedliner band profile), and bandBannerUrl.
pricingobjectonline and door are decimal strings (e.g. "25.00") or null; doorSellerName is a free-text string or null.
linksobjectticketing, facebookEvent, website — URLs or null.

meta

  • count — number of events in data.
  • nextCursor — uuid to pass as ?cursor= on the next request, or null if 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:

  1. Call with your desired filters and no cursor.
  2. If meta.nextCursor is not null, call again with the same filters plus ?cursor=<nextCursor>.
  3. Stop when meta.nextCursor is null.

Errors

All errors are JSON with an error string and an HTTP status code.

StatusMeaning
400Invalid query parameter (bad date format, out-of-range limit, etc.). The response includes details from Zod.
401Missing, malformed, or revoked token. Also returned if the token does not match any stored key.
403Token is valid but lacks the scope required by this endpoint.
404The requested event does not exist or is not owned by the key's venue.
501Write 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: Bearer header. Do not log the token.
  • Default to GET /api/v1/events with no filters — this returns the next 90 days of non-recurring events for the venue.
  • To page through everything, loop until meta.nextCursor is null. 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, and setEndTime in venue.timezone. They are not UTC.
  • Treat any field typed as | null as genuinely optional. Do not invent placeholder values.
  • Write operations (POST, PATCH, DELETE) currently return 501. Do not retry; surface the status to the caller and stop.
  • On 401 or 403, 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.