Search code examples
office365office365api

Able to write events to read-only calendar via API


Here is what I believe to be a bug in the Calendar REST API - but I'm hoping to find a workaround.

In short, I'm able to POST calendar events to a read-only calendar via the API without error. The odd part is that the 365 UI knows that the calendar is read only, and wont allow edits via the UI.

This causes problems with our sync, as when the original calendar publishes again all the new events get deleted. My question is how can I know for certain that the calendar I'm writing to has proper write permissions (as the UI does), and secondly, is it a bug that I can write via API but not through UI?

Steps to reproduce:

  1. Grab a public, read-only ical calendar address. Eg this
  2. In 365, right click 'My calendars' and 'open calendar' enter image description here
  3. Paste in the address from (1) in the 'internet calendar' field. Calendar should appear under 'My Calendars'. Note that you are unable to create events for this calendar through the UI
  4. Use GET https://outlook.office.com/api/v1.0/me/calendars to get the newly added calendar's ID
  5. Use POST https://outlook.office.com/api/v1.0/me/calendars/[CALENDAR_ID]/events to create an event to the new calendar.

Expected behaviour Like the UI, the API does not allow you to write to this calendar.

Actual behaviour Successful creation, 201 created returned. Surprise! After some time (4-6 hours), the newly created event will be deleted. This causes issues if you are syncing this calendar, as the deletion will propagate to whichever client is syncing with that calendar.

enter image description here


Solution

  • Thank you for reporting this. I looked into this, and unfortunately there's not currently a good answer for this. It's something we're working on improving to make the API more consistent with Outlook and OWA. Unfortunately I don't have any timeline to share.

    Basically, when you subscribe to an internet calendar, a secondary calendar is created in the mailbox. It isn't truly read-only, but Outlook and OWA know that it's intended for syncing with the internet calendar and won't let you create items there. That logic is all on the client, not on the server, which is why it behaves the way it does today.

    The event gets deleted the next time the sync process with the webcal URL is kicked off since it doesn't exist in the ICS pulled down from the webcal link.

    As a workaround, if you're willing to dip into the /beta endpoint, you could retrieve the PidTagExtendedFolderFlags property on the calendar. That's a binary property, so you'd need to do some parsing on it to get at the data. The format is documented in MS-OXOCFG. You'd need to parse for the sub-property with Id equal to 0x01, then test the Data as a bitmask for the 0x40 bit. If it's set, the folder should be treated as read-only.

    To get this property, you need to expand the SingleValueExtendedProperties on the Calendar entities, like so:

    GET https://outlook.office.com/api/beta/me/calendars?
    $expand=SingleValueExtendedProperties($filter=PropertyId eq 'Binary 0x36da')
    

    This will return something like:

    {
      "value": [
        {
          "Id": "AAMkAGRm...AAA=",
          "Name": "Calendar",
          "Color": "Auto",
          "ChangeKey": "nxdFEDVaMUqvOVUO3592PQAAFmsEKg==",
          "SingleValueExtendedProperties": [
            {
              "PropertyId": "Binary 0x36da",
              "Value": "AQQAABAA"
            }
          ]
        },
        {
          "Id": "AAMkAGRm...AAA=",
          "Name": "Internet Calendar",
          "Color": "Auto",
          "ChangeKey": "nxdFEDVaMUqvOVUO3592PQAAFmsELQ==",
          "SingleValueExtendedProperties": [
            {
              "PropertyId": "Binary 0x36da",
              "Value": "AQRAJRAC"
            }
          ]
        }
      ]
    }
    

    The values for those properties are base64-encoded binary blobs. If you decode them, you get something like:

    • For Calendar: 010400001000
    • For Internet Calendar: 010440251002

    Interpreting those per the format, we have:

    Id: 0x01
    Cb: 0x04
    Data: 0x02102540
    

    The 0x40 bit is set in the Data field, so that one is read-only.