Skip to content

Events API

API endpoints for creating and managing events within organizations.

Overview

The Events API allows authenticated users to create, update, and retrieve events within their organizations. All endpoints require authentication and appropriate organization membership.

Authentication

All event endpoints require session-based authentication. Include the session cookie received from successful login:

Cookie: session=<session-cookie>

Base URL

/organizations/:organizationId/events

All event operations are scoped to a specific organization.

Endpoints

Create Event

Creates a new event in the specified organization.

http
POST /organizations/:organizationId/events
Content-Type: application/json

Path Parameters

ParameterTypeDescription
organizationIdstring (UUID)The organization ID where the event will be created

Request Body

FieldTypeRequiredDescription
namestringYesEvent name (1-255 characters)
descriptionstringNoEvent description (max 5000 characters)
targetDatestringNoISO 8601 date string for the event
statusstringNoEvent status: BACKLOG, PLANNING, PLANNED, IN_PROGRESS, COMPLETED, CANCELLED (default: BACKLOG)
eventTypestringNoONE_OFF or RECURRING (default: ONE_OFF)
metadataobjectNoEvent metadata (see Metadata Schema)
addressobjectNoEvent address (see Address Schema)

Example Request

json
{
  "name": "Annual Gala",
  "description": "Corporate fundraising event",
  "targetDate": "2024-12-31T00:00:00.000Z",
  "metadata": {
    "category": "other",
    "customCategory": "Corporate",
    "guestCount": {
      "approximate": 500
    },
    "budgetRange": {
      "min": 10000,
      "max": 50000,
      "currency": "CAD"
    }
  },
  "address": {
    "streetAddress": "123 Main St",
    "city": "Toronto",
    "state": "ON",
    "postalCode": "M5V 3A8",
    "country": "CA"
  }
}

Success Response

Status: 201 Created

json
{
  "data": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "name": "Annual Gala",
    "description": "Corporate fundraising event",
    "organizationId": "650e8400-e29b-41d4-a716-446655440000"
  }
}

Error Responses

400 Bad Request - Validation error

json
{
  "errors": [
    {
      "field": "name",
      "message": "The name field is required",
      "rule": "required"
    }
  ]
}

403 Forbidden - Insufficient permissions

json
{
  "errors": [
    {
      "message": "You do not have permission to create events in this organization"
    }
  ]
}

500 Internal Server Error - Server error

json
{
  "errors": [
    {
      "message": "Failed to create event"
    }
  ]
}

Update Event

Updates an existing event with partial data. Only provided fields will be updated.

http
PATCH /organizations/:organizationId/events/:id
Content-Type: application/json

Path Parameters

ParameterTypeDescription
organizationIdstring (UUID)The organization ID that owns the event
idstring (UUID)The event ID to update

Request Body

All fields are optional. Only include fields you want to update.

FieldTypeDescription
namestringEvent name (1-255 characters)
descriptionstringEvent description (max 5000 characters)
targetDatestringISO 8601 date string
statusstringEvent status: BACKLOG, PLANNING, PLANNED, IN_PROGRESS, COMPLETED, CANCELLED
metadataobjectEvent metadata (deep merged with existing)
addressobjectEvent address (creates or updates)

Metadata Deep Merging

When updating metadata, new fields are merged with existing metadata without overwriting unspecified fields:

json
// Existing metadata
{
  "category": "wedding",
  "guestCount": { "approximate": 500 },
  "budgetRange": { "min": 10000, "max": 50000 }
}

// Update request
{
  "metadata": {
    "guestCount": { "approximate": 600 }
  }
}

// Resulting metadata (category and budgetRange preserved)
{
  "category": "wedding",
  "guestCount": { "approximate": 600 },
  "budgetRange": { "min": 10000, "max": 50000 }
}

To remove a metadata field, set it to null:

json
{
  "metadata": {
    "budgetRange": null
  }
}

Example Request

json
{
  "name": "Updated Event Name",
  "metadata": {
    "guestCount": {
      "approximate": 600
    }
  }
}

Success Response

Status: 200 OK

json
{
  "data": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "name": "Updated Event Name",
    "description": "Corporate fundraising event",
    "organizationId": "650e8400-e29b-41d4-a716-446655440000"
  }
}

Error Responses

400 Bad Request - Validation error 403 Forbidden - Insufficient permissions 404 Not Found - Event not found 500 Internal Server Error - Server error


Get Event

Retrieves detailed information about a specific event.

http
GET /organizations/:organizationId/events/:id

Path Parameters

ParameterTypeDescription
organizationIdstring (UUID)The organization ID that owns the event
idstring (UUID)The event ID to retrieve

Success Response

Status: 200 OK

json
{
  "data": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "name": "Annual Gala",
    "description": "Corporate fundraising event",
    "organizationId": "650e8400-e29b-41d4-a716-446655440000",
    "createdAt": "2024-01-01T00:00:00.000Z",
    "updatedAt": "2024-01-15T10:30:00.000Z"
  }
}

Error Responses

400 Bad Request - Invalid event ID 403 Forbidden - Insufficient permissions 404 Not Found - Event not found


Data Schemas

Metadata Schema

The metadata object supports flexible event details:

typescript
{
  category?: 'wedding' | 'birthday' | 'graduation' | 'proposal' | 'other'
  customCategory?: string | null // Used when category is 'other'
  guestCount?: {
    approximate?: number | null // Single estimate (0-99999)
    min?: number | null // Range minimum
    max?: number | null // Range maximum
  } | null
  budgetRange?: {
    min?: number | null // Minimum budget in dollars
    max?: number | null // Maximum budget in dollars
    currency?: string | null // ISO 4217 code (defaults to 'CAD')
  } | null
}

Metadata Examples

Simple event with category:

json
{
  "metadata": {
    "category": "wedding"
  }
}

Event with custom category:

json
{
  "metadata": {
    "category": "other",
    "customCategory": "Corporate Team Building"
  }
}

Event with guest count estimate:

json
{
  "metadata": {
    "guestCount": {
      "approximate": 150
    }
  }
}

Event with guest count range:

json
{
  "metadata": {
    "guestCount": {
      "min": 100,
      "max": 200
    }
  }
}

Event with budget range:

json
{
  "metadata": {
    "budgetRange": {
      "min": 5000,
      "max": 10000,
      "currency": "USD"
    }
  }
}

Complete metadata example:

json
{
  "metadata": {
    "category": "wedding",
    "guestCount": {
      "approximate": 150
    },
    "budgetRange": {
      "min": 15000,
      "max": 30000,
      "currency": "CAD"
    }
  }
}

Address Schema

The address object captures event location details:

typescript
{
  streetAddress?: string // Primary street address (max 200 chars)
  streetAddress2?: string // Secondary line (apt, suite, etc., max 200 chars)
  city: string // Required city name (1-100 chars)
  state?: string // State/province/region (2-100 chars)
  postalCode?: string // Postal/ZIP code (validated per country)
  country?: string // ISO 3166-1 alpha-2 code (US, CA, GB, etc.)
}

Address Examples

Minimal address (city only):

json
{
  "address": {
    "city": "Toronto"
  }
}

Full Canadian address:

json
{
  "address": {
    "streetAddress": "123 Main St",
    "streetAddress2": "Suite 400",
    "city": "Toronto",
    "state": "ON",
    "postalCode": "M5V 3A8",
    "country": "CA"
  }
}

US address:

json
{
  "address": {
    "streetAddress": "456 Broadway",
    "city": "New York",
    "state": "NY",
    "postalCode": "10013",
    "country": "US"
  }
}

International address:

json
{
  "address": {
    "streetAddress": "10 Downing Street",
    "city": "London",
    "postalCode": "SW1A 2AA",
    "country": "GB"
  }
}

Authorization

Organization Membership

All event operations require the authenticated user to be a member of the target organization. The API checks membership before allowing any operation:

  • Create: User must be a member of the organization specified in the URL
  • Update: User must be a member of the organization that owns the event
  • View: User must be a member of the organization that owns the event

Future Enhancements

Role-based permissions are planned but not yet implemented. Currently, all organization members have equal access to event operations.

Rate Limiting

Event API endpoints are subject to the global API rate limits:

  • Limited to 100 requests per authenticated user per minute
  • Limited to 10 requests per ip per minute if not authenticated

Validation Rules

Field Constraints

FieldConstraint
name1-255 characters, required
descriptionMax 5000 characters
statusMust be one of: BACKLOG, PLANNING, PLANNED, IN_PROGRESS, COMPLETED, CANCELLED
metadata.categoryMust be one of: wedding, birthday, graduation, proposal, other
metadata.customCategoryMax 100 characters
metadata.guestCount.approximate0-99999
metadata.guestCount.min0-99999
metadata.guestCount.max0-99999
metadata.budgetRange.minMinimum 0
metadata.budgetRange.maxMinimum 0
metadata.budgetRange.currencyValid ISO 4217 currency code
address.streetAddressMax 200 characters
address.streetAddress2Max 200 characters
address.city1-100 characters, required
address.state2-100 characters
address.postalCodeFormat validated per country code
address.countryValid ISO 3166-1 alpha-2 code

Custom Validators

  • Currency codes - Validates against ISO 4217 standard (e.g., CAD, USD, EUR, GBP)
  • Country codes - Validates against ISO 3166-1 alpha-2 standard (e.g., CA, US, GB, FR)
  • Postal codes - Format validation based on country code (e.g., Canadian postal codes require format A1A 1A1)

Default Values

When creating events, the following defaults are applied:

FieldDefault Value
statusBACKLOG
eventTypeONE_OFF
metadata{} (empty object)
descriptionnull
targetDatenull
metadata.budgetRange.currencyCAD (if budgetRange is provided without currency)

Common Use Cases

Create a simple event

http
POST /organizations/650e8400-e29b-41d4-a716-446655440000/events
Content-Type: application/json
json
{
  "name": "Team Lunch"
}

Create an event with full details

http
POST /organizations/650e8400-e29b-41d4-a716-446655440000/events
Content-Type: application/json
json
{
  "name": "Annual Conference",
  "description": "Company-wide annual conference",
  "targetDate": "2024-09-15T09:00:00.000Z",
  "metadata": {
    "category": "other",
    "customCategory": "Conference",
    "guestCount": {
      "min": 200,
      "max": 300
    },
    "budgetRange": {
      "min": 50000,
      "max": 100000,
      "currency": "USD"
    }
  },
  "address": {
    "streetAddress": "Convention Center",
    "city": "San Francisco",
    "state": "CA",
    "country": "US"
  }
}

Update event status

http
PATCH /organizations/650e8400-e29b-41d4-a716-446655440000/events/550e8400-e29b-41d4-a716-446655440000
Content-Type: application/json
json
{
  "status": "IN_PROGRESS"
}

Update guest count

http
PATCH /organizations/650e8400-e29b-41d4-a716-446655440000/events/550e8400-e29b-41d4-a716-446655440000
Content-Type: application/json
json
{
  "metadata": {
    "guestCount": {
      "approximate": 250
    }
  }
}

Add address to existing event

http
PATCH /organizations/650e8400-e29b-41d4-a716-446655440000/events/550e8400-e29b-41d4-a716-446655440000
Content-Type: application/json
json
{
  "address": {
    "streetAddress": "789 Event Plaza",
    "city": "Vancouver",
    "state": "BC",
    "postalCode": "V6B 4Y8",
    "country": "CA"
  }
}

Notes

  • All timestamps are returned in ISO 8601 format with UTC timezone
  • Event IDs and organization IDs are UUID v7 (generated by BaseModelWithUuid @beforeCreate hook). Note: Better Auth-managed tables (sessions, accounts) use UUID v4.
  • Address updates are upserts - if an address exists, it's updated; otherwise, a new one is created
  • Metadata updates use deep merging to preserve unspecified fields
  • To remove metadata fields, explicitly set them to null

See Also

Built with ❤️ by the Jubiloop team