SlideShare a Scribd company logo
ONTIME | Group Calendar
AN INTRODUCTION TO THE ONTIME API
Agenda (part 1)
• Introduction
• Demos – seeing is believing
• Core Concepts
• API Explorer
• OnTime Frameworks
• How we did the demos – code walk-thru
Agenda (part 2)
• Advanced Topics (character encoding, logging,
batching commands, etc.)
• Access Examples (JavaScript, Java, LotusScript)
• Native IBM Notes (NRPC) Access
• Reference Material
INTRODUCTION
Target Audience
• OnTime Group Calendar
– Customers
– Partners
• Developers
• Solution Architects
Many User Interfaces
1. Notes
2. Browser
3. Mobile
4. Sidebar
5. Social
6. Room Signs
1 API
• This is an API created and
maintained by OnTime – not by
IBM
• Everything we do in the user
interfaces you can do with the API
as well – there are no secret calls
• New user interface features adds
new capabilities to the API e.g.
when we added Out of Office
functionality it became available to
API customers
Requirements
• OnTime Group Calendar installed and configured
• Open API License – purchased separately – price
based on total license price
• Application ID – issued by OnTime on request
– All installations come with a special Application ID
called ”ApiExplorer” – don’t use for production as it’s
throttled
• Access by a user in OnTime
Skills Required
• JSON (JavaScript Object Notation)
• IBM Notes/Domino API for LotusScript / Java
access via NRPC
• Virtually any other programming language for
access via HTTP(S)
What can you do with it?
• Custom user interfaces
• Custom reports and analysis
• Integration
– CRM systems
– Phone systems
– Booking systems
DEMOS
SEEING IS BELIEVING…
Demos
• JavaScript and Java
– Create appointment
– Read calendar entries
– Free time search
– Out of Office
• XPages
– Use Java framework to build application
CORE CONCEPTS
Endpoints
• An endpoint is the ”address” you make API
requests against
• OnTime supports two types of endpoints
– HTTP using URL’s
– NRPC using an agent
• This presentation will focus on using HTTP (there
are slides on NRPC near the end)
HTTP Endpoint in Detail
• HTTP uses two endpoints – one for getting an Access Token
and one for data
• An Access Token is required for all API data access
• The API endpoints are in the Client database
1. Token – /ontime/ontimegcclient.nsf/apihttptoken
2. Data – /ontime/ontimegcclient.nsf/apihttp
• If using the servlet (offers caching and much higher
performance) for API access
1. Data (servlet) – /servlet/ontimegc
Access Token (”token”)
• All requests to the token endpoint requires you to be authenticated to
IBM Domino (basic, form, certificate)
• All requests to the API endpoint requires a token obtained from the Token
endpoint
• A token may be used without the user being authenticated to IBM Domino
• A token may be cached – expiration set in configuration (Server
Settings/OnTime Token Timeout)
• From API version 5 the token is fully cluster and load balancer compliant
Please note: New token returned with each request – doesn’t expire the old
one though – ”timeout” is in effect an Idle Timeout
JSON (1)
• Industry standard – http://www.json.org
• Some languages like JavaScript has native support
for JSON
• Some languages like Java and LotusScript require
a separate parser to consumer and writer to
produce JSON
Bonus: We supply a JSON parser and writer for
LotusScript that you may use with the OnTime API
JSON (2)
{
”name”: ”Chris Holmes”,
”age”: 34,
”male”: true,
”emails”: [”ch@ontime.com”, ”chris.holmes@ontime.com”],
”address”: {
”street”: ”101 Main Street”,
”zipcode”: ”23821”,
”city”: ”Cleveland”
”country”: ”USA”
}
}
Please note: Keys are in quotes
JSON (3)
{
”product”: ”OnTimeu00ae Group Calendar”,
”userInterfaces”: [
{”name”: ”Notes”, ”language”: ”Java”},
{”name”: ”Browser”, ”langauge”: ”JavaScript”},
{”name”: ”Mobile”, ”language”: ”JavaScript”},
{”name”: ”Social”, ”language”: ”JavaScript”},
{”name”: ”Sidebar”, ”language”: ”Java”}
]
}
Please note: Keys are case sensitive
Please note: Non-ASCII characters should
be Unicode encoded – very important when
using the agent based API (HTTP only)
Operations
• An operation is a ”command” you send the API to let it know what
you would like to do
• Currently 40+ different operations
• Examples
– Login (current user information)
– Version (retrieve version information)
– UsersAll (retrieve users)
– Calendar (retrieve calendar entries)
– AppointmentCreate (create a calendar entry)
– OutOfOfficeGet (retrieve out of office information)
Application ID and Version
• All requests must contain an Application ID
(ApplID) in the Main section
– The Application ID is verified against your OnTime
Group Calendar license key
• All requests must contain an Application
Version (ApplVer) in the Main section
– The Application Version may be any string
API Versioning
• To be backwards compatible the API is versioned
– From v. 4.4 we will be at APIVer=6
• API versioning allows us to continueously update
the API and add new features without breaking
custom applications
• API version is specified using ”APIVer” key in the
Main section
• You must specify an API version for each request
Basic Request Format
• Each request must contain a payload describing the request
• The payload always has a Main section with APIVer, ApplID, ApplVer and a
Token
{
”Main”: {”APIVer”: 6,
”ApplID”: ”ApiExplorer”,
”ApplVer”: ”0.0.1”,
”Token”: ”<access token>”
},
”Command1”: {<command specific data>}
}
Basic Response Format
• The response always contains an overall status
code, the server API version, a new token and a
response object per command sent
{
”APIVersion”: ”4.2.0”,
”Command1”: {...},
”Token”: ”1234567890abcdefghijk==”,
”Status”: ”OK”
}
Example – obtaining a token
POST >> apihttptoken
Authorization: Basic ZGVtbzpkZW1v
{”Main”: {”APIVer”: 6,
”ApplID”: ”ApiExplorer”,
”ApplVer”: ”0.0.1”
}}
{”APIVersion”: ”4.2.0”,
”APIBuild”: 650,
”Token”: ”abc111==”,
”Status”: ”OK”
}
Example –the Login operation
POST >> apihttp
{”Main”: {”APIVer”: 6,
”ApplID”: ”ApiExplorer”,
”ApplVer”: ”0.0.1”,
”Token”, ”abc111==”
}, ”Login”: {}}
{”APIVersion”: ”4.2.0”,
”Login”: {
”Global”: {...},
”User”: {”ID”: ”X”,
”Name”: ”Chris Holmes/OnTime”,
”Email”: ”chris.holmes@ontime.com”,
”MailSource”: ”Domino”
}
},
”Token”: ”abc222==”,
”Status”: ”OK”
}
Handling Errors
• If an error occurs it is sent back to the caller
• The error contains an error code and a description
• It is a best practice to always verify that ”Status” is ”OK”
{APIVersion: "4.2.0”,
Status: "Error”,
ErrorCode: "NotValidApplID”,
Error: "Not a valid Application ID"
}
{APIVersion: "4.2.0”,
Status: "Error”,
ErrorCode: "TokenTimeout”,
Error: "Token Timeout"
}
An introduction to the API for OnTime for IBM
Dates
• All dates should be encoded as strings in ISO8601
format using the UTC timezone
– {YYYY}-{MM}-{dd}T{HH}:{mm}:{ss}Z
• UTC doesn’t adjust for daylight savings time
• OnTime provided frameworks handle time zone
conversion automatically
• Please note: Using UTC may be confusing at first as a
the date/time may be ”tomorrow” or ”yesterday”
Dates
• 2015-12-31T13:15:00Z
– 2.15pm, 31 December 2015 in Denmark (UTC+1, winter time)
– 10.15pm, 31 December 2015 in Japan (UTC+9)
• 2015-06-23T22:00:00Z
– Midnight, 24 June 2015 in Denmark (UTC+2, summer time)
– 7am, 24 June 2015 in Japan (UTC+9)
• 2015-06-30T15:00:00Z
– 8am, 30 June 2015 in California, (UTC-7)
– Midnight, 1 July 2015 in Japan (UTC+9)
API EXPLORER
Getting the API Explorer
• You already have it – it is in the Clients database
– http://<hostname>/<ontime client db>/apiexplorer
– https://demo.ontimesuite.com/ontime/ontimegcclient.nsf/apiexplor
er (same as
https://demo.ontimesuite.com/apiexplorer)
• It’s the tool we use when we develop for OnTime
• Preconfigured with ApiExplorer Application ID for
testing
Demo – API Explorer
• Show API Explorer
• Log in, obtain token and do requests
• Show how the API Explorer lets you
inspect requests and responses
• Log out and continue to do requests
• Show built in examples
ONTIME FRAMEWORKS
Current Stack
OnTime Core Server
OnTime API
(”low level” JSON based API)
Notes
JavaJavaScript
Team-At-
A-Glance
MobileWeb
Custom
App RoomSigns
Socia
l
Social
Coming Stack
OnTime Core Server
OnTime API
(”low level” JSON based API)
CustomApp
Java FrameworkJavaScript Framework (ivcore.js)
Team-At-
A-Glance
Mobile
(new)
Web
Custom
App
Custom
App
Room
Signs
Notes SocialSocial
Mobile(iOS)
The Goal
• Do not reinvent the wheel – calendaring and
timezones are hard to get right so use our code
• Time proven code – the framework code is what’s
in the products – it’s not something we make just
for customers
• The frameworks handle authentication, tokens,
network transport and often dealing with the
underlying data
HOW WE DID THE DEMOS
JavaScript Examples
• Create appointment
• Read calendar entries
• Free time search
• Out of Office
Create Appointment, JavaScript
// create appointment
ivcore.api.AppointmentCreate({
"UserID": this.userID,
"Subject": this.getFormFieldValue("subject"),
"Location": this.getFormFieldValue("location"),
"StartDT": this.getFormFieldValue("start"),
"EndDT": this.getFormFieldValue("end")
});
ivcore.api.process(function(json) {
if (json.Status === ”OK”) {
...
}
}.bind(this));
Read Calendar Entries, JavaScript
// read calendar entries
ivcore.api.Calendars({
"FromDT": start,
"ToDT": end,
"IDs": [this.userID]
});
ivcore.api.process(function(json) {
// get calendar entries and sort using wrapper class
var calitems = new iv.ontimegc.CalItemArr(json.Calendars.IDs[0].Items);
calitems.sort();
...
}.bind(this));
Free Time Search, JavaScript
// perform freetime search
ivcore.api.FreeTimeSearch({
"FromDT": from,
"ToDT": to,
"IDs": this.searchIDs,
"Duration": 360
});
ivcore.api.process(function(json) {
...
}.bind(this));
Out Of Office, JavaScript
// request OOO for a user
ivcore.api.OutOfOfficeGet({
"UserID": this.userID
});
ivcore.api.process(function(json) {
if (json.Status === ”OK”) {
// read OOO info and use wrapper class for date/time formatting
var ooo = json.OutOfOfficeGet;
var dateBack = ooo.DateTimeBack.ivToDate();
var strBack = ivcore.langreg.region("<dd MMM, HH:NN>", dateBack);
...
}
}.bind(this));
Java Examples
• Create appointment
• Read calendar entries
• Free time search
• Out of Office
Create Appointment, Java (1)
// create facade with default values (and configure, omitted for brevity)
IGroupCalendarAPIFacade facade = new GroupCalendarAPIFacade();
// create appointment
CalEntryResponse response = facade.createAppointment(null,
120,
"Test Appointment",
"OnTime Example Code");
if (response.isSuccess()) {
System.out.println("Created appointment”);
}
Create Appointment, Java (2)
// create facade with default values (and configure, omitted for brevity)
IGroupCalendarAPIFacade facade = new GroupCalendarAPIFacade();
// create calendar and get dates using utility classes
Calendar cal = facade.createJavaCalendar();
CalendarUtil.setTime(cal, 13, 0);
Date start = cal.getTime();
CalendarUtil.setTime(cal, 14, 0);
Date end = cal.getTime();
// create appointment
CalEntryResponse response = facade.createAppointment(start, end, "Test Appointment",
"OnTime Example Code");
if (response.isSuccess()) {
System.out.println("Created appointment”);
}
Read Calendar Entries, Java
// create facade with default values (and configure, omitted for brevity)
IGroupCalendarAPIFacade facade = new GroupCalendarAPIFacade();
// create date/time range (date construction omitted for brevity)
DateTimeRange range = new DateTimeRange(start, end);
// fetch appointments
facade.fetchAppointments(false, range);
// get appointments
IAppointment[] apps = facade.getActAsCalendar().getAppointments();
// show result
for (IAppointment app : apps) {
System.out.println(app.getDateTimeRange() + " - " + app.getSubject());
}
Free Time Search, Java
// create facade with default values (and configure, omitted for brevity)
IGroupCalendarAPIFacade facade = new GroupCalendarAPIFacade();
// create dates (date construction omitted for brevity)
Date from = ...
Date to = ...
// get calendars
Date[] results = facade.searchFreeTime(60, from, to,
ID_TYPE.EMAIL,
"chris.holmes@ontime.com", "amanda.jones@ontime.com");
for (int i=0, count=ArrayUtil.count(results); i<count; ) {
Date d1 = results[i++];
Date d2 = results[i++];
System.out.println(d1 + " --> " + d2);
}
Out of Office, Java
// create facade with default values (and configure, omitted for brevity)
IGroupCalendarAPIFacade facade = new GroupCalendarAPIFacade();
// actually fetch OOO
OutOfOfficeResult ooo = facade.fetchOutOfOffice();
// show result
System.out.println("Out of office for <" +
facade.getActAsUser().getDispName() +
”> of is <" + (ooo.isEnabled() ? "ENABLED" : "DISABLED") +
">");
System.out.println(ooo.getDateOut());
System.out.println(ooo.getGeneralSubject());
System.out.println(ooo.getGeneralBody());
XPages Example
• Let us do a code walk-thru in Domino
Designer
• Techniques used
– Jar design elements w/ OnTime Java Framework
– Data tables to loop data
– AppointmentFilter for easy filtering and sorting
ADVANCED TOPICS
Character Encoding
• It is a best practice to always encode non-ASCII
charcters using the Unicode character code using
uXXXX
– ® == u00ae
– 東 == u6771
– 京 == u4EAC
• Failure to do so may result in character encoding issues
• OnTime provided frameworks handle character
encoding automatically
Character Encoding
{"Main" : {
"APIVer": 5,
"ApplID": "ApiExplorer",
"ApplVer": "0.0.1"
},
"AppointmentCreate": {
"AppointmentType": "0",
"UserID": "7",
"StartDT": "2015-05-18T07:00:00Z",
"EndDT": "2015-05-18T10:00:00Z",
"Subject": "OnTime API ワークショップ",
"Location": "新宿区, 東京"
}
Character Encoding
{"Main" : {
"APIVer": 5,
"ApplID": "ApiExplorer",
"ApplVer": "0.0.1"
},
"AppointmentCreate": {
"AppointmentType": "0",
"UserID": "7",
"StartDT": "2015-05-18T07:00:00Z",
"EndDT": "2015-05-18T10:00:00Z",
"Subject": "OnTime API
u30EFu30FCu30AFu30B7u30E7u30C3u30D7",
"Location": "u65B0u5BBFu533A, u6771u4EAC"
}
More on Tokens
• As mentioned previously a token may be cached on the client
• When caching please be aware of token expiration – expiration time is set on the
server – defaults to 24 hours
• A token may be revoked on the server by forcing a new web logon (see
screeenshot, means setting a new ”token ID” for the user)
• Token related error codes
– NoToken
– NoUserWithToken
– TokenTimeout
– WrongTokenID
– InvalidTokenTimeType
– TokenDecryptError
– WrongTokenSign
API Log (1)
The API log is an excellent debugging tool as it shows
exactly what the API received and what it returned
API Log (2)
• Starting with v. 4.0 – API logging is no longer only
controllable on the OnTime server document but
from code and on a per user basis
• There are 3 ways to have API traffic logged for a
user
• Please note: Never leave API logging turned on in
production as it may affect performance.
API Log (3)
1. The Main section contains ”APILog” = true
Controlled by application code and enabled
logging only for the specific calls
{"Main": {"APIVer": 6, "ApplVer": "0.0.1", "ApplID":
"ApiExplorer", "Token": ”aaa111==", "APILog": true},
"Login": {}}
API Log (4)
2. Enable user debug – enables logging for all calls
until turned of. Benefit is that it’s done on the
server (no app changes). Setting actually does two
things:
– Enables extended logging
for the user (sync. logging)
– Enables API logging
API Log (5)
3. OnTime UI specific option (actually toggles on APILog=true)
– Web UI by appending &debug=true
– Eclipse UI’s through menu actions
OnBehalfOf
• All operations are performed as the current user (as
represented by the token / signer)
• For some applications you may need to act as someone else –
we call this OnBehalfOf
• Access to use OnBehalfOf
is explicitly granted on a
per user basis in Server
Settings (set on all servers)
OnBehalfOf – Login as user self
Request
{"Main": {"APIVer": 6, "ApplVer": "0.0.1",
"ApplID": ”ApiExplorer", "Token":
"aaa111=="}, "Login": {}}
(Logged in as Chris Holmes/OnTime)
Response
{"APIVersion":"4.1.4","APIBuild":655,"Logi
n":{"Global":{"PreSort":false,"SyncBack":2
1,"PhotoEnabled":true},"User":{"ID":"7","N
ame":”Chris
Holmes/OnTime","Email":”chris.holmes@
ontime.com","MailSource":"Domino"},"Sect
ionProcessTime":16},"Token":”aaa222==","
Status":"OK"}
OnBehalfOf – Login w/ OnBehalfOf
Request
{"Main": {"APIVer": 6, "ApplVer": "0.0.1",
"ApplID": ”ApiExplorer", "Token":
"aaa222==", ”OnBehalfOf": ”Amanda
Jones/OnTime"}, "Login": {}}
(Logged in as Chris Holmes/OnTime and he’s
allowed to do OnBehalfOf requests)
Response
{"APIVersion":"4.1.4","APIBuild":655,"Logi
n":{"Global":{"PreSort":false,"SyncBack":2
1,"PhotoEnabled":true},"User":{"ID":"1","N
ame":”Amanda
Jones/OnTime","Email":”aj@ontime.com",
"MailSource":"Domino"},"SectionProcessTi
me":0},"Token":”aaa333==","Status":"OK"}
OnBehalfOf – GetToken (1)
Request
{"Main": {"APIVer": 5, "ApplVer": "0.0.1",
"ApplID": ”ApiExplorer", "Token":
"aaa333==", ”OnBehalfOf": ”Amanda
Jones/OnTime"}, ”GetToken": {}}
Response
{"APIVersion":"4.1.4","APIBuild":655,"GetT
oken":{"Token":”bbb111==","User":”Am
anda
Jones/OnTime","ID":"1","CurrentTimeout"
:168,"SectionProcessTime":0},"Token":”aa
a444==","Status":"OK"}
Excellent solution for performing Single-Sign-On with portals built on other
technologies than IBM – issue a token to the user and save in a cookie…
OnBehalfOf – GetToken (2)
Request
{"Main": {"APIVer": 5, "ApplVer": "0.0.1",
"ApplID": ”ApiExplorer", "Token":
”bbb111==”}, ”Login": {}}
Response
{"APIVersion":"4.1.4","APIBuild":655,"Logi
n":{"Global":{"PreSort":false,"SyncBack":2
1,"PhotoEnabled":true},"User":{"ID":"1","N
ame":”Amanda
Jones/OnTime","Email":”aj@ontime.com",
"MailSource":"Domino"},"SectionProcessTi
me":0},"Token":”bbb222==","Status":"OK"}
Now just using token
obtained on previous
slide
Batching commands (1)
• Each request to the API may contain multiple
commands – even multiple versions of the same
command (e.g. multiple OutOfOfficeGet)
• We call this ”batching commands”
• Keys must be unique in JSON so the API only
checks the beginning of the keys
– OutOfOfficeGet == OutOfOfficeGet_MySuffix
• Response uses the same keys as the request
Batching commands (2)
Request
{"Main": {
"APIVer": 5,
"ApplVer": "0.0.1",
"ApplID": "ApiExplorer",
"Token": ”aaa111=="},
"Login_1": {},
"Login_XYZ": {}
}
Response
{"APIVersion":"4.1.4","APIBuild":655,
"Login_1":{"Global":{…},"User":{"ID":"7","Name"
:”Chris
Holmes/OnTime","Email":”chris.holmes@ontime.
com","MailSource":"Domino"},"SectionProcessTi
me":0},
"Login_XYZ":{"Global":{…},"User":{"ID":"7","Na
me":”Chris
Holmes/OnTime","Email":”chris.holmes@ontime.
com,"MailSource":"Domino"},
"SectionProcessTime":0},"Token":”aaa222==","St
atus":"OK"}
Custom ID (1)
• When doing multiple requests – even multiple
requests at the same time – keeping track of
them can be hard
• To make it easier to discern the requests you may
add a custom ID to each request
• The custom ID is returned in the corresponding
response
• The custom ID may be any string value
Custom ID (2)
Request
{"Main": {
"APIVer": 5,
"ApplVer": "0.0.1",
"ApplID": "ApiExplorer",
"Token": ”aaa111==",
”CustomID": ”MyCustomID”},
"Login": {}
}
Response
{"APIVersion":"4.1.4","APIBuild":655,
"CustomID": "MyCustomID",
"Login":{"Global":{…},"User":{"ID":"7","Na
me":”Chris
Holmes/OnTime","Email":”chris.holmes@o
ntime.com","MailSource":"Domino"},"Secti
onProcessTime":0},
"Token":”aaa222==","Status":"OK"}
USING PLAIN JAVASCRIPT
Character Encoding
Access w/ JavaScript (1)
var apirequest = function(payload, callback) {
var xmlhttp = new XMLHttpRequest();
xmlhttp.open("POST", ”/servlet/ontimegc", true);
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4) {
if (xmlhttp.status == 200) {
// handle response
var result = JSON.parse(xmlhttp.responseText);
if (callback) callback(result);
}
}
}
// post
xmlhttp.send(JSON.stringify(payload));
}
Access w/ JavaScript (2)
// payload
var payload = {"Main": {"APIVer": 6,
"ApplID": "ApiExplorer",
"ApplVer": "0.0.1", "Token":
"aaa111=="}, "Login": {}
};
// do request
apirequest(payload, function(obj) {
console.log(obj);
});
USING PLAIN JAVA
Character Encoding
Access w/ Java (1)
URL url = new URL(https://demo.ontimesuite.com/servlet/ontimegc");
HttpURLConnection con =(HttpURLConnection)url.openConnection();
con.setRequestMethod("POST");
con.addRequestProperty("Content-Type", "application/json");
con.addRequestProperty("Accept", "*/*");
con.setDoInput(true);
// handle post
con.setDoOutput(true);
OutputStream out = con.getOutputStream();
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out));
writer.write(request);
writer.flush();
Access w/ Java (2)
// get response code and read response if code 200 (OK)
if (200 != con.getResponseCode()) throw new Exception("Non OK");
BufferedReader reader = new BufferedReader(
new InputStreamReader(con.getInputStream()));
StringBuilder buffer = new StringBuilder(2048);
String line = null;
while (null != (line = reader.readLine())) {
buffer.append(line).append('n');
}
// disconnect and return result;
con.disconnect();
return buffer.toString();
USING NRPC
Native IBM Notes API Access via Notes Remote
Procedure Calls
Endpoints in Detail (NRPC)
• Starting with version 3.8 all API requests are made
against a single database – the Client database1
• API requests are done by
1. Creating/updating a document in the Client database
2. Signing the document (NotesDocument.sign())
3. Running an agent on the server with the document as
context
• The agent is called ApiNotes and can be found in the
Client database
1 Prior to this version there were two possible API endpoint databases; 1) the API database and 2) the Web database
Authentication
• User access is verified using IBM Notes digital signatures
• Ideal for LotusScript as HTTP access is troublesome
• May be used with Java as well
• Requires access to the IBM Notes/Domino backend API (Local
or DIIOP)
• Cluster and failover aware through the IBM Notes/Domino API
• Please note: NRPC access doesn’t use OnTime Access Tokens
Access w/ NRPC (1)
Requests are done as follows:
1. Create/update an API document in the Client database
2. Set JSON request (same payload as with HTTP)
3. Set Authors field (ensure only user and server can read document)
4. Sign document
5. Run (ApiNotes) agent on document on the server
6. Refetch the API document
7. Read the JSON response
Access w/ NRPC (2)
Requests are done as follows:
1. Create/update an API document in the Client database
2. Set JSON request in a field called $Request_0 (if bigger than 32 kb continue
in $Request_1 and so on…)
3. Set Authors field called _Authors to
[ReadAll], <Server DN>, <User DN>
4. Sign document (NotesDocument.Sign())
5. Run (ApiNotes) agent on document on the server
(NotesAgent.RunOnServer(noteid))
6. Refetch the API document by note ID
7. Read the JSON response from a field called $Response_0 (if bigger than 32
kb continue in $Response_1 and so on)
Access w/ LotusScript (1)
Function ProcessString(Request As String) As String
Dim session As New NotesSession
Dim dbApi As NotesDatabase
Dim agentApi As NotesAgent
Dim docApi As NotesDocument
Dim noteid As String
Dim item As NotesItem
Dim values(0 To 2) As String
values(0) = session.UserName
values(1) = "[ReadAll]"
values(2) = session.EffectiveUsername
Set dbApi = session.GetDatabase("Server1/OnTime", "ontime/ontimegcclient.nsf")
Set agentApi = dbApi.GetAgent("ApiNotes")
Set docApi = New NotesDocument(dbApi)
Call SetLongString(docApi, "$Request", Request)
Set item = New NotesItem(docApi, "_Author", values)
item.Isauthors = true
item.Isreaders = true
Call docApi.Sign()
Call docApi.Save(True,False)
noteid = doc.Noteid
Delete docApi
Call agentApi.Runonserver(noteid)
Set docApi = dbApi.GetDocumentByNoteID(noteid)
ProcessString = GetLongString(docApi, "$Response")
Exit Function
Declarations
Access for API document
Access Client database,
API agent, create API document,
sign and save
Delete document reference, run
agent on and refetch document
Read response
Character Encoding in LotusScript
Private Function encode(s As String) As String
Dim result As String
Dim i As Integer
Dim ch As String
Dim u As Long
For i = 1 To Len(s)
ch = Mid(s,i,1)
u = Uni(ch)
Select Case u
Case 34 : result = result & {"}
Case 92 : result = result & {}
Case 47 : result = result & {/}
Case 8 : result = result & {b}
Case 12 : result = result & {f}
Case 10 : result = result & {n}
Case 13 : result = result & {r}
Case 9 : result = result & {t}
Case Else
If (u>=32) And (u<127) Then
result = result & ch
Else
result = result & "u" & Right("0000" & Hex(u), 4)
End If
End Select
Next
encode = result
End Function
If (u>=32) And (u<127) Then
r = r & ch
Else
u = Uni(ch)
r = r & "u" & Right("0000" & Hex(u), 4)
End If
LotusScript Examples
1. Login (Does a login request to the server)
2. Version (requests the version information from
the server)
3. Calendars, raw (requests 7 days worth of
calendar information for the current user by DN)
4. Calendars, processed (same as 3 but parses the
response using the JSON parser)
REFERENCE MATERIAL
Operations
• Login
• Logout
• Version
• UsersAll
• UsersInfo
• Calendars
• AppointmentCreate
• AppointmentChange
• AppointmentRemove
• AppointmentRead
• AppointmentInviteeStatus
• AppointmentRepeatDates
• CustomFieldsList
• FreeResources
• FreeRooms
• FreeTimeSearch
• GetToken
• GroupList
• GroupPrivateChange
• GroupPrivateRemove
• GroupUserIDs
• LanguageList
• LanguageText
• Legends
• LegendsSets
• LegendsSetsList
• MailSend
• NameFormat
• NoticeAccept
• NoticeDecline
• NoticeUpdate
• Notices
• OutOfOfficeGet
• OutOfOfficeSet
• RegionList
• RegionText
• SettingsGet
• SettingsSet
• UserBusyInfo
• UsersAccess
• UsersPhoto
• UsersSearch
Links
• OnTime Group Calendar demo environment
https://demo.ontimesuite.com
• OnTime Group Calendar demo API Explorer
https://demo.ontimesuite.com/apiexplorer
(login with username ”demo” and password ”demo”)
Main object keys
Key name Description Required
ApplID Application ID – issued by OnTime support on request.
ApplVer Application version – can be any string
APIVer API version to use. Currently it should be 5. From v. 4.4 it
should be 6.
Token The token to identify the user if using HTTP
CustomID Custom string to discern multiple concurrent requests
APILog Should the API request be logged on the server
OnTime Group Calendar databases
• Configuration database
– Default location: /ontime/ontimegc.nsf
• Log database
– Default location: /ontime/ontimegclog.nsf
• Client database
– Default location: /ontime/ontimegcclient.nsf
• Broadcast database
– Default location: /ontime/ontimegcbroadcast.nsf
An introduction to the API for OnTime for IBM

More Related Content

PPTX
Building a scalable API with Grails
PDF
Building Awesome APIs in Grails
PPTX
System insight without Interference
PDF
Cooking your Ravioli "al dente" with Hexagonal Architecture
PDF
Leveraging the Security of AWS's Own APIs for Your App - AWS Serverless Web Day
PDF
Node.js vs Play Framework (with Japanese subtitles)
PDF
Building Beautiful REST APIs with ASP.NET Core
PPTX
MicroProfile: A Quest for a Lightweight and Modern Enterprise Java Platform
Building a scalable API with Grails
Building Awesome APIs in Grails
System insight without Interference
Cooking your Ravioli "al dente" with Hexagonal Architecture
Leveraging the Security of AWS's Own APIs for Your App - AWS Serverless Web Day
Node.js vs Play Framework (with Japanese subtitles)
Building Beautiful REST APIs with ASP.NET Core
MicroProfile: A Quest for a Lightweight and Modern Enterprise Java Platform

What's hot (20)

PPTX
REST API Security: OAuth 2.0, JWTs, and More!
PPTX
Araport Workshop Tutorial 2: Authentication and the Agave Profiles Service
KEY
Rails as iOS Application Backend
PDF
MesosCon - Be a microservices hero
PDF
Developing Skills for Amazon Echo
PDF
Rails and iOS with RestKit
PDF
Test-Driven Documentation for your REST(ful) service
PDF
Externalizing Chatter Using Heroku, Angular.js, Node.js and Chatter REST APIs
PDF
SPIFFE Meetup Tokyo #2 - Attestation Internals in SPIRE - Shingo Omura
PPTX
Ntu workshop : REST, PayPal APIs & Async
PDF
Seven Versions of One Web Application
ODP
Http programming in play
PDF
Securty Testing For RESTful Applications
PPTX
Externally Testing Modern AD Domains - Arcticcon
PDF
Intro to JavaScript
PPTX
Api security
PDF
Why your next serverless project should use AWS AppSync
PDF
Introduction to CloudStack API
PPTX
In app search 1
PDF
PHP, OAuth, Web Services and YQL
REST API Security: OAuth 2.0, JWTs, and More!
Araport Workshop Tutorial 2: Authentication and the Agave Profiles Service
Rails as iOS Application Backend
MesosCon - Be a microservices hero
Developing Skills for Amazon Echo
Rails and iOS with RestKit
Test-Driven Documentation for your REST(ful) service
Externalizing Chatter Using Heroku, Angular.js, Node.js and Chatter REST APIs
SPIFFE Meetup Tokyo #2 - Attestation Internals in SPIRE - Shingo Omura
Ntu workshop : REST, PayPal APIs & Async
Seven Versions of One Web Application
Http programming in play
Securty Testing For RESTful Applications
Externally Testing Modern AD Domains - Arcticcon
Intro to JavaScript
Api security
Why your next serverless project should use AWS AppSync
Introduction to CloudStack API
In app search 1
PHP, OAuth, Web Services and YQL
Ad

Viewers also liked (20)

ODP
非表示式とご相談
PDF
Penn State Cooperative Extension Marcellus Education Fact Sheet
PPS
Artajona fiestas patronales 25 fotos
PPTX
Wwrd holiday webinar3_final
PPTX
Arma virumque cano (nidicaciones sobre c+¦mo y por qu+® leer la e neida)
PDF
Boletín Tierra num. 220 28/mayo/2014
PDF
Canada oportunidades
PPSX
Presentación xat2
PPTX
Siete flores para conocer Malambo
PDF
Portfolio Profesional Oihane Santiuste Mayo 2010
PDF
Agileee Agile Journeys Hussman
PPTX
B i l i s
PDF
Comps on 2124 Lipari ct las vegas nv 89123
PPTX
Integrating cortana with wp8 app
PPT
Las tic en la educacion 2
PPTX
Gofres – tu merienda perfecta
PDF
Erfolg Ausgabe 10/2010 vom 29.10.2010
PDF
English twitter 08
PPTX
Alvaro Hervas[1]
PPT
Lucas g. santiago g. juan g. ramiro z. isaac r.
非表示式とご相談
Penn State Cooperative Extension Marcellus Education Fact Sheet
Artajona fiestas patronales 25 fotos
Wwrd holiday webinar3_final
Arma virumque cano (nidicaciones sobre c+¦mo y por qu+® leer la e neida)
Boletín Tierra num. 220 28/mayo/2014
Canada oportunidades
Presentación xat2
Siete flores para conocer Malambo
Portfolio Profesional Oihane Santiuste Mayo 2010
Agileee Agile Journeys Hussman
B i l i s
Comps on 2124 Lipari ct las vegas nv 89123
Integrating cortana with wp8 app
Las tic en la educacion 2
Gofres – tu merienda perfecta
Erfolg Ausgabe 10/2010 vom 29.10.2010
English twitter 08
Alvaro Hervas[1]
Lucas g. santiago g. juan g. ramiro z. isaac r.
Ad

Similar to An introduction to the API for OnTime for IBM (20)

PDF
Api fundamentals
PDF
Automating Cloud Operations - Everything you wanted to know about cURL and RE...
PDF
Api_testing.pdf
PPTX
Api Testing
PPTX
Api Testing
PDF
Api FUNdamentals #MHA2017
PDF
07-IM-REST-json.pdf slide for restapi explaination
PPTX
Soap UI and postman
PDF
There is REST and then there is "REST"
ODP
Attacking REST API
PPTX
API Testing Using REST Assured with TestNG
PPTX
Best Practices for Architecting a Pragmatic Web API.
PPT
Postman.ppt
PDF
API Testing. Streamline your testing process.
PPTX
Rest WebAPI with OData
ODP
PPTX
Api crash
PPTX
Api crash
PPTX
Api crash
Api fundamentals
Automating Cloud Operations - Everything you wanted to know about cURL and RE...
Api_testing.pdf
Api Testing
Api Testing
Api FUNdamentals #MHA2017
07-IM-REST-json.pdf slide for restapi explaination
Soap UI and postman
There is REST and then there is "REST"
Attacking REST API
API Testing Using REST Assured with TestNG
Best Practices for Architecting a Pragmatic Web API.
Postman.ppt
API Testing. Streamline your testing process.
Rest WebAPI with OData
Api crash
Api crash
Api crash

Recently uploaded (20)

PDF
Addressing The Cult of Project Management Tools-Why Disconnected Work is Hold...
PPTX
ManageIQ - Sprint 268 Review - Slide Deck
PPTX
Transform Your Business with a Software ERP System
PDF
Internet Downloader Manager (IDM) Crack 6.42 Build 42 Updates Latest 2025
PDF
System and Network Administration Chapter 2
PDF
top salesforce developer skills in 2025.pdf
PDF
Raksha Bandhan Grocery Pricing Trends in India 2025.pdf
PDF
Design an Analysis of Algorithms I-SECS-1021-03
PPTX
CHAPTER 2 - PM Management and IT Context
PPTX
Online Work Permit System for Fast Permit Processing
PDF
SAP S4 Hana Brochure 3 (PTS SYSTEMS AND SOLUTIONS)
PDF
Digital Strategies for Manufacturing Companies
PPTX
Agentic AI : A Practical Guide. Undersating, Implementing and Scaling Autono...
PDF
How to Choose the Right IT Partner for Your Business in Malaysia
PDF
Adobe Illustrator 28.6 Crack My Vision of Vector Design
PDF
Odoo Companies in India – Driving Business Transformation.pdf
PDF
Claude Code: Everyone is a 10x Developer - A Comprehensive AI-Powered CLI Tool
PDF
How to Migrate SBCGlobal Email to Yahoo Easily
PDF
Softaken Excel to vCard Converter Software.pdf
PPTX
Lecture 3: Operating Systems Introduction to Computer Hardware Systems
Addressing The Cult of Project Management Tools-Why Disconnected Work is Hold...
ManageIQ - Sprint 268 Review - Slide Deck
Transform Your Business with a Software ERP System
Internet Downloader Manager (IDM) Crack 6.42 Build 42 Updates Latest 2025
System and Network Administration Chapter 2
top salesforce developer skills in 2025.pdf
Raksha Bandhan Grocery Pricing Trends in India 2025.pdf
Design an Analysis of Algorithms I-SECS-1021-03
CHAPTER 2 - PM Management and IT Context
Online Work Permit System for Fast Permit Processing
SAP S4 Hana Brochure 3 (PTS SYSTEMS AND SOLUTIONS)
Digital Strategies for Manufacturing Companies
Agentic AI : A Practical Guide. Undersating, Implementing and Scaling Autono...
How to Choose the Right IT Partner for Your Business in Malaysia
Adobe Illustrator 28.6 Crack My Vision of Vector Design
Odoo Companies in India – Driving Business Transformation.pdf
Claude Code: Everyone is a 10x Developer - A Comprehensive AI-Powered CLI Tool
How to Migrate SBCGlobal Email to Yahoo Easily
Softaken Excel to vCard Converter Software.pdf
Lecture 3: Operating Systems Introduction to Computer Hardware Systems

An introduction to the API for OnTime for IBM

  • 1. ONTIME | Group Calendar AN INTRODUCTION TO THE ONTIME API
  • 2. Agenda (part 1) • Introduction • Demos – seeing is believing • Core Concepts • API Explorer • OnTime Frameworks • How we did the demos – code walk-thru
  • 3. Agenda (part 2) • Advanced Topics (character encoding, logging, batching commands, etc.) • Access Examples (JavaScript, Java, LotusScript) • Native IBM Notes (NRPC) Access • Reference Material
  • 5. Target Audience • OnTime Group Calendar – Customers – Partners • Developers • Solution Architects
  • 6. Many User Interfaces 1. Notes 2. Browser 3. Mobile 4. Sidebar 5. Social 6. Room Signs
  • 7. 1 API • This is an API created and maintained by OnTime – not by IBM • Everything we do in the user interfaces you can do with the API as well – there are no secret calls • New user interface features adds new capabilities to the API e.g. when we added Out of Office functionality it became available to API customers
  • 8. Requirements • OnTime Group Calendar installed and configured • Open API License – purchased separately – price based on total license price • Application ID – issued by OnTime on request – All installations come with a special Application ID called ”ApiExplorer” – don’t use for production as it’s throttled • Access by a user in OnTime
  • 9. Skills Required • JSON (JavaScript Object Notation) • IBM Notes/Domino API for LotusScript / Java access via NRPC • Virtually any other programming language for access via HTTP(S)
  • 10. What can you do with it? • Custom user interfaces • Custom reports and analysis • Integration – CRM systems – Phone systems – Booking systems
  • 12. Demos • JavaScript and Java – Create appointment – Read calendar entries – Free time search – Out of Office • XPages – Use Java framework to build application
  • 14. Endpoints • An endpoint is the ”address” you make API requests against • OnTime supports two types of endpoints – HTTP using URL’s – NRPC using an agent • This presentation will focus on using HTTP (there are slides on NRPC near the end)
  • 15. HTTP Endpoint in Detail • HTTP uses two endpoints – one for getting an Access Token and one for data • An Access Token is required for all API data access • The API endpoints are in the Client database 1. Token – /ontime/ontimegcclient.nsf/apihttptoken 2. Data – /ontime/ontimegcclient.nsf/apihttp • If using the servlet (offers caching and much higher performance) for API access 1. Data (servlet) – /servlet/ontimegc
  • 16. Access Token (”token”) • All requests to the token endpoint requires you to be authenticated to IBM Domino (basic, form, certificate) • All requests to the API endpoint requires a token obtained from the Token endpoint • A token may be used without the user being authenticated to IBM Domino • A token may be cached – expiration set in configuration (Server Settings/OnTime Token Timeout) • From API version 5 the token is fully cluster and load balancer compliant Please note: New token returned with each request – doesn’t expire the old one though – ”timeout” is in effect an Idle Timeout
  • 17. JSON (1) • Industry standard – http://www.json.org • Some languages like JavaScript has native support for JSON • Some languages like Java and LotusScript require a separate parser to consumer and writer to produce JSON Bonus: We supply a JSON parser and writer for LotusScript that you may use with the OnTime API
  • 18. JSON (2) { ”name”: ”Chris Holmes”, ”age”: 34, ”male”: true, ”emails”: [”ch@ontime.com”, ”chris.holmes@ontime.com”], ”address”: { ”street”: ”101 Main Street”, ”zipcode”: ”23821”, ”city”: ”Cleveland” ”country”: ”USA” } } Please note: Keys are in quotes
  • 19. JSON (3) { ”product”: ”OnTimeu00ae Group Calendar”, ”userInterfaces”: [ {”name”: ”Notes”, ”language”: ”Java”}, {”name”: ”Browser”, ”langauge”: ”JavaScript”}, {”name”: ”Mobile”, ”language”: ”JavaScript”}, {”name”: ”Social”, ”language”: ”JavaScript”}, {”name”: ”Sidebar”, ”language”: ”Java”} ] } Please note: Keys are case sensitive Please note: Non-ASCII characters should be Unicode encoded – very important when using the agent based API (HTTP only)
  • 20. Operations • An operation is a ”command” you send the API to let it know what you would like to do • Currently 40+ different operations • Examples – Login (current user information) – Version (retrieve version information) – UsersAll (retrieve users) – Calendar (retrieve calendar entries) – AppointmentCreate (create a calendar entry) – OutOfOfficeGet (retrieve out of office information)
  • 21. Application ID and Version • All requests must contain an Application ID (ApplID) in the Main section – The Application ID is verified against your OnTime Group Calendar license key • All requests must contain an Application Version (ApplVer) in the Main section – The Application Version may be any string
  • 22. API Versioning • To be backwards compatible the API is versioned – From v. 4.4 we will be at APIVer=6 • API versioning allows us to continueously update the API and add new features without breaking custom applications • API version is specified using ”APIVer” key in the Main section • You must specify an API version for each request
  • 23. Basic Request Format • Each request must contain a payload describing the request • The payload always has a Main section with APIVer, ApplID, ApplVer and a Token { ”Main”: {”APIVer”: 6, ”ApplID”: ”ApiExplorer”, ”ApplVer”: ”0.0.1”, ”Token”: ”<access token>” }, ”Command1”: {<command specific data>} }
  • 24. Basic Response Format • The response always contains an overall status code, the server API version, a new token and a response object per command sent { ”APIVersion”: ”4.2.0”, ”Command1”: {...}, ”Token”: ”1234567890abcdefghijk==”, ”Status”: ”OK” }
  • 25. Example – obtaining a token POST >> apihttptoken Authorization: Basic ZGVtbzpkZW1v {”Main”: {”APIVer”: 6, ”ApplID”: ”ApiExplorer”, ”ApplVer”: ”0.0.1” }} {”APIVersion”: ”4.2.0”, ”APIBuild”: 650, ”Token”: ”abc111==”, ”Status”: ”OK” }
  • 26. Example –the Login operation POST >> apihttp {”Main”: {”APIVer”: 6, ”ApplID”: ”ApiExplorer”, ”ApplVer”: ”0.0.1”, ”Token”, ”abc111==” }, ”Login”: {}} {”APIVersion”: ”4.2.0”, ”Login”: { ”Global”: {...}, ”User”: {”ID”: ”X”, ”Name”: ”Chris Holmes/OnTime”, ”Email”: ”chris.holmes@ontime.com”, ”MailSource”: ”Domino” } }, ”Token”: ”abc222==”, ”Status”: ”OK” }
  • 27. Handling Errors • If an error occurs it is sent back to the caller • The error contains an error code and a description • It is a best practice to always verify that ”Status” is ”OK” {APIVersion: "4.2.0”, Status: "Error”, ErrorCode: "NotValidApplID”, Error: "Not a valid Application ID" } {APIVersion: "4.2.0”, Status: "Error”, ErrorCode: "TokenTimeout”, Error: "Token Timeout" }
  • 29. Dates • All dates should be encoded as strings in ISO8601 format using the UTC timezone – {YYYY}-{MM}-{dd}T{HH}:{mm}:{ss}Z • UTC doesn’t adjust for daylight savings time • OnTime provided frameworks handle time zone conversion automatically • Please note: Using UTC may be confusing at first as a the date/time may be ”tomorrow” or ”yesterday”
  • 30. Dates • 2015-12-31T13:15:00Z – 2.15pm, 31 December 2015 in Denmark (UTC+1, winter time) – 10.15pm, 31 December 2015 in Japan (UTC+9) • 2015-06-23T22:00:00Z – Midnight, 24 June 2015 in Denmark (UTC+2, summer time) – 7am, 24 June 2015 in Japan (UTC+9) • 2015-06-30T15:00:00Z – 8am, 30 June 2015 in California, (UTC-7) – Midnight, 1 July 2015 in Japan (UTC+9)
  • 32. Getting the API Explorer • You already have it – it is in the Clients database – http://<hostname>/<ontime client db>/apiexplorer – https://demo.ontimesuite.com/ontime/ontimegcclient.nsf/apiexplor er (same as https://demo.ontimesuite.com/apiexplorer) • It’s the tool we use when we develop for OnTime • Preconfigured with ApiExplorer Application ID for testing
  • 33. Demo – API Explorer • Show API Explorer • Log in, obtain token and do requests • Show how the API Explorer lets you inspect requests and responses • Log out and continue to do requests • Show built in examples
  • 35. Current Stack OnTime Core Server OnTime API (”low level” JSON based API) Notes JavaJavaScript Team-At- A-Glance MobileWeb Custom App RoomSigns Socia l Social
  • 36. Coming Stack OnTime Core Server OnTime API (”low level” JSON based API) CustomApp Java FrameworkJavaScript Framework (ivcore.js) Team-At- A-Glance Mobile (new) Web Custom App Custom App Room Signs Notes SocialSocial Mobile(iOS)
  • 37. The Goal • Do not reinvent the wheel – calendaring and timezones are hard to get right so use our code • Time proven code – the framework code is what’s in the products – it’s not something we make just for customers • The frameworks handle authentication, tokens, network transport and often dealing with the underlying data
  • 38. HOW WE DID THE DEMOS
  • 39. JavaScript Examples • Create appointment • Read calendar entries • Free time search • Out of Office
  • 40. Create Appointment, JavaScript // create appointment ivcore.api.AppointmentCreate({ "UserID": this.userID, "Subject": this.getFormFieldValue("subject"), "Location": this.getFormFieldValue("location"), "StartDT": this.getFormFieldValue("start"), "EndDT": this.getFormFieldValue("end") }); ivcore.api.process(function(json) { if (json.Status === ”OK”) { ... } }.bind(this));
  • 41. Read Calendar Entries, JavaScript // read calendar entries ivcore.api.Calendars({ "FromDT": start, "ToDT": end, "IDs": [this.userID] }); ivcore.api.process(function(json) { // get calendar entries and sort using wrapper class var calitems = new iv.ontimegc.CalItemArr(json.Calendars.IDs[0].Items); calitems.sort(); ... }.bind(this));
  • 42. Free Time Search, JavaScript // perform freetime search ivcore.api.FreeTimeSearch({ "FromDT": from, "ToDT": to, "IDs": this.searchIDs, "Duration": 360 }); ivcore.api.process(function(json) { ... }.bind(this));
  • 43. Out Of Office, JavaScript // request OOO for a user ivcore.api.OutOfOfficeGet({ "UserID": this.userID }); ivcore.api.process(function(json) { if (json.Status === ”OK”) { // read OOO info and use wrapper class for date/time formatting var ooo = json.OutOfOfficeGet; var dateBack = ooo.DateTimeBack.ivToDate(); var strBack = ivcore.langreg.region("<dd MMM, HH:NN>", dateBack); ... } }.bind(this));
  • 44. Java Examples • Create appointment • Read calendar entries • Free time search • Out of Office
  • 45. Create Appointment, Java (1) // create facade with default values (and configure, omitted for brevity) IGroupCalendarAPIFacade facade = new GroupCalendarAPIFacade(); // create appointment CalEntryResponse response = facade.createAppointment(null, 120, "Test Appointment", "OnTime Example Code"); if (response.isSuccess()) { System.out.println("Created appointment”); }
  • 46. Create Appointment, Java (2) // create facade with default values (and configure, omitted for brevity) IGroupCalendarAPIFacade facade = new GroupCalendarAPIFacade(); // create calendar and get dates using utility classes Calendar cal = facade.createJavaCalendar(); CalendarUtil.setTime(cal, 13, 0); Date start = cal.getTime(); CalendarUtil.setTime(cal, 14, 0); Date end = cal.getTime(); // create appointment CalEntryResponse response = facade.createAppointment(start, end, "Test Appointment", "OnTime Example Code"); if (response.isSuccess()) { System.out.println("Created appointment”); }
  • 47. Read Calendar Entries, Java // create facade with default values (and configure, omitted for brevity) IGroupCalendarAPIFacade facade = new GroupCalendarAPIFacade(); // create date/time range (date construction omitted for brevity) DateTimeRange range = new DateTimeRange(start, end); // fetch appointments facade.fetchAppointments(false, range); // get appointments IAppointment[] apps = facade.getActAsCalendar().getAppointments(); // show result for (IAppointment app : apps) { System.out.println(app.getDateTimeRange() + " - " + app.getSubject()); }
  • 48. Free Time Search, Java // create facade with default values (and configure, omitted for brevity) IGroupCalendarAPIFacade facade = new GroupCalendarAPIFacade(); // create dates (date construction omitted for brevity) Date from = ... Date to = ... // get calendars Date[] results = facade.searchFreeTime(60, from, to, ID_TYPE.EMAIL, "chris.holmes@ontime.com", "amanda.jones@ontime.com"); for (int i=0, count=ArrayUtil.count(results); i<count; ) { Date d1 = results[i++]; Date d2 = results[i++]; System.out.println(d1 + " --> " + d2); }
  • 49. Out of Office, Java // create facade with default values (and configure, omitted for brevity) IGroupCalendarAPIFacade facade = new GroupCalendarAPIFacade(); // actually fetch OOO OutOfOfficeResult ooo = facade.fetchOutOfOffice(); // show result System.out.println("Out of office for <" + facade.getActAsUser().getDispName() + ”> of is <" + (ooo.isEnabled() ? "ENABLED" : "DISABLED") + ">"); System.out.println(ooo.getDateOut()); System.out.println(ooo.getGeneralSubject()); System.out.println(ooo.getGeneralBody());
  • 50. XPages Example • Let us do a code walk-thru in Domino Designer • Techniques used – Jar design elements w/ OnTime Java Framework – Data tables to loop data – AppointmentFilter for easy filtering and sorting
  • 52. Character Encoding • It is a best practice to always encode non-ASCII charcters using the Unicode character code using uXXXX – ® == u00ae – 東 == u6771 – 京 == u4EAC • Failure to do so may result in character encoding issues • OnTime provided frameworks handle character encoding automatically
  • 53. Character Encoding {"Main" : { "APIVer": 5, "ApplID": "ApiExplorer", "ApplVer": "0.0.1" }, "AppointmentCreate": { "AppointmentType": "0", "UserID": "7", "StartDT": "2015-05-18T07:00:00Z", "EndDT": "2015-05-18T10:00:00Z", "Subject": "OnTime API ワークショップ", "Location": "新宿区, 東京" }
  • 54. Character Encoding {"Main" : { "APIVer": 5, "ApplID": "ApiExplorer", "ApplVer": "0.0.1" }, "AppointmentCreate": { "AppointmentType": "0", "UserID": "7", "StartDT": "2015-05-18T07:00:00Z", "EndDT": "2015-05-18T10:00:00Z", "Subject": "OnTime API u30EFu30FCu30AFu30B7u30E7u30C3u30D7", "Location": "u65B0u5BBFu533A, u6771u4EAC" }
  • 55. More on Tokens • As mentioned previously a token may be cached on the client • When caching please be aware of token expiration – expiration time is set on the server – defaults to 24 hours • A token may be revoked on the server by forcing a new web logon (see screeenshot, means setting a new ”token ID” for the user) • Token related error codes – NoToken – NoUserWithToken – TokenTimeout – WrongTokenID – InvalidTokenTimeType – TokenDecryptError – WrongTokenSign
  • 56. API Log (1) The API log is an excellent debugging tool as it shows exactly what the API received and what it returned
  • 57. API Log (2) • Starting with v. 4.0 – API logging is no longer only controllable on the OnTime server document but from code and on a per user basis • There are 3 ways to have API traffic logged for a user • Please note: Never leave API logging turned on in production as it may affect performance.
  • 58. API Log (3) 1. The Main section contains ”APILog” = true Controlled by application code and enabled logging only for the specific calls {"Main": {"APIVer": 6, "ApplVer": "0.0.1", "ApplID": "ApiExplorer", "Token": ”aaa111==", "APILog": true}, "Login": {}}
  • 59. API Log (4) 2. Enable user debug – enables logging for all calls until turned of. Benefit is that it’s done on the server (no app changes). Setting actually does two things: – Enables extended logging for the user (sync. logging) – Enables API logging
  • 60. API Log (5) 3. OnTime UI specific option (actually toggles on APILog=true) – Web UI by appending &debug=true – Eclipse UI’s through menu actions
  • 61. OnBehalfOf • All operations are performed as the current user (as represented by the token / signer) • For some applications you may need to act as someone else – we call this OnBehalfOf • Access to use OnBehalfOf is explicitly granted on a per user basis in Server Settings (set on all servers)
  • 62. OnBehalfOf – Login as user self Request {"Main": {"APIVer": 6, "ApplVer": "0.0.1", "ApplID": ”ApiExplorer", "Token": "aaa111=="}, "Login": {}} (Logged in as Chris Holmes/OnTime) Response {"APIVersion":"4.1.4","APIBuild":655,"Logi n":{"Global":{"PreSort":false,"SyncBack":2 1,"PhotoEnabled":true},"User":{"ID":"7","N ame":”Chris Holmes/OnTime","Email":”chris.holmes@ ontime.com","MailSource":"Domino"},"Sect ionProcessTime":16},"Token":”aaa222=="," Status":"OK"}
  • 63. OnBehalfOf – Login w/ OnBehalfOf Request {"Main": {"APIVer": 6, "ApplVer": "0.0.1", "ApplID": ”ApiExplorer", "Token": "aaa222==", ”OnBehalfOf": ”Amanda Jones/OnTime"}, "Login": {}} (Logged in as Chris Holmes/OnTime and he’s allowed to do OnBehalfOf requests) Response {"APIVersion":"4.1.4","APIBuild":655,"Logi n":{"Global":{"PreSort":false,"SyncBack":2 1,"PhotoEnabled":true},"User":{"ID":"1","N ame":”Amanda Jones/OnTime","Email":”aj@ontime.com", "MailSource":"Domino"},"SectionProcessTi me":0},"Token":”aaa333==","Status":"OK"}
  • 64. OnBehalfOf – GetToken (1) Request {"Main": {"APIVer": 5, "ApplVer": "0.0.1", "ApplID": ”ApiExplorer", "Token": "aaa333==", ”OnBehalfOf": ”Amanda Jones/OnTime"}, ”GetToken": {}} Response {"APIVersion":"4.1.4","APIBuild":655,"GetT oken":{"Token":”bbb111==","User":”Am anda Jones/OnTime","ID":"1","CurrentTimeout" :168,"SectionProcessTime":0},"Token":”aa a444==","Status":"OK"} Excellent solution for performing Single-Sign-On with portals built on other technologies than IBM – issue a token to the user and save in a cookie…
  • 65. OnBehalfOf – GetToken (2) Request {"Main": {"APIVer": 5, "ApplVer": "0.0.1", "ApplID": ”ApiExplorer", "Token": ”bbb111==”}, ”Login": {}} Response {"APIVersion":"4.1.4","APIBuild":655,"Logi n":{"Global":{"PreSort":false,"SyncBack":2 1,"PhotoEnabled":true},"User":{"ID":"1","N ame":”Amanda Jones/OnTime","Email":”aj@ontime.com", "MailSource":"Domino"},"SectionProcessTi me":0},"Token":”bbb222==","Status":"OK"} Now just using token obtained on previous slide
  • 66. Batching commands (1) • Each request to the API may contain multiple commands – even multiple versions of the same command (e.g. multiple OutOfOfficeGet) • We call this ”batching commands” • Keys must be unique in JSON so the API only checks the beginning of the keys – OutOfOfficeGet == OutOfOfficeGet_MySuffix • Response uses the same keys as the request
  • 67. Batching commands (2) Request {"Main": { "APIVer": 5, "ApplVer": "0.0.1", "ApplID": "ApiExplorer", "Token": ”aaa111=="}, "Login_1": {}, "Login_XYZ": {} } Response {"APIVersion":"4.1.4","APIBuild":655, "Login_1":{"Global":{…},"User":{"ID":"7","Name" :”Chris Holmes/OnTime","Email":”chris.holmes@ontime. com","MailSource":"Domino"},"SectionProcessTi me":0}, "Login_XYZ":{"Global":{…},"User":{"ID":"7","Na me":”Chris Holmes/OnTime","Email":”chris.holmes@ontime. com,"MailSource":"Domino"}, "SectionProcessTime":0},"Token":”aaa222==","St atus":"OK"}
  • 68. Custom ID (1) • When doing multiple requests – even multiple requests at the same time – keeping track of them can be hard • To make it easier to discern the requests you may add a custom ID to each request • The custom ID is returned in the corresponding response • The custom ID may be any string value
  • 69. Custom ID (2) Request {"Main": { "APIVer": 5, "ApplVer": "0.0.1", "ApplID": "ApiExplorer", "Token": ”aaa111==", ”CustomID": ”MyCustomID”}, "Login": {} } Response {"APIVersion":"4.1.4","APIBuild":655, "CustomID": "MyCustomID", "Login":{"Global":{…},"User":{"ID":"7","Na me":”Chris Holmes/OnTime","Email":”chris.holmes@o ntime.com","MailSource":"Domino"},"Secti onProcessTime":0}, "Token":”aaa222==","Status":"OK"}
  • 72. Access w/ JavaScript (1) var apirequest = function(payload, callback) { var xmlhttp = new XMLHttpRequest(); xmlhttp.open("POST", ”/servlet/ontimegc", true); xmlhttp.onreadystatechange = function() { if (xmlhttp.readyState == 4) { if (xmlhttp.status == 200) { // handle response var result = JSON.parse(xmlhttp.responseText); if (callback) callback(result); } } } // post xmlhttp.send(JSON.stringify(payload)); }
  • 73. Access w/ JavaScript (2) // payload var payload = {"Main": {"APIVer": 6, "ApplID": "ApiExplorer", "ApplVer": "0.0.1", "Token": "aaa111=="}, "Login": {} }; // do request apirequest(payload, function(obj) { console.log(obj); });
  • 76. Access w/ Java (1) URL url = new URL(https://demo.ontimesuite.com/servlet/ontimegc"); HttpURLConnection con =(HttpURLConnection)url.openConnection(); con.setRequestMethod("POST"); con.addRequestProperty("Content-Type", "application/json"); con.addRequestProperty("Accept", "*/*"); con.setDoInput(true); // handle post con.setDoOutput(true); OutputStream out = con.getOutputStream(); BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out)); writer.write(request); writer.flush();
  • 77. Access w/ Java (2) // get response code and read response if code 200 (OK) if (200 != con.getResponseCode()) throw new Exception("Non OK"); BufferedReader reader = new BufferedReader( new InputStreamReader(con.getInputStream())); StringBuilder buffer = new StringBuilder(2048); String line = null; while (null != (line = reader.readLine())) { buffer.append(line).append('n'); } // disconnect and return result; con.disconnect(); return buffer.toString();
  • 78. USING NRPC Native IBM Notes API Access via Notes Remote Procedure Calls
  • 79. Endpoints in Detail (NRPC) • Starting with version 3.8 all API requests are made against a single database – the Client database1 • API requests are done by 1. Creating/updating a document in the Client database 2. Signing the document (NotesDocument.sign()) 3. Running an agent on the server with the document as context • The agent is called ApiNotes and can be found in the Client database 1 Prior to this version there were two possible API endpoint databases; 1) the API database and 2) the Web database
  • 80. Authentication • User access is verified using IBM Notes digital signatures • Ideal for LotusScript as HTTP access is troublesome • May be used with Java as well • Requires access to the IBM Notes/Domino backend API (Local or DIIOP) • Cluster and failover aware through the IBM Notes/Domino API • Please note: NRPC access doesn’t use OnTime Access Tokens
  • 81. Access w/ NRPC (1) Requests are done as follows: 1. Create/update an API document in the Client database 2. Set JSON request (same payload as with HTTP) 3. Set Authors field (ensure only user and server can read document) 4. Sign document 5. Run (ApiNotes) agent on document on the server 6. Refetch the API document 7. Read the JSON response
  • 82. Access w/ NRPC (2) Requests are done as follows: 1. Create/update an API document in the Client database 2. Set JSON request in a field called $Request_0 (if bigger than 32 kb continue in $Request_1 and so on…) 3. Set Authors field called _Authors to [ReadAll], <Server DN>, <User DN> 4. Sign document (NotesDocument.Sign()) 5. Run (ApiNotes) agent on document on the server (NotesAgent.RunOnServer(noteid)) 6. Refetch the API document by note ID 7. Read the JSON response from a field called $Response_0 (if bigger than 32 kb continue in $Response_1 and so on)
  • 83. Access w/ LotusScript (1) Function ProcessString(Request As String) As String Dim session As New NotesSession Dim dbApi As NotesDatabase Dim agentApi As NotesAgent Dim docApi As NotesDocument Dim noteid As String Dim item As NotesItem Dim values(0 To 2) As String values(0) = session.UserName values(1) = "[ReadAll]" values(2) = session.EffectiveUsername Set dbApi = session.GetDatabase("Server1/OnTime", "ontime/ontimegcclient.nsf") Set agentApi = dbApi.GetAgent("ApiNotes") Set docApi = New NotesDocument(dbApi) Call SetLongString(docApi, "$Request", Request) Set item = New NotesItem(docApi, "_Author", values) item.Isauthors = true item.Isreaders = true Call docApi.Sign() Call docApi.Save(True,False) noteid = doc.Noteid Delete docApi Call agentApi.Runonserver(noteid) Set docApi = dbApi.GetDocumentByNoteID(noteid) ProcessString = GetLongString(docApi, "$Response") Exit Function Declarations Access for API document Access Client database, API agent, create API document, sign and save Delete document reference, run agent on and refetch document Read response
  • 84. Character Encoding in LotusScript Private Function encode(s As String) As String Dim result As String Dim i As Integer Dim ch As String Dim u As Long For i = 1 To Len(s) ch = Mid(s,i,1) u = Uni(ch) Select Case u Case 34 : result = result & {"} Case 92 : result = result & {} Case 47 : result = result & {/} Case 8 : result = result & {b} Case 12 : result = result & {f} Case 10 : result = result & {n} Case 13 : result = result & {r} Case 9 : result = result & {t} Case Else If (u>=32) And (u<127) Then result = result & ch Else result = result & "u" & Right("0000" & Hex(u), 4) End If End Select Next encode = result End Function If (u>=32) And (u<127) Then r = r & ch Else u = Uni(ch) r = r & "u" & Right("0000" & Hex(u), 4) End If
  • 85. LotusScript Examples 1. Login (Does a login request to the server) 2. Version (requests the version information from the server) 3. Calendars, raw (requests 7 days worth of calendar information for the current user by DN) 4. Calendars, processed (same as 3 but parses the response using the JSON parser)
  • 87. Operations • Login • Logout • Version • UsersAll • UsersInfo • Calendars • AppointmentCreate • AppointmentChange • AppointmentRemove • AppointmentRead • AppointmentInviteeStatus • AppointmentRepeatDates • CustomFieldsList • FreeResources • FreeRooms • FreeTimeSearch • GetToken • GroupList • GroupPrivateChange • GroupPrivateRemove • GroupUserIDs • LanguageList • LanguageText • Legends • LegendsSets • LegendsSetsList • MailSend • NameFormat • NoticeAccept • NoticeDecline • NoticeUpdate • Notices • OutOfOfficeGet • OutOfOfficeSet • RegionList • RegionText • SettingsGet • SettingsSet • UserBusyInfo • UsersAccess • UsersPhoto • UsersSearch
  • 88. Links • OnTime Group Calendar demo environment https://demo.ontimesuite.com • OnTime Group Calendar demo API Explorer https://demo.ontimesuite.com/apiexplorer (login with username ”demo” and password ”demo”)
  • 89. Main object keys Key name Description Required ApplID Application ID – issued by OnTime support on request. ApplVer Application version – can be any string APIVer API version to use. Currently it should be 5. From v. 4.4 it should be 6. Token The token to identify the user if using HTTP CustomID Custom string to discern multiple concurrent requests APILog Should the API request be logged on the server
  • 90. OnTime Group Calendar databases • Configuration database – Default location: /ontime/ontimegc.nsf • Log database – Default location: /ontime/ontimegclog.nsf • Client database – Default location: /ontime/ontimegcclient.nsf • Broadcast database – Default location: /ontime/ontimegcbroadcast.nsf