Microsoft Graph の getSchedule

Microsoft Graph の getSchedule は、空き時間情報を取得する API です。Outlook のスケジュール アシスタントのように、他人の予定の詳細ではなく空いているかどうかを取得します。基本的なことは Get free/busy schedule of users and resourcescalendar: getSchedule を参照してください。

空き時間情報にも何段階かあります。どこまでの情報が取得できるのかは、参照先ユーザーの予定表に対してどこまでの権限を持っているのかによって異なります。いくつかのパターンで見ていきましょう。

まずはテスト用にメールボックスを 6 個作ります。User01 はそれぞれ以下のようにアクセス権を持っています。

ユーザー予定表に対して User01 が持っている権限
User01(本人)
User02なし
User03空き時間情報のみ
User04空き時間・件名・場所
User05参照者
User06代理人 + 非公開の予定

PowerShell では以下の状態です。

PS C:\> Get-MailboxFolderPermission User02:\予定表 | ft -AutoSize                                                       
FolderName User AccessRights SharingPermissionFlags
---------- ---- ------------ ----------------------
予定表     既定 {None}
予定表     匿名 {None}


PS C:\> Get-MailboxFolderPermission User03:\予定表 | ft -AutoSize                                                       
FolderName User AccessRights       SharingPermissionFlags
---------- ---- ------------       ----------------------
予定表     既定 {AvailabilityOnly}
予定表     匿名 {None}


PS C:\> Get-MailboxFolderPermission User04:\予定表 | ft -AutoSize                                                       
FolderName User   AccessRights       SharingPermissionFlags
---------- ----   ------------       ----------------------
予定表     既定   {AvailabilityOnly}
予定表     匿名   {None}
予定表     User01 {LimitedDetails}


PS C:\> Get-MailboxFolderPermission User05:\予定表 | ft -AutoSize                                                       
FolderName User   AccessRights       SharingPermissionFlags
---------- ----   ------------       ----------------------
予定表     既定   {AvailabilityOnly}
予定表     匿名   {None}
予定表     User01 {Reviewer}


PS C:\> Get-MailboxFolderPermission User06:\予定表 | ft -AutoSize                                                       
FolderName User   AccessRights       SharingPermissionFlags
---------- ----   ------------       ----------------------
予定表     既定   {AvailabilityOnly}
予定表     匿名   {None}
予定表     User01 {Editor}           Delegate, CanViewPrivateItems

各ユーザーには以下のように予定が入っています。

時間 (日本時間)内容
2019/08/26 09:00 – 09:30User01 の通常の予定
2019/08/26 09:30 – 10:00User01 の非公開の予定
2019/08/27 09:00 – 09:30User02 の通常の予定
2019/08/27 09:30 – 10:00User02 の非公開の予定
2019/08/28 09:00 – 09:30User03 の通常の予定
2019/08/28 09:30 – 10:00User03 の非公開の予定
2019/08/29 09:00 – 09:30User04 の通常の予定
2019/08/29 09:30 – 10:00User04 の非公開の予定
2019/08/30 09:00- 09:30User05 の通常の予定
2019/08/30 09:30 – 10:00User05 の非公開の予定
2019/09/02 09:00 – 09:30User06 の通常の予定
2019/09/02 09:30 – 10:00User06 の非公開の予定

各ユーザーの空き時間情報を getSchedule で取得してみます。予定表に対する権限の違いを見たいので、今回は User01 の Delegate のアクセス トークンを使います。基本的な Microsoft Graph の試し方が分からない方は Microsoft Graph の試し方 の「[委任されたアクセス許可] を Office365APIEditor で試す (ビルトイン編)」を参照してください。以下のリクエストを送信します。

POST https://graph.microsoft.com/v1.0/me/calendar/getSchedule
Prefer : outlook.timezone="Tokyo Standard Time"

{
  "schedules": [
    "User01@contoso.com",
    "User02@contoso.com",
    "User03@contoso.com",
    "User04@contoso.com",
    "User05@contoso.com",
    "User06@contoso.com"],
  "startTime": {
    "dateTime": "2019-08-26T09:00:00",
    "timeZone": "Tokyo Standard Time"
  },
  "endTime": {
    "dateTime": "2019-09-02T18:00:00",
    "timeZone": "Tokyo Standard Time"
  },
  "availabilityViewInterval": 30
}

すると以下のようなレスポンスを得られます。

{
  "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#Collection(microsoft.graph.scheduleInformation)",
  "value": [
    {
      "scheduleId": "User01@contoso.com",
      "availabilityView": "220000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
      "scheduleItems": [
        {
          "isPrivate": false,
          "status": "busy",
          "subject": "User01 Normal",
          "location": "Harry's Bar",
          "start": {
            "dateTime": "2019-08-26T09:00:00",
            "timeZone": "Tokyo Standard Time"
          },
          "end": {
            "dateTime": "2019-08-26T09:30:00",
            "timeZone": "Tokyo Standard Time"
          }
        },
        {
          "isPrivate": true,
          "status": "busy",
          "subject": "User01 Private",
          "location": "Harry's Bar",
          "start": {
            "dateTime": "2019-08-26T09:30:00",
            "timeZone": "Tokyo Standard Time"
          },
          "end": {
            "dateTime": "2019-08-26T10:00:00",
            "timeZone": "Tokyo Standard Time"
          }
        }
      ],
      "workingHours": {
        "daysOfWeek": [
          "monday",
          "tuesday",
          "wednesday",
          "thursday",
          "friday"
        ],
        "startTime": "08:00:00.0000000",
        "endTime": "17:00:00.0000000",
        "timeZone": {
          "name": "Tokyo Standard Time"
        }
      }
    },
    {
      "scheduleId": "User02@contoso.com",
      "error": {
        "message": "Microsoft.Exchange.InfoWorker.Common.Availability.NoFreeBusyAccessException: The caller does not have access to free/busy data.\r\n. Name of the server where exception originated: TY1PR01MB1692. LID: 44348",
        "responseCode": "ErrorNoFreeBusyAccess"
      }
    },
    {
      "scheduleId": "User03@rykoma.net",
      "availabilityView": "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000220000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
      "scheduleItems": [
        {
          "status": "busy",
          "start": {
            "dateTime": "2019-08-28T09:00:00",
            "timeZone": "Tokyo Standard Time"
          },
          "end": {
            "dateTime": "2019-08-28T09:30:00",
            "timeZone": "Tokyo Standard Time"
          }
        },
        {
          "status": "busy",
          "start": {
            "dateTime": "2019-08-28T09:30:00",
            "timeZone": "Tokyo Standard Time"
          },
          "end": {
            "dateTime": "2019-08-28T10:00:00",
            "timeZone": "Tokyo Standard Time"
          }
        }
      ],
      "workingHours": {
        "daysOfWeek": [
          "monday",
          "tuesday",
          "wednesday",
          "thursday",
          "friday"
        ],
        "startTime": "08:00:00.0000000",
        "endTime": "17:00:00.0000000",
        "timeZone": {
          "@odata.type": "#microsoft.graph.customTimeZone",
          "bias": -540,
          "name": "Customized Time Zone",
          "standardOffset": {
            "time": "00:00:00.0000000",
            "dayOccurrence": 0,
            "dayOfWeek": "sunday",
            "month": 0,
            "year": 0
          },
          "daylightOffset": {
            "daylightBias": 0,
            "time": "00:00:00.0000000",
            "dayOccurrence": 0,
            "dayOfWeek": "sunday",
            "month": 0,
            "year": 0
          }
        }
      }
    },
    {
      "scheduleId": "User04@contoso.com",
      "availabilityView": "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000220000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
      "scheduleItems": [
        {
          "isPrivate": false,
          "status": "busy",
          "subject": "User04 Normal",
          "location": "Harry's Bar",
          "start": {
            "dateTime": "2019-08-29T09:00:00",
            "timeZone": "Tokyo Standard Time"
          },
          "end": {
            "dateTime": "2019-08-29T09:30:00",
            "timeZone": "Tokyo Standard Time"
          }
        },
        {
          "isPrivate": true,
          "status": "busy",
          "subject": "Private Appointment",
          "location": "",
          "start": {
            "dateTime": "2019-08-29T09:30:00",
            "timeZone": "Tokyo Standard Time"
          },
          "end": {
            "dateTime": "2019-08-29T10:00:00",
            "timeZone": "Tokyo Standard Time"
          }
        }
      ],
      "workingHours": {
        "daysOfWeek": [
          "monday",
          "tuesday",
          "wednesday",
          "thursday",
          "friday"
        ],
        "startTime": "08:00:00.0000000",
        "endTime": "17:00:00.0000000",
        "timeZone": {
          "@odata.type": "#microsoft.graph.customTimeZone",
          "bias": -540,
          "name": "Customized Time Zone",
          "standardOffset": {
            "time": "00:00:00.0000000",
            "dayOccurrence": 0,
            "dayOfWeek": "sunday",
            "month": 0,
            "year": 0
          },
          "daylightOffset": {
            "daylightBias": 0,
            "time": "00:00:00.0000000",
            "dayOccurrence": 0,
            "dayOfWeek": "sunday",
            "month": 0,
            "year": 0
          }
        }
      }
    },
    {
      "scheduleId": "User05@contoso.com",
      "availabilityView": "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000220000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
      "scheduleItems": [
        {
          "isPrivate": false,
          "status": "busy",
          "subject": "User05 Normal",
          "location": "Harry's Bar",
          "start": {
            "dateTime": "2019-08-30T09:00:00",
            "timeZone": "Tokyo Standard Time"
          },
          "end": {
            "dateTime": "2019-08-30T09:30:00",
            "timeZone": "Tokyo Standard Time"
          }
        },
        {
          "isPrivate": true,
          "status": "busy",
          "subject": "Private Appointment",
          "location": "",
          "start": {
            "dateTime": "2019-08-30T09:30:00",
            "timeZone": "Tokyo Standard Time"
          },
          "end": {
            "dateTime": "2019-08-30T10:00:00",
            "timeZone": "Tokyo Standard Time"
          }
        }
      ],
      "workingHours": {
        "daysOfWeek": [
          "monday",
          "tuesday",
          "wednesday",
          "thursday",
          "friday"
        ],
        "startTime": "08:00:00.0000000",
        "endTime": "17:00:00.0000000",
        "timeZone": {
          "@odata.type": "#microsoft.graph.customTimeZone",
          "bias": -540,
          "name": "Customized Time Zone",
          "standardOffset": {
            "time": "00:00:00.0000000",
            "dayOccurrence": 0,
            "dayOfWeek": "sunday",
            "month": 0,
            "year": 0
          },
          "daylightOffset": {
            "daylightBias": 0,
            "time": "00:00:00.0000000",
            "dayOccurrence": 0,
            "dayOfWeek": "sunday",
            "month": 0,
            "year": 0
          }
        }
      }
    },
    {
      "scheduleId": "User06@contoso.com",
      "availabilityView": "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000220000000000000000",
      "scheduleItems": [
        {
          "isPrivate": false,
          "status": "busy",
          "subject": "User06 Normal",
          "location": "Harry's Bar",
          "start": {
            "dateTime": "2019-09-02T09:00:00",
            "timeZone": "Tokyo Standard Time"
          },
          "end": {
            "dateTime": "2019-09-02T09:30:00",
            "timeZone": "Tokyo Standard Time"
          }
        },
        {
          "isPrivate": true,
          "status": "busy",
          "subject": "Private Appointment",
          "location": "",
          "start": {
            "dateTime": "2019-09-02T09:30:00",
            "timeZone": "Tokyo Standard Time"
          },
          "end": {
            "dateTime": "2019-09-02T10:00:00",
            "timeZone": "Tokyo Standard Time"
          }
        }
      ],
      "workingHours": {
        "daysOfWeek": [
          "monday",
          "tuesday",
          "wednesday",
          "thursday",
          "friday"
        ],
        "startTime": "08:00:00.0000000",
        "endTime": "17:00:00.0000000",
        "timeZone": {
          "@odata.type": "#microsoft.graph.customTimeZone",
          "bias": -540,
          "name": "Customized Time Zone",
          "standardOffset": {
            "time": "00:00:00.0000000",
            "dayOccurrence": 0,
            "dayOfWeek": "sunday",
            "month": 0,
            "year": 0
          },
          "daylightOffset": {
            "daylightBias": 0,
            "time": "00:00:00.0000000",
            "dayOccurrence": 0,
            "dayOfWeek": "sunday",
            "month": 0,
            "year": 0
          }
        }
      }
    }
  ]
}

この通り、基本的には権限通りに空き時間情報が取得できることが分かります。また、非公開の予定を参照する権限は getSchedule による空き時間情報の取得では効かないことも分かります。