# OData Query Parameters

## Introduction

Whether you are using Mindflow, Power Automate, Azure Logic Apps, or custom Python/Node.js scripts—efficiency is the difference between a flow that runs in seconds and one that hits API rate limits and crashes.

OData query parameters are the "surgical tools" of the Microsoft Graph API. Here is why they are non-negotiable for automation:

## 1. Performance and Latency

By default, an API request might return dozens of fields you don't need (like metadata, IDs, and timestamps).

- **The Problem:** Large JSON payloads take longer to generate on the server and longer for your flow to parse.
- **The OData Fix:** Use `$select` to fetch only the specific keys your automation needs. This reduces the "payload weight" significantly.

## 2. Avoiding Rate Limits (Throttling)

Microsoft Graph enforces **Throttling Limits**. If your automation loops through 1,000 users just to find the 5 who are in "Marketing," you are wasting your request quota.

- **The Problem:** Over-fetching data leads to `429 Too Many Requests` errors.
- **The OData Fix:** Use `$filter` to let the Microsoft server do the heavy lifting. Only the relevant records reach your flow, preserving your API quota.

## 3. Simplifying Logic (Server-Side vs. Client-Side)

Without OData, your automation script has to include complex "If/Else" blocks and "Filter Array" actions to sort through data.

- **The Problem:** Complex logic inside a flow makes it harder to maintain and slower to execute.
- **The OData Fix:** Using `$orderby` and `$filter` ensures the data arrives "pre-processed." Your flow becomes a simple, linear path rather than a messy web of conditions.

## 4. Data Privacy and Security

When automating sensitive tasks (like HR reporting), you often want to avoid even _touching_ certain data points.

- **The Problem:** Logging or storing full API responses might inadvertently capture PII (Personally Identifiable Information) you aren't authorized to handle.
- **The OData Fix:** Use `$select` to ensure that sensitive fields never even leave the Microsoft Cloud and never enter your automation logs.

:::note
**The Golden Rule of Automation:** > _Never ask the API for "everything" and then filter it yourself. Ask the API for exactly what you want, in the order you want it._
:::

## Walkthrough

To master OData in Microsoft Graph, it’s helpful to understand that some parameters are simple filters, while others are "shapers" that change the structure of the data itself.

Below are the main OData Query parameters explained, including advanced filtering, lambda operators, and media streams.

## 1. Advanced Filtering (`$filter`)

Beyond simple equality (`eq`), `$filter` supports complex logic and **Lambda Operators** for collections.

### Lambda Operators: `any` and `all`

These are used when you want to filter a parent object based on a collection property (an array).

- **`any`**: Returns true if at least one item in the collection matches.
- **`all`**: Returns true only if every item in the collection matches.

## Example: Get users who have a specific license assigned

```json
GET https://graph.microsoft.com/v1.0/users?$filter=assignedLicenses/any(s:s/skuId eq c42b9cae-ea4f-4ab7-9717-81576235ccac)
```

### Advanced Query Header

For certain properties (like `mail` or `displayName` on Users), you must enable **Advanced Queries** by adding a specific header to your request:

- **Header:** `ConsistencyLevel: eventual`
- **Query:** Must include `$count=true`

## Example: Find users whose email ends with a specific domain

```json
GET https://graph.microsoft.com/v1.0/users?$filter=endsWith(mail, '@gmail.com')&$count=true
ConsistencyLevel: eventual
```

## 2. Raw Content & Streams (`$value`)

The `/$value` segment is used to bypass the JSON metadata and download the "actual" content. This is essential for files and binary data.

### Example 1: Downloading a OneDrive File

Instead of getting the JSON description of a file, this gets the file bytes.

```json
GET https://graph.microsoft.com/v1.0/me/drive/items/{item-id}/content
```

## (Note: For DriveItems, `/content` is an alias for `/$value`.)

### Example 2: Outlook Item Attachments

If an email has another email attached to it (an `itemAttachment`), you can get that attached email's **MIME** content:

```json
GET https://graph.microsoft.com/v1.0/me/messages/{msg-id}/attachments/{att-id}/$value
```

## 3. Deep Shaping (`$expand` & `$select`)

You can "nest" query parameters inside an expand to clean up the related data before it even reaches you.

### Example: Get Groups and only the Names of their Members

Instead of getting every property of every member, we "nest" a `$select` inside the `$expand`.

```json
GET https://graph.microsoft.com/v1.0/groups?$expand=members($select=displayName,mail)
```

- **Syntax Tip:** Inside the parentheses of an `$expand`, multiple parameters are separated by a **semicolon** (`;`), not an ampersand (`&`).

## 4. Full-Text Search (`$search`)

While `$filter` is for structured data (e.g., `status eq 'active'`), `$search` is for "finding a needle in a haystack."

| **Feature**   | **$filter**            | **$search**                              |
| ------------- | ---------------------- | ---------------------------------------- |
| **Logic**     | Strict (Boolean)       | Tokenized / Scored                       |
| **Wildcards** | Limited (`startsWith`) | Powerful (KQL - Keyword Query Language)  |
| **Target**    | Specific Property      | Default Properties (Body, Subject, etc.) |

Example: Search for emails about "Project Delta" with high importance

```json
GET https://graph.microsoft.com/v1.0/me/messages?$search="Project Delta" AND importance:high
```

## 5. Pagination & Sorting (`$top`, `$skip`, `$orderby`)

These are most often used in UI applications to build data tables.

Example: The "Leaderboard" Query, get the 5 most recently updated files in a site.

```json
GET https://graph.microsoft.com/v1.0/sites/{site-id}/drive/root/children?$orderby=lastModifiedDateTime desc&$top=5
```

## 6. Support Matrix & Tips

- **Case Sensitivity:** OData parameters themselves (`$filter`, `$select`) are case-sensitive.
- **URL Encoding:** Always URL-encode your query strings. A space should be `%20` and a single quote should be `%27`.
- **Beta vs v1.0:** Some advanced filtering (like `contains`) is only available in the `/beta` endpoint. In `v1.0`, you are usually limited to `startsWith` and `endsWith`.

## 7. Common Error: "Property not supported"

If you receive a `400 Bad Request` saying a property is not supported for filtering:

1. Check if the property is **indexable** in the Graph documentation.
2. Try adding the `ConsistencyLevel: eventual` header.
3. Check if you are trying to filter a property that requires `$search` (like the body of a message).
