Events & Registrations
Publish events with ticket types, show them anywhere with the global events Liquid variable, manage them in the dashboard or over MCP, and see what registration features are not built yet.
Overview
Events let an account publish something people can attend, such as a workshop, a fundraiser or a webinar. Each event can offer one or more ticket types. Attendance is recorded as a registration that links a constituent to the event.
Events are a separate kind of record, not a collection. You manage them in the dashboard or over MCP, and every page on your site can show them through the events Liquid variable.
Events
An event has these fields:
- Title (required), location and summary.
- A rich-text description and a rich-text after-sale message for confirmation text.
- A start time (required) and an optional end time.
- An optional capacity and an optional image.
- Two display flags: collects fee and display tickets remaining.
- A published flag, off by default.
Publishing is separate from the dates, so you can draft an event well before it goes live.
starts_atis required. Ifends_atis set, it can't be earlier thanstarts_at(the two can be equal).- If
capacityis set, it must be greater than zero. - Event IDs start with
event_, ticket IDs withevttix_and registration IDs withrgstr_.
Tickets
Each event can offer several ticket types. Every ticket needs a name and has a ticket type:
- Free: must have no cost, or a cost of zero.
- Paid: must have a cost greater than zero.
- Donation: can have a suggested amount, or none.
Other ticket fields:
- Cost is stored in cents. You can also enter it in dollars; see the
dollar_costparameter under MCP below. - Visible controls whether the ticket is shown on your site. Turn it off for complimentary or staff-only tickets.
- Quantity available and an availability window (
available_at/available_until) are saved with the ticket and available to templates and MCP. The platform does not enforce them yet: nothing limits the number of tickets or blocks sales outside the window. - Description: optional text shown with the ticket.
Registrations
A registration records that a constituent is attending an event. It belongs to a constituent and an event, and optionally to a specific ticket. Each registration has:
- Status: pending, confirmed, canceled or attended.
- Quantity, which must be greater than zero. For example, one constituent can register a table of four.
registered_at, filled in automatically when the registration is created if you don't provide it.
If a registration has a ticket, the ticket must belong to the same event. A constituent's registrations appear, read-only, on their CRM profile and in their member portal.
Managing events in the dashboard
Open Events in the dashboard sidebar (/content/events). Events are listed with the most recent start date first. From there you can:
- Create, view, edit and delete events, and set the title, location, summary, description, after-sale message, start and end times, capacity, the fee and tickets-remaining flags, published state and image.
- Add and edit ticket types from each event's page: name, type, cost (in dollars or cents), visibility, quantity available, availability window and description.
Deleting an event also deletes its ticket types.
Displaying events in Liquid
events is a global Liquid variable available on every page. It holds every published event, past and future, with the soonest start first. It is not a collection, so {% query %} and collection routing don't apply, and events don't get their own URLs. To show only upcoming events, compare dates in your template:
{% assign now = "now" | date: "%s" | plus: 0 %}
{% for event in events %}
{% assign starts = event.starts_at | date: "%s" | plus: 0 %}
{% if starts >= now %}
<h3>{{ event.title }}</h3>
<p>{{ event.location }}</p>
<p>{{ event.starts_end_description }}</p>
{% for ticket in event.tickets %}
<span>{{ ticket.name }}: {% if ticket.ticket_type == "free" %}Free{% else %}{{ ticket.cost | money }}{% endif %}</span>
{% endfor %}
{% endif %}
{% endfor %}
Event properties
| Property | Description |
|---|---|
id | Event ID (event_…) |
title, location, summary | Plain text |
starts_at, ends_at | Start and end times; ends_at may be empty. Format them with the date filter |
starts_end_description | Ready-made date range such as "Wed, March 4, 2026 6:00 PM - 8:00 PM", shown in UTC |
capacity | Maximum attendees, or empty for unlimited |
collects_fee, display_tickets_remaining | True/false display flags |
description, after_sale_message | Rich text as HTML |
image_url | URL of the event image, if one is set |
tickets | The event's visible ticket types |
Ticket properties
| Property | Description |
|---|---|
id, name, description | Ticket ID (evttix_…), name and description |
ticket_type | free, paid or donation |
free?, paid?, donation? | True/false shortcuts for the ticket type |
cost | Price in dollars, for example 25.0. Use {{ ticket.cost | money }} to show $25.00 |
quantity_available | Stored quantity (not enforced) |
available_at, available_until | Stored availability window (not enforced) |
visible | Always true here, because hidden tickets are left out |
In Liquid, ticket.cost is in dollars. In MCP, the cost field is in cents.
Managing events over MCP
All event tools use the events:read or events:write scope (or mcp) and require account_id.
| Tool | Parameters |
|---|---|
events_list | published (bool), upcoming (bool), page, per_page (max 100). Tickets are not included |
events_get | event_id. Includes tickets |
events_save | event_id (omit to create; title and starts_at are then needed), title, location, summary, description (HTML), after_sale_message (HTML), starts_at, ends_at (ISO 8601), capacity, collects_fee, display_tickets_remaining, published, image_asset_id, dry_run. Updates are partial: fields you omit keep their values |
events_delete | event_id. Also deletes the event's tickets |
event_tickets_save | ticket_id (omit to create; event_id and name are then required), name, ticket_type (free / paid / donation), dollar_cost (number, in dollars) or cost (integer, in cents; used if both are sent), visible, quantity_available, available_at, available_until, description, dry_run |
event_tickets_delete | ticket_id |
To add an image, upload it first with an asset tool, then pass its asset ID (actast_…) as image_asset_id. Event tools don't support if_match.
Registrations are not available over MCP. Like the rest of the constituent CRM, attendee data is personal data tied to a real person. It is managed in the staff CRM or by the constituent in their own portal, not by an AI tool.
Public event signup
The starter site's events page adds a form_for signup form (handle event_signup) to each event card. It collects a name, an email and a guest count (0 to 10), and passes the event title in a hidden field. The form has constituent ingestion turned on, so name and email are matched to a constituent and repeat signups are recognised as the same person. The full submission, including the event and guest count, is also saved as an entry in the event_signups collection. The form has a honeypot field for bots but no background spam check.
Starter sites also include one published sample event with a free ticket.
This form signup is separate from the formal registration records described above: it doesn't create a registration. See Form For Tag for rendering forms and Constituents & CRM for how ingestion matches submissions to constituents.
Not built yet
These features are not available yet:
- Buying tickets or paying online.
collects_feeand paid tickets are for display only, and no checkout takes payment for a ticket. - Limits on capacity, quantity or the availability window, and automatic sold-out status.
- Self-service registration: members can't create registrations from your site.
- Attendance check-in.
attendedis a stored status with no screen to set it.