Recently I've decided to give users at my site the following functionality: online time slot booking in calendars of my employees. All employees have Google accounts linked to our domain in Google Apps (free edition). Users make booking in some front-end (e.g. not directly in employees Google calendars), then request is processed at our PHP server and if it is correct, server should be able to create new calendar entry in selected employee Google calendar. Note - neither user, nor employee should not be asked for authentication during booking.
I've scanned Google calendar v3 API and forums and still didn't get neither clear answer not concise examples - is such scenario possible with Google calendar? Can someone help me to answer the Q (and if possible - share a link with proper example)?
Are you familiar with adding an event with authentication? Like i answered here.
And like in the code below. If you are... you can go to the next level ;)
(You can download the Google Api Php-client on this page. On this page there is a tutorial. It's for Google+ but the principle is the same)
The first time you would always need authentication. There is no way around that. In the example below you get a token back after authentication, which includes an access_token and a refresh_token. The access_token is only valid for 3600 seconds and is used for direct access. When the access_token is expired you get a 401 error and you can use the refresh_token (together with client_id, client_secret and the correct grant_type) to request a new access_token.
You can find some more information on this page (at the bottom "Using a Refresh Token"). There are some limits in numbers to request these, mentioned on that page at the bottom.
This is some testing code i made the last time i helped someone with this. It only shows getting the authentication and storing the token in a cookie. It does not request a new access_token after it expires.
But as i already said you need to store the token (in a database?) and when you get a 401 you need to request a new access_token with the client_id, client_secret, correct grant_type and refresh_token. There is no (re-)authentication necessary for that.
<?php
error_reporting(E_ALL);
require_once 'google-api-php-client/src/Google_Client.php';
require_once 'google-api-php-client/src/contrib/Google_CalendarService.php';
session_start();
if ((isset($_SESSION)) && (!empty($_SESSION))) {
echo "There are cookies<br>";
echo "<pre>";
print_r($_SESSION);
echo "</pre>";
}
$client = new Google_Client();
$client->setApplicationName("Google Calendar PHP Starter Application");
$client->setClientId('###');
$client->setClientSecret('###');
$client->setRedirectUri('http://###/add_calendar.php'); // <- registered web-page
//$client->setDeveloperKey('###'); // <- not always needed
$cal = new Google_CalendarService($client);
if (isset($_GET['logout'])) {
echo "<br><br><font size=+2>Logging out</font>";
unset($_SESSION['token']);
}
if (isset($_GET['code'])) {
echo "<br>I got a code from Google = ".$_GET['code']; // You won't see this if redirected later
$client->authenticate(); // $_GET['code']
$_SESSION['token'] = $client->getAccessToken();
header('Location: http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF']);
// not strictly necessary to redirect but cleaner for the url in address-bar
echo "<br>I got the token = ".$_SESSION['token']; // <-- not needed to get here unless location uncommented
}
if (isset($_SESSION['token'])) {
echo "<br>Getting access";
$client->setAccessToken($_SESSION['token']);
}
if ($client->getAccessToken()){
echo "<hr><font size=+1>I have access to your calendar</font>";
$event = new Google_Event();
$event->setSummary('=== I ADDED THIS ===');
$event->setLocation('The Neighbourhood');
$start = new Google_EventDateTime();
$start->setDateTime('2013-11-29T10:00:00.000-05:00');
$event->setStart($start);
$end = new Google_EventDateTime();
$end->setDateTime('2013-11-29T10:25:00.000-05:00');
$event->setEnd($end);
$createdEvent = $cal->events->insert('###', $event); // <- ### = email of calendar
echo "<br><font size=+1>Event created</font>";
echo "<hr><br><font size=+1>Already connected</font> (No need to login)";
} else {
$authUrl = $client->createAuthUrl();
print "<hr><br><font size=+2><a href='$authUrl'>Connect Me!</a></font>";
}
$url = 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'];
echo "<br><br><font size=+2><a href=$url?logout>Logout</a></font>";
?>
Edit:
If you don't want the initial authentication Google has its "Service Acounts", as you pointed out.
(I didn't know about these :)
I dug up some links where you can find code to use after you got the key-file.
Edit Google calendar events from Google service account: 403
Access Google calendar events from with service account: { "error" : "access_denied" }. No google apps
Google OAuth 2.0 Service Account - Calendar API (PHP Client)
https://groups.google.com/forum/#!topic/google-api-php-client/B7KXVQvx1k8
https://groups.google.com/forum/?fromgroups#!topic/google-api-php-client/IiwRBKZMZxw
Edit #2: YES, got it working. (even with my free Google account ;)
Here is the working code:
<?
error_reporting(E_ALL);
require_once 'google-api-php-client/src/Google_Client.php';
require_once 'google-api-php-client/src/contrib/Google_CalendarService.php';
session_start();
echo "Busy<br>";
const CLIENT_ID = 'xxxxxxxxxx.apps.googleusercontent.com';
const SERVICE_ACCOUNT_NAME = 'xxxxxxxxxxx#developer.gserviceaccount.com';
const KEY_FILE = 'xxxxxxxxxxxxxxxxxxx-privatekey.p12';
const CALENDAR_NAME = 'xxxxxxx#gmail.com';
$client = new Google_Client();
$client->setApplicationName("mycal");
if (isset($_SESSION['token'])) {
$client->setAccessToken($_SESSION['token']);
}
$key = file_get_contents(KEY_FILE);
$client->setClientId(CLIENT_ID);
$client->setAssertionCredentials(new Google_AssertionCredentials(
SERVICE_ACCOUNT_NAME,
array('https://www.google.com/calendar/feeds/'),
$key)
);
$client->setClientId(CLIENT_ID);
$service = new Google_CalendarService($client);
$event = new Google_Event();
$event->setSummary('=== I MADE THIS ===');
$event->setLocation('Somewhere else');
$start = new Google_EventDateTime();
$start->setDateTime('2013-11-30T10:00:00.000-02:00');
$event->setStart($start);
$end = new Google_EventDateTime();
$end->setDateTime('2013-11-30T10:25:00.000-02:00');
$event->setEnd($end);
$createdEvent = $service->events->insert(CALENDAR_NAME, $event);
echo "Done<br>";
?>
I needed to make a "new project" on https://cloud.google.com/console#/project. I couldn't use the existing one. After activating "Calendar API" and registering a new Web-app with Certificate i only needed to share my calendar with the xxxx#developer.gserviceaccount.com and above code worked
(without authentication).
Edit #3: and now it also seems to be working in the default "Google+ API Project"
Related
Im trying to create a Youtube upload script that does not require the end user to login in order to upload a video to my channel. The issue is I can gain the access token but it expires after an hour of being inactive.
Also I am unsure where you can get the "refresh_token" from.
So essentially I wish to have this Google API v3 script not require any client side authentication in order to upload video's.
From what I gather from the API documentation at google if I had the "refresh_token" I could renew the token without the need of user interaction required.
Please see below my existing code on the matter.
<?php
$key = json_decode(file_get_contents('the_key.txt'));
require_once 'Client.php';
require_once 'Service/YouTube.php';
session_start();
$OAUTH2_CLIENT_ID = 'YOUR_CLIENT_ID.apps.googleusercontent.com';
$OAUTH2_CLIENT_SECRET = 'YOUR_SECRET_KEY';
$REDIRECT = 'http://example.com/test.php';//Must be exact as setup on google API console
$APPNAME = "Test upload app";
$client = new Google_Client();
$client->setClientId($OAUTH2_CLIENT_ID);
$client->setClientSecret($OAUTH2_CLIENT_SECRET);
$client->setScopes('https://www.googleapis.com/auth/youtube');
$client->setRedirectUri($REDIRECT);
$client->setApplicationName($APPNAME);
$client->setAccessType('offline');
// Define an object that will be used to make all API requests.
$youtube = new Google_Service_YouTube($client);
if (isset($_GET['code'])) {
if (strval($_SESSION['state']) !== strval($_GET['state'])) {
die('The session state did not match.');
}
$client->authenticate($_GET['code']);
$_SESSION['token'] = $client->getAccessToken();
}
if (isset($_SESSION['token'])) {
//if session current save to file updates token key
$client->setAccessToken($_SESSION['token']);
echo '<code>' . $_SESSION['token'] . '</code><br>';
file_put_contents('the_key.txt', $_SESSION['token']);
}
// Check to ensure that the access token was successfully acquired.
if ($client->getAccessToken()) {
if($client->isAccessTokenExpired()) {
echo "Token Expired<br>Attempt Refresh: ";
$client->refreshToken($key->access_token);
//refresh token, now need to update it in session
$_SESSION['access_token']= $client->getAccessToken();
}
$_SESSION['token'] = $client->getAccessToken();
///////////////////////////////////////////////////////////////////////
//Run Upload script here from google Youtube API v3
//https://developers.google.com/youtube/v3/code_samples/php#resumable_uploads
///////////////////////////////////////////////////////////////////////
} else {
$state = mt_rand();
$client->setState($state);
$_SESSION['state'] = $state;
$authUrl = $client->createAuthUrl();
$htmlBody = '<h3>Authorization Required</h3><p>You need to authorise access before proceeding.<p>';
}
?>
<!doctype html>
<html>
<head>
<title>My Uploads</title>
</head>
<body>
<?php echo $htmlBody?>
</body>
</html>
If someone can look over this code and tell me what I'm missing would be great.
I finally figured it out!!!
Thanks to Burcu Dogan for the solution:
Automatically refresh token using google drive api with php script
It turns out that the refresh_token will only be returned on the first $client->authenticate(), for that account you login with and you need to permanently store it remove the need for the user authentication.
As I had already authenticated desired user I was unable to regenerate the refresh_token with this project so I had to delete the project and recreate it.
Re-Authenticate the user and the refresh_token appeared! I then stored this token safe and have not had any issues since.
If you do not wish to delete your project and start again you can also go to oAuth Playground and aquire your refresh_token that way.
YouTube run through
Hope this help solve a lot of peoples problems online.
I'm trying to use a service account to create entries on a Google calendar. I'm really close on this, but the very last line won't work. I get a 500 Internal Service Error when I let this run. Otherwise, the program runs error free, for whatever that is worth.
The Calendar.php file contents can be found here. The insert() method that I am trying to call begins on line 1455 of that file.
<?php
function calendarize ($title, $desc, $ev_date, $cal_id) {
session_start();
/************************************************
Make an API request authenticated with a service
account.
************************************************/
set_include_path( '../google-api-php-client/src/');
require_once 'Google/Client.php';
require_once 'Google/Service/Calendar.php';
// (not real keys)
$client_id = '843319906820-jarm3f5ctbtjj9b7lp5qdcqal54p1he6.apps.googleusercontent.com';
$service_account_name = '843319906820-jarm3f5ctbtjj7b7lp5qdcqal54p1he6#developer.gserviceaccount.com';
$key_file_location = '../google-api-php-client/calendar-249226a7a27a.p12';
// echo pageHeader("Service Account Access");
if (!strlen($service_account_name) || !strlen($key_file_location))
echo missingServiceAccountDetailsWarning();
$client = new Google_Client();
$client->setApplicationName("xxxx Add Google Calendar Entries");
if (isset($_SESSION['service_token'])) {
$client->setAccessToken($_SESSION['service_token']);
}
$key = file_get_contents($key_file_location);
$cred = new Google_Auth_AssertionCredentials(
$service_account_name,
array('https://www.googleapis.com/auth/calendar'),
$key
);
$client->setAssertionCredentials($cred);
if($client->getAuth()->isAccessTokenExpired()) {
$client->getAuth()->refreshTokenWithAssertion($cred);
}
$_SESSION['service_token'] = $client->getAccessToken();
// Prior to this, the code has mostly come from Google's example
// google-api-php-client / examples / service-account.php
// and relates to getting the access tokens.
// The rest of this is about setting up the calendar entry.
//Set the Event data
$event = new Google_Service_Calendar_Event();
$event->setSummary($title);
$event->setDescription($desc);
$start = new Google_Service_Calendar_EventDateTime();
$start->setDate($ev_date);
$event->setStart($start);
$end = new Google_Service_Calendar_EventDateTime();
$end->setDate($ev_date);
$event->setEnd($end);
$calendarService = new Google_Service_Calendar($client);
$calendarList = $calendarService->calendarList;
$events = $calendarService->events;
// if I leave this line, my code won't crash (but it won't do anything, either)
//echo "here"; die();
$events.insert($cal_id, $event, false);
}
?>
I figured this out. Since I don't see any complete examples of using service accounts with API v3, I'm just going to post my complete solution for reference. There are a few of things that you need to do in addition to implementing the code, however:
1) You need to go to the Google Developer's console and mark your account as a 'service account'. This will differentiate it from a web application. The important difference is that nobody will be prompted to log in to their account before the events are added since the account will belong to your application, not an end user. For more information see this article, starting on page 5.
2) You need to create a public/private key pair. From the developer's console, click on Credentials. Under you service account, click on 'Generate new P12 key'. You'll need to store this somewhere. That file location becomes the $key_file_location variable string in the code below.
3) Also from the developer's console, you need to enable the Calendar API. From your project, on the left margin you'll see APIs. Select that and find the Calendar API. Click it, accept the terms of service, and verify that it is now displayed under Enabled APIs with a status of On
4) In Google Calendar that you want to add events to, under settings, click Calendar Settings then on 'Share this Calendar' at the top. Under 'Share with specific people' in the 'Person' field, paste in the email address from the service account credentials. Change the permission settings to 'Make changes to events'. Don't forget to save the change.
Then, implement this code somewhere.
Comment if something is confusing or omitted. Good luck!
<?php
function calendarize ($title, $desc, $ev_date, $cal_id) {
session_start();
/************************************************
Make an API request authenticated with a service
account.
************************************************/
set_include_path( '../google-api-php-client/src/');
require_once 'Google/Client.php';
require_once 'Google/Service/Calendar.php';
//obviously, insert your own credentials from the service account in the Google Developer's console
$client_id = '843319906820-xxxxxxxxxxxxxxxxxxxdcqal54p1he6.apps.googleusercontent.com';
$service_account_name = '843319906820-xxxxxxxxxxxxxxxxxxxdcqal54p1he6#developer.gserviceaccount.com';
$key_file_location = '../google-api-php-client/calendar-xxxxxxxxxxxx.p12';
if (!strlen($service_account_name) || !strlen($key_file_location))
echo missingServiceAccountDetailsWarning();
$client = new Google_Client();
$client->setApplicationName("Whatever the name of your app is");
if (isset($_SESSION['service_token'])) {
$client->setAccessToken($_SESSION['service_token']);
}
$key = file_get_contents($key_file_location);
$cred = new Google_Auth_AssertionCredentials(
$service_account_name,
array('https://www.googleapis.com/auth/calendar'),
$key
);
$client->setAssertionCredentials($cred);
if($client->getAuth()->isAccessTokenExpired()) {
$client->getAuth()->refreshTokenWithAssertion($cred);
}
$_SESSION['service_token'] = $client->getAccessToken();
$calendarService = new Google_Service_Calendar($client);
$calendarList = $calendarService->calendarList;
//Set the Event data
$event = new Google_Service_Calendar_Event();
$event->setSummary($title);
$event->setDescription($desc);
$start = new Google_Service_Calendar_EventDateTime();
$start->setDateTime($ev_date);
$event->setStart($start);
$end = new Google_Service_Calendar_EventDateTime();
$end->setDateTime($ev_date);
$event->setEnd($end);
$createdEvent = $calendarService->events->insert($cal_id, $event);
echo $createdEvent->getId();
}
?>
Some helpful resources:
Github example for service accounts
Google Developers Console for inserting events in API v3
Using OAuth 2.0 to Access Google APIs
Here is the Google API Client 2.0 way to do
Follow Alex's Answer Go Google Developer's console to create Service Account, but create credential in JSON
Follow Google API Client Upgrade Guide, install by composer and include in the way of
require_once 'vendor/autoload.php';
Follow Alex's Answer to go to Google Calendar to share the calendar with Service Account ID
xxxxx#yyyy.iam.gserviceaccount.com
Take Ref. to below coding and the most important one is the calendar id should be the email of calendar creator, but not primary
<?php
require_once __DIR__.'/vendor/autoload.php';
session_start();
$client = new Google_Client();
$application_creds = __DIR__.'/secret.json'; //the Service Account generated cred in JSON
$credentials_file = file_exists($application_creds) ? $application_creds : false;
define("APP_NAME","Google Calendar API PHP"); //whatever
$client->setAuthConfig($credentials_file);
$client->setApplicationName(APP_NAME);
$client->addScope(Google_Service_Calendar::CALENDAR);
$client->addScope(Google_Service_Calendar::CALENDAR_READONLY);
//Setting Complete
//Go Google Calendar to set "Share with ..." Created in Service Account (xxxxxxx#sustained-vine-198812.iam.gserviceaccount.com)
//Example of Use of API
$service = new Google_Service_Calendar($client);
$calendarId = 'xxxx#gmail.com'; //NOT primary!! , but the email of calendar creator that you want to view
$optParams = array(
'maxResults' => 10,
'orderBy' => 'startTime',
'singleEvents' => TRUE,
'timeMin' => date('c'),
);
$results = $service->events->listEvents($calendarId, $optParams);
if (count($results->getItems()) == 0) {
print "No upcoming events found.\n";
} else {
echo "Upcoming events:";
echo "<hr>";
echo "<table>";
foreach ($results->getItems() as $event) {
$start = $event->start->dateTime;
if (empty($start)) {
$start = $event->start->date;
}
echo "<tr>";
echo"<td>".$event->getSummary()."</td>";
echo"<td>".$start."</td>";
echo "</tr>";
}
echo "</table>";
}
I'm trying to insert some activity app in a Google+ profile as shown in this documentation page:
https://developers.google.com/+/api/latest/moments/insert
I successfully obtain the access token needed, but seems the moments->insert method doesn't make anything.
If successful I would expect to see something on this page, once made the access, but nothing happen
https://plus.google.com/u/0/apps/activities
That's my code
<?php
require_once '../google-api-php-client/Google_Client.php';
require_once '../google-api-php-client/contrib/Google_PlusService.php';
session_start();
$client = new Google_Client();
$client->setClientId('xxxxxxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.apps.googleusercontent.com');
$client->setClientSecret('xxxxxxxxxxxxxxxxxxxxxxxx');
$client->setRedirectUri('http://www.myregisteredcallbackurl.com');
$client->setAccessType('offline');
$client->setScopes(array('https://www.googleapis.com/auth/plus.login'));
$client->setApprovalPrompt('force');
$plus = new Google_PlusService($client);
if (isset($_GET['logout'])) {
unset($_SESSION['token']);
}
if (isset($_GET['code'])) {
$client->authenticate($_GET['code']);
$_SESSION['token'] = $client->getAccessToken();
header('Location: http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF']);
}
if (isset($_SESSION['token'])) {
echo 'Logout<br><br>'.PHP_EOL.PHP_EOL;
$client->setAccessToken($_SESSION['token']);
$moment = new Google_Moment();
$moment->setType('http://schemas.google.com/AddActivity');
$itemScope = new Google_ItemScope();
$itemScope->setUrl('https://developers.google.com/+/plugins/snippet/examples/thing');
$moment->setTarget($itemScope);
$plus->moments->insert('me', 'vault', $moment);
}
if ($client->getAccessToken()) {
$_SESSION['token'] = $client->getAccessToken();
} else {
$authUrl = $client->createAuthUrl();
echo 'Connect<br>';
}
You need to add the requestvisibleactions permissions to your scope. The easiest way to do this is to switch from the conventional OAuth 2.0 flow to the new Google+ Sign-In flow - the Google+ team provides a PHP sample for Google+ Sign-In. If you want to continue using the older OAuth flow, you need to append request_visible_actions=[the app activity types] to your authorization URL.
Related questions:
Google+ PHP moments not working
Google+ Insert moment using dot-net-client
Google+ unable to insert moment
In your code, you are really close, the following seems to work for me:
$client = new Google_Client();
$client->setClientId('YOUR_CLIENT_ID');
$client->setClientSecret('YOUR_CLIENT_SECRET');
$client->setRedirectUri('http://example.com/callback.php');
$client->setAccessType('offline');
$client->setScopes(array('https://www.googleapis.com/auth/plus.login'));
$client->setRequestVisibleActions(array('https://schemas.google.com/AddActivity'));
$plus = new Google_PlusService($client);
To check the app activities that you have written, visit the app activity log.
I'm trying to get some info of my Google Analytics account using PHP. I already followed the steps for creating a Service Account in the Google Console API in this answer. I'm using the Google API Client for PHP.
This is the code I've got so far:
<?php
$path_to_src = 'src';
// These files are in /src, upload its contents to your web server
require_once $path_to_src . '/Google_Client.php';
require_once $path_to_src . '/contrib/Google_AnalyticsService.php';
$path_to_keyfile = '***'; //my private key
// Initialise the Google Client object
$client = new Google_Client();
// Your 'Product name'
$client->setApplicationName('My App Name');
$client->setAssertionCredentials(
new Google_AssertionCredentials(
'**', //gserviceaccount mail
array('https://www.googleapis.com/auth/analytics.readonly'),
file_get_contents($path_to_keyfile)
)
);
// Get this from the Google Console, API Access page
$client->setClientId('***'); // my cliente ID
$client->setAccessType('offline_access');
$analytics = new Google_AnalyticsService($client);
// create service and get data
$service = new Google_AnalyticsService($client);
// We have finished setting up the connection,
// now get some data and output the number of visits this week.
// Your analytics profile id. (Admin -> Profile Settings -> Profile ID)
$analytics_id = 'ga:****'; // my profile id
$lastWeek = date('Y-m-d', strtotime('-1 week'));
$today = date('Y-m-d');
try {
$results = $analytics->data_ga->get($analytics_id,
$lastWeek,
$today,'ga:visits');
echo '<b>Number of visits this week:</b> ';
echo $results['totalsForAllResults']['ga:visits'];
} catch(Exception $e) {
echo 'There was an error : - ' . $e->getMessage();
}
I've enabled the openssl extension in PHP:
When browsing to the location of the php script, I just get a almost forever loading and the following error:
I'm using PHP 5.4.7:
After debuging the Google API Client code, it looks like the script is breaking at this line:
if (!openssl_sign($data, $signature, $this->privateKey, "sha256"))
Anything below this line does not get called. Looks like the error happens in this line. Is there a incompatibility here, or something?
One thing for starters you should change:
You instantiate the AnalyticsService twice. Take out the one you're not using:
$service = new Google_AnalyticsService($client);
See if that helps your problem at all.
Using version 3 of the Google Calendar API. I can add one event at a time, but I want to add multiple events at once. Any idea how to do this? I assign $authUrl to my template below, the user clicks a link that says "add all items to google calendar", authorizes that Google can access the account, it goes back to my callback URL with $_GET['code'] assigned so the whole $client->getAccessToken() block gets executed.
Obviously I'm using dummy data now, but I want to populate the fields with data from expression engine. I have that data available, but for the sake of simplicity for this question, spared the crap and put in test data.
This code works for one event:
$client = new apiClient();
$client->setApplicationName("Band Calendar");
$cal = new apiCalendarService($client);
if (isset($_GET['logout'])) {
unset($_SESSION['token']);
}
if (isset($_GET['code'])) {
$client->authenticate();
$_SESSION['token'] = $client->getAccessToken();
header('Location: http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF']);
}
if (isset($_SESSION['token'])) {
$client->setAccessToken($_SESSION['token']);
}
$authUrl = $client->createAuthUrl();
if ($client->getAccessToken()) {
$event = new Event();
$event->setSummary("test title");
$event->setLocation("test location");
$start = new EventDateTime();
$start->setDateTime('2012-03-03T09:25:00.000-05:00');
$event->setStart($start);
$end = new EventDateTime();
$end->setDateTime('2012-03-03T10:25:00.000-05:00');
$event->setEnd($end);
$attendee1 = new EventAttendee();
$attendee1->setEmail('email#email.com');
$attendees = array($attendee1);
$event->attendees = $attendees;
$createdEvent = $cal->events->insert('primary', $event);
echo $createdEvent->getId();
$_SESSION['token'] = $client->getAccessToken();
}
I've noticed that there's a "class Events" that I can instantiate (rather than just instantiating a single Event object) and that it has an $items member variable. I'm guessing I can add a bunch of Event objects to the $item member variable and then send a bunch of events at once, but can't seem to get it right. Anyone have experience with this?
Judging from the PHP and Java documentation for v3 this is not possible. Calendar.Events (in Java) is a wrapper around a calendar's event-related methods in the API: you can ask it to insert one event, but you cannot use it as a representation of several events and e.g. pass it to the server (for bulk insert).
At least that's what I've concluded for now. (I could also use the feature.)