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.
| Param | Values | Meaning |
|---|---|---|
upcoming / past | true | Not ended / ended (past sorts newest first). Not both. |
category, subcategory | id | Taxonomy match. An unknown id returns an empty page. |
q | text, max 200 | Every 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, to | ISO date or date-time | Events 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. |
featured | true | Only the featured event. |
limit, cursor | Page 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().