Overview
The Events API provides operations to manage calendar events. Access throughgraphClient.Me.Events, graphClient.Me.Calendar.Events, or graphClient.Users[userId].Events.
Request Builders
// All events for current user
public EventsRequestBuilder Events { get; }
// Access: graphClient.Me.Events
// Events in specific calendar
public EventsRequestBuilder Events { get; }
// Access: graphClient.Me.Calendar.Events
// Access: graphClient.Me.Calendars["calendar-id"].Events
// Group calendar events
public EventsRequestBuilder Events { get; }
// Access: graphClient.Groups["group-id"].Events
Operations
List Events
Retrieve calendar events.public async Task<EventCollectionResponse> GetAsync(
Action<RequestConfiguration<EventsRequestBuilderGetQueryParameters>> requestConfiguration = default,
CancellationToken cancellationToken = default
)
Properties to return (e.g.,
["subject", "start", "end", "attendees"])Filter expression (e.g.,
"start/dateTime ge '2024-03-01T00:00:00Z'")Sort order (e.g.,
["start/dateTime"])Number of events to return
Expand related entities (e.g.,
["attachments"])// Get all events
var events = await graphClient.Me.Events.GetAsync();
foreach (var evt in events.Value)
{
Console.WriteLine($"{evt.Subject}");
Console.WriteLine($" Start: {evt.Start.DateTime} {evt.Start.TimeZone}");
Console.WriteLine($" End: {evt.End.DateTime} {evt.End.TimeZone}");
}
// Get upcoming events
var upcomingEvents = await graphClient.Me.Events.GetAsync(config =>
{
config.QueryParameters.Filter = $"start/dateTime ge '{DateTime.UtcNow:yyyy-MM-ddTHH:mm:ssZ}'";
config.QueryParameters.Orderby = new[] { "start/dateTime" };
config.QueryParameters.Top = 10;
});
// Get events in date range
var startDate = new DateTime(2024, 3, 1);
var endDate = new DateTime(2024, 3, 31);
var monthEvents = await graphClient.Me.Events.GetAsync(config =>
{
config.QueryParameters.Filter =
$"start/dateTime ge '{startDate:yyyy-MM-ddTHH:mm:ssZ}' and " +
$"end/dateTime le '{endDate:yyyy-MM-ddTHH:mm:ssZ}'";
});
Create Event
Create a new calendar event.public async Task<Event> PostAsync(
Event body,
Action<RequestConfiguration<DefaultQueryParameters>> requestConfiguration = default,
CancellationToken cancellationToken = default
)
var newEvent = new Event
{
Subject = "Project Kickoff Meeting",
Body = new ItemBody
{
ContentType = BodyType.Html,
Content = "<p>Discuss project objectives and timeline</p>"
},
Start = new DateTimeTimeZone
{
DateTime = "2024-03-20T10:00:00",
TimeZone = "Pacific Standard Time"
},
End = new DateTimeTimeZone
{
DateTime = "2024-03-20T11:00:00",
TimeZone = "Pacific Standard Time"
},
Location = new Location
{
DisplayName = "Conference Room A",
LocationType = LocationType.ConferenceRoom
},
Attendees = new List<Attendee>
{
new Attendee
{
EmailAddress = new EmailAddress
{
Address = "[email protected]",
Name = "John Doe"
},
Type = AttendeeType.Required
},
new Attendee
{
EmailAddress = new EmailAddress
{
Address = "[email protected]",
Name = "Jane Smith"
},
Type = AttendeeType.Optional
}
},
IsOnlineMeeting = true,
OnlineMeetingProvider = OnlineMeetingProviderType.TeamsForBusiness
};
var evt = await graphClient.Me.Events.PostAsync(newEvent);
Console.WriteLine($"Event created: {evt.Id}");
Console.WriteLine($"Teams meeting URL: {evt.OnlineMeeting.JoinUrl}");
Get Event by ID
var evt = await graphClient.Me.Events["event-id"].GetAsync();
// Select specific properties
var evt = await graphClient.Me.Events["event-id"].GetAsync(config =>
{
config.QueryParameters.Select = new[] { "subject", "start", "end", "attendees" };
});
Update Event
var updateEvent = new Event
{
Subject = "Updated Meeting Title",
Location = new Location
{
DisplayName = "Conference Room B"
}
};
await graphClient.Me.Events["event-id"].PatchAsync(updateEvent);
Delete Event
await graphClient.Me.Events["event-id"].DeleteAsync();
Event Actions
Accept Event
var acceptBody = new AcceptPostRequestBody
{
Comment = "I'll be there!",
SendResponse = true
};
await graphClient.Me.Events["event-id"].Accept.PostAsync(acceptBody);
Decline Event
var declineBody = new DeclinePostRequestBody
{
Comment = "Unable to attend",
SendResponse = true,
ProposedNewTime = new TimeSlot
{
Start = new DateTimeTimeZone
{
DateTime = "2024-03-20T14:00:00",
TimeZone = "Pacific Standard Time"
},
End = new DateTimeTimeZone
{
DateTime = "2024-03-20T15:00:00",
TimeZone = "Pacific Standard Time"
}
}
};
await graphClient.Me.Events["event-id"].Decline.PostAsync(declineBody);
Tentatively Accept
var tentativelyAcceptBody = new TentativelyAcceptPostRequestBody
{
Comment = "Tentatively accepting, will confirm later",
SendResponse = true
};
await graphClient.Me.Events["event-id"].TentativelyAccept.PostAsync(tentativelyAcceptBody);
Cancel Event (Organizer)
var cancelBody = new CancelPostRequestBody
{
Comment = "Meeting cancelled due to scheduling conflict"
};
await graphClient.Me.Events["event-id"].Cancel.PostAsync(cancelBody);
Forward Event
var forwardBody = new ForwardPostRequestBody
{
Comment = "Please attend on my behalf",
ToRecipients = new List<Recipient>
{
new Recipient
{
EmailAddress = new EmailAddress
{
Address = "[email protected]"
}
}
}
};
await graphClient.Me.Events["event-id"].Forward.PostAsync(forwardBody);
Snooze Reminder
var snoozeBody = new SnoozeReminderPostRequestBody
{
NewReminderTime = new DateTimeTimeZone
{
DateTime = DateTime.Now.AddMinutes(10).ToString("yyyy-MM-ddTHH:mm:ss"),
TimeZone = "Pacific Standard Time"
}
};
await graphClient.Me.Events["event-id"].SnoozeReminder.PostAsync(snoozeBody);
Dismiss Reminder
await graphClient.Me.Events["event-id"].DismissReminder.PostAsync();
Recurring Events
Create Recurring Event
var recurringEvent = new Event
{
Subject = "Weekly Team Sync",
Start = new DateTimeTimeZone
{
DateTime = "2024-03-18T09:00:00",
TimeZone = "Pacific Standard Time"
},
End = new DateTimeTimeZone
{
DateTime = "2024-03-18T09:30:00",
TimeZone = "Pacific Standard Time"
},
Recurrence = new PatternedRecurrence
{
Pattern = new RecurrencePattern
{
Type = RecurrencePatternType.Weekly,
Interval = 1,
DaysOfWeek = new[] { DayOfWeek.Monday }
},
Range = new RecurrenceRange
{
Type = RecurrenceRangeType.NoEnd,
StartDate = new Date(2024, 3, 18)
}
}
};
await graphClient.Me.Events.PostAsync(recurringEvent);
Get Event Instances
Get instances of a recurring event.var startDate = DateTime.UtcNow;
var endDate = startDate.AddMonths(3);
var instances = await graphClient.Me.Events["recurring-event-id"]
.Instances.GetAsync(config =>
{
config.QueryParameters.StartDateTime = startDate.ToString("yyyy-MM-ddTHH:mm:ssZ");
config.QueryParameters.EndDateTime = endDate.ToString("yyyy-MM-ddTHH:mm:ssZ");
});
foreach (var instance in instances.Value)
{
Console.WriteLine($"{instance.Subject} - {instance.Start.DateTime}");
}
Update Single Instance
var exception = new Event
{
Subject = "Weekly Team Sync (Special Topic)",
Start = new DateTimeTimeZone
{
DateTime = "2024-03-25T10:00:00", // Different time
TimeZone = "Pacific Standard Time"
},
End = new DateTimeTimeZone
{
DateTime = "2024-03-25T11:00:00",
TimeZone = "Pacific Standard Time"
}
};
await graphClient.Me.Events["instance-id"].PatchAsync(exception);
Attachments
List Attachments
var attachments = await graphClient.Me.Events["event-id"].Attachments.GetAsync();
foreach (var attachment in attachments.Value)
{
if (attachment is FileAttachment fileAttachment)
{
Console.WriteLine($"File: {fileAttachment.Name}");
}
}
Add File Attachment
var fileBytes = File.ReadAllBytes("agenda.pdf");
var attachment = new FileAttachment
{
Name = "agenda.pdf",
ContentType = "application/pdf",
ContentBytes = fileBytes
};
await graphClient.Me.Events["event-id"].Attachments.PostAsync(attachment);
Online Meetings
Create Event with Teams Meeting
var teamsEvent = new Event
{
Subject = "Virtual Team Meeting",
Start = new DateTimeTimeZone
{
DateTime = "2024-03-20T14:00:00",
TimeZone = "Pacific Standard Time"
},
End = new DateTimeTimeZone
{
DateTime = "2024-03-20T15:00:00",
TimeZone = "Pacific Standard Time"
},
Attendees = new List<Attendee>
{
new Attendee
{
EmailAddress = new EmailAddress { Address = "[email protected]" },
Type = AttendeeType.Required
}
},
IsOnlineMeeting = true,
OnlineMeetingProvider = OnlineMeetingProviderType.TeamsForBusiness
};
var evt = await graphClient.Me.Events.PostAsync(teamsEvent);
Console.WriteLine($"Teams Join URL: {evt.OnlineMeeting.JoinUrl}");
Console.WriteLine($"Conference ID: {evt.OnlineMeeting.ConferenceId}");
Event Types and Patterns
All-Day Event
var allDayEvent = new Event
{
Subject = "Company Holiday",
Start = new DateTimeTimeZone
{
DateTime = "2024-12-25",
TimeZone = "Pacific Standard Time"
},
End = new DateTimeTimeZone
{
DateTime = "2024-12-26",
TimeZone = "Pacific Standard Time"
},
IsAllDay = true
};
Daily Recurrence
Recurrence = new PatternedRecurrence
{
Pattern = new RecurrencePattern
{
Type = RecurrencePatternType.Daily,
Interval = 1
},
Range = new RecurrenceRange
{
Type = RecurrenceRangeType.EndDate,
StartDate = new Date(2024, 3, 1),
EndDate = new Date(2024, 12, 31)
}
}
Monthly Recurrence
Recurrence = new PatternedRecurrence
{
Pattern = new RecurrencePattern
{
Type = RecurrencePatternType.AbsoluteMonthly,
Interval = 1,
DayOfMonth = 15 // 15th of each month
},
Range = new RecurrenceRange
{
Type = RecurrenceRangeType.Numbered,
StartDate = new Date(2024, 1, 15),
NumberOfOccurrences = 12
}
}
Delta Query
Get incremental changes.var deltaResponse = await graphClient.Me.Calendar.Events.Delta.GetAsync();
foreach (var evt in deltaResponse.Value)
{
Console.WriteLine($"Changed: {evt.Subject}");
}
// Store deltaLink for next query
var deltaLink = deltaResponse.OdataDeltaLink;
Common Filtering
// Events today
var today = DateTime.Today;
var tomorrow = today.AddDays(1);
config.QueryParameters.Filter =
$"start/dateTime ge '{today:yyyy-MM-ddTHH:mm:ssZ}' and " +
$"end/dateTime lt '{tomorrow:yyyy-MM-ddTHH:mm:ssZ}'";
// Events this week
var weekStart = DateTime.Today.AddDays(-(int)DateTime.Today.DayOfWeek);
var weekEnd = weekStart.AddDays(7);
config.QueryParameters.Filter =
$"start/dateTime ge '{weekStart:yyyy-MM-ddTHH:mm:ssZ}' and " +
$"end/dateTime lt '{weekEnd:yyyy-MM-ddTHH:mm:ssZ}'";
// Events I organized
config.QueryParameters.Filter = "isOrganizer eq true";
// Events with specific attendee
config.QueryParameters.Filter = "attendees/any(a:a/emailAddress/address eq '[email protected]')";
Error Handling
using Microsoft.Graph.Models.ODataErrors;
try
{
var evt = await graphClient.Me.Events["invalid-id"].GetAsync();
}
catch (ODataError error)
{
if (error.Error.Code == "ErrorItemNotFound")
{
Console.WriteLine("Event not found");
}
else
{
Console.WriteLine($"Error: {error.Error.Message}");
}
}
See Also
Event Model
Event resource properties
Calendar API
Calendar operations
Messages API
Email message operations
Online Meetings
Teams online meetings
