Working with events
In the public API the top-level resource is an event. Its scheduled instances are occurrences, and an event can have tickets and recurring schedules — all nested under the event:
/2025_06/events/{id}
/2025_06/events/{id}/occurrences
/2025_06/events/{id}/recurring_schedules
/2025_06/events/{id}/tickets
This page covers the concepts the endpoint reference doesn't: the event lifecycle, how occurrences and recurring schedules relate, and how dates and timezones work. All write actions here require the events_write scope.
Lifecycle and status
Every event carries a status:
draft— the starting state forPOST /events. Not publicly visible.published— live and visible.deleted— terminal.
The transitions:
| Action | Effect |
|---|---|
POST /events | Creates a draft. The token owner becomes the event owner. |
POST /events/{id}/publish | Draft → published. Requires at least one active occurrence — an event with no occurrences, or whose occurrences are all canceled, returns 422. A canceled event cannot be published. |
POST /events/{id}/unpublish | Published → draft. |
DELETE /events/{id} | Moves the event to the terminal deleted state and cancels its future occurrences (processed asynchronously). It does not email attendees and does not issue refunds. Returns 200 with an empty object. |
Once an event is canceled (for example, from the Viewcy dashboard), all nested writes — occurrences, recurring schedules, tickets, and publish — are rejected.
Occurrences
An occurrence is a single scheduled instance of an event, with a startsAt and endsAt. Create one-off occurrences with POST /events/{id}/occurrences:
{ "startsAt": "2026-06-01T19:00:00Z", "endsAt": "2026-06-01T22:00:00Z" }
Occurrence times are absolute instants — they must include a UTC offset or Z.
Recurring schedules
A recurring schedule generates occurrences from a rule, instead of you creating each instance by hand. Create one with POST /events/{id}/recurring_schedules:
{
"frequency": "weekly",
"startDate": "2026-06-10",
"time": "19:00",
"durationMinutes": 90,
"weekdays": ["monday", "wednesday"],
"ends": { "type": "after", "count": 6 }
}
frequency—weeklyormonthly.weekdays(weekly) — an array of weekday names. A request with multiple weekdays fans out into one schedule per weekday.monthly(monthly) — either{ "type": "onWeekday", "weekday": "friday", "occurrence": 2 }(the 2nd Friday of the month) or{ "type": "onDate", "dayOfMonth": 15 }.ends— one of{ "type": "never" },{ "type": "after", "count": 6 }, or{ "type": "on", "date": "2026-12-15" }.startDate,time(HH:MM),durationMinutes— when the series starts and how long each occurrence runs.
A schedule's response uses the singular weekday, and exposes monthly, ends, repeatUntil, and completedAt. Expand the generated instances with ?expand=occurrences.
Tickets
Tickets are created under an event (POST /events/{id}/tickets). A single ticket can apply to more than one occurrence and to more than one event, so its per-placement fields are relative to how you fetch it:
- Fetched under an event URL,
occurrenceIdslists that event's occurrences the ticket covers, andadditionalEventIdslists the other events it's linked to. - Fetched standalone, per-placement fields are omitted and
additionalEventIdslists every linked event.
Dates, times, and timezones
An event's timezone is an IANA zone name — America/New_York, Europe/London, and so on. It controls how times are displayed. It does not shift the absolute instants you submit: an occurrence stored as 2026-06-01T19:00:00Z stays that instant regardless of the event's zone. See Creating and updating resources for the timestamp format rules.
Images
An event's featuredImageId and imageIds take the signed id of a direct upload — see File uploads.
See also
- Creating and updating resources — the
null-vs-omitted rules and validation errors. - Async, destructive, and idempotent operations — what
DELETEtriggers in the background. - Webhooks — react to occurrence cancellations and ticket changes.