Msg.Calendar.Events (msg v0.3.8)

Interact with Microsoft Graph Calendar Events API.

Provides functions to create, read, update, and delete calendar events for both user calendars (personal) and group calendars (shared). Supports open extensions for tagging events with custom metadata.

Required Permissions

User Calendars

  • Application: Calendars.ReadWrite - read/write all users' calendars
  • Delegated: Calendars.ReadWrite - read/write user's calendars

Group Calendars

  • Application: ❌ Not supported
  • Delegated: Calendars.ReadWrite.Shared - required for group calendar access

Authentication

  • User calendars (/users/{user_id}/events): Works with application-only authentication
  • Group calendars (/groups/{group_id}/calendar/events): Requires delegated permissions

Examples

# User calendar with application-only authentication
app_client = Msg.Client.new(%{
  client_id: "...",
  client_secret: "...",
  tenant_id: "..."
})
{:ok, events} = Msg.Calendar.Events.list(app_client, user_id: "user@contoso.com")

# Group calendar with delegated permissions (refresh token)
delegated_client = Msg.Client.new(refresh_token, credentials)
{:ok, events} = Msg.Calendar.Events.list(delegated_client, group_id: "group-id")

# Create event with extension
event = %{subject: "Team Meeting", start: %{...}, end: %{...}}
extension = %{extension_name: "com.example.metadata", project_id: "123"}
{:ok, created} = Msg.Calendar.Events.create_with_extension(
  app_client, event, extension, user_id: "user@contoso.com"
)

References

Summary

Functions

Creates a new calendar event.

Creates a calendar event with an open extension in a single optimized operation.

Deletes a calendar event.

Gets a single calendar event.

Gets a calendar event with a specific extension.

Lists calendar events.

Updates an existing calendar event.

Functions

create(client, event, opts)

@spec create(Req.Request.t(), map(), keyword()) :: {:ok, map()} | {:error, term()}

Creates a new calendar event.

Parameters

  • client - Authenticated Req.Request client
  • event - Map with event properties:
    • :subject (required) - Event title
    • :start (required) - Start datetime map with date_time and time_zone
    • :end (required) - End datetime map with date_time and time_zone
    • :body (optional) - Event body/description
    • :location (optional) - Location information
    • :attendees (optional) - List of attendees
    • :is_all_day (optional) - Boolean
  • opts - Keyword list of options:
    • :user_id - User ID or UPN (for personal calendar)
    • :group_id - Group ID (for group calendar)

Note: Either :user_id or :group_id is required.

Returns

  • {:ok, event} - Created event with generated ID
  • {:error, :unauthorized} - Invalid or expired token
  • {:error, {:invalid_request, message}} - Validation error
  • {:error, term} - Other errors

Examples

event = %{
  subject: "Team Meeting",
  start: %{
    date_time: "2025-01-15T14:00:00",
    time_zone: "Pacific Standard Time"
  },
  end: %{
    date_time: "2025-01-15T15:00:00",
    time_zone: "Pacific Standard Time"
  }
}

{:ok, created} = Msg.Calendar.Events.create(client, event,
  user_id: "user@contoso.com"
)

create_with_extension(client, event, extension, opts)

@spec create_with_extension(Req.Request.t(), map(), map(), keyword()) ::
  {:ok, map()} | {:error, term()}

Creates a calendar event with an open extension in a single optimized operation.

This function creates the event first, then immediately adds the extension.

Parameters

  • client - Authenticated Req.Request client
  • event - Event data map (see create/3)
  • extension - Extension data map:
    • :extension_name (required) - Unique name (e.g., "com.example.metadata")
    • Custom properties as needed
  • opts - Keyword list of options:
    • :user_id - User ID or UPN (for personal calendar)
    • :group_id - Group ID (for group calendar)

Note: Either :user_id or :group_id is required.

Returns

  • {:ok, event} - Created event with extension
  • {:error, term} - Error

Examples

event = %{subject: "Project Milestone", start: %{...}, end: %{...}}
extension = %{
  extension_name: "com.example.metadata",
  project_id: "proj_abc123",
  resource_id: "res_xyz789"
}

{:ok, event_with_ext} = Msg.Calendar.Events.create_with_extension(
  client, event, extension, user_id: "user@contoso.com"
)

delete(client, event_id, opts)

@spec delete(Req.Request.t(), String.t(), keyword()) :: :ok | {:error, term()}

Deletes a calendar event.

Parameters

  • client - Authenticated Req.Request client
  • event_id - ID of event to delete
  • opts - Keyword list of options:
    • :user_id - User ID or UPN (for personal calendar)
    • :group_id - Group ID (for group calendar)

Note: Either :user_id or :group_id is required.

Returns

  • :ok - Event deleted successfully (204 status)
  • {:error, :not_found} - Event doesn't exist
  • {:error, term} - Other errors

Examples

:ok = Msg.Calendar.Events.delete(client, event_id, user_id: "user@contoso.com")
:ok = Msg.Calendar.Events.delete(client, event_id, group_id: "group-id-here")

get(client, event_id, opts)

@spec get(Req.Request.t(), String.t(), keyword()) :: {:ok, map()} | {:error, term()}

Gets a single calendar event.

Parameters

  • client - Authenticated Req.Request client
  • event_id - ID of the event to retrieve
  • opts - Keyword list of options:
    • :user_id - User ID or UPN (for personal calendar)
    • :group_id - Group ID (for group calendar)
    • :expand_extensions - Boolean, include extensions in response
    • :select - List of fields to select

Note: Either :user_id or :group_id is required.

Returns

  • {:ok, event} - Event map
  • {:error, :not_found} - Event doesn't exist
  • {:error, term} - Other errors

Examples

{:ok, event} = Msg.Calendar.Events.get(client, "event-id",
  user_id: "user@contoso.com",
  expand_extensions: true
)

{:ok, event} = Msg.Calendar.Events.get(client, "event-id",
  group_id: "group-id-here"
)

get_with_extensions(client, event_id, extension_id, opts)

@spec get_with_extensions(Req.Request.t(), String.t(), String.t(), keyword()) ::
  {:ok, map()} | {:error, term()}

Gets a calendar event with a specific extension.

Note: Microsoft Graph does not support listing all extensions on calendar events. To retrieve an extension, you must know its ID. Use this function to get an event along with a specific extension by providing the extension ID.

Parameters

  • client - Authenticated Req.Request client
  • event_id - ID of the event
  • extension_id - ID of the extension to retrieve (e.g., "com.example.metadata")
  • opts - Keyword list of options:
    • :user_id - User ID or UPN (for personal calendar)
    • :group_id - Group ID (for group calendar)

Note: Either :user_id or :group_id is required.

Returns

  • {:ok, event} - Event map with extensions field populated with the requested extension
  • {:error, :not_found} - Event or extension doesn't exist
  • {:error, term} - Other errors

Examples

{:ok, event} = Msg.Calendar.Events.get_with_extensions(client, event_id,
  "com.example.metadata",
  user_id: "user@contoso.com"
)

ext = List.first(event["extensions"])
project_id = ext["projectId"]

list(client, opts)

@spec list(
  Req.Request.t(),
  keyword()
) :: {:ok, [map()]} | {:ok, map()} | {:error, term()}

Lists calendar events.

Parameters

  • client - Authenticated Req.Request client
  • opts - Keyword list of options:
    • :user_id - User ID or UPN (for personal calendar)
    • :group_id - Group ID (for group calendar)
    • :start_datetime - Filter events starting after this DateTime
    • :end_datetime - Filter events starting before this DateTime
    • :auto_paginate - Boolean, default true (fetch all pages)
    • :filter - OData filter string
    • :select - List of fields to select
    • :orderby - OData orderby string

Note: Either :user_id or :group_id is required.

Returns

  • {:ok, [event]} - List of events (when auto_paginate: true)
  • {:ok, %{items: [event], next_link: url}} - First page with next link (when auto_paginate: false)
  • {:error, term} - Error

Examples

# List user calendar events
{:ok, events} = Msg.Calendar.Events.list(client,
  user_id: "user@contoso.com",
  start_datetime: ~U[2025-01-01 00:00:00Z],
  end_datetime: ~U[2025-12-31 23:59:59Z]
)

# List group calendar events
{:ok, events} = Msg.Calendar.Events.list(client,
  group_id: "group-id-here",
  auto_paginate: true
)

update(client, event_id, updates, opts)

@spec update(Req.Request.t(), String.t(), map(), keyword()) ::
  {:ok, map()} | {:error, term()}

Updates an existing calendar event.

Parameters

  • client - Authenticated Req.Request client
  • event_id - ID of event to update
  • updates - Map of fields to update
  • opts - Keyword list of options:
    • :user_id - User ID or UPN (for personal calendar)
    • :group_id - Group ID (for group calendar)

Note: Either :user_id or :group_id is required.

Returns

  • {:ok, event} - Updated event
  • {:error, :not_found} - Event doesn't exist
  • {:error, term} - Other errors

Examples

{:ok, updated} = Msg.Calendar.Events.update(client, event_id,
  %{subject: "Updated Title"},
  user_id: "user@contoso.com"
)