↑ ↓ to navigate
↵ to select
esc to close
Guides Intermediate

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_at is required. If ends_at is set, it can't be earlier than starts_at (the two can be equal).
  • If capacity is set, it must be greater than zero.
  • Event IDs start with event_, ticket IDs with evttix_ and registration IDs with rgstr_.

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_cost parameter 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

PropertyDescription
idEvent ID (event_…)
title, location, summaryPlain text
starts_at, ends_atStart and end times; ends_at may be empty. Format them with the date filter
starts_end_descriptionReady-made date range such as "Wed, March 4, 2026 6:00 PM - 8:00 PM", shown in UTC
capacityMaximum attendees, or empty for unlimited
collects_fee, display_tickets_remainingTrue/false display flags
description, after_sale_messageRich text as HTML
image_urlURL of the event image, if one is set
ticketsThe event's visible ticket types

Ticket properties

PropertyDescription
id, name, descriptionTicket ID (evttix_…), name and description
ticket_typefree, paid or donation
free?, paid?, donation?True/false shortcuts for the ticket type
costPrice in dollars, for example 25.0. Use {{ ticket.cost | money }} to show $25.00
quantity_availableStored quantity (not enforced)
available_at, available_untilStored availability window (not enforced)
visibleAlways 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.

ToolParameters
events_listpublished (bool), upcoming (bool), page, per_page (max 100). Tickets are not included
events_getevent_id. Includes tickets
events_saveevent_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_deleteevent_id. Also deletes the event's tickets
event_tickets_saveticket_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_deleteticket_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_fee and 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. attended is a stored status with no screen to set it.