# 📌 Microsoft Graph API: Email Pinning Workaround

Microsoft Graph does not have a native endpoint for pinning emails. Instead, official Outlook clients track the pinned state under the hood using a low-level MAPI property called `PidTagRenewTime`.

### The "Magic" Mechanics
* **Property Tag:** `SystemTime 0x0F02`
* **Pinned State:** Outlook sets this timestamp to the far-future date: **`4500-01-01T00:00:00Z`**.
* **Unpinned State:** Outlook resets this timestamp to the email's original `receivedDateTime`.

---

## 🚀 API Implementation

### 1. Fetching Pin Status (`GET`)
To read the pinned status, you must explicitly expand the target MAPI property using an OData filter.

```http
GET https://microsoft.com
  ?$expand=singleValueExtendedProperties($filter=id eq 'SystemTime 0x0F02')
  &$top=20
```

#### 📋 UI Parsing Logic
Iterate through the returned `singleValueExtendedProperties` array for each message:
```javascript
const isPinned = message.singleValueExtendedProperties?.some(
  prop => prop.id === "SystemTime 0x0F02" && prop.value.startsWith("4500")
);

if (isPinned) {
  // 1. Render pin icon in UI
  // 2. Anchor/Sort to the top of the folder list
}
```

---

### 2. Pinning an Email (`PATCH`)
To pin a message so it syncs natively back to official Outlook clients, update its MAPI property to the year 4500.

```http
PATCH https://microsoft.com{message-id}
Content-Type: application/json

{
  "singleValueExtendedProperties": [
    {
      "id": "SystemTime 0x0F02",
      "value": "4500-01-01T00:00:00Z"
    }
  ]
}
```

---

### 3. Unpinning an Email (`PATCH`)
To unpin a message, update its value back to the email's original `receivedDateTime`.

```http
PATCH https://microsoft.com{message-id}
Content-Type: application/json

{
  "singleValueExtendedProperties": [
    {
      "id": "SystemTime 0x0F02",
      "value": "2026-09-22T14:44:00Z" 
    }
  ]
}
```

---

## ⚠️ Critical Gotchas for Coding Agents
1. **SDK Serialization Issues:** Official Microsoft Graph SDK libraries (especially .NET and TypeScript/Graph Client) frequently fail to serialize nested `singleValueExtendedProperties` collections properly during `PATCH` requests. **If updates silently fail, bypass the SDK models and drop down to a raw HTTP request.**
2. **Case Sensitivity:** The returned property ID string is strictly case-sensitive (`SystemTime 0x0F02`). Ensure parsing matches exact casings.
3. **No Unpin Deletion:** Do not attempt to clear or delete the property to unpin; Outlook explicitly expects a valid timestamp string to sort it back down chronologically.
