TL;DR: Migrating Sticky Notes from EWS to Microsoft Graph is possible via the Messages endpoint, despite what current LLMs (and the lack of official documentation) might tell you. While custom folders add a layer of difficulty, this post goes over the detail around stickynotes to try to give a path for a seamless transition and highlight things to be aware of. Notes
Sticky Notes are also one of the few multi surface datatypes as they are used by both Outlook and the Windows Sticky Note app which first appeared in Windows Vista and is still around today in Windows 11 and they are also now apart of the OneNote app which gives cross platform access from Android. While the Exchange mailbox acts as the storage for Notes there are two different versions and different clients will read different extended properties with the modern apps also using the /NotesFabric/api/v2.0/me/notes substrate API.
How do they work in Exchange
In your Mailbox folder tree you have a Notes folder which is part of the WellKnownfolder enums and has a folder class of IPF.StickyNote .However, Exchange is flexible in that you can create custom StickyNote folders (or an entire hierarchy of folders) using that same IPF.StickyNote class to organize your notes beyond the default view.
Sticky Note Items
For Outlook Classic, Sticky Notes are Exchange items with an ItemClass of IPM.StickyNote. The actual data is held in Extended MAPI properties, which are all defined in the MS-OXONOTE Exchange protocol document.
For Notes from modern apps (New Outlook, OWA), they are still the same Exchange items, but the Substrate handles synchronizing and setting the legacy MAPI properties alongside newer extension properties. Note that there are some alignment differences between note colors and feature sets between the two versions. The most noticeable thing a user may complain about is setting the Note colour in a modern app doesn’t get reflected in Outlook Classic.
Migrating EWS Code
The first thing to determine is whether you are dealing with Outlook Classic notes or something that is modifying the modern properties. Generally, any EWS Sticky Note code will be the Outlook classic variety, targeting the properties defined in the Exchange protocol document.
Even if you are modifying the new properties, they are all just Extended Properties, which should be still viable to use in the Microsoft Graph. In EWS, there were no strongly typed properties for notes, so your existing EWS code likely looks like the following:
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
| private static readonly Guid PSETID_Note = new Guid("{0006200E-0000-0000-C000-000000000046}"); | |
| Item note = new Item(service); | |
| note.ItemClass = "IPM.StickyNote"; | |
| // 3. Set basic content | |
| note.Subject = "My EWS Sticky Note"; | |
| note.Body = "This is the content of the sticky note.\nCreated via EWS Managed API."; | |
| // 4. Define Extended Properties (based on MS-OXONOTE spec) | |
| // PidNameNoteColor: 0=Blue, 1=Green, 2=Pink, 3=Yellow, 4=White | |
| ExtendedPropertyDefinition noteColor = new ExtendedPropertyDefinition(PSETID_Note, 0x8B00, MapiPropertyType.Integer); | |
| // Dimensions and Position (optional, but part of the spec) | |
| ExtendedPropertyDefinition noteWidth = new ExtendedPropertyDefinition(PSETID_Note, 0x8B01, MapiPropertyType.Integer); | |
| ExtendedPropertyDefinition noteHeight = new ExtendedPropertyDefinition(PSETID_Note, 0x8B02, MapiPropertyType.Integer); | |
| ExtendedPropertyDefinition noteX = new ExtendedPropertyDefinition(PSETID_Note, 0x8B03, MapiPropertyType.Integer); | |
| ExtendedPropertyDefinition noteY = new ExtendedPropertyDefinition(PSETID_Note, 0x8B04, MapiPropertyType.Integer); | |
| // Set the property values | |
| note.SetExtendedProperty(noteColor, 3); // Yellow | |
| note.SetExtendedProperty(noteWidth, 200); | |
| note.SetExtendedProperty(noteHeight, 150); | |
| note.SetExtendedProperty(noteX, 100); | |
| note.SetExtendedProperty(noteY, 100); | |
| // 5. Save the note to the default Notes folder | |
| note.Save(WellKnownFolderName.Notes); | |
| Console.WriteLine("Sticky Note created successfully!"); |
When migrating Sticky Notes functionality to Microsoft Graph, it’s important to understand the current API limitations.
Microsoft Graph provides full access to Sticky Note items, but not full folder metadata access in the same way as Exchange Web Services (EWS).
Sticky Notes are stored in the mailbox as an exchange item within a folder of type (Folder Class) IPF.StickyNote. Because of this
You cannot directly retrieve folder properties using the mailfolders navigation :
GET https://graph.microsoft.com/v1.0/me/mailfolders/notesHowever, you can enumerate all Sticky Note items within the default Notes folder:
GET https://graph.microsoft.com/v1.0/me/mailfolders/notes/messagesThis allows you to:
List all Sticky Notes (in the default notes folder)
Read and update note properties
Create new Sticky Notes
Delete Sticky Notes
If you’ve created custom Sticky Note folders (outside the default Notes folder), you can enumerate them using the new import/export MailFolders endpoint.
Connect-MgGraph -Scopes “MailboxFolder.Read, MailboxSettings.Read”
# Get Primary Mailbox ID (required for Exchange Admin endpoint)
$MailboxId = (Invoke-MgGraphRequest -Method Get `
-Uri “https://graph.microsoft.com/beta/users/user@domain77.onmicrosoft.com/settings/exchange”
).primaryMailboxId
# Query Sticky Note folders
$uri = “https://graph.microsoft.com/beta/admin/exchange/mailboxes/$MailboxId/folders?`$filter=type eq ‘IPF.StickyNote’”
Invoke-MgGraphRequest -Method Get -Uri $uriTop-level Sticky Note folders under the mailbox IPM folder root
Folder IDs required to enumerate messages inside those folders
The query above returns only top-level folders.
If your Sticky Notes are organized into subfolders, you must:
Recursively enumerate child folders
Or expand folder hierarchies using additional calls
You can do this by querying:
/mailFolders/{id}/childFoldersand repeating until the full hierarchy is discovered.
Creating a new Sticky note in the Microsoft Graph
To create a new Stickynote in the Graph you can just migrate your EWS code to the Graph then use the Messages endpoint of the default notes folder to post/patch or delete sticky notes and it should work eg
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
| $mailbox = "mailbox@domain.com" | |
| # PSETID_Note GUID | |
| $noteGuid = "0006200E-0000-0000-C000-000000000046" | |
| # Build sticky note payload | |
| $body = @{ | |
| subject = "" # Sticky notes typically have no subject | |
| body = @{ | |
| contentType = "Text" | |
| content = "This is a sticky note created via Microsoft Graph" | |
| } | |
| singleValueExtendedProperties = @( | |
| # PR_MESSAGE_CLASS | |
| @{ | |
| id = "String 0x001A" | |
| value = "IPM.StickyNote" | |
| }, | |
| # PidLidNoteColor (0x8B00) | |
| @{ | |
| id = "Integer {$noteGuid} Id 0x8B00" | |
| value = "3" # Yellow | |
| }, | |
| # PidLidNoteHeight (0x8B02) | |
| @{ | |
| id = "Integer {$noteGuid} Id 0x8B02" | |
| value = "200" | |
| }, | |
| # PidLidNoteWidth (0x8B03) | |
| @{ | |
| id = "Integer {$noteGuid} Id 0x8B03" | |
| value = "166" | |
| }, | |
| # PidLidNoteX (Left) (0x8B04) | |
| @{ | |
| id = "Integer {$noteGuid} Id 0x8B04" | |
| value = "80" | |
| }, | |
| # PidLidNoteY (Top) (0x8B05) | |
| @{ | |
| id = "Integer {$noteGuid} Id 0x8B05" | |
| value = "80" | |
| } | |
| ) | |
| } | |
| # Create the sticky note | |
| $uri = "https://graph.microsoft.com/v1.0/users/$mailbox/mailFolders/notes/messages" | |
| $response = Invoke-MgGraphRequest ` | |
| -Method POST ` | |
| -Uri $uri ` | |
| -Body ($body | ConvertTo-Json -Depth 6) | |
| Write-Host "Sticky note created. ID:" $response.id |
Modern Sticky Notes
Modern Sticky notes aren’t documented but seem to use the following 3 properties on an Outlook item as well as the attachments collection for images.
While exploring the undocumented corners of the Microsoft Graph, you might stumble upon a “ghost” endpoint: https://graph.microsoft.com/beta/me/notes. Despite appearing in various permission lists for years, it remains a phantom—functional, yet completely absent from official documentation or metadata comments.
The most compelling reason to use this endpoint is the ShortNotes.Read (and ShortNotes.ReadWrite) permission.
In a world where security teams are increasingly hesitant to grant broad Mail.Read access, ShortNotes.Read offers a path toward the Principle of Least Privilege. It allows an application to access a user’s Sticky Notes without being able to read their private emails or calendar invites.
If you call this endpoint today, you’ll notice something familiar: the response structure is similar to the Messages endpoint but returns the microsoft.graph.note datatype which has a lot fewer properties but does expand the extendedproperites navigation.
The Catch:
Documentation: There is none. You are essentially “flying blind” on a Beta endpoint that Microsoft could change or deprecate without notice.
Extended Properties: Just like the standard Messages endpoint, the
/me/notesendpoint requires MAPI Extended Properties to retrieve specific metadata (like note color or custom formatting) that isn’t part of the basic JSON response.
Conclusion
For those migrating, it is generally best to stick with the Messages endpoint in Microsoft Graph. Unless you are managing custom notes folders, the migration should be relatively straightforward. However, maintaining a broader understanding of how Sticky Notes function across cloud platforms and multiple applications is crucial. As the Outlook classic install base continues to decline, discrepancies in metadata properties—such as note colors—may transition from minor nuances into technical liabilities in the code you migrate.

Comments
Nothing yet. Say the first thing.
Sign in to join the conversation.