Imagine an app that helps users find the best hiking routes. By adding the hiking plan as a calendar event, the users get a lot of help in staying organized automatically. Google Calendar helps them to share the plan and reminds them about it so they can get prepared with no stress. Also, thanks to seamless integration of Google products, Google Now pings them about the time to leave and Google Maps direct them to the meeting spot on time.
This article explains how to create calendar events and add them to your users' calendars.
Add an event
To create an event, call the
events.insert()
method providing at
least these parameters:
calendarId
is the calendar identifier and can either be the email address of the calendar on which to create the event or a special keyword'primary'
which will use the primary calendar of the logged in user. If you don't know the email address of the calendar you would like to use, you can check it either in the calendar's settings of the Google Calendar web UI (in the section "Calendar Address") or you can look for it in the result of thecalendarList.list()
call.event
is the event to create with all the necessary details such as start and end. The only two required fields are thestart
andend
times. See theevent
reference for the full set of event fields.
In order to successfully create events, you need to:
- Set your OAuth scope to
https://www.googleapis.com/auth/calendar
so that you have edit access to the user's calendar. - Ensure the authenticated user has write access to the calendar with the
calendarId
you provided (for example by callingcalendarList.get()
for thecalendarId
and checking theaccessRole
).
Add event metadata
You can optionally add event metadata when you create a calendar event. If you
choose not to add metadata during creation, you can update many fields using the
events.update()
; however, some fields,
such as the event ID, can only be set during an
events.insert()
operation.
- Location
Adding an address into the location field enables features such as
"time to leave" or displaying a map with the directions.
- Event ID
When creating an event, you can choose to generate your own event ID
that conforms to our format requirements. This enables you to keep entities in your local database in sync with events in Google Calendar. It also prevents duplicate event creation if the operation fails at some point after it is successfully executed in the Calendar backend. If no event ID is provided, the server generates one for you. See the event ID reference for more information.
- Attendees
The event you create appears on all the primary Google Calendars of
the attendees you included with the same event ID. If you set
sendNotifications
totrue
on your insert request, the attendees will also receive an email notification for your event. See the events with multiple attendees guide for more information.
The following examples demonstrate creating an event and setting its metadata:
Go
// Refer to the Go quickstart on how to setup the environment:
// https://developers.google.com/calendar/quickstart/go
// Change the scope to calendar.CalendarScope and delete any stored credentials.
event := &calendar.Event{
Summary: "Google I/O 2015",
Location: "800 Howard St., San Francisco, CA 94103",
Description: "A chance to hear more about Google's developer products.",
Start: &calendar.EventDateTime{
DateTime: "2015-05-28T09:00:00-07:00",
TimeZone: "America/Los_Angeles",
},
End: &calendar.EventDateTime{
DateTime: "2015-05-28T17:00:00-07:00",
TimeZone: "America/Los_Angeles",
},
Recurrence: []string{"RRULE:FREQ=DAILY;COUNT=2"},
Attendees: []*calendar.EventAttendee{
&calendar.EventAttendee{Email:"[email protected]"},
&calendar.EventAttendee{Email:"[email protected]"},
},
}
calendarId := "primary"
event, err = srv.Events.Insert(calendarId, event).Do()
if err != nil {
log.Fatalf("Unable to create event. %v\n", err)
}
fmt.Printf("Event created: %s\n", event.HtmlLink)
Java
// Refer to the Java quickstart on how to setup the environment:
// https://developers.google.com/calendar/quickstart/java
// Change the scope to CalendarScopes.CALENDAR and delete any stored
// credentials.
Event event = new Event()
.setSummary("Google I/O 2015")
.setLocation("800 Howard St., San Francisco, CA 94103")
.setDescription("A chance to hear more about Google's developer products.");
DateTime startDateTime = new DateTime("2015-05-28T09:00:00-07:00");
EventDateTime start = new EventDateTime()
.setDateTime(startDateTime)
.setTimeZone("America/Los_Angeles");
event.setStart(start);
DateTime endDateTime = new DateTime("2015-05-28T17:00:00-07:00");
EventDateTime end = new EventDateTime()
.setDateTime(endDateTime)
.setTimeZone("America/Los_Angeles");
event.setEnd(end);
String[] recurrence = new String[] {"RRULE:FREQ=DAILY;COUNT=2"};
event.setRecurrence(Arrays.asList(recurrence));
EventAttendee[] attendees = new EventAttendee[] {
new EventAttendee().setEmail("[email protected]"),
new EventAttendee().setEmail("[email protected]"),
};
event.setAttendees(Arrays.asList(attendees));
EventReminder[] reminderOverrides = new EventReminder[] {
new EventReminder().setMethod("email").setMinutes(24 * 60),
new EventReminder().setMethod("popup").setMinutes(10),
};
Event.Reminders reminders = new Event.Reminders()
.setUseDefault(false)
.setOverrides(Arrays.asList(reminderOverrides));
event.setReminders(reminders);
String calendarId = "primary";
event = service.events().insert(calendarId, event).execute();
System.out.printf("Event created: %s\n", event.getHtmlLink());
JavaScript
// Refer to the JavaScript quickstart on how to setup the environment:
// https://developers.google.com/calendar/quickstart/js
// Change the scope to 'https://www.googleapis.com/auth/calendar' and delete any
// stored credentials.
const event = {
'summary': 'Google I/O 2015',
'location': '800 Howard St., San Francisco, CA 94103',
'description': 'A chance to hear more about Google\'s developer products.',
'start': {
'dateTime': '2015-05-28T09:00:00-07:00',
'timeZone': 'America/Los_Angeles'
},
'end': {
'dateTime': '2015-05-28T17:00:00-07:00',
'timeZone': 'America/Los_Angeles'
},
'recurrence': [
'RRULE:FREQ=DAILY;COUNT=2'
],
'attendees': [
{'email': '[email protected]'},
{'email': '[email protected]'}
],
'reminders': {
'useDefault': false,
'overrides': [
{'method': 'email', 'minutes': 24 * 60},
{'method': 'popup', 'minutes': 10}
]
}
};
const request = gapi.client.calendar.events.insert({
'calendarId': 'primary',
'resource': event
});
request.execute(function(event) {
appendPre('Event created: ' + event.htmlLink);
});
Node.js
// Refer to the Node.js quickstart on how to setup the environment:
// https://developers.google.com/calendar/quickstart/node
// Change the scope to 'https://www.googleapis.com/auth/calendar' and delete any
// stored credentials.
const event = {
'summary': 'Google I/O 2015',
'location': '800 Howard St., San Francisco, CA 94103',
'description': 'A chance to hear more about Google\'s developer products.',
'start': {
'dateTime': '2015-05-28T09:00:00-07:00',
'timeZone': 'America/Los_Angeles',
},
'end': {
'dateTime': '2015-05-28T17:00:00-07:00',
'timeZone': 'America/Los_Angeles',
},
'recurrence': [
'RRULE:FREQ=DAILY;COUNT=2'
],
'attendees': [
{'email': '[email protected]'},
{'email': '[email protected]'},
],
'reminders': {
'useDefault': false,
'overrides': [
{'method': 'email', 'minutes': 24 * 60},
{'method': 'popup', 'minutes': 10},
],
},
};
calendar.events.insert({
auth: auth,
calendarId: 'primary',
resource: event,
}, function(err, event) {
if (err) {
console.log('There was an error contacting the Calendar service: ' + err);
return;
}
console.log('Event created: %s', event.htmlLink);
});
PHP
$event = new Google_Service_Calendar_Event(array(
'summary' => 'Google I/O 2015',
'location' => '800 Howard St., San Francisco, CA 94103',
'description' => 'A chance to hear more about Google\'s developer products.',
'start' => array(
'dateTime' => '2015-05-28T09:00:00-07:00',
'timeZone' => 'America/Los_Angeles',
),
'end' => array(
'dateTime' => '2015-05-28T17:00:00-07:00',
'timeZone' => 'America/Los_Angeles',
),
'recurrence' => array(
'RRULE:FREQ=DAILY;COUNT=2'
),
'attendees' => array(
array('email' => '[email protected]'),
array('email' => '[email protected]'),
),
'reminders' => array(
'useDefault' => FALSE,
'overrides' => array(
array('method' => 'email', 'minutes' => 24 * 60),
array('method' => 'popup', 'minutes' => 10),
),
),
));
$calendarId = 'primary';
$event = $service->events->insert($calendarId, $event);
printf('Event created: %s\n', $event->htmlLink);
Python
# Refer to the Python quickstart on how to setup the environment:
# https://developers.google.com/calendar/quickstart/python
# Change the scope to 'https://www.googleapis.com/auth/calendar' and delete any
# stored credentials.
event = {
'summary': 'Google I/O 2015',
'location': '800 Howard St., San Francisco, CA 94103',
'description': 'A chance to hear more about Google\'s developer products.',
'start': {
'dateTime': '2015-05-28T09:00:00-07:00',
'timeZone': 'America/Los_Angeles',
},
'end': {
'dateTime': '2015-05-28T17:00:00-07:00',
'timeZone': 'America/Los_Angeles',
},
'recurrence': [
'RRULE:FREQ=DAILY;COUNT=2'
],
'attendees': [
{'email': '[email protected]'},
{'email': '[email protected]'},
],
'reminders': {
'useDefault': False,
'overrides': [
{'method': 'email', 'minutes': 24 * 60},
{'method': 'popup', 'minutes': 10},
],
},
}
event = service.events().insert(calendarId='primary', body=event).execute()
print 'Event created: %s' % (event.get('htmlLink'))
Ruby
event = Google::Apis::CalendarV3::Event.new(
summary: 'Google I/O 2015',
location: '800 Howard St., San Francisco, CA 94103',
description: 'A chance to hear more about Google\'s developer products.',
start: Google::Apis::CalendarV3::EventDateTime.new(
date_time: '2015-05-28T09:00:00-07:00',
time_zone: 'America/Los_Angeles'
),
end: Google::Apis::CalendarV3::EventDateTime.new(
date_time: '2015-05-28T17:00:00-07:00',
time_zone: 'America/Los_Angeles'
),
recurrence: [
'RRULE:FREQ=DAILY;COUNT=2'
],
attendees: [
Google::Apis::CalendarV3::EventAttendee.new(
email: '[email protected]'
),
Google::Apis::CalendarV3::EventAttendee.new(
email: '[email protected]'
)
],
reminders: Google::Apis::CalendarV3::Event::Reminders.new(
use_default: false,
overrides: [
Google::Apis::CalendarV3::EventReminder.new(
reminder_method: 'email',
minutes: 24 * 60
),
Google::Apis::CalendarV3::EventReminder.new(
reminder_method: 'popup',
minutes: 10
)
]
)
)
result = client.insert_event('primary', event)
puts "Event created: #{result.html_link}"
Add Drive attachments to events
You can attach Google Drive
files such as meeting notes in Docs, budgets in
Sheets, presentations in Slides, or any other
relevant Google Drive files to your calendar events. You can add the
attachment when you create an event with
events.insert()
or later as part of an
update such as with events.patch()
The two parts of attaching a Google Drive file to an event are:
- Get the file
alternateLink
URL,title
, andmimeType
from the Drive API Files resource, typically with thefiles.get()
method. - Create or update an event with the
attachments
fields set in the request body and thesupportsAttachments
parameter set totrue
.
The following code example demonstrates how to update an existing event to add an attachment:
Java
public static void addAttachment(Calendar calendarService, Drive driveService, String calendarId,
String eventId, String fileId) throws IOException {
File file = driveService.files().get(fileId).execute();
Event event = calendarService.events().get(calendarId, eventId).execute();
List<EventAttachment> attachments = event.getAttachments();
if (attachments == null) {
attachments = new ArrayList<EventAttachment>();
}
attachments.add(new EventAttachment()
.setFileUrl(file.getAlternateLink())
.setMimeType(file.getMimeType())
.setTitle(file.getTitle()));
Event changes = new Event()
.setAttachments(attachments);
calendarService.events().patch(calendarId, eventId, changes)
.setSupportsAttachments(true)
.execute();
}
PHP
function addAttachment($calendarService, $driveService, $calendarId, $eventId, $fileId) {
$file = $driveService->files->get($fileId);
$event = $calendarService->events->get($calendarId, $eventId);
$attachments = $event->attachments;
$attachments[] = array(
'fileUrl' => $file->alternateLink,
'mimeType' => $file->mimeType,
'title' => $file->title
);
$changes = new Google_Service_Calendar_Event(array(
'attachments' => $attachments
));
$calendarService->events->patch($calendarId, $eventId, $changes, array(
'supportsAttachments' => TRUE
));
}
Python
def add_attachment(calendarService, driveService, calendarId, eventId, fileId):
file = driveService.files().get(fileId=fileId).execute()
event = calendarService.events().get(calendarId=calendarId,
eventId=eventId).execute()
attachments = event.get('attachments', [])
attachments.append({
'fileUrl': file['alternateLink'],
'mimeType': file['mimeType'],
'title': file['title']
})
changes = {
'attachments': attachments
}
calendarService.events().patch(calendarId=calendarId, eventId=eventId,
body=changes,
supportsAttachments=True).execute()
Add video and phone conferences to events
You can associate events with Hangouts and Google Meet conferences to allow your users to meet remotely via a phone call or a video call.
The conferenceData
field can
be used to read, copy, and clear existing conference details; it can also be
used to request generation of new conferences. To allow creation and
modification of conference details, set the conferenceDataVersion
request
parameter to 1
.
There are three types of conferenceData
currently supported, as denoted by the
conferenceData.conferenceSolution.key.type
:
- Hangouts for consumers (
eventHangout
) - Classic Hangouts for Google Workspace users
(deprecated;
eventNamedHangout
) - Google Meet (
hangoutsMeet
)
You can learn which conference type is supported for any given calendar of a
user by looking at the conferenceProperties.allowedConferenceSolutionTypes
in
the calendars
and
calendarList
collections. You can also
learn whether the user prefers to have Hangouts created for all their newly
created events by checking the autoAddHangouts
setting in the
settings
collection.
Besides the type
, the conferenceSolution
also provides the name
and the
iconUri
fields that you can use to represent the conference solution as shown
below:
JavaScript
const solution = event.conferenceData.conferenceSolution;
const content = document.getElementById("content");
const text = document.createTextNode("Join " + solution.name);
const icon = document.createElement("img");
icon.src = solution.iconUri;
content.appendChild(icon);
content.appendChild(text);
You can create a new conference for an event by providing a createRequest
with
a newly generated requestId
which can be a random string
. Conferences are
created asynchronously, but you can always check the status of your request to
let your users know what’s happening.
For example, to request conference generation for an existing event:
JavaScript
const eventPatch = {
conferenceData: {
createRequest: {requestId: "7qxalsvy0e"}
}
};
gapi.client.calendar.events.patch({
calendarId: "primary",
eventId: "7cbh8rpc10lrc0ckih9tafss99",
resource: eventPatch,
sendNotifications: true,
conferenceDataVersion: 1
}).execute(function(event) {
console.log("Conference created for event: %s", event.htmlLink);
});
The immediate response to this call might not yet contain the fully-populated
conferenceData
; this is indicated by a status code of pending
in the
status
field. The status code changes to success
after the conference information is
populated. The entryPoints
field contains information about which video and
phone URIs are available for your users to dial in.
If you wish to schedule multiple Calendar events with the same
conference details, you can copy the entire conferenceData
from one event to
another.
Copying is useful in certain situations. For example, suppose you are developing a recruiting application that sets up separate events for the candidate and the interviewer—you want to protect the interviewer’s identity, but you also want to make sure all participants join the same conference call.