{
  "openapi": "3.1.0",
  "info": {
    "title": "sending.ac Mailbox API",
    "version": "v1alpha1",
    "summary": "A drop-in Microsoft Graph proxy for mailboxes you provisioned through sending.ac.",
    "description": "The Mailbox API lets you send and read mail from mailboxes you own on sending.ac, using **an unmodified Microsoft Graph SDK**.\n\nPoint your Graph client at this base URL and authenticate with a sending.ac API key. We handle the rest.\n\n## Stability\n\n`v1alpha1` is explicitly **unstable**. Endpoints, payloads and error codes may change without notice and without a version bump. Do not build anything you cannot redeploy.\n\n## Authentication\n\nSend your key as a bearer token:\n\n```\nAuthorization: Bearer sk_live_xxxxxxxxxxxx\n```\n\nThe key must be **scope `mailbox`** and **environment `live`**. Both are enforced:\n\n- a Provisioning key returns `403` / `ErrorAccessDenied`\n- a sandbox key returns `403` / `ErrorAccessDenied`\n\nSandbox keys are refused by design rather than downgraded to a mock. Every call here touches a real Microsoft 365 mailbox and `sendMail` delivers real mail to real recipients, so there is nothing sandbox-like to offer. Mint a Mailbox key under **Production Credentials** in the customer portal.\n\n## Using a Microsoft Graph SDK\n\nThe `/azure` surface mirrors Graph's own URL layout, so an official SDK works unchanged — but two settings are mandatory:\n\n```javascript\nimport { Client } from '@microsoft/microsoft-graph-client';\n\nconst client = Client.init({\n  baseUrl: 'https://api.customers.ac/api/mailbox/v1alpha1/azure',\n  defaultVersion: 'v1.0',\n  authProvider: (done) => done(null, 'sk_live_xxxxxxxxxxxx'),\n  // Required: the SDK only attaches the Authorization header to hosts it trusts.\n  // Without this your requests arrive unauthenticated and fail with 401.\n  customHosts: new Set(['api.customers.ac']),\n});\n\nawait client.api('/users/sender@yourdomain.com/sendMail').post({ message, saveToSentItems: true });\n```\n\nThe SDK also refuses to authenticate over plain `http://`, so there is no way to point it at a non-TLS host for testing.\n\n## Paging\n\n`@odata.nextLink` in responses is rewritten to point back at this API, so `PageIterator` and equivalent helpers follow pages through the proxy with the same API key. You never receive a raw `graph.microsoft.com` link.\n\n## Error format\n\nErrors on `/azure` and `/google` use **Microsoft's OData error shape**, not a sending.ac envelope, so Graph SDKs deserialise them as ordinary `GraphError`s:\n\n```json\n{\n  \"error\": {\n    \"code\": \"InvalidAuthenticationToken\",\n    \"message\": \"The API key is invalid or has been revoked.\",\n    \"innerError\": { \"request-id\": \"…\", \"date\": \"…\" }\n  }\n}\n```\n\n`innerError.request-id` is the correlation id for the request. Quote it in support requests.\n\n## Rate limits\n\n60 requests per minute per API key on the Graph surface. Exceeding it returns `429` with `Retry-After`, `X-RateLimit-Limit`, `X-RateLimit-Remaining` and `X-RateLimit-Reset`.\n\n## Retries\n\n`sendMail` is **never retried automatically** on a transport error, because the failure is ambiguous — Microsoft may already have accepted and delivered the message. Retry it yourself only if a duplicate send is acceptable. Read-only calls are safe to retry.",
    "contact": {
      "name": "sending.ac support",
      "url": "https://api.customers.ac"
    }
  },
  "servers": [
    {
      "url": "https://api.customers.ac/api/mailbox/v1alpha1",
      "description": "Production. Note the /api prefix — omitting it returns 404."
    }
  ],
  "security": [
    {
      "BearerAuth": []
    }
  ],
  "tags": [
    {
      "name": "Service",
      "description": "Service metadata."
    },
    {
      "name": "Mail",
      "description": "The Microsoft Graph surface. Only the operations listed here are reachable — the proxy runs a strict allow-list, so any other Graph path returns `404` even if it exists upstream.\n\nThe `{email}` in each path must be a mailbox owned by the account the API key belongs to. A mailbox you do not own returns `404`, not `403`, so the API never reveals which addresses are sending.ac mailboxes."
    },
    {
      "name": "Events",
      "description": "**Not yet available.** Delivery and engagement events are planned for a future `v1alpha` revision and are documented here only so you can see what is coming. There is no endpoint to call today — the paths below are not routed and will return `404`.\n\nUntil this ships, read mail state with `GET /users/{email}/messages`."
    },
    {
      "name": "Google Workspace",
      "description": "**Not yet available.** The route is reserved and answers `501` so client code can detect it deliberately rather than by guessing. Only Microsoft 365 mailboxes are supported."
    }
  ],
  "paths": {
    "/": {
      "get": {
        "tags": [
          "Service"
        ],
        "summary": "Service root",
        "description": "Returns service metadata. This is the only unauthenticated endpoint — useful as a reachability check before you debug credentials.",
        "operationId": "getServiceRoot",
        "security": [],
        "responses": {
          "200": {
            "description": "Service metadata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "service": {
                      "type": "string",
                      "examples": [
                        "mailbox-api"
                      ]
                    },
                    "version": {
                      "type": "string",
                      "examples": [
                        "v1alpha1"
                      ]
                    },
                    "status": {
                      "type": "string",
                      "examples": [
                        "alpha"
                      ]
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/azure/v1.0/users/{email}/sendMail": {
      "parameters": [
        {
          "$ref": "#/components/parameters/MailboxEmail"
        }
      ],
      "post": {
        "tags": [
          "Mail"
        ],
        "summary": "Send mail",
        "description": "Sends a message as the mailbox in the path. Mirrors Graph's [`POST /users/{id}/sendMail`](https://learn.microsoft.com/graph/api/user-sendmail).\n\nReturns `202 Accepted` with an empty body once Microsoft has accepted the message — that is acceptance for delivery, not proof of delivery.\n\n**This operation is not retried for you.** If the forward to Graph fails at the transport layer, the request may still have been accepted and sent upstream, so the proxy surfaces `502` rather than risking a duplicate send. Treat a `502` here as *unknown*, not *failed*, and only retry if sending twice is acceptable.\n\nBodies larger than 10 MB are rejected with `413` before any call to Microsoft. Graph itself rejects payloads over roughly 4 MB, so attachments should stay well below that.",
        "operationId": "sendMail",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SendMailRequest"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Accepted by Microsoft for delivery. Empty body.",
            "headers": {
              "x-ms-request-id": {
                "$ref": "#/components/headers/MsRequestId"
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "413": {
            "$ref": "#/components/responses/PayloadTooLarge"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "502": {
            "$ref": "#/components/responses/UpstreamUnavailable"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/azure/v1.0/users/{email}/messages": {
      "parameters": [
        {
          "$ref": "#/components/parameters/MailboxEmail"
        }
      ],
      "get": {
        "tags": [
          "Mail"
        ],
        "summary": "List messages",
        "description": "Lists messages in the mailbox. Mirrors Graph's [`GET /users/{id}/messages`](https://learn.microsoft.com/graph/api/user-list-messages).\n\nOData query parameters are forwarded to Microsoft untouched, so `$select`, `$filter`, `$top`, `$orderby` and `$search` behave exactly as they do against Graph directly. `$search` additionally requires the `ConsistencyLevel: eventual` header, which is one of the headers the proxy forwards.\n\n`@odata.nextLink` in the response is rewritten to this API, so SDK page iterators work unchanged.",
        "operationId": "listMessages",
        "parameters": [
          {
            "name": "$select",
            "in": "query",
            "description": "Comma-separated properties to return. Strongly recommended — the default projection is large.",
            "schema": {
              "type": "string"
            },
            "example": "id,subject,from,receivedDateTime,isRead"
          },
          {
            "name": "$filter",
            "in": "query",
            "description": "OData filter expression.",
            "schema": {
              "type": "string"
            },
            "example": "receivedDateTime ge 2026-07-01T00:00:00Z"
          },
          {
            "name": "$top",
            "in": "query",
            "description": "Page size.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 999
            },
            "example": 25
          },
          {
            "name": "$orderby",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "example": "receivedDateTime desc"
          }
        ],
        "responses": {
          "200": {
            "description": "A page of messages.",
            "headers": {
              "x-ms-request-id": {
                "$ref": "#/components/headers/MsRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MessageCollection"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "502": {
            "$ref": "#/components/responses/UpstreamUnavailable"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/azure/v1.0/users/{email}/messages/{id}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/MailboxEmail"
        },
        {
          "name": "id",
          "in": "path",
          "required": true,
          "description": "Graph message id. Opaque and forwarded byte-for-byte — do not decode or re-encode it, as ids routinely contain `=`, `+` and `/`.",
          "schema": {
            "type": "string"
          }
        }
      ],
      "get": {
        "tags": [
          "Mail"
        ],
        "summary": "Get a message",
        "description": "Fetches a single message by id. Mirrors Graph's [`GET /users/{id}/messages/{message-id}`](https://learn.microsoft.com/graph/api/message-get).\n\nUse the `id` returned by **List messages**.",
        "operationId": "getMessage",
        "parameters": [
          {
            "name": "$select",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "example": "id,subject,body,from,toRecipients,receivedDateTime"
          }
        ],
        "responses": {
          "200": {
            "description": "The message.",
            "headers": {
              "x-ms-request-id": {
                "$ref": "#/components/headers/MsRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Message"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "502": {
            "$ref": "#/components/responses/UpstreamUnavailable"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/azure/v1.0/users/{email}/mailFolders": {
      "parameters": [
        {
          "$ref": "#/components/parameters/MailboxEmail"
        }
      ],
      "get": {
        "tags": [
          "Mail"
        ],
        "summary": "List mail folders",
        "description": "Lists the mailbox's folders. Mirrors Graph's [`GET /users/{id}/mailFolders`](https://learn.microsoft.com/graph/api/user-list-mailfolders).\n\nUse this to discover folder ids and to read `totalItemCount` / `unreadItemCount` without pulling messages.",
        "operationId": "listMailFolders",
        "responses": {
          "200": {
            "description": "A page of mail folders.",
            "headers": {
              "x-ms-request-id": {
                "$ref": "#/components/headers/MsRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MailFolderCollection"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "502": {
            "$ref": "#/components/responses/UpstreamUnavailable"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/events": {
      "get": {
        "tags": [
          "Events"
        ],
        "summary": "List mailbox events — NOT YET AVAILABLE",
        "description": "> **Not yet available.** This endpoint is not routed. Calling it today returns `404`.\n\nPlanned: a pollable feed of delivery and engagement events (sent, delivered, bounced, opened, replied) across the mailboxes you own, so you do not have to poll each mailbox's messages to detect state changes.\n\nWhen it ships it will carry a tighter rate limit than the Graph surface — 10 requests per minute per key rather than 60 — because it is a substantially heavier query.\n\nNo request or response shape is committed yet; treat everything about this operation as subject to change. Do not implement against it.",
        "operationId": "listEventsNotYetAvailable",
        "deprecated": true,
        "responses": {
          "404": {
            "description": "Not routed. This endpoint does not exist yet.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HouseError"
                }
              }
            }
          }
        }
      }
    },
    "/events/subscriptions": {
      "post": {
        "tags": [
          "Events"
        ],
        "summary": "Create an event webhook subscription — NOT YET AVAILABLE",
        "description": "> **Not yet available.** This endpoint is not routed. Calling it today returns `404`.\n\nPlanned: push delivery of the same events as `GET /events`, so you can react without polling.\n\nNo request or response shape is committed yet. Do not implement against it.",
        "operationId": "createEventSubscriptionNotYetAvailable",
        "deprecated": true,
        "responses": {
          "404": {
            "description": "Not routed. This endpoint does not exist yet.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HouseError"
                }
              }
            }
          }
        }
      }
    },
    "/google/v1/{path}": {
      "get": {
        "tags": [
          "Google Workspace"
        ],
        "summary": "Gmail proxy — NOT YET AVAILABLE",
        "description": "> **Not yet available.** Reserved for a Gmail equivalent of the `/azure` surface.\n\nUnlike the Events paths, this one **is** routed and deliberately answers `501` so client code can distinguish \"not supported yet\" from \"wrong URL\".",
        "operationId": "googleProxyNotImplemented",
        "deprecated": true,
        "parameters": [
          {
            "name": "path",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "501": {
            "description": "Google Workspace mailboxes are not available through the Mailbox API yet.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GraphError"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "BearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "A sending.ac API key with scope `mailbox` and environment `live`. Issue one under **Production Credentials** in the customer portal. Provisioning keys and sandbox keys are rejected with `403`."
      }
    },
    "parameters": {
      "MailboxEmail": {
        "name": "email",
        "in": "path",
        "required": true,
        "description": "The mailbox address, which must belong to the account owning the API key. A mailbox that exists but is not yours returns `404` rather than `403`, so this endpoint cannot be used to discover which addresses are sending.ac mailboxes.",
        "schema": {
          "type": "string",
          "format": "email"
        },
        "example": "sender@yourdomain.com"
      }
    },
    "headers": {
      "MsRequestId": {
        "description": "Microsoft's own request id for the upstream call. Quote this when raising an issue with Microsoft support. (Graph returns it as `request-id`; it is re-emitted under this name because `Request-ID` is already used for our own request identifier.)",
        "schema": {
          "type": "string"
        }
      },
      "RetryAfter": {
        "description": "Seconds to wait before retrying.",
        "schema": {
          "type": "integer"
        }
      }
    },
    "responses": {
      "BadRequest": {
        "description": "Malformed request — for example an invalid OData query or a body Graph refused.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/GraphError"
            },
            "example": {
              "error": {
                "code": "BadRequest",
                "message": "The request is malformed or incorrect.",
                "innerError": {
                  "request-id": "a26397a7-04e1-4c8f",
                  "date": "2026-07-31T08:24:57+00:00"
                }
              }
            }
          }
        }
      },
      "Unauthorized": {
        "description": "Missing or invalid API key. Also returned when the key has been revoked.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/GraphError"
            },
            "example": {
              "error": {
                "code": "InvalidAuthenticationToken",
                "message": "The API key is invalid or has been revoked.",
                "innerError": {
                  "request-id": "a26397a7-04e1-4c8f",
                  "date": "2026-07-31T08:24:57+00:00"
                }
              }
            }
          }
        }
      },
      "Forbidden": {
        "description": "The key is valid but not usable here: it is a Provisioning key rather than a Mailbox key, it is a sandbox key, or it is not linked to a sending.ac account.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/GraphError"
            },
            "example": {
              "error": {
                "code": "ErrorAccessDenied",
                "message": "The Mailbox API requires a live API key; sandbox keys are not accepted because these calls send and read real mail.",
                "innerError": {
                  "request-id": "a26397a7-04e1-4c8f",
                  "date": "2026-07-31T08:24:57+00:00"
                }
              }
            }
          }
        }
      },
      "NotFound": {
        "description": "Either the mailbox is not yours (or does not exist), or the Graph path is outside the allow-list. Both answer `404` so the API does not disclose which.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/GraphError"
            },
            "example": {
              "error": {
                "code": "ResourceNotFound",
                "message": "No such mailbox.",
                "innerError": {
                  "request-id": "a26397a7-04e1-4c8f",
                  "date": "2026-07-31T08:24:57+00:00"
                }
              }
            }
          }
        }
      },
      "PayloadTooLarge": {
        "description": "Request body above 10 MB. Rejected before any call to Microsoft.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/GraphError"
            }
          }
        }
      },
      "TooManyRequests": {
        "description": "Rate limit exceeded — 60 requests per minute per API key.",
        "headers": {
          "Retry-After": {
            "$ref": "#/components/headers/RetryAfter"
          },
          "X-RateLimit-Limit": {
            "schema": {
              "type": "integer"
            }
          },
          "X-RateLimit-Remaining": {
            "schema": {
              "type": "integer"
            }
          },
          "X-RateLimit-Reset": {
            "description": "Unix timestamp at which the window resets.",
            "schema": {
              "type": "integer"
            }
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/GraphError"
            },
            "example": {
              "error": {
                "code": "TooManyRequests",
                "message": "Too many requests. Retry after the number of seconds in Retry-After.",
                "innerError": {
                  "request-id": "a26397a7-04e1-4c8f",
                  "date": "2026-07-31T08:24:57+00:00"
                }
              }
            }
          }
        }
      },
      "UpstreamUnavailable": {
        "description": "Microsoft Graph could not be reached, or its response was too large to relay.\n\nFor `sendMail` this is **ambiguous**: the message may already have been accepted and sent. Do not retry automatically.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/GraphError"
            },
            "example": {
              "error": {
                "code": "UnknownError",
                "message": "Could not reach Microsoft Graph. The request may not have been processed; retry only if it is safe to repeat.",
                "innerError": {
                  "request-id": "a26397a7-04e1-4c8f",
                  "date": "2026-07-31T08:24:57+00:00"
                }
              }
            }
          }
        }
      },
      "ServiceUnavailable": {
        "description": "The Mailbox API is temporarily unavailable, or credentials could not be verified. Safe to retry with backoff.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/GraphError"
            }
          }
        }
      }
    },
    "schemas": {
      "GraphError": {
        "type": "object",
        "title": "OData error",
        "description": "Microsoft's error shape, used on the `/azure` and `/google` surfaces so Graph SDKs deserialise failures as ordinary errors.",
        "properties": {
          "error": {
            "type": "object",
            "properties": {
              "code": {
                "type": "string",
                "description": "Microsoft's error code for the status.",
                "enum": [
                  "BadRequest",
                  "InvalidAuthenticationToken",
                  "ErrorAccessDenied",
                  "ResourceNotFound",
                  "RequestNotSupported",
                  "RequestEntityTooLarge",
                  "TooManyRequests",
                  "UnknownError",
                  "NotImplemented",
                  "ServiceUnavailable",
                  "Timeout"
                ]
              },
              "message": {
                "type": "string"
              },
              "innerError": {
                "type": "object",
                "properties": {
                  "request-id": {
                    "type": "string",
                    "description": "Correlation id for this request. Quote it in support requests."
                  },
                  "date": {
                    "type": "string",
                    "format": "date-time"
                  }
                }
              }
            },
            "required": [
              "code",
              "message"
            ]
          }
        },
        "required": [
          "error"
        ]
      },
      "HouseError": {
        "type": "object",
        "title": "sending.ac error",
        "description": "The envelope used outside the provider-native surfaces.",
        "properties": {
          "error": {
            "type": "object",
            "properties": {
              "code": {
                "type": "string",
                "examples": [
                  "service.unavailable"
                ]
              },
              "message": {
                "type": "string"
              }
            },
            "required": [
              "code",
              "message"
            ]
          }
        },
        "required": [
          "error"
        ]
      },
      "EmailAddress": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "examples": [
              "Jane Doe"
            ]
          },
          "address": {
            "type": "string",
            "format": "email",
            "examples": [
              "jane@example.com"
            ]
          }
        },
        "required": [
          "address"
        ]
      },
      "Recipient": {
        "type": "object",
        "properties": {
          "emailAddress": {
            "$ref": "#/components/schemas/EmailAddress"
          }
        },
        "required": [
          "emailAddress"
        ]
      },
      "ItemBody": {
        "type": "object",
        "properties": {
          "contentType": {
            "type": "string",
            "enum": [
              "text",
              "html"
            ],
            "default": "text"
          },
          "content": {
            "type": "string"
          }
        },
        "required": [
          "content"
        ]
      },
      "SendMailRequest": {
        "type": "object",
        "description": "Graph's `sendMail` payload, passed through unchanged.",
        "properties": {
          "message": {
            "$ref": "#/components/schemas/Message"
          },
          "saveToSentItems": {
            "type": "boolean",
            "default": true,
            "description": "Whether to keep a copy in Sent Items."
          }
        },
        "required": [
          "message"
        ],
        "examples": [
          {
            "message": {
              "subject": "Following up",
              "body": {
                "contentType": "html",
                "content": "<p>Hi — following up on my last note.</p>"
              },
              "toRecipients": [
                {
                  "emailAddress": {
                    "address": "prospect@example.com"
                  }
                }
              ]
            },
            "saveToSentItems": true
          }
        ]
      },
      "Message": {
        "type": "object",
        "description": "A Graph message. Only commonly used properties are listed; the full Graph resource is returned and accepted.",
        "properties": {
          "id": {
            "type": "string",
            "description": "Opaque message id. Forward it byte-for-byte — ids contain `=`, `+` and `/`."
          },
          "subject": {
            "type": "string"
          },
          "body": {
            "$ref": "#/components/schemas/ItemBody"
          },
          "bodyPreview": {
            "type": "string"
          },
          "from": {
            "$ref": "#/components/schemas/Recipient"
          },
          "toRecipients": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Recipient"
            }
          },
          "ccRecipients": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Recipient"
            }
          },
          "receivedDateTime": {
            "type": "string",
            "format": "date-time"
          },
          "sentDateTime": {
            "type": "string",
            "format": "date-time"
          },
          "isRead": {
            "type": "boolean"
          },
          "hasAttachments": {
            "type": "boolean"
          },
          "conversationId": {
            "type": "string"
          },
          "internetMessageId": {
            "type": "string"
          }
        }
      },
      "MessageCollection": {
        "type": "object",
        "properties": {
          "value": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Message"
            }
          },
          "@odata.nextLink": {
            "type": "string",
            "format": "uri",
            "description": "Link to the next page, rewritten to point at this API rather than graph.microsoft.com. Follow it with the same API key."
          }
        }
      },
      "MailFolder": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "displayName": {
            "type": "string",
            "examples": [
              "Inbox"
            ]
          },
          "parentFolderId": {
            "type": "string"
          },
          "childFolderCount": {
            "type": "integer"
          },
          "unreadItemCount": {
            "type": "integer"
          },
          "totalItemCount": {
            "type": "integer"
          }
        }
      },
      "MailFolderCollection": {
        "type": "object",
        "properties": {
          "value": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/MailFolder"
            }
          },
          "@odata.nextLink": {
            "type": "string",
            "format": "uri"
          }
        }
      }
    }
  }
}
