Event instances
List upcoming or past performances, filter them by date, venue, and category, and look up one instance by ID
Use these endpoints to power calendars, "what is on" feeds, and event detail widgets in a theme or embedded site.
By default the list endpoint returns published, future event instances for the current site, sorted by start date.
List event instances
GET {your-domain}/api/event-instances.jsonQuery parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
page | integer | 1 | Page number to return. The maximum is 1000. Basker reduces a higher value to 1000. |
limit | integer | 500 | Page size. The maximum is 500. Basker reduces a higher value to 500. |
showPast | boolean | false | When true, includes instances that start before today. |
eventId | string | None | Returns the instances of one event. |
venueId | string | None | Returns the instances at one venue. |
seriesId | string | None | Returns the instances in one series. |
seasonId | string | None | Returns the instances whose parent event is in one season. |
where | filter | None | Filters on any field, including a start-date range. See Filter by date, venue, and category. |
attributeWhere | filter | None | Filters on a custom attribute, such as a category. See Filter by date, venue, and category. |
tenant | string | (current site) | Slug of a tenant to filter by, when the requesting site has access to multiple. Most calls can omit this. |
depth | integer (0 to 5) | 2 | How deeply to expand related records (event, venue, series, and others). Higher values return more inline data. Lower values are faster. |
select | string | None | Comma-separated dotted field paths to narrow the response. See Field selection. |
locale | string | (site default) | Language code for translated fields, for example cy. An unknown or unavailable code returns a 400. |
Response
A standard paginated list:
{
"docs": [
{
"id": "000000000000000000000001",
"startDate": "2030-06-12T19:30:00.000Z",
"startDate_tz": "Europe/London",
"startDateLocalAsUTC": "2030-06-12T19:30:00.000Z",
"event": {
"id": "000000000000000000000002",
"title": "Moonclock",
"slug": "moonclock",
"url": "/events/moonclock",
"image": { "url": "https://..." },
"description": "...",
"venue": { "title": "Remarkable Theatre Main Hall", "slug": "main-hall" },
"series": [],
"season": null
},
"venue": { "id": "000000000000000000000003", "title": "Remarkable Theatre Main Hall", "slug": "main-hall" },
"series": [],
"ticketingSystem": "Tessitura",
"booking": { "bookingLinkURL": "https://...", "bookingLinkLabel": "Book now" },
"tessitura": { "performanceId": "...", "productionSeasonId": "...", "availability": "available" }
}
],
"totalDocs": 1,
"limit": 500,
"totalPages": 1,
"page": 1,
"pagingCounter": 1,
"hasPrevPage": false,
"hasNextPage": false,
"prevPage": null,
"nextPage": null
}Per-instance fields you can rely on:
| Field | Description |
|---|---|
id | Unique identifier. |
startDate | ISO timestamp in UTC. |
startDate_tz | IANA timezone for the venue. |
startDateLocalAsUTC | The local wall-clock time, encoded as UTC. Use it to group by calendar day in the venue timezone without a timezone conversion in your code. |
event | The parent event: title, slug, url, image, description, venue, series, season. |
venue, series | Related records set on the instance, when present. series is an array. The season comes through the parent event. |
ticketingSystem | General, Spektrix, Tessitura, Elevent, or Lineup. |
booking.bookingLinkURL, booking.bookingLinkLabel | The performance's External Booking URL (Instance) and External Booking Button Label (Instance). The parent event has its own booking.bookingLinkURL and booking.bookingLinkLabel. booking appears only when the Booking app is installed. |
tessitura, spektrix, elevent | Ticketing-system-specific data, present when that integration is installed. On list items, tessitura holds availability, keywords, performanceId, and productionSeasonId. |
theme.settings | The instance's saved template settings. The parent event carries its own at event.theme.settings. The theme key is missing when there are no saved template settings. |
The instance booking fields override the event's for that date only. A blank instance value means "use the event's value", but the feed does not fill it in for you. Test the instance value first and fall back to the event:
const url = instance.booking?.bookingLinkURL || instance.event?.booking?.bookingLinkURL;People inside custom attributes, such as an artist or composer, carry hasBiography instead of their biography. hasBlocks sits on the person too. Read them on the person, for example attributes.custom.artists[0].person.hasBiography, not on the attribute row.
The event object also carries rendered-HTML companions for its rich-text fields (richTitle_html and richDescription_html alongside title and description). Place that markup directly in a calendar card.
Filter by date, venue, and category
This endpoint filters at the edge. A browser can request one month, at one venue, in two categories, and read the answer from the edge cache. The filters below follow the same contract as the other content endpoints.
Date range
Filter the start date with where[startDate]. Values are ISO 8601 timestamps.
/api/event-instances.json
?where[startDate][greater_than_equal]=2026-10-01T00:00:00.000Z
&where[startDate][less_than]=2026-11-01T00:00:00.000ZPast dates need showPast
The endpoint excludes instances before the start of today unless the request sets showPast=true. A range that ends in the past returns an empty list without it, because the two conditions combine with AND.
Venue and other relationships
Use the shortcut parameters for the relationships a calendar filters on most:
/api/event-instances.json?venueId=000000000000000000000003
/api/event-instances.json?eventId=000000000000000000000002&showPast=truewhere[venue][equals]= does the same work as venueId=. Use the where form when you need an operator other than an exact match.
Category and other custom attributes
Filter on a custom attribute with attributeWhere. Pass several values to in as one comma-separated list:
/api/event-instances.json?attributeWhere[custom.category][in]=bookbug,family-funThe content endpoints page lists the operators that each attribute type accepts.
Combined query
Filters combine with AND. This request asks for one venue, one month, and two categories, and returns four fields per instance:
const params = new URLSearchParams({
'where[startDate][greater_than_equal]': '2026-10-01T00:00:00.000Z',
'where[startDate][less_than]': '2026-11-01T00:00:00.000Z',
venueId: '000000000000000000000003',
'attributeWhere[custom.category][in]': 'bookbug,family-fun',
select: 'startDate,event.title,event.url,venue.title',
limit: '200',
});
const res = await fetch(`/api/event-instances.json?${params}`);
const { docs } = await res.json();What a filter cannot reach
A filter narrows the list. It never widens it. Unpublished instances, hidden instances, and instances of an unpublished event stay out of the response whatever the query asks for.
Custom data on event feeds
An event instance response can include custom attributes from the instance, from the parent event, and from related records such as the venue. A deeper response can also include relationships to pages, media, files, or custom objects.
Each relationship-style custom attribute has a Public API response setting:
| Setting | Response shape |
|---|---|
| Full record | Returns the expanded related record when the requested depth includes it. |
| Summary | Returns a compact object with identifying fields such as id, title, name, label, slug, or url. |
| Reference only | Returns only the related record ID, or an array of IDs for fields that allow multiple values. |
Use ?select= together with Summary or Reference only for calendar feeds that need custom data but not every field from every related record.
Examples
Fetch the next 10 upcoming instances:
const res = await fetch('/api/event-instances.json?limit=10');
const { docs } = await res.json();Paginate through everything, including past dates:
async function* allInstances() {
let page = 1;
while (true) {
const res = await fetch(`/api/event-instances.json?page=${page}&limit=200&showPast=true`);
const data = await res.json();
yield* data.docs;
if (!data.hasNextPage) break;
page += 1;
}
}Get an event instance by ID
GET {your-domain}/api/event-instances/{id}Returns the instance wrapped in a doc key: { "doc": { ... } }. The record inside has the same field shape as items in the list response, plus a few fields the list leaves out. These include bookingStatus (the Booking Status override, such as soldOut) and tessitura.availSaleIndicator.
Path parameters
| Parameter | Type | Description |
|---|---|---|
id | string | The instance ID, taken from a list response or a relationship field on another record. |
Errors
| Status | Meaning |
|---|---|
400 | The id is missing or not a valid identifier. |
404 | No instance with that ID exists, or your site does not have access to it. |
500 | Server error. |
Field selection
Pass ?select= with a comma-separated list of dotted field paths to drop everything else. The response always includes the full pagination wrapper. The select parameter narrows only the items inside docs.
?select=startDate,event.title,event.url,venue.titleUse field selection to keep payloads small for calendar grids that only need the date, the event title, and a link.
Caching
When edge caching is enabled for your site, list responses can be served from the edge. Public responses carry Cache-Control: public, s-maxage=3600, max-age=60, stale-while-revalidate=86400, stale-if-error=86400. The cache invalidates when an editor publishes, schedules, or deletes an event instance.
Filtered URLs cache the same way unfiltered ones do. Build the same query for every visitor who sees the same view, and the second visitor reads the first cached response. Avoid query parameters that vary per visitor, such as cache-busters and timestamps, unless you need a fresh response.