读取个人日历的基本事件
用 Calendars.ReadBasic 委托权限读取日历事件标题与起止时间,掌握 UTC、翻页及周期事件的含义。
← 返回平台功能接入准备
- 用户具有可访问的 Outlook 日历;应用申请委托权限 Calendars.ReadBasic 并取得用户同意。
- 本例只读取事件基本字段,不请求正文、附件或写入权限;不使用应用身份。
准备环境变量
示例值需要替换为自己的凭证或资源 ID。代码在本机或服务端运行;密钥不应放进公开网页。
MS_GRAPH_ACCESS_TOKEN- 用户登录并同意本场景 Microsoft Graph 委托权限后取得的 access token;不是 ID token,也不是客户端凭证模式 token。
export MS_GRAPH_ACCESS_TOKEN='replace_with_delegated_graph_access_token'以上 export 适用于 macOS / Linux 的终端。按调用步骤保存代码文件,再在同一终端执行。
调用步骤
- 01
进入 Microsoft Entra 管理中心 → App registrations,创建应用并选择自己需要的账号类型;配置与客户端匹配的 Redirect URI。
- 02
在 API permissions → Microsoft Graph → Delegated permissions 添加本场景权限;组织要求时请管理员同意。通过授权码流程让用户登录并同意,取得 Microsoft Graph access token。
- 03
把 access token 设置为 MS_GRAPH_ACCESS_TOKEN,在本机或服务器运行示例;令牌过期后用自己的授权流程刷新或重新登录。
- 04
确认 access token 已包含 Calendars.ReadBasic;获取列表后按 @odata.nextLink 的完整 URL 翻页,不自行重组 skiptoken。
- 05
如需指定时间窗内每一次周期会议,另外使用 calendarView;本页 events 列表的周期主项不能直接当作所有发生次数。
取得默认日历事件第一页
只选 id、subject、start、end 和 type,默认返回 UTC。示例只演示第一页,不会创建会议或通知参会人。
https://graph.microsoft.com/v1.0/me/events?$select=id,subject,start,end,type&$top=10请求头
AuthorizationBearer ${MS_GRAPH_ACCESS_TOKEN}Acceptapplication/json
参数说明
参数表可左右滑动,查看完整说明。
| 字段 / 位置 | 类型 / 必填 | 说明 |
|---|---|---|
$selectQuery | string可选 | 本例 id,subject,start,end,type;Calendars.ReadBasic 不包含正文、附件和扩展等属性。 |
$topQuery | integer可选 | 本例每页请求 10 条;响应可能提供下一页链接,不能用本页长度判断已读完。 |
Prefer: outlook.timezoneHeader | string可选 | 可指定官方支持的时区名;本例省略,起止时间按 UTC 返回。 |
调用代码
替换示例 ID 与请求体内容后运行。cURL 会报 HTTP 错误,业务状态还需按下方返回示例核对。
# 执行后核对返回 JSON 的业务状态;HTTP 200 仍可能包含业务错误。
curl --silent --show-error --fail-with-body \
--request GET \
--url "https://graph.microsoft.com/v1.0/me/events?\$select=id,subject,start,end,type&\$top=10" \
--header "Authorization: Bearer ${MS_GRAPH_ACCESS_TOKEN}" \
--header "Accept: application/json"
import json
import os
import re
import urllib.request
import urllib.error
def expand(value):
return re.sub(r"\$\{([A-Z][A-Z0-9_]*)\}",
lambda match: os.environ[match.group(1)], value)
url = expand("https://graph.microsoft.com/v1.0/me/events?$select=id,subject,start,end,type&$top=10")
headers = {
"Authorization": expand("Bearer ${MS_GRAPH_ACCESS_TOKEN}"),
"Accept": expand("application/json"),
}
data = None
request = urllib.request.Request(url, data=data, headers=headers, method="GET")
try:
with urllib.request.urlopen(request, timeout=30) as response:
result = json.load(response)
except urllib.error.HTTPError as error:
print(f"HTTP {error.code}: {error.read().decode('utf-8', errors='replace')}")
raise SystemExit(1)
print(json.dumps(result, ensure_ascii=False, indent=2))
// Node.js 22+,保存为 request.mjs 后运行 node request.mjs
function expand(value) {
return value.replace(/\$\{([A-Z][A-Z0-9_]*)\}/g, (_, name) => {
if (!process.env[name]) throw new Error(`缺少环境变量 ${name}`);
return process.env[name];
});
}
const url = expand("https://graph.microsoft.com/v1.0/me/events?$select=id,subject,start,end,type&$top=10");
const headers = Object.fromEntries(
Object.entries({
"Authorization": "Bearer ${MS_GRAPH_ACCESS_TOKEN}",
"Accept": "application/json"
}).map(([key, value]) => [key, expand(value)])
);
const response = await fetch(url, {
method: "GET",
headers,
signal: AbortSignal.timeout(30000),
});
const text = await response.text();
if (!response.ok) throw new Error(`HTTP ${response.status}: ${text}`);
const result = JSON.parse(text);
console.log(JSON.stringify(result, null, 2));
返回示例
按官方字段整理的节选结构示意,事件 ID、日期和主题均为虚构。start/end 含 dateTime 与 timeZone;type 区分单次与周期主项等。若返回 @odata.nextLink,使用完整链接继续。 以下为结构示意,非本站实测结果。
{
"@odata.context": "https://graph.microsoft.com/v1.0/$metadata#users('example-user')/events(id,subject,start,end,type)",
"value": [
{
"id": "example-event-id",
"subject": "示例日程",
"start": {
"dateTime": "2026-10-20T02:00:00.0000000",
"timeZone": "UTC"
},
"end": {
"dateTime": "2026-10-20T02:30:00.0000000",
"timeZone": "UTC"
},
"type": "singleInstance"
}
]
}常见错误与排查
HTTP 401 / InvalidAuthenticationToken访问令牌缺失、过期或不适用于 Graph。- 从对应云环境重新获取 Graph access token;检查令牌用途和到期,不要使用 ID token。
HTTP 403 / ErrorAccessDenied缺少权限、许可或受组织策略限制。- 检查令牌中已同意的 scope、资源服务许可和条件访问;需要时由管理员授权,扩大权限前先确认具体资源。
HTTP 429触发服务限流。- 按 Retry-After 等待再重试;减少重复轮询。若响应无该头,使用指数退避。
HTTP 404目标资源或邮箱未找到。- 确认登录账号有已开通并可访问的日历/邮箱服务,查询路径与所属云环境正确;不要用重试替代服务开通检查。
调用注意
- /me/events 返回单次事件及周期系列主项,不展开每次发生;日程时间窗应使用 calendarView,不能把两者混为一种结果。
- Calendars.ReadBasic 是委托权限名。后台应用的基本日历权限为 Calendars.ReadBasic.All,需要管理员同意,并改用 /users/{id}/events 等支持路径;本代码没有申请它。
- 有 @odata.nextLink 时按链接读取下一页并保留 Authorization;日志与缓存不要泄露访问令牌或私人日程。
注意事项
- 仅演示当前登录用户基本日历读取,未覆盖共享日历、组织群组日历或应用权限后台同步。
- API 权限不会自动提供 Exchange/Microsoft 365 许可;服务可用性与标准 API 费用边界分别核对。
核验来源
本站按官方资料整理本场景的必要调用步骤与代码,覆盖范围以本页列出的接口为准。官方资料用于追溯规范及查看变更。
- 01身份与委托/应用访问核验日期 2026-10-15
- 02Microsoft Entra 应用注册核验日期 2026-10-15
- 03代表用户获取访问令牌核验日期 2026-10-15
- 04标准 API 与计量 API 费用边界核验日期 2026-10-15
- 05列出用户日历事件核验日期 2026-10-15
- 06Microsoft Graph 权限参考核验日期 2026-10-15
- 07Microsoft Graph 错误响应核验日期 2026-10-15
- 08Microsoft Graph 限流与退避核验日期 2026-10-15