# `GraphApi`
[🔗](https://github.com/keenmate/microsoft_graph/blob/v1.0.0-rc.1/lib/graph_api.ex#L1)

Elixir client for the Microsoft Graph API.

GraphApi provides a clean, idiomatic interface to Microsoft Graph API resources
with built-in authentication, OData query building, batch requests, pagination,
schema casting, and error handling.

## Architecture Overview

```
┌─────────────────────────────────────────────────────────┐
│                    YOUR APPLICATION                     │
└─────────────────────────────────────────────────────────┘
                           │
            ┌──────────────┴──────────────┐
            │                             │
            ▼                             ▼
  ┌───────────────────┐       ┌───────────────────┐
  │   App-Only Auth   │       │  Delegated Auth   │
  │ (Client Creds)    │       │ (User OAuth Token) │
  │                   │       │                   │
  │ Config + secret → │       │ access_token per  │
  │ auto token mgmt   │       │ request           │
  └─────────┬─────────┘       └─────────┬─────────┘
            │                           │
            └─────────────┬─────────────┘
                          │
                          ▼
            ┌───────────────────────────┐
            │      GraphApi.Client      │
            │  Req.Request + middleware  │
            └─────────────┬─────────────┘
                          │
            ┌─────────────┼─────────────┐
            │             │             │
            ▼             ▼             ▼
      ┌──────────┐ ┌──────────┐ ┌──────────┐
      │   Auth   │ │  Error   │ │  Retry   │
      │Middleware│ │ Handling │ │Middleware│
      └──────────┘ └──────────┘ └──────────┘
                          │
                          ▼
┌─────────────────────────────────────────────────────────┐
│                  RESOURCE MODULES                       │
│                                                         │
│  Users · Groups · Mail · Calendar · Files · Subscriptions│
│                                                         │
│  Each function returns {:ok, result} | {:error, error}  │
│  Each has a _query variant for batch requests            │
└─────────────────────────┬───────────────────────────────┘
                          │
            ┌─────────────┼─────────────┐
            │             │             │
            ▼             ▼             ▼
      ┌──────────┐ ┌──────────┐ ┌──────────┐
      │  OData   │ │  Batch   │ │  Delta   │
      │  Query   │ │ Requests │ │ Queries  │
      │ Builder  │ │ (up to   │ │ (change  │
      │ + Filter │ │  20/call)│ │ tracking)│
      └──────────┘ └──────────┘ └──────────┘
            │             │             │
            └─────────────┼─────────────┘
                          │
                          ▼
            ┌───────────────────────────┐
            │     Schema Casting        │
            │  JSON → typed structs     │
            │  v1.0 + Beta schemas      │
            │  Views for projections    │
            └───────────────────────────┘
```

## Authentication Modes

**App-only (client credentials)** — configure once, tokens managed automatically:

    config :keen_microsoft_graphapi, :config,
      tenant_id: System.fetch_env!("AZURE_TENANT_ID"),
      client_id: System.fetch_env!("AZURE_CLIENT_ID"),
      client_secret: System.fetch_env!("AZURE_CLIENT_SECRET")

    {:ok, users} = GraphApi.Users.list()

**Delegated (user token)** — pass an OAuth access token per request:

    client = GraphApi.Client.new()
    {:ok, me} = GraphApi.Users.get("me", client: client, access_token: user_token)

**Multi-tenant** — explicit config per tenant:

    config = GraphApi.Config.new!(tenant_id: "aaa", client_id: "bbb", client_secret: "ccc")
    client = GraphApi.Client.new(config: config)
    {:ok, users} = GraphApi.Users.list(client: client)

## Resource Modules

| Module | Endpoints | Description |
|--------|-----------|-------------|
| `GraphApi.Users` | 30 | CRUD, manager, memberships, licenses, photos, auth methods |
| `GraphApi.Groups` | 26 | CRUD, members, owners, app roles, permission grants |
| `GraphApi.Mail` | 9 | Messages, send, drafts, folders, delta |
| `GraphApi.Calendar` | 8 | Events CRUD, calendar view, calendars list |
| `GraphApi.Files` | 23 | Drives, items, upload/download, permissions, versions |
| `GraphApi.Subscriptions` | 5 | Webhook subscriptions CRUD |

Every function has a `_query` variant that returns a `%GraphApi.Batch.Request{}`
for use in batch operations.

## Query Building

    alias GraphApi.OData
    alias GraphApi.OData.Filter
    alias GraphApi.Schema.User

    # Functional OData builder
    query = OData.new()
      |> OData.select(["displayName", "mail"])
      |> OData.filter(User, account_enabled: true)
      |> OData.top(25)

    # Or build complex filters
    filter = Filter.new(User)
      |> Filter.where(:display_name, :starts_with, "A")
      |> Filter.or_where(:department, :eq, "Engineering")

    {:ok, response} = GraphApi.Users.list(query: OData.new() |> OData.filter(filter))

## Error Handling

All operations return `{:ok, result}`, `:ok`, or `{:error, error}`:

* `GraphApi.Error.ApiError` — non-2xx Graph API responses
* `GraphApi.Error.AuthError` — authentication failures
* `GraphApi.Error.RateLimitError` — 429 after retry exhaustion (with `retry_after`)

## Key Features

* **Batch requests** — up to 20 requests per HTTP call via `GraphApi.Batch`
* **Delta queries** — incremental change tracking via `GraphApi.Delta`
* **Pagination** — lazy streaming via `GraphApi.Pagination`
* **Schema casting** — auto-cast JSON to typed structs with the `:as` option
* **Views** — field projections that auto-inject `$select` via `GraphApi.View`
* **Webhooks** — parse and validate Graph notifications via `GraphApi.Webhook`

---

*Consult [api-reference.md](api-reference.md) for complete listing*
