> ## Documentation Index
> Fetch the complete documentation index at: https://replyke-feat-push-rich-payload-fields.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Events

> Create and manage events, RSVPs, hosts, and invites from the server

The `events` module covers the full events surface: creating and editing events, the RSVP lifecycle, host and invite management, and the guest list. It maps directly to the [Events API](/api-reference/events/create-event).

Because the Node SDK authenticates with a **service key** (it acts as the whole project, not a single end user), most write functions take an explicit `userId` naming the user the action is performed as. For host- and invite-management functions, `userId` is instead the **target** user (the host/invitee), and the action is authorized as the project.

<Note>
  **Image upload caveat.** The Node SDK does not support inline cover/gallery
  upload on `createEvent`/`updateEvent` yet. Create the event first, then attach
  images with [`sublay.storage.uploadImage`](/v7/node-sdk/storage) using its
  `eventId` parameter. (The browser [JS SDK](/v7/js-sdk/events) and the
  [React SDK](/sdk/events/overview) do support inline upload.)
</Note>

Requires the `events` bundle. Space-scoping needs the `spaces` bundle; images need `files-images`; notifications need `notifications`.

***

### createEvent

Creates an event. The `userId` you pass becomes the creator and is auto-added to `hostIds`. Returns the event with inline `rsvpCounts`.

```typescript theme={null}
const event = await sublay.events.createEvent({
  userId: "usr_abc123",
  title: "Launch Party",
  type: "physical",
  startTime: "2026-09-01T18:00:00.000Z",
  endTime: "2026-09-01T22:00:00.000Z",
  timezone: "America/New_York",
  venueName: "The Loft",
  address: "123 Main St, New York, NY",
  location: { latitude: 40.7128, longitude: -74.006 },
  capacity: 100,
  visibility: "public",
});
```

<ParamField body="title" type="string" required>Event title. 1–300 characters.</ParamField>
<ParamField body="startTime" type="string" required>ISO datetime when the event starts.</ParamField>

<ParamField body="type" type="&#x22;online&#x22; | &#x22;physical&#x22; | &#x22;hybrid&#x22;" required>
  Event format. `online` requires `url`; `physical` requires `address` or `location`; `hybrid` requires both.
</ParamField>

<ParamField body="userId" type="string">
  The user to create the event as (creator + first host). With a service key this may be any user.
</ParamField>

<ParamField body="description" type="string">Optional description.</ParamField>
<ParamField body="endTime" type="string">Optional ISO end datetime.</ParamField>
<ParamField body="timezone" type="string">Optional IANA timezone.</ParamField>
<ParamField body="url" type="string">Join/stream URL.</ParamField>
<ParamField body="venueName" type="string">Venue name.</ParamField>
<ParamField body="address" type="string">Street address.</ParamField>
<ParamField body="location" type="{ latitude: number; longitude: number }">Coordinates for proximity search.</ParamField>
<ParamField body="spaceId" type="string">Scope the event to a space. Required when `visibility` is `"members"`.</ParamField>
<ParamField body="visibility" type="&#x22;public&#x22; | &#x22;members&#x22; | &#x22;invite&#x22;">Defaults to `"public"`.</ParamField>
<ParamField body="capacity" type="number">Max `going` RSVPs. Omit for unlimited.</ParamField>
<ParamField body="allowMaybe" type="boolean">Allow `"maybe"` RSVPs. Defaults to `true`.</ParamField>
<ParamField body="guestListVisible" type="boolean">Expose the named guest list to non-hosts. Defaults to `true`.</ParamField>
<ParamField body="hostIds" type="string[]">Additional host user IDs (the creator is always added).</ParamField>
<ParamField body="metadata" type="object">Arbitrary key-value data. Up to 1 MB.</ParamField>

**Returns** — `Promise<Event>`

***

### fetchEvent

Fetches a single event by ID. Pass `userId` to resolve visibility for that user and to populate `userRsvp` (with the `userRsvp` include).

```typescript theme={null}
const event = await sublay.events.fetchEvent({
  eventId: "evt_abc123",
  include: "user,space,files,userRsvp",
  userId: "usr_abc123",
});
```

<ParamField body="eventId" type="string" required>The event ID.</ParamField>
<ParamField body="include" type="string">Comma-separated associations: `"user"`, `"space"`, `"files"`, `"userRsvp"`.</ParamField>
<ParamField body="userId" type="string">The requester id, for visibility resolution and `userRsvp` enrichment.</ParamField>

**Returns** — `Promise<Event>`

***

### fetchManyEvents

Lists events with visibility enforced, plus filtering, sorting, geo, and free-text search. Pass `userId` to resolve member/invite/host visibility and to use the `myRsvp` filter.

```typescript theme={null}
const { data, pagination } = await sublay.events.fetchManyEvents({
  timeWindow: "upcoming",
  sortBy: "startTime",
  sortDir: "asc",
  type: "physical",
  page: 1,
  limit: 20,
  userId: "usr_abc123",
  include: "user,userRsvp",
});
```

<ParamField body="page" type="number">Page number (1-indexed). Defaults to `1`.</ParamField>
<ParamField body="limit" type="number">Results per page. Capped at `100`.</ParamField>
<ParamField body="sortBy" type="&#x22;startTime&#x22; | &#x22;going&#x22;">Sort field. Defaults to `"startTime"`.</ParamField>
<ParamField body="sortDir" type="&#x22;asc&#x22; | &#x22;desc&#x22;">Sort direction. Defaults to `"asc"`.</ParamField>
<ParamField body="timeWindow" type="&#x22;upcoming&#x22; | &#x22;ongoing&#x22; | &#x22;past&#x22;">Derived time window.</ParamField>
<ParamField body="startsAfter" type="string">ISO datetime lower bound on `startTime`.</ParamField>
<ParamField body="startsBefore" type="string">ISO datetime upper bound on `startTime`.</ParamField>
<ParamField body="spaceId" type="string">Restrict to one space.</ParamField>
<ParamField body="hostId" type="string">Only events this user hosts.</ParamField>
<ParamField body="type" type="&#x22;online&#x22; | &#x22;physical&#x22; | &#x22;hybrid&#x22;">Filter by type.</ParamField>
<ParamField body="status" type="&#x22;active&#x22; | &#x22;cancelled&#x22;">Defaults to `"active"`.</ParamField>
<ParamField body="myRsvp" type="string">Comma-separated statuses the requester RSVP'd with, e.g. `"going,maybe"`. Requires `userId`.</ParamField>
<ParamField body="locationFilters" type="{ latitude: string; longitude: string; radius: string }">Proximity filter (radius in meters).</ParamField>
<ParamField body="titleFilters" type="{ hasTitle?; includes?; doesNotInclude? }">Free-text filter on `title`.</ParamField>
<ParamField body="descriptionFilters" type="{ hasDescription?; includes?; doesNotInclude? }">Free-text filter on `description`.</ParamField>
<ParamField body="include" type="string">Comma-separated associations.</ParamField>
<ParamField body="userId" type="string">The requester id (visibility + `myRsvp` + `userRsvp`).</ParamField>

**Returns** — `Promise<PaginatedResponse<Event>>`

***

### updateEvent

Edits an event's mutable fields. Host-only at the API level; with a service key the call is authorized as the project. `hostIds`, `status`, and `spaceId` are not editable here.

```typescript theme={null}
const event = await sublay.events.updateEvent({
  eventId: "evt_abc123",
  capacity: 150,
  description: "Now with more space!",
});
```

<ParamField body="eventId" type="string" required>The event ID.</ParamField>
<ParamField body="title" type="string">New title.</ParamField>
<ParamField body="description" type="string">New description.</ParamField>
<ParamField body="startTime" type="string">New ISO start datetime.</ParamField>
<ParamField body="endTime" type="string">New ISO end datetime.</ParamField>
<ParamField body="timezone" type="string">New timezone.</ParamField>
<ParamField body="type" type="&#x22;online&#x22; | &#x22;physical&#x22; | &#x22;hybrid&#x22;">New type (re-validates location fields).</ParamField>
<ParamField body="url" type="string">New URL.</ParamField>
<ParamField body="venueName" type="string">New venue name.</ParamField>
<ParamField body="address" type="string">New address.</ParamField>
<ParamField body="location" type="{ latitude: number; longitude: number }">New coordinates.</ParamField>
<ParamField body="visibility" type="&#x22;public&#x22; | &#x22;members&#x22; | &#x22;invite&#x22;">New visibility.</ParamField>
<ParamField body="capacity" type="number">New capacity.</ParamField>
<ParamField body="allowMaybe" type="boolean">Allow `"maybe"` RSVPs.</ParamField>
<ParamField body="guestListVisible" type="boolean">Expose the guest list.</ParamField>
<ParamField body="metadata" type="object">New metadata.</ParamField>

**Returns** — `Promise<Event>`

***

### cancelEvent

Cancels an event (sets `status: "cancelled"`). The event stays fetchable but rejects new RSVPs.

```typescript theme={null}
const event = await sublay.events.cancelEvent({ eventId: "evt_abc123" });
```

<ParamField body="eventId" type="string" required>The event ID.</ParamField>

**Returns** — `Promise<Event>`

***

### deleteEvent

Permanently (or soft-, per the project's `eventDeletion` settings) deletes an event and cleans up its RSVPs and invites.

```typescript theme={null}
await sublay.events.deleteEvent({ eventId: "evt_abc123" });
```

<ParamField body="eventId" type="string" required>The event ID.</ParamField>

**Returns** — `Promise<void>`

***

### setRsvp

Sets or changes a user's RSVP. Transitions into `going` are capacity-checked.

```typescript theme={null}
const event = await sublay.events.setRsvp({
  eventId: "evt_abc123",
  status: "going",
  userId: "usr_abc123",
});
```

<ParamField body="eventId" type="string" required>The event ID.</ParamField>
<ParamField body="status" type="&#x22;going&#x22; | &#x22;maybe&#x22; | &#x22;not_going&#x22;" required>The RSVP response.</ParamField>
<ParamField body="userId" type="string">The user to RSVP as. With a service key this may be any user.</ParamField>

**Returns** — `Promise<Event>` (with refreshed `rsvpCounts`)

***

### withdrawRsvp

Removes a user's RSVP. Idempotent.

```typescript theme={null}
const event = await sublay.events.withdrawRsvp({
  eventId: "evt_abc123",
  userId: "usr_abc123",
});
```

<ParamField body="eventId" type="string" required>The event ID.</ParamField>
<ParamField body="userId" type="string">The user to withdraw. With a service key this may be any user.</ParamField>

**Returns** — `Promise<Event>`

***

### addHost

Grants a user host privileges. The `userId` is the **target** host; the action is authorized as the project.

```typescript theme={null}
const event = await sublay.events.addHost({
  eventId: "evt_abc123",
  userId: "usr_cohost",
});
```

<ParamField body="eventId" type="string" required>The event ID.</ParamField>
<ParamField body="userId" type="string" required>The user to grant host on the event.</ParamField>

**Returns** — `Promise<Event>`

***

### removeHost

Revokes a user's host privileges. Rejected if it would leave the event with no hosts.

```typescript theme={null}
const event = await sublay.events.removeHost({
  eventId: "evt_abc123",
  userId: "usr_cohost",
});
```

<ParamField body="eventId" type="string" required>The event ID.</ParamField>
<ParamField body="userId" type="string" required>The host to remove.</ParamField>

**Returns** — `Promise<Event>`

***

### addInvite

Invites a user to the event. Idempotent. The `userId` is the **target** invitee.

```typescript theme={null}
const event = await sublay.events.addInvite({
  eventId: "evt_abc123",
  userId: "usr_guest",
});
```

<ParamField body="eventId" type="string" required>The event ID.</ParamField>
<ParamField body="userId" type="string" required>The user to invite (userId only — never a foreign ID).</ParamField>

**Returns** — `Promise<Event>`

***

### removeInvite

Removes a user's invite, revoking their access and dropping their RSVP.

```typescript theme={null}
const event = await sublay.events.removeInvite({
  eventId: "evt_abc123",
  userId: "usr_guest",
});
```

<ParamField body="eventId" type="string" required>The event ID.</ParamField>
<ParamField body="userId" type="string" required>The invitee to remove.</ParamField>

**Returns** — `Promise<Event>`

***

### fetchInvitees

Host-only invitee (guest) list. Returns paginated [EventInvite](/data-models/event-invite) records with the invited user populated.

```typescript theme={null}
const { data, pagination } = await sublay.events.fetchInvitees({
  eventId: "evt_abc123",
  page: 1,
  limit: 20,
});
```

<ParamField body="eventId" type="string" required>The event ID.</ParamField>
<ParamField body="page" type="number">Page number (1-indexed).</ParamField>
<ParamField body="limit" type="number">Results per page. Capped at `100`.</ParamField>

**Returns** — `Promise<PaginatedResponse<EventInvite>>`

***

### fetchEventRsvps

Named RSVP (guest) list. Returns paginated [EventRsvp](/data-models/event-rsvp) records with the user populated. Visible to hosts always, to any viewer when `guestListVisible` is `true`, or to service keys. RSVP counts themselves are public via the event's `rsvpCounts`.

```typescript theme={null}
const { data, pagination } = await sublay.events.fetchEventRsvps({
  eventId: "evt_abc123",
  status: "going,maybe",
  page: 1,
  limit: 20,
});
```

<ParamField body="eventId" type="string" required>The event ID.</ParamField>
<ParamField body="status" type="string">Comma-separated statuses to filter by, e.g. `"going,maybe"`. Omit for all.</ParamField>
<ParamField body="page" type="number">Page number (1-indexed).</ParamField>
<ParamField body="limit" type="number">Results per page. Capped at `100`.</ParamField>

**Returns** — `Promise<PaginatedResponse<EventRsvp>>`

***

## Attaching images

Create the event, then upload a cover or gallery image and associate it with `eventId`:

```typescript theme={null}
import { readFile } from "node:fs/promises";

const event = await sublay.events.createEvent({
  userId: "usr_abc123",
  title: "Launch Party",
  type: "online",
  url: "https://meet.example.com/launch",
  startTime: "2026-09-01T18:00:00.000Z",
});

const buffer = await readFile("./cover.jpg");
await sublay.storage.uploadImage({
  file: new Uint8Array(buffer),
  filename: "cover.jpg",
  mimeType: "image/jpeg",
  imageOptions: { mode: "original-aspect", sizes: { full: 1600 }, format: "webp" },
  eventId: event.id,
  userId: "usr_abc123",
});
```

<Note>
  Uploading via `storage.uploadImage` attaches a gallery image (a `File` with the
  event's `eventId`). Setting it as the event's single cover (`coverImageId`) is
  done by the inline-upload path, which the Node SDK does not yet expose.
</Note>
