Reference
Events

Events

Methods of @cobuntu/embed for listing and filtering events, registration, invitations, attendance, magic links and the create-event wizard routes. Setup, sessions and errors are on the client overview; each method links to its endpoint in the REST API reference.

events

events.list

list(params?)

Route: GET /events
Returns: { events, hasMore, nextCursor }. Params below.

events.facets

facets({ upcoming?, past?, q?, from?, to?, featured? })

Route: GET /events/facets
Returns: EventFacets: per-option counts for filters

events.get

get(idOrSlug)

Route: GET /events/:idOrSlug
Returns: EventDetail (adds refundPolicy). 403 MEMBERS_ONLY without a member session on a members-only event.

events.tiers

tiers(idOrSlug)

Route: GET /events/:idOrSlug/tiers
Returns: EventTier[]

events.form

form(tierId)

Route: GET /tiers/:tierId/form
Returns: TierForm or null

events.rsvp

rsvp(idOrSlug, { email, tierId?, formAnswers?, donation?, successUrl?, cancelUrl? })

Route: POST /events/:idOrSlug/rsvp
Returns: { attendanceId, status, alreadyRegistered }, or { checkoutUrl, sessionId } with a donation

events.checkout

checkout(slug, { tierId, successUrl, cancelUrl, quantity?, customer?, formAnswers?, donation?, customAmount?, paymentPlan?, invitationToken? })

Route: POST /events/:slug/checkout
Returns: { checkoutUrl, sessionId } (no checkoutUrl for a free result)

events.donate

donate(slug, { donation, customer?, successUrl, cancelUrl })

Route: POST /events/:slug/donate
Returns: { checkoutUrl, sessionId }

events.donationsSummary

donationsSummary(slug)

Route: GET /events/:slug/donations/summary
Returns: { total, count, currency }

events.invitations.check

invitations.check(idOrSlug, token)

Route: GET /events/:idOrSlug/invitations/check
Returns: { valid, status, email, eventSlug, requiresPayment }

events.invitations.accept

invitations.accept(idOrSlug, { token, email? })

Route: POST /events/:idOrSlug/invitations/accept
Returns: { status: "attended" } or { status: "needs_payment", invitationToken }

events.attendanceStatus

attendanceStatus(idOrSlug, { token? , email? })

Route: GET /events/:idOrSlug/attendance-status
Returns: { attendanceId, status, cancellationReason, registered?, lookupMode }. Session or token (the guest's emailed manage link) for the full status; email answers only registered (yes/no).

events.leave

leave(idOrSlug, { token?, forceWithoutRefund? })

Route: POST /events/:idOrSlug/leave
Returns: { message, wasPaidAttendee, refundProcessed, refundAmount? }. Session, or the emailed token.

events.cancelPending

cancelPending(idOrSlug)

Route: POST /events/:idOrSlug/attendees/me/cancel-pending
Returns: Session.

events.refund

refund(slug, { saleId, reason, amount?, refundType? })

Route: POST /events/:slug/sales/me/refund
Returns: Session. amount is in major units (the route multiplies by 100); omit it for a full refund.

events.memberPricingPreview

memberPricingPreview(tierId)

Route: GET /tiers/:tierId/member-pricing/preview
Returns: { listPrice, currency, buyerOverride, bestOffer: { segmentId?, segmentName, finalPrice, joinable, joinMode, membership, joinPath } | null, ... }. Event or product variant tier. See Join to Save.

Browsing and filters

Every list param is optional and applied before paging, so each page is full.

ParamValuesMeaning
upcoming / pasttrueNot ended / ended (past sorts newest first). Not both.
category, subcategoryidTaxonomy match. An unknown id returns an empty page.
qtext, max 200Every word must appear (case- and accent-insensitive) in the name, description, location, tags or host.
sort"soonest" (default) | "name"Start date, or name A to Z.
from, toISO date or date-timeEvents overlapping the range. from = to = "2026-11-03" is that whole day.
price"free" | "paid"Paid: any live tier costs more than 0.
format"in_person" | "online" | "hybrid"Inclusive: a hybrid event counts as in person and as online.
featuredtrueOnly the featured event.
limit, cursorPage size (1-100, default 20) and the previous nextCursor. Keep the same sort across pages.

Events carry categoryId, subCategoryId, category: { id, name } | null and subcategory: { id, name } | null.

facets() takes the scope params and returns counts over the same events the list would show, not narrowed by category, price or format (those are what it counts):

const facets = await cobuntu.events.facets({ upcoming: true });
// { total: 4,
//   categories: [{ id, name: "Workshops", count: 2, subcategories: [{ id, name: "Pottery", count: 1 }] }],
//   uncategorized: 1,
//   price: { free: 2, paid: 2 },
//   format: { in_person: 2, online: 2, hybrid: 1, tba: 1 } }

Bad values are 400 INVALID_INPUT with field naming the param. For ready-made filter controls, see Event filters.

Common checkout codes: TIER_NOT_ON_SALE, TIER_FULL, ALREADY_HAS_TICKET, MEMBERS_ONLY, FORM_ANSWERS_REQUIRED (details.missingFields), CUSTOM_AMOUNT_REQUIRED, CUSTOM_AMOUNT_TOO_LOW (details.minAmount), INSTALLMENTS_NOT_OFFERED, FULL_PAYMENT_NOT_OFFERED, SESSION_REQUIRED.

magicLinks

magicLinks.verify

magicLinks.verify(token)

Route: GET /magic-links/verify
Returns: { purpose, eventSlug, eventName, startDate, email, saleId, attendanceId, refundEligible, refundReason }

Event wizard routes (me)

The routes behind the embedded create-event wizard. Secret key with MEMBER_AUTH plus a session. See Host an event from your site.

me.drafts.list

drafts.list()

Route: GET /me/drafts?kind=event
Returns: EventDraftSummary[]: personal drafts and this community's

me.drafts.get

drafts.get(id)

Route: GET /me/drafts/event/:id
Returns: EventDraftRow. 403 another member's, 404 unknown, 409 no longer a draft

me.drafts.save

drafts.save(id, body, { keepalive? })

Route: PUT /me/drafts/event/:id
Returns: EventDraftRow. Upsert; name required; 409 once it became an event

me.drafts.delete

drafts.delete(id)

Route: DELETE /me/drafts/event/:id
Returns: nothing (204)

me.packages

packages()

Route: GET /me/packages?productType=EVENT
Returns: MemberPackage[]. rate is a percentage (20 = 20%)

me.stripe

stripe()

Route: GET /me/stripe
Returns: MemberStripe: { connected, chargesEnabled, ..., connectUrl }

me.permissions

permissions()

Route: GET /me/permissions
Returns: { permissions, canCreateForCommunity, memberCreate: { allowed, reason } }

me.events.create

events.create(body)

Route: POST /me/events
Returns: CreatedMemberEvent (id, slug, name, ...). 400 STRIPE_REQUIRED with details.stripeScope

me.events.saveDonations

events.saveDonations(eventId, body)

Route: PUT /me/events/:eventId/donations
Returns: { donationConfig }

me.tags.search / me.tags.create

tags.search(q) / tags.create(name)

Route: GET / POST /me/tags
Returns: EventTag[] / EventTag

me.events(params) still reads the member's events; create and saveDonations hang off the same function. categories({ type: "EVENT" }) (top level, GET /categories) lists the community's categories with their subcategories.

Return URLs must be https on your site's origin, or the answer is INVALID_RETURN_URL. Build them with returnUrl().