An event is the central resource for ticketing. Events come in three flavors:
type |
Description |
|---|---|
date |
A single-date event with a starts_at and ends_at. The default and most common type. |
parent |
A container event with one or more child sessions (each itself a date event). Use this for multi-session experiences sold as a single offering. |
recurring |
A template event that auto-generates child date events on a schedule (daily, weekly, etc.). Configure with one or more recurrences. |
Most operations target the date type. The same endpoint creates all three — pass type on create.
Default response fields
Unless ?fields= is specified, the following fields are returned:
id, created_at, updated_at, name, slug, status, venue_id, parent_event_id, calendar_id, published_at, capacity, type, start, end, deletable
Relationships (venue, sessions, recurrences, categories, campaigns, tags, registration_types, list) are returned only when listed in ?include=.
List events
GET /events
List events
curl -X GET \
'https://app.guestmanager.com/api/public/v2/events?page[cursor]=&page[size]=25' \
-H 'Authorization: Token abcdefg' \
-H 'Content-Type: application/json'
List events with registration types and prices, sorted by
starts_at
curl -X GET \
'https://app.guestmanager.com/api/public/v2/events?page[cursor]=&include=registration_types.prices&sort[starts_at]=asc' \
-H 'Authorization: Token abcdefg' \
-H 'Content-Type: application/json'
Sample response
{
"data": [
{
"id": 59978,
"name": "Gourmet Steam Oven",
"slug": "gourmet-steam-oven-10-30am-12-00pm",
"type": "date",
"status": "future",
"venue_id": 1989,
"parent_event_id": null,
"calendar_id": null,
"published_at": "2026-04-17T01:08:42.038414Z",
"capacity": 50,
"deletable": true,
"start": {
"tz": "Melbourne",
"local": "2026-10-28T10:30:00+11:00",
"utc": "2026-10-27T23:30:00Z"
},
"end": {
"tz": "Melbourne",
"local": "2026-10-28T12:00:00+11:00",
"utc": "2026-10-28T01:00:00Z"
},
"registration_types": [
{
"id": 24,
"variant_id": 1867,
"name": "General admission",
"price": 0,
"prices": [
{
"decimal": "0.0",
"amount": 0,
"currency": "AUD",
"default": true,
"formatted": "$0.00"
}
]
}
]
}
],
"meta": {
"count": 25,
"page": {
"size": 25,
"next_cursor": "WyIyMDI2LTA1LTAxVDEyOjMwOjAwWiIsNDIxXQ",
"last": false,
"first": true
},
"links": {
"self": "https://app.guestmanager.com/api/public/v2/events?page[cursor]=&page[size]=25",
"next": "https://app.guestmanager.com/api/public/v2/events?page[cursor]=WyIyMDI2LTA1LTAxVDEyOjMwOjAwWiIsNDIxXQ&page[size]=25"
}
}
}
Request parameters
| Parameter | Type | Description |
|---|---|---|
page[cursor] |
string |
Opaque cursor token. Send empty for first page. See Pagination. |
page[size] |
integer |
Records per page. Default 10, maximum 200 for events. |
sort[{field}] |
string |
Sort by name, starts_at, ends_at, venue_id, parent_event_id, published_at, position. Value is asc or desc. |
fields |
string |
Comma separated list of fields to return. Add counts to include attendance/availability counts (forces extra preloads — pay only when needed). |
include |
string |
Comma separated relationships. See Relationships. |
filter[search] |
string |
Full-text search across event names and metadata. Routes through Elasticsearch when available. |
filter[name] |
string |
Exact name match. |
filter[venue_id] |
integer |
Filter by venue. |
filter[parent_event_id] |
integer |
Filter by parent (recurring or parent event). Use to list sessions of a parent, or generated dates of a recurring template. |
filter[archived_at] |
boolean |
true returns only archived events; false excludes them. |
filter[permanence] |
string |
permanent or non_permanent. |
filter[starts_at][from] |
date |
Events starting on or after this date. |
filter[starts_at][to] |
date |
Events starting before this date. |
filter[ends_at][from] |
date |
Events ending on or after this date. Generally starts_at is more useful. |
filter[ends_at][to] |
date |
Events ending before this date. |
filter[status] |
string |
One of active, over, past, future, today, tomorrow, this_week, next_week, next_month. See Status filter below. |
Date ranges
When using [from] / [to] ranges, you can specify dates in any common format (e.g. 2026-05-25) or iso8601 datetime strings. When both from and to are specified, the SQL query is a BETWEEN — from is rounded to start of day and to to end of day if no time is provided.
Status filter
filter[status] is a convenience wrapper over date predicates:
| Value | Meaning |
|---|---|
active |
Events in progress and future events. |
over |
ends_at < now. |
future |
starts_at > now (excludes events in progress). |
past |
starts_at < now. |
today |
Events occurring today (local timezone of event). |
tomorrow |
Events occurring tomorrow. |
this_week |
Monday–Sunday of the current week. |
next_week |
Monday–Sunday of the following week. |
next_month |
The full calendar month after the current one. |
Relationships
Pass via ?include= (comma separated):
| Relationship | Notes |
|---|---|
venue |
The event’s venue. |
venue.address |
Venue with full address (country, state). |
categories |
Event categories. |
campaigns |
Active marketing campaigns attached to the event. |
tags |
Free-form tags. |
list |
The default attendee list for the event. |
list.setting |
List with its template settings (description, image). |
recurrences |
Recurrence rules (only meaningful for type: recurring). |
registration_types |
Registration types (formerly “ticket tiers” in v1). |
registration_types.prices |
Registration types with full pricing (multi-currency). |
registration_types.stock_item |
Inventory state. May be cached and slightly stale — do not use for hard inventory decisions. |
registration_types.ticket_type |
The underlying ticket type config (PDF/wallet template, attachable, transferable, required fields). |
registration_types.pickups |
Configured product pickups for each registration type. |
registration_types.event.venue |
Useful for parent events when fetching session pricing — resolves the session’s venue per registration type. |
Get event
GET /events/{id}
Returns a single event. The full graph (sessions, registration types with prices and stock, list, etc.) is preloaded for ?include= you specify; pass an empty ?include= to get just the top-level fields.
curl -X GET \
'https://app.guestmanager.com/api/public/v2/events/123456?include=registration_types.prices,venue' \
-H 'Authorization: Token abcdefg' \
-H 'Content-Type: application/json'
Create event
POST /events
Creates an event. Required: name, venue_id, starts_at, ends_at.
Create a single-date event
curl -X POST \
https://app.guestmanager.com/api/public/v2/events \
-H 'Authorization: Token abcdefg' \
-H 'Content-Type: application/json' \
-d '{
"event": {
"type": "date",
"name": "New Year''s Eve Gala",
"venue_id": 2847,
"starts_at": "2026-12-31T20:00:00Z",
"ends_at": "2027-01-01T02:00:00Z",
"capacity": 500
}
}'
Create a parent event with two sessions and registration types
curl -X POST \
https://app.guestmanager.com/api/public/v2/events \
-H 'Authorization: Token abcdefg' \
-H 'Content-Type: application/json' \
-d '{
"event": {
"type": "parent",
"name": "Tasting Tour",
"venue_id": 2847,
"starts_at": "2026-09-01T17:00:00Z",
"ends_at": "2026-09-01T22:00:00Z",
"sessions": [
{
"name": "Session A",
"venue_id": 2847,
"starts_at": "2026-09-01T17:00:00Z",
"ends_at": "2026-09-01T19:00:00Z",
"registration_types": [
{ "name": "GA", "price": 50, "inventory": 50, "ticket_type_id": 2217 },
{ "name": "VIP", "price": 125, "inventory": 10, "ticket_type_id": 2217 }
]
},
{
"name": "Session B",
"venue_id": 2847,
"starts_at": "2026-09-01T19:30:00Z",
"ends_at": "2026-09-01T22:00:00Z",
"registration_types": [
{ "name": "GA", "price": 50, "inventory": 50, "ticket_type_id": 2217 }
]
}
]
}
}'
Create a recurring event template
curl -X POST \
https://app.guestmanager.com/api/public/v2/events \
-H 'Authorization: Token abcdefg' \
-H 'Content-Type: application/json' \
-d '{
"event": {
"type": "recurring",
"name": "Weekly Tasting",
"venue_id": 2847,
"starts_at": "2026-06-01T18:00:00Z",
"ends_at": "2026-06-01T20:00:00Z",
"recurrences": [
{
"starts_at": "2026-06-01T18:00:00Z",
"ends_at": "2026-12-31T23:59:00Z",
"ends": "on_date",
"repeat_unit": "week",
"repeat_value": 1,
"duration": 2,
"days": ["monday", "wednesday"],
"operating_hours": [{ "open": "18:00", "close": "20:00" }]
}
]
}
}'
Response: X-Event-Operation-ID
Successful create and update responses include an X-Event-Operation-ID header. The event is fully created in the database before the response returns, but post-create work runs asynchronously:
- Recurrence fan-out (for
type: recurringevents) — generates the child date events from the recurrence rules. - Ticket structure setup (
Workers::Events::Sync::BuildTickets) — wires up registration types, pickups, and stock items. - Shopify product mirroring — for Shopify-installed companies only, creates the corresponding Shopify products. Skipped silently for non-Shopify companies.
The header is meaningful for every customer, not just Shopify. Use the operation ID to poll status via GET /events/{event_id}/operations/{id} if your integration needs to wait for sync completion before proceeding.
Event params
| Parameter | Type | Required | Description |
|---|---|---|---|
event[type] |
string |
no (default date) |
One of date, parent, recurring. |
event[name] |
string |
yes | Event name. |
event[venue_id] |
integer |
yes | ID of an existing venue. Create venues via Venues first. |
event[starts_at] |
datetime |
yes | UTC iso8601 datetime. |
event[ends_at] |
datetime |
yes | UTC iso8601 datetime. |
event[published_at] |
datetime |
no | Set to publish the event explicitly. For type: date events, omitting (or sending null) keeps the event draft. Parent events (type: parent) are auto-published on create regardless of this field; their child sessions inherit published_at: null (draft) and need to be published individually if you want them live before the parent’s publish flow runs. |
event[capacity] |
integer |
no | Optional event-wide capacity cap. Stacks with per-registration-type inventory. |
event[setting_id] |
integer |
no | Reuse an existing event setting (PDF/wallet/email templates) by ID. |
event[settings] |
object |
no | Inline settings overrides. Currently supports pos_processing (enabled / disabled / inherit). |
event[sessions] |
array |
no (parent only) | Required for type: parent. See Sessions. |
event[registration_types] |
array |
no | Tickets and passes both live here, discriminated by kind. See Registration types. |
event[recurrences] |
array |
no (recurring only) | Required for type: recurring. See Recurrences. |
Sessions
Preview The sessions parameter shape is in preview. The nested registration_types and field set may change with at least 90 days of notice. See Stability & versioning.
Sessions are nested events under a parent. Each session is itself a date event with its own venue, capacity, and registration types.
| Field | Type | Description |
|---|---|---|
id |
integer |
Required when updating an existing session. Omit on create. |
_destroy |
boolean |
Set to true to remove an existing session. |
name |
string |
Session name. |
starts_at, ends_at |
datetime |
Session times (UTC iso8601). |
venue_id |
integer |
Override the parent’s venue for this session. Defaults to parent venue if omitted. |
capacity |
integer |
Per-session capacity cap. |
registration_types |
array |
Registration types for this session — same shape as event-level. See below. |
Registration types
Registration types are the canonical representation of “what someone is buying” — GA, VIP, Early Bird, weekend wristband, etc. Both tickets and passes live in this one array, discriminated by kind.
Tickets vs passes: A ticket (
kind: "ticket", the default) is scoped to a single date/session. A pass (kind: "pass") spans an entire parent event and covers every session under it. Use a ticket for “GA to Friday’s show”; use a pass for “weekend wristband, all three nights.” Single-date events typically don’t need passes — tickets are enough.
| Field | Type | Description |
|---|---|---|
id |
integer |
Required to update existing. Omit on create. |
_destroy |
boolean |
Set to true to remove. |
kind |
string |
"ticket" (default) or "pass". Discriminator for the two flavors. Omitted = ticket. |
name |
string |
Display name (GA, VIP, etc). |
ticket_type_id |
integer |
Required for tickets. The underlying ticket type. Re-used across registration types when ticket configuration is identical. Must be sent on every ticket entry that isn’t being destroyed (including updates). Passes use inline ticket_type (below) instead. |
price |
decimal |
Price in dollars (or your account’s major currency unit). 100 means $100.00, not $1.00. Returned as a decimal string on read (e.g., "70.0"). |
inventory |
integer |
Inventory available for purchase. Absolute set. Use inventory_change instead when you want delta semantics. |
inventory_change |
object |
Optional {mode, quantity} for Adjust/Set semantics. mode: "set" replaces the total with quantity; mode: "adjust" adds the signed quantity to the current total (negative to reduce). Takes precedence over inventory when both are sent. Use this when sales are happening — Adjust composes with concurrent purchases; Set overwrites them. |
quantity |
integer |
Tickets issued per purchase unit. Use for “table of 10” or “group of 4” registration types where one purchase yields multiple tickets. Defaults to 1. Distinct from order_min/order_max (per-order limits) and inventory (total available). |
grouped |
boolean |
Ticket-only. When buying multiple of this registration type in one order, issue a single grouped ticket instead of one ticket per quantity unit. Default false. |
editable |
boolean |
Whether the buyer can edit ticket details after purchase. |
editable_change_fee |
decimal |
Fee charged for post-purchase edits, in major currency unit (dollars). Same shape as price. |
editable_minutes |
integer |
Time window in minutes after purchase during which edits are allowed. null for unlimited. |
service_fee_amount |
decimal |
Per-ticket flat service fee, in major currency unit (dollars). Same shape as price. |
service_fee_percentage |
number |
Per-ticket percentage fee (0–100). |
order_min |
integer |
Minimum quantity per order. |
order_max |
integer |
Maximum quantity per order. |
pickups |
array |
Product pickups associated with this registration type. Each item: {pickup_type_id, quantity}. Use _destroy: true to remove. |
separate |
boolean |
Pass-only. true to issue a separate physical ticket per pass holder; false to issue one combined ticket. |
ticket_type |
object |
Pass-only. Inline ticket type definition (rather than referencing one by id via ticket_type_id). Useful when a pass needs unique attachable/email/wallet behavior. |
publishing |
string |
Which Shopify sales channels this tier’s variants are published to. One of default (sells wherever the product sells), pos_only (Point of Sale only), none (not for sale on any channel). Defaults to default. Set on a master tier; cascades to its per-date tiers. On a shop with no Point of Sale channel, pos_only behaves as none. |
Preview Passes (kind: "pass") are in preview. The shape may change as we evolve the relationship between passes and tickets. See Stability & versioning.
Recurrences
Preview Recurrence rules are in preview. The repeat_unit/repeat_value/days/operating_hours shape may consolidate into a standard format (RFC 5545 RRULE) in a future revision. See Stability & versioning.
For type: recurring, define one or more recurrence rules. Each rule generates child date events on save. On an existing rule only the window bounds (ends_at, max_occurrences, active_occurrences) and an earlier starts_at are editable; the repeat pattern (repeat_unit, repeat_value, days, operating_hours, time_slots) is fixed at creation.
| Field | Type | Description |
|---|---|---|
id |
integer |
Required to update existing rule. |
starts_at |
datetime |
Earliest occurrence. On an existing rule it may only be moved earlier, keeping the same time of day, which adds the missing sessions at the start of the series. A later date, a changed time of day, or a change on a rule that ends after a number of occurrences / repeats monthly / has its sessions split across several Shopify products by date returns 422 (immutable_recurring_attribute or a validation_error on starts_at). |
ends_at |
datetime |
Latest occurrence (used when ends: "on_date"). |
ends |
string |
Termination strategy: never, on_date, or after_occurrences. |
max_occurrences |
integer |
Required when ends: "after_occurrences". |
active_occurrences |
integer |
Number of occurrences currently active. |
repeat_unit |
string |
day, week, month, year. |
repeat_value |
integer |
Interval (e.g., 2 with repeat_unit: "week" means every other week). |
duration |
number |
Hours each occurrence lasts. |
days |
array |
For weekly recurrences, an array of weekday names (monday, tuesday, …). |
operating_hours |
array |
Array of {open, close} time-of-day windows. |
time_slots |
array |
For daily/weekly recurrences, explicit {key, start, end, name} intraday slots (HH:MM). Create-only; slot times can be changed later via Retime recurrence slots. |
Update event
PATCH /events/{id}
Same parameter shape as create. Pass only the fields you want to change.
Update event name
curl -X PATCH \
https://app.guestmanager.com/api/public/v2/events/71383 \
-H 'Authorization: Token abcdefg' \
-H 'Content-Type: application/json' \
-d '{ "event": { "name": "New name" } }'
Concurrent edit protection
If an operation (initial creation, recurring fan-out, or Shopify mirror) is in progress for an event, update requests return:
HTTP/1.1 409 Conflict
{
"type": "uneditable",
"message": "Event is currently syncing and cannot be edited until finished."
}
Poll the operation (X-Event-Operation-ID from the original create response, or GET /events/{id}/operations/{job_id}) until completion before retrying.
Update event setting
Preview The setting sub-endpoint is in preview. The setting parameter set will likely expand and may consolidate as we unify event-level and template-level configuration. See Stability & versioning.
PATCH /events/{id}/setting
Updates the event’s template/email config. Returns the updated setting resource.
| Parameter | Type | Description |
|---|---|---|
setting[pdf_template_id] |
integer |
ID of a PDF ticket design template. |
setting[wallet_template_id] |
integer |
ID of an Apple Wallet pass template. |
setting[ticket_email_template_id] |
integer |
ID of the email template used for ticket delivery. |
setting[tally_template_id] |
integer |
ID of the tally/onsite template. |
Refund event
Preview Bulk refund is in preview. The parameter shape may change as we unify refund flows across single-ticket, order, and event scopes. See Stability & versioning.
PATCH /events/{id}/refund
Bulk-refund tickets attached to this event. Asynchronous — returns 202 Accepted with an X-Event-Operation-ID header for status polling.
| Parameter | Type | Description |
|---|---|---|
refund[refund_method] |
string |
original (refund to original payment method), store_credit, or none (cancel without refund). |
refund[date_ids] |
array |
Optional array of session IDs to scope the refund to (parent events only). |
refund[void_tickets] |
boolean |
true to mark tickets as void after refund. |
refund[refund_checked_in] |
boolean |
true to also refund tickets that have already been checked in. |
refund[notify_customer] |
boolean |
true to send a refund confirmation email. |
refund[send_email] |
boolean |
Send a custom email along with the refund. |
refund[email_template] |
object |
{subject, body} — required when send_email: true. |
refund[expiration_date] |
datetime |
For store_credit refunds, when the credit expires. |
refund[note] |
string |
Internal note attached to the refund record. |
Retime recurrence slots
Preview Slot retiming is in preview alongside recurrence rules. See Stability & versioning.
GET /events/{id}/retime · PATCH /events/{id}/retime
Changes the start/end times of an existing recurrence’s time slots and moves every upcoming session onto the new times in place. Session, tier, and Shopify variant identities are preserved, and sold tickets move with their session. Adding or removing slots is not supported. GET returns what the change would do; PATCH performs it asynchronously and returns 202 Accepted with an X-Event-Operation-ID header.
| Parameter | Type | Description |
|---|---|---|
recurrence_id |
integer |
The rule whose slots change. |
time_slots |
array |
The full slot set, each {key, start, end, name}. key must match the persisted slot; start/end are HH:MM. name is optional. |
GET response:
{ "sessions_moving": 99, "tickets_affected": 0, "skipped": [{ "session_id": 123, "reason": "already_started" }], "errors": [] }
PATCH errors: 422 unsupported_slot_change (slot added/removed, duplicate start, a slot that already ran today, or a recurrence without time slots); 409 uneditable while another operation is in progress.
Event lists
Each event has one or more lists — guest-list scoping for the event. The default list is created automatically; additional lists can be created for sub-promotions, hospitality groups, etc.
List event lists
GET /events/{event_id}/lists
curl -X GET \
'https://app.guestmanager.com/api/public/v2/events/12345/lists?include=permanent_list' \
-H 'Authorization: Token abcdefg' \
-H 'Content-Type: application/json'
| Parameter | Description |
|---|---|
page[cursor], page[size] |
See Pagination. |
sort[name] |
asc or desc. |
filter[permanent_list_id] |
Filter by permanent list reference. |
include |
permanent_list, setting. |
images[list][image] |
Image transformations. See Image transformations. |
The list response uses the extended serializer, which includes links.event_page and links.order_page URLs scoped to the merchant’s storefront.
Create event list
POST /events/{event_id}/lists
If you provide an image, you must use a multipart/form-data request body.
curl -X POST \
https://app.guestmanager.com/api/public/v2/events/71339/lists \
-H 'Authorization: Token abcdefg' \
-H 'Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW' \
-F 'list[name]=VIP Hospitality' \
-F 'list[description]=Exclusive lounge access' \
-F 'list[image]=@/path/to/image.png'
| Parameter | Type | Required | Description |
|---|---|---|---|
list[name] |
string |
yes | Name of the list. |
list[description] |
string |
no | Rich-text description. Renders on tickets and the event order page. |
list[image] |
multipart |
no | JPG or non-interlaced PNG. Multipart-only — sending this field via JSON has no effect. |
Update event list
PATCH /events/{event_id}/lists/{id}
Same fields as create. Pass only what’s changed.
Event ticket types
Ticket types define the ticketing-level configuration (PDF design, Apple Wallet, attachable, transferable, required fields). Many events can re-use the same ticket type. Two endpoints attach a ticket type to an event:
Add an existing ticket type
POST /events/{event_id}/ticket_types/add
curl -X POST \
https://app.guestmanager.com/api/public/v2/events/71389/ticket_types/add \
-H 'Authorization: Token abcdefg' \
-H 'Content-Type: application/json' \
-d '{ "ticket_type_id": 2217 }'
| Parameter | Type | Required | Description |
|---|---|---|---|
ticket_type_id |
integer |
yes | ID of an existing ticket type to attach. |
Create and add a new ticket type
POST /events/{event_id}/ticket_types
Creates a new ticket type and attaches it to the event in one call. Prefer creating ticket types via Ticket types first when possible — duplicate-named ticket types create confusion in reporting.
| Parameter | Type | Default | Description |
|---|---|---|---|
ticket_type[name] |
string |
(required) | Ticket type name. |
ticket_type[display_name] |
string |
Display name shown to attendees. | |
ticket_type[pdf_template_id] |
integer |
null |
PDF ticket design template. |
ticket_type[wallet_template_id] |
integer |
null |
Apple Wallet pass template. |
ticket_type[attachable] |
boolean |
true |
Attach the PDF to the ticket email. false includes a download link instead. |
ticket_type[transferable] |
boolean |
true |
Allow attendees to transfer the ticket to someone else. |
ticket_type[question_set_id] |
integer |
null |
Question set defining the attendee form (name, email, photo, custom questions). Blank inherits the company default. |
ticket_type[enforce_barcode_pool] |
boolean |
false |
Restrict barcode generation to a managed pool. |