[{"data":1,"prerenderedAt":1037},["ShallowReactive",2],{"navigation":3,"page:\u002Fevents":45},{"title":4,"links":5},"API reference",[6,9,12,15,18,21,24,27,30,33,36,39,42],{"title":7,"href":8},"Accounts","\u002Freference\u002Faccounts",{"title":10,"href":11},"Connect","\u002Freference\u002Fconnect",{"title":13,"href":14},"Calendars","\u002Freference\u002Fcalendars",{"title":16,"href":17},"Events","\u002Freference\u002Fevents",{"title":19,"href":20},"Availability","\u002Freference\u002Favailability",{"title":22,"href":23},"Meetings","\u002Freference\u002Fmeetings",{"title":25,"href":26},"Invitations","\u002Freference\u002Finvitations",{"title":28,"href":29},"Webhooks","\u002Freference\u002Fwebhooks",{"title":31,"href":32},"Metadata","\u002Freference\u002Fmetadata",{"title":34,"href":35},"Keys","\u002Freference\u002Fkeys",{"title":37,"href":38},"Sandbox","\u002Freference\u002Fsandbox",{"title":40,"href":41},"Usage","\u002Freference\u002Fusage",{"title":43,"href":44},"Logs","\u002Freference\u002Flogs",{"kind":46,"title":16,"description":47,"sections":48,"doc":79},"guide","A single event format for Google, Outlook and Pyas calendars, covering times and time zones, recurrence, meeting links, your own metadata, and keeping a copy in sync.",[49,52,55,58,61,64,67,70,73,76],{"id":50,"title":51},"choose-a-calendar","Choose a calendar",{"id":53,"title":54},"times-and-time-zones","Times and time zones",{"id":56,"title":57},"create-update-and-delete-events","Create, update and delete events",{"id":59,"title":60},"recurring-events","Recurring events",{"id":62,"title":63},"meeting-links","Meeting links",{"id":65,"title":66},"your-own-data-on-events","Your own data on events",{"id":68,"title":69},"read-several-calendars-in-one-request","Read several calendars in one request",{"id":71,"title":72},"prevent-conflicting-updates","Prevent conflicting updates",{"id":74,"title":75},"keeping-a-copy-in-sync","Keeping a copy in sync",{"id":77,"title":78},"what-else-events-can-do","What else events can do",{"id":80,"title":16,"body":81,"description":47,"extension":1028,"hero":1029,"meta":1030,"navigation":425,"path":1031,"rawbody":1032,"sections":1033,"seo":1034,"stem":87,"v1":1035,"__hash__":1036},"docs\u002Fevents.md",{"type":82,"value":83,"toc":1016},"minimark",[84,88,95,98,120,142,144,231,254,256,597,603,618,675,677,690,693,705,712,714,741,752,754,767,819,822,851,856,864,866,888,898,900,922,973,975,1003,1005,1012],[85,86,16],"h1",{"id":87},"events",[89,90,91],"lead",{},[92,93,94],"p",{},"Events have the same format on every calendar. You read, write and search them the same way on Google, Outlook and Pyas calendars. When a provider doesn't support a feature, the API returns an error or lists the feature in the response, instead of silently skipping it.",[96,97,51],"h2",{"id":50},[92,99,100,101,105,106,109,110,113,114,116,117,119],{},"Every event request must include an account (",[102,103,104],"code",{},"accountId",") and can include a calendar (",[102,107,108],{},"calendarRef","). If you don't specify a calendar, the API uses the account's ",[102,111,112],{},"primary"," calendar. A ",[102,115,108],{}," is either ",[102,118,112],{}," or a calendar id returned by this request:",[121,122,127],"pre",{"className":123,"code":124,"language":125,"meta":126,"style":126},"language-http shiki shiki-themes css-variables","GET \u002Fv2\u002Fcalendars\n","http","",[102,128,129],{"__ignoreMap":126},[130,131,134,138],"span",{"class":132,"line":133},"line",1,[130,135,137],{"class":136},"sag7P","GET",[130,139,141],{"class":140},"sqSWz"," \u002Fv2\u002Fcalendars\n",[96,143,54],{"id":53},[145,146,147,160],"table",{},[148,149,150],"thead",{},[151,152,153,157],"tr",{},[154,155,156],"th",{},"Field",[154,158,159],{},"Description",[161,162,163,182,198,211],"tbody",{},[151,164,165,175],{},[166,167,168,171,172],"td",{},[102,169,170],{},"startsAt",", ",[102,173,174],{},"endsAt",[166,176,177,178,181],{},"The time in UTC (",[102,179,180],{},"2026-10-21T15:00:00Z",")",[151,183,184,192],{},[166,185,186,171,189],{},[102,187,188],{},"startsAtLocal",[102,190,191],{},"endsAtLocal",[166,193,194,195,181],{},"The same time in the event's time zone, with that zone's offset (",[102,196,197],{},"2026-10-21T11:00:00-04:00",[151,199,200,205],{},[166,201,202],{},[102,203,204],{},"timezone",[166,206,207,208,181],{},"The IANA name of the event's time zone (",[102,209,210],{},"America\u002FNew_York",[151,212,213,218],{},[166,214,215],{},[102,216,217],{},"isAllDay",[166,219,220,221,223,224,226,227,230],{},"Whether the event is an all-day event. If it is, its times are midnight in ",[102,222,204],{}," (",[102,225,188],{}," is ",[102,228,229],{},"2026-10-21T00:00:00-04:00",").",[92,232,233,234,237,238,241,242,245,246,249,250,253],{},"When you create or update an event, include a time zone offset with each time (",[102,235,236],{},"Z"," or ",[102,239,240],{},"+02:00","), or use plain dates (",[102,243,244],{},"2026-10-21",") for an all-day event. The API rejects a time without an offset, because the time is ambiguous without one. For the same reason, the ",[102,247,248],{},"from"," and ",[102,251,252],{},"to"," parameters for reading events also require an offset.",[96,255,57],{"id":56},[257,258,259,508],"code-group",{},[121,260,265],{"className":261,"code":262,"filename":263,"language":264,"meta":126,"style":126},"language-js shiki shiki-themes css-variables","const event = await pyas.events.create({\n  accountId,\n  title: 'Weekly review',\n  startsAt: '2026-10-21T15:00:00Z',\n  endsAt: '2026-10-21T15:30:00Z',\n  attendees: [{ email: 'sam.patel@example.org', name: 'Sam Patel' }],\n  recurrence: 'FREQ=WEEKLY;COUNT=6',\n  metadata: { dealId: 'deal_1007' },\n})\n\nawait pyas.events.update({ accountId, eventId: event.id, title: 'Weekly review (moved)' })\nawait pyas.events.delete({ accountId, eventId: event.id, notifyAttendees: true })\n","Node.js","js",[102,266,267,297,307,322,335,348,380,393,414,420,427,470],{"__ignoreMap":126},[130,268,269,272,276,279,282,285,289,291,294],{"class":132,"line":133},[130,270,271],{"class":136},"const",[130,273,275],{"class":274},"sXULy"," event",[130,277,278],{"class":136}," =",[130,280,281],{"class":136}," await",[130,283,284],{"class":274}," pyas",[130,286,288],{"class":287},"s1IGz",".",[130,290,87],{"class":274},[130,292,293],{"class":287},".create",[130,295,296],{"class":140},"({\n",[130,298,300,303],{"class":132,"line":299},2,[130,301,302],{"class":140},"  accountId",[130,304,306],{"class":305},"sEEt9",",\n",[130,308,310,313,316,320],{"class":132,"line":309},3,[130,311,312],{"class":140},"  title",[130,314,315],{"class":136},":",[130,317,319],{"class":318},"sk1Au"," 'Weekly review'",[130,321,306],{"class":305},[130,323,325,328,330,333],{"class":132,"line":324},4,[130,326,327],{"class":140},"  startsAt",[130,329,315],{"class":136},[130,331,332],{"class":318}," '2026-10-21T15:00:00Z'",[130,334,306],{"class":305},[130,336,338,341,343,346],{"class":132,"line":337},5,[130,339,340],{"class":140},"  endsAt",[130,342,315],{"class":136},[130,344,345],{"class":318}," '2026-10-21T15:30:00Z'",[130,347,306],{"class":305},[130,349,351,354,356,359,361,364,367,370,372,375,378],{"class":132,"line":350},6,[130,352,353],{"class":140},"  attendees",[130,355,315],{"class":136},[130,357,358],{"class":140}," [{ email",[130,360,315],{"class":136},[130,362,363],{"class":318}," 'sam.patel@example.org'",[130,365,366],{"class":305},",",[130,368,369],{"class":140}," name",[130,371,315],{"class":136},[130,373,374],{"class":318}," 'Sam Patel'",[130,376,377],{"class":140}," }]",[130,379,306],{"class":305},[130,381,383,386,388,391],{"class":132,"line":382},7,[130,384,385],{"class":140},"  recurrence",[130,387,315],{"class":136},[130,389,390],{"class":318}," 'FREQ=WEEKLY;COUNT=6'",[130,392,306],{"class":305},[130,394,396,399,401,404,406,409,412],{"class":132,"line":395},8,[130,397,398],{"class":140},"  metadata",[130,400,315],{"class":136},[130,402,403],{"class":140}," { dealId",[130,405,315],{"class":136},[130,407,408],{"class":318}," 'deal_1007'",[130,410,411],{"class":140}," }",[130,413,306],{"class":305},[130,415,417],{"class":132,"line":416},9,[130,418,419],{"class":140},"})\n",[130,421,423],{"class":132,"line":422},10,[130,424,426],{"emptyLinePlaceholder":425},true,"\n",[130,428,430,433,435,437,439,442,445,447,450,452,454,457,459,462,464,467],{"class":132,"line":429},11,[130,431,432],{"class":136},"await",[130,434,284],{"class":274},[130,436,288],{"class":287},[130,438,87],{"class":274},[130,440,441],{"class":287},".update",[130,443,444],{"class":140},"({ accountId",[130,446,366],{"class":305},[130,448,449],{"class":140}," eventId",[130,451,315],{"class":136},[130,453,275],{"class":274},[130,455,456],{"class":140},".id",[130,458,366],{"class":305},[130,460,461],{"class":140}," title",[130,463,315],{"class":136},[130,465,466],{"class":318}," 'Weekly review (moved)'",[130,468,469],{"class":140}," })\n",[130,471,473,475,477,479,481,484,486,488,490,492,494,496,498,501,503,506],{"class":132,"line":472},12,[130,474,432],{"class":136},[130,476,284],{"class":274},[130,478,288],{"class":287},[130,480,87],{"class":274},[130,482,483],{"class":287},".delete",[130,485,444],{"class":140},[130,487,366],{"class":305},[130,489,449],{"class":140},[130,491,315],{"class":136},[130,493,275],{"class":274},[130,495,456],{"class":140},[130,497,366],{"class":305},[130,499,500],{"class":140}," notifyAttendees",[130,502,315],{"class":136},[130,504,505],{"class":274}," true",[130,507,469],{"class":140},[121,509,514],{"className":510,"code":511,"filename":512,"language":513,"meta":126,"style":126},"language-bash shiki shiki-themes css-variables","curl -X POST https:\u002F\u002Fapi.pyas.io\u002Fv2\u002Fevents \\\n  -H \"x-api-key: $PYAS_API_KEY\" \\\n  -H \"content-type: application\u002Fjson\" \\\n  -d '{\n    \"accountId\": \"'$ACCOUNT_ID'\",\n    \"title\": \"Weekly review\",\n    \"startsAt\": \"2026-10-21T15:00:00Z\",\n    \"endsAt\": \"2026-10-21T15:30:00Z\",\n    \"recurrence\": \"FREQ=WEEKLY;COUNT=6\"\n  }'\n","cURL","bash",[102,515,516,534,544,553,561,572,577,582,587,592],{"__ignoreMap":126},[130,517,518,521,525,528,531],{"class":132,"line":133},[130,519,520],{"class":287},"curl",[130,522,524],{"class":523},"sTB4W"," -X",[130,526,527],{"class":523}," POST",[130,529,530],{"class":523}," https:\u002F\u002Fapi.pyas.io\u002Fv2\u002Fevents",[130,532,533],{"class":140}," \\\n",[130,535,536,539,542],{"class":132,"line":299},[130,537,538],{"class":523},"  -H",[130,540,541],{"class":318}," \"x-api-key: $PYAS_API_KEY\"",[130,543,533],{"class":140},[130,545,546,548,551],{"class":132,"line":309},[130,547,538],{"class":523},[130,549,550],{"class":318}," \"content-type: application\u002Fjson\"",[130,552,533],{"class":140},[130,554,555,558],{"class":132,"line":324},[130,556,557],{"class":523},"  -d",[130,559,560],{"class":318}," '{\n",[130,562,563,566,569],{"class":132,"line":337},[130,564,565],{"class":318},"    \"accountId\": \"'",[130,567,568],{"class":140},"$ACCOUNT_ID",[130,570,571],{"class":318},"'\",\n",[130,573,574],{"class":132,"line":350},[130,575,576],{"class":318},"    \"title\": \"Weekly review\",\n",[130,578,579],{"class":132,"line":382},[130,580,581],{"class":318},"    \"startsAt\": \"2026-10-21T15:00:00Z\",\n",[130,583,584],{"class":132,"line":395},[130,585,586],{"class":318},"    \"endsAt\": \"2026-10-21T15:30:00Z\",\n",[130,588,589],{"class":132,"line":416},[130,590,591],{"class":318},"    \"recurrence\": \"FREQ=WEEKLY;COUNT=6\"\n",[130,593,594],{"class":132,"line":422},[130,595,596],{"class":318},"  }'\n",[92,598,599,600,288],{},"In an update request, include only the fields you want to update. To clear a field that can be empty, set it to ",[102,601,602],{},"null",[92,604,605,606,609,610,613,614,617],{},"When you create, update or delete an event that has attendees, they get an email about it. To stop the email, set ",[102,607,608],{},"notifyAttendees"," to ",[102,611,612],{},"false",". Outlook always emails attendees, and Microsoft doesn't offer a way to stop it. On an Outlook calendar, the change is still made, and the response includes ",[102,615,616],{},"meta.notifyAttendees"," to tell you that attendees were emailed:",[121,619,623],{"className":620,"code":621,"language":622,"meta":126,"style":126},"language-json shiki shiki-themes css-variables","\"meta\": {\n  \"notifyAttendees\": {\n    \"applied\": false,\n    \"reason\": \"Outlook emails attendees about changes to events that have them, and Microsoft Graph has no setting to stop it.\"\n  }\n}\n","json",[102,624,625,633,643,655,665,670],{"__ignoreMap":126},[130,626,627,630],{"class":132,"line":133},[130,628,629],{"class":318},"\"meta\"",[130,631,632],{"class":140},": {\n",[130,634,635,638,640],{"class":132,"line":299},[130,636,637],{"class":136},"  \"notifyAttendees\"",[130,639,315],{"class":305},[130,641,642],{"class":140}," {\n",[130,644,645,648,650,653],{"class":132,"line":309},[130,646,647],{"class":136},"    \"applied\"",[130,649,315],{"class":305},[130,651,652],{"class":274}," false",[130,654,306],{"class":305},[130,656,657,660,662],{"class":132,"line":324},[130,658,659],{"class":136},"    \"reason\"",[130,661,315],{"class":305},[130,663,664],{"class":318}," \"Outlook emails attendees about changes to events that have them, and Microsoft Graph has no setting to stop it.\"\n",[130,666,667],{"class":132,"line":337},[130,668,669],{"class":140},"  }\n",[130,671,672],{"class":132,"line":350},[130,673,674],{"class":140},"}\n",[96,676,60],{"id":59},[92,678,679,682,683,686,687,288],{},[102,680,681],{},"recurrence"," is an RFC 5545 rule (",[102,684,685],{},"FREQ=WEEKLY;BYDAY=MO,WE;COUNT=10","). A list request returns each series once. To get every occurrence in the time window instead, pass ",[102,688,689],{},"expand=true",[92,691,692],{},"To list the occurrences of a single series, call:",[121,694,696],{"className":123,"code":695,"language":125,"meta":126,"style":126},"GET \u002Fv2\u002Fevents\u002F{eventId}\u002Finstances\n",[102,697,698],{"__ignoreMap":126},[130,699,700,702],{"class":132,"line":133},[130,701,137],{"class":136},[130,703,704],{"class":140}," \u002Fv2\u002Fevents\u002F{eventId}\u002Finstances\n",[92,706,707,708,711],{},"Each occurrence includes a ",[102,709,710],{},"series"," field that identifies its series. When you update an occurrence, only that occurrence is updated.",[96,713,63],{"id":62},[92,715,716,717,720,721,724,725,728,729,732,733,736,737,740],{},"To add a meeting link to an event, set ",[102,718,719],{},"conferencing.provider",". You can use ",[102,722,723],{},"meet"," on a Google calendar, ",[102,726,727],{},"teams"," on an Outlook calendar, or ",[102,730,731],{},"zoom"," on any calendar. For Zoom, you also set ",[102,734,735],{},"conferencing.accountId"," to a connected Zoom account. The response includes ",[102,738,739],{},"conferencing.joinUrl",", the meeting id, the passcode and the dial-in numbers.",[92,742,743,744,747,748,751],{},"To configure the meeting, such as who can join without waiting, recording and muting participants on entry, use ",[102,745,746],{},"conferencing.options",". The options are the same for all three services. If a service doesn't support a setting, the API rejects the request instead of ignoring the setting. If a service doesn't keep a setting, the response lists it in ",[102,749,750],{},"meta.conferencing.notApplied",", along with the reason.",[96,753,66],{"id":65},[92,755,756,757,760,761,249,764,766],{},"Use ",[102,758,759],{},"metadata"," to store your own fields on any event. Values can be text, numbers, ",[102,762,763],{},"true",[102,765,612],{},", or lists of those:",[121,768,770],{"className":620,"code":769,"language":622,"meta":126,"style":126},"\"metadata\": { \"dealId\": \"deal_1007\", \"seats\": 4, \"tags\": [\"Food\", \"Hiking\"] }\n",[102,771,772],{"__ignoreMap":126},[130,773,774,777,780,783,785,788,790,793,795,798,800,803,805,808,811,813,816],{"class":132,"line":133},[130,775,776],{"class":318},"\"metadata\"",[130,778,779],{"class":140},": { ",[130,781,782],{"class":136},"\"dealId\"",[130,784,315],{"class":305},[130,786,787],{"class":318}," \"deal_1007\"",[130,789,366],{"class":305},[130,791,792],{"class":136}," \"seats\"",[130,794,315],{"class":305},[130,796,797],{"class":274}," 4",[130,799,366],{"class":305},[130,801,802],{"class":136}," \"tags\"",[130,804,315],{"class":305},[130,806,807],{"class":140}," [",[130,809,810],{"class":318},"\"Food\"",[130,812,366],{"class":305},[130,814,815],{"class":318}," \"Hiking\"",[130,817,818],{"class":140},"] }\n",[92,820,821],{},"Metadata works with every provider, and you can search for events by these fields across your whole app. A search for a list's item finds every event whose list holds it:",[121,823,825],{"className":510,"code":824,"language":513,"meta":126,"style":126},"curl \"https:\u002F\u002Fapi.pyas.io\u002Fv2\u002Fevents?metadata.dealId=deal_1007\" -H \"x-api-key: $PYAS_API_KEY\"\ncurl \"https:\u002F\u002Fapi.pyas.io\u002Fv2\u002Fevents?metadata.tags=Hiking\" -H \"x-api-key: $PYAS_API_KEY\"\n",[102,826,827,840],{"__ignoreMap":126},[130,828,829,831,834,837],{"class":132,"line":133},[130,830,520],{"class":287},[130,832,833],{"class":318}," \"https:\u002F\u002Fapi.pyas.io\u002Fv2\u002Fevents?metadata.dealId=deal_1007\"",[130,835,836],{"class":523}," -H",[130,838,839],{"class":318}," \"x-api-key: $PYAS_API_KEY\"\n",[130,841,842,844,847,849],{"class":132,"line":299},[130,843,520],{"class":287},[130,845,846],{"class":318}," \"https:\u002F\u002Fapi.pyas.io\u002Fv2\u002Fevents?metadata.tags=Hiking\"",[130,848,836],{"class":523},[130,850,839],{"class":318},[92,852,853,854,288],{},"When you update an event, the keys you send are changed and the others are kept. A list you send replaces the list that was there. To remove a key, send it as ",[102,855,602],{},[92,857,858,859,288],{},"If you stored data as extended properties in v1, see ",[860,861,863],"a",{"href":862},"\u002Fmigrating-from-v1#extended-properties","Migrating from v1",[96,865,69],{"id":68},[92,867,868,869,872,873,249,875,877,878,881,882,884,885,288],{},"To read events from several calendars in one request, pass ",[102,870,871],{},"accountIds"," with ",[102,874,248],{},[102,876,252],{},". To include every connected account of one of your users, pass a ",[102,879,880],{},"subjectId"," instead of ",[102,883,871],{},". The API returns the events as a single timeline sorted by start time, and each event's account is in ",[102,886,887],{},"providerRefs.accountId",[92,889,890,891,894,895,230],{},"When the same meeting appears on two calendars, the API either flags it as a duplicate (",[102,892,893],{},"duplicates=flag",", the default) or returns it only once (",[102,896,897],{},"duplicates=collapse",[96,899,72],{"id":71},[92,901,902,903,906,907,910,911,914,915,223,918,921],{},"Every event has a ",[102,904,905],{},"version",", which the API also returns in the ",[102,908,909],{},"ETag"," header. When you update or delete the event, send that value in the ",[102,912,913],{},"If-Match"," header, exactly as you received it, including the quotes. If someone else updated the event after you read it, the API rejects the request with ",[102,916,917],{},"RESOURCE_CONFLICT",[102,919,920],{},"409 Conflict","). In that case, read the event again, decide what to do, and retry the request.",[121,923,925],{"className":510,"code":924,"language":513,"meta":126,"style":126},"curl -X PATCH \"https:\u002F\u002Fapi.pyas.io\u002Fv2\u002Fevents\u002F$EVENT_ID?accountId=$ACCOUNT_ID\" \\\n  -H \"x-api-key: $PYAS_API_KEY\" \\\n  -H \"If-Match: $VERSION\" \\\n  -H \"content-type: application\u002Fjson\" \\\n  -d '{ \"title\": \"Renamed\" }'\n",[102,926,927,941,949,958,966],{"__ignoreMap":126},[130,928,929,931,933,936,939],{"class":132,"line":133},[130,930,520],{"class":287},[130,932,524],{"class":523},[130,934,935],{"class":523}," PATCH",[130,937,938],{"class":318}," \"https:\u002F\u002Fapi.pyas.io\u002Fv2\u002Fevents\u002F$EVENT_ID?accountId=$ACCOUNT_ID\"",[130,940,533],{"class":140},[130,942,943,945,947],{"class":132,"line":299},[130,944,538],{"class":523},[130,946,541],{"class":318},[130,948,533],{"class":140},[130,950,951,953,956],{"class":132,"line":309},[130,952,538],{"class":523},[130,954,955],{"class":318}," \"If-Match: $VERSION\"",[130,957,533],{"class":140},[130,959,960,962,964],{"class":132,"line":324},[130,961,538],{"class":523},[130,963,550],{"class":318},[130,965,533],{"class":140},[130,967,968,970],{"class":132,"line":337},[130,969,557],{"class":523},[130,971,972],{"class":318}," '{ \"title\": \"Renamed\" }'\n",[96,974,75],{"id":74},[92,976,977,978,981,982,985,986,989,990,993,994,997,998,1002],{},"To keep a copy of a calendar in your own database, start a sync for a time window by passing ",[102,979,980],{},"sync=true",". The API returns every event, page by page, and the last page includes ",[102,983,984],{},"meta.syncToken",". Later, send only ",[102,987,988],{},"syncToken"," to get the changes since that sync. Deleted events are listed in ",[102,991,992],{},"meta.deletedIds",". Use the ",[102,995,996],{},"event.*"," ",[860,999,1001],{"href":1000},"\u002Fwebhooks","webhooks"," to find out when to sync again.",[96,1004,78],{"id":77},[92,1006,1007,1008,1011],{},"The ",[860,1009,1010],{"href":17},"Events reference"," covers everything else you can do with events. This includes attachments (links and files), responding to invitations (with a proposed new time on Outlook), moving an event to another calendar, forwarding an event, reminders, creating an event from a sentence (quick add), and importing events.",[1013,1014,1015],"style",{},"html pre.shiki code .sag7P, html code.shiki .sag7P{--shiki-default:var(--shiki-token-keyword)}html pre.shiki code .sqSWz, html code.shiki .sqSWz{--shiki-default:var(--shiki-foreground)}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .sXULy, html code.shiki .sXULy{--shiki-default:var(--shiki-token-constant)}html pre.shiki code .s1IGz, html code.shiki .s1IGz{--shiki-default:var(--shiki-token-function)}html pre.shiki code .sEEt9, html code.shiki .sEEt9{--shiki-default:var(--shiki-token-punctuation)}html pre.shiki code .sk1Au, html code.shiki .sk1Au{--shiki-default:var(--shiki-token-string-expression)}html pre.shiki code .sTB4W, html code.shiki .sTB4W{--shiki-default:var(--shiki-token-string)}",{"title":126,"searchDepth":309,"depth":309,"links":1017},[1018,1019,1020,1021,1022,1023,1024,1025,1026,1027],{"id":50,"depth":299,"text":51},{"id":53,"depth":299,"text":54},{"id":56,"depth":299,"text":57},{"id":59,"depth":299,"text":60},{"id":62,"depth":299,"text":63},{"id":65,"depth":299,"text":66},{"id":68,"depth":299,"text":69},{"id":71,"depth":299,"text":72},{"id":74,"depth":299,"text":75},{"id":77,"depth":299,"text":78},"md",false,{},"\u002Fevents","---\ntitle: Events\ndescription: A single event format for Google, Outlook and Pyas calendars, covering times and time zones, recurrence, meeting links, your own metadata, and keeping a copy in sync.\nv1: \u002Frest-api-reference\u002Fgoogle-calendar\u002Fevents\n---\n\n# Events\n\n::lead\nEvents have the same format on every calendar. You read, write and search them the same way on Google, Outlook and Pyas calendars. When a provider doesn't support a feature, the API returns an error or lists the feature in the response, instead of silently skipping it.\n::\n\n## Choose a calendar\n\nEvery event request must include an account (`accountId`) and can include a calendar (`calendarRef`). If you don't specify a calendar, the API uses the account's `primary` calendar. A `calendarRef` is either `primary` or a calendar id returned by this request:\n\n```http\nGET \u002Fv2\u002Fcalendars\n```\n\n## Times and time zones\n\n| Field | Description |\n|---|---|\n| `startsAt`, `endsAt` | The time in UTC (`2026-10-21T15:00:00Z`) |\n| `startsAtLocal`, `endsAtLocal` | The same time in the event's time zone, with that zone's offset (`2026-10-21T11:00:00-04:00`) |\n| `timezone` | The IANA name of the event's time zone (`America\u002FNew_York`) |\n| `isAllDay` | Whether the event is an all-day event. If it is, its times are midnight in `timezone` (`startsAtLocal` is `2026-10-21T00:00:00-04:00`). |\n\nWhen you create or update an event, include a time zone offset with each time (`Z` or `+02:00`), or use plain dates (`2026-10-21`) for an all-day event. The API rejects a time without an offset, because the time is ambiguous without one. For the same reason, the `from` and `to` parameters for reading events also require an offset.\n\n## Create, update and delete events\n\n::code-group\n```js [Node.js]\nconst event = await pyas.events.create({\n  accountId,\n  title: 'Weekly review',\n  startsAt: '2026-10-21T15:00:00Z',\n  endsAt: '2026-10-21T15:30:00Z',\n  attendees: [{ email: 'sam.patel@example.org', name: 'Sam Patel' }],\n  recurrence: 'FREQ=WEEKLY;COUNT=6',\n  metadata: { dealId: 'deal_1007' },\n})\n\nawait pyas.events.update({ accountId, eventId: event.id, title: 'Weekly review (moved)' })\nawait pyas.events.delete({ accountId, eventId: event.id, notifyAttendees: true })\n```\n\n```bash [cURL]\ncurl -X POST https:\u002F\u002Fapi.pyas.io\u002Fv2\u002Fevents \\\n  -H \"x-api-key: $PYAS_API_KEY\" \\\n  -H \"content-type: application\u002Fjson\" \\\n  -d '{\n    \"accountId\": \"'$ACCOUNT_ID'\",\n    \"title\": \"Weekly review\",\n    \"startsAt\": \"2026-10-21T15:00:00Z\",\n    \"endsAt\": \"2026-10-21T15:30:00Z\",\n    \"recurrence\": \"FREQ=WEEKLY;COUNT=6\"\n  }'\n```\n::\n\nIn an update request, include only the fields you want to update. To clear a field that can be empty, set it to `null`.\n\nWhen you create, update or delete an event that has attendees, they get an email about it. To stop the email, set `notifyAttendees` to `false`. Outlook always emails attendees, and Microsoft doesn't offer a way to stop it. On an Outlook calendar, the change is still made, and the response includes `meta.notifyAttendees` to tell you that attendees were emailed:\n\n```json\n\"meta\": {\n  \"notifyAttendees\": {\n    \"applied\": false,\n    \"reason\": \"Outlook emails attendees about changes to events that have them, and Microsoft Graph has no setting to stop it.\"\n  }\n}\n```\n\n## Recurring events\n\n`recurrence` is an RFC 5545 rule (`FREQ=WEEKLY;BYDAY=MO,WE;COUNT=10`). A list request returns each series once. To get every occurrence in the time window instead, pass `expand=true`.\n\nTo list the occurrences of a single series, call:\n\n```http\nGET \u002Fv2\u002Fevents\u002F{eventId}\u002Finstances\n```\n\nEach occurrence includes a `series` field that identifies its series. When you update an occurrence, only that occurrence is updated.\n\n## Meeting links\n\nTo add a meeting link to an event, set `conferencing.provider`. You can use `meet` on a Google calendar, `teams` on an Outlook calendar, or `zoom` on any calendar. For Zoom, you also set `conferencing.accountId` to a connected Zoom account. The response includes `conferencing.joinUrl`, the meeting id, the passcode and the dial-in numbers.\n\nTo configure the meeting, such as who can join without waiting, recording and muting participants on entry, use `conferencing.options`. The options are the same for all three services. If a service doesn't support a setting, the API rejects the request instead of ignoring the setting. If a service doesn't keep a setting, the response lists it in `meta.conferencing.notApplied`, along with the reason.\n\n## Your own data on events\n\nUse `metadata` to store your own fields on any event. Values can be text, numbers, `true` and `false`, or lists of those:\n\n```json\n\"metadata\": { \"dealId\": \"deal_1007\", \"seats\": 4, \"tags\": [\"Food\", \"Hiking\"] }\n```\n\nMetadata works with every provider, and you can search for events by these fields across your whole app. A search for a list's item finds every event whose list holds it:\n\n```bash\ncurl \"https:\u002F\u002Fapi.pyas.io\u002Fv2\u002Fevents?metadata.dealId=deal_1007\" -H \"x-api-key: $PYAS_API_KEY\"\ncurl \"https:\u002F\u002Fapi.pyas.io\u002Fv2\u002Fevents?metadata.tags=Hiking\" -H \"x-api-key: $PYAS_API_KEY\"\n```\n\nWhen you update an event, the keys you send are changed and the others are kept. A list you send replaces the list that was there. To remove a key, send it as `null`.\n\nIf you stored data as extended properties in v1, see [Migrating from v1](\u002Fmigrating-from-v1#extended-properties).\n\n## Read several calendars in one request\n\nTo read events from several calendars in one request, pass `accountIds` with `from` and `to`. To include every connected account of one of your users, pass a `subjectId` instead of `accountIds`. The API returns the events as a single timeline sorted by start time, and each event's account is in `providerRefs.accountId`.\n\nWhen the same meeting appears on two calendars, the API either flags it as a duplicate (`duplicates=flag`, the default) or returns it only once (`duplicates=collapse`).\n\n## Prevent conflicting updates\n\nEvery event has a `version`, which the API also returns in the `ETag` header. When you update or delete the event, send that value in the `If-Match` header, exactly as you received it, including the quotes. If someone else updated the event after you read it, the API rejects the request with `RESOURCE_CONFLICT` (`409 Conflict`). In that case, read the event again, decide what to do, and retry the request.\n\n```bash\ncurl -X PATCH \"https:\u002F\u002Fapi.pyas.io\u002Fv2\u002Fevents\u002F$EVENT_ID?accountId=$ACCOUNT_ID\" \\\n  -H \"x-api-key: $PYAS_API_KEY\" \\\n  -H \"If-Match: $VERSION\" \\\n  -H \"content-type: application\u002Fjson\" \\\n  -d '{ \"title\": \"Renamed\" }'\n```\n\n## Keeping a copy in sync\n\nTo keep a copy of a calendar in your own database, start a sync for a time window by passing `sync=true`. The API returns every event, page by page, and the last page includes `meta.syncToken`. Later, send only `syncToken` to get the changes since that sync. Deleted events are listed in `meta.deletedIds`. Use the `event.*` [webhooks](\u002Fwebhooks) to find out when to sync again.\n\n## What else events can do\n\nThe [Events reference](\u002Freference\u002Fevents) covers everything else you can do with events. This includes attachments (links and files), responding to invitations (with a proposed new time on Outlook), moving an event to another calendar, forwarding an event, reminders, creating an event from a sentence (quick add), and importing events.\n",null,{"title":16,"description":47},"\u002Frest-api-reference\u002Fgoogle-calendar\u002Fevents","fyrvtlCRHfYslcixf5zEhfOfdm0F54IPg37MFqDBIJY",1794697271290]