Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
This article walks you through how to onboard to the Graph-based Message Trace API. This Microsoft Graph REST API lets you trace email messages that have passed through your Exchange Online organization within the last 90 days.
If you're new to Microsoft Graph, start with the Microsoft Graph overview.
Prerequisites
Before you onboard to the Graph-based message trace API, make sure that the following requirements are met.
Configure authentication
To call Microsoft Graph, your application must obtain an access token from the Microsoft identity platform. For background information, see Authentication and authorization basics. This article uses app-only authentication. App-only authentication lets the app run without a signed-in user. For more information, see Get access without a user. The following sections describe the required setup steps.
Register an application
Register an app in the Microsoft identity platform. For step-by-step instructions, see Register an application with the Microsoft identity platform.
Caution
For production workloads, Microsoft recommends using a certificate over secrets. Don't use self-signed certificates. They can reduce the security of your application due to various factors like use of an outdated hash and cipher suites or lack of validation. Get certificates from a well-known trusted certificate authority.
During registration, record the following information:
- The Application (client) ID
- One of the following credentials:
- A client secret
- A certificate
- A federated identity credential
Configure Microsoft Graph permissions
Grant your application the required application permissions in Microsoft Entra ID.
- In the Microsoft Entra admin center, open App registrations, and then select your app.
- Select
API permissions, and then chooseAdd a permission. - Select
Microsoft Graph, and then selectApplication permissions. - Add the
ExchangeMessageTrace.Read.Allpermission. - Grant admin consent for your tenant.
Request an access token
Use the application ID and credential that you created during app registration to request an access token from the Microsoft identity platform. Include the access token in the Authorization header when calling the Graph-based message trace API.
Provision a service principal
To use the Graph-based message trace API, you must provision a service principal in your tenant for the Microsoft application with the following application (client) ID: 8bd644d1-64a1-4d4b-ae52-2e0cbf64e373
This step creates a local representation of the multi-tenant Microsoft application in your tenant and enables authentication and authorization. For more background information, see Create an enterprise application from a multitenant application..
Create the service principal by using Microsoft Graph PowerShell
You can provision the service principal by using the Microsoft Graph PowerShell SDK.
- Connect to Microsoft Graph:
Connect-MgGraph -Scopes "Application.ReadWrite.All" - Run the following request:
Import-Module Microsoft.Graph.Applications $params = @{ appId = "8bd644d1-64a1-4d4b-ae52-2e0cbf64e373" } New-MgServicePrincipal -BodyParameter $params
Create the service principal by using Microsoft Graph Explorer
You can provision the service principal by calling Microsoft Graph.
Go to Graph explorer
Sign in with an account that has administrator permissions in the tenant where you want to create the service principal.
Run the following request:
POST https://graph.microsoft.com/v1.0/servicePrincipals { "appId" : "8bd644d1-64a1-4d4b-ae52-2e0cbf64e373" }
After you create the service principal, provisioning might take several hours to complete. During this time, requests to the Graph-based message trace API can return 401 (Unauthorized) errors:
Service principal-less authentication failed: The service principal for App ID 8bd644d1-64a1-4d4b-ae52-2e0cbf64e373 was not found. Please create a service principal for this app in your tenant. Provisioning may take several hours to complete.
Call the message trace API
The Graph-based message trace API supports querying message trace data from the last 90 days.
- If you call the API without query parameters, it returns data from the last 48 hours.
- Each request can query up to 10 days of data. To retrieve a larger time range, split the request into multiple queries.
Result limits and paging
By default, the API returns up to 1,000 results per request. You can control the number of returned items by using the $top query parameter.
- Supported range for
$top: 1-5,000 - Maximum results per request: 5,000
If the total number of matching items exceeds the specified page size, the response includes an @odata.nextLink value.
To retrieve the next page of results, send a follow-up request by using the entire URL provided in @odata.nextLink. This URL already includes the required $skiptoken parameter. For more information, see Paging Microsoft Graph data in your app.
Optional Query Parameters
The following query parameters are supported when calling the Graph-based message trace API.
| Parameter | Description |
|---|---|
$filter |
Filters results by supported properties. You can filter on the following fields: id, messageId, receivedDateTime, recipientAddress, senderAddress, status, subject, toIP |
$top |
Specifies the maximum number of items to return in a single response. Supported values range from 1 to 5,000. |
$skiptoken |
Retrieves the next page of results. Use the value provided in the @odata.nextLink property of the previous response. Do not create or modify this value manually. |
Best Practices
- Use the
$topquery parameter to control the number of results returned per request. - Narrow the query time range and apply additional filters (for example,
senderAddress) whenever possible to reduce result size and improve performance.
Examples
The following example shows a basic request to the Graph-based message trace API.
Request headers:
| Name | Description |
|---|---|
| Authorization | Bearer {access_token} |
HTTP Request:
GET https://graph.microsoft.com/beta/admin/exchange/tracing/messageTraces
Reponse:
If the request is successful, the API returns an HTTP 200 OK response and a collection of exchangeMessageTrace objects in the response body:
HTTP/1.1 200 OK
Content-Type: application/json
{
"@odata.context": "https://graph.microsoft.com/beta/$metadata#admin/exchange/tracing/messageTraces",
"value": [
{
"id": "4451a062-48cb-e80d-e8c0-196330437ae6",
"senderAddress": "sender@contoso.com",
"recipientAddress": "recipient@contoso.com",
"messageId": "<d9683b4c-127b-413a-ae2e-fa7dfb32c69d@contoso.com>",
"receivedDateTime": "2025-06-13T10:30:00Z",
"subject": "Quarterly Report",
"size": 45678,
"fromIP": "192.168.1.100",
"toIP": "",
"status": "delivered"
}
]
}
Example 1: Filter messages by message trace ID
The following example retrieves a specific message trace by using the message trace ID.
GET https://graph.microsoft.com/beta/admin/exchange/tracing/messageTraces?$filter=id eq 'a3f6d2c1-5c3b-4f7a-9d1e-2c8f1b0a6e45'
Example 2: Filter messages by time range
To retrieve message traces for a specific time period, filter on the receivedDateTime property and specify both a start and end time:
$filter=receivedDateTime ge {startDate} and receivedDateTime le {endDate}
The following constraints apply:
- The time range must not exceed 10 days.
{startDate}must not be more than 90 days before the current date.{endDate}must not be later than the current date.- Specify both values in ISO 8601 format
(YYYY-MM-DDThh:mm:ssZ).
The following example retrieves message traces for messages received between January 20, 2026 and January 23, 2026 (UTC):
GET https://graph.microsoft.com/beta/admin/exchange/tracing/messageTraces?$filter=receivedDateTime ge 2026-01-20T00:00:00Z and receivedDateTime le 2026-01-23T00:00:00Z
Example 3: Filter messages by subject
The subject property supports the contains, startswith, and endswith filter functions.
The following example lists message traces for messages where the subject contains "Weekly digest":
GET https://graph.microsoft.com/beta/admin/exchange/tracing/messageTraces?$filter=contains(subject, 'Weekly digest')
Example 4: Filter messages by multiple conditions
You can combine multiple filter conditions by using logical operators.
The following example retrieves message traces for messages that were sent to john@contoso.com and have a delivery status of delivered:
GET https://graph.microsoft.com/beta/admin/exchange/tracing/messageTraces?$filter=recipientAddress eq 'john@contoso.com' and status eq 'delivered'
Get message trace details
The Graph-based message trace API provides the getDetailsByRecipient method to retrieve detailed information about the processing steps applied to an email message as it passed through your Exchange Online organization within the last 90 days.
To call this method, you must provide:
- The message trace ID
- The recipient email address
Examples
The following example retrieves message trace details for a specific message and recipient.
Request headers:
| Name | Description |
|---|---|
| Authorization | Bearer {access_token} |
HTTP Request:
GET https://graph.microsoft.com/v1.0/admin/exchange/tracing/messageTraces/7e3b2b2e-1b5e-4b17-80cc-2af6c1d9a3b1/getDetailsByRecipient(recipientAddress='robert@contoso.com')
Reponse:
If the request is successful, the API returns an HTTP 200 OK response and a collection of exchangeMessageTraceDetail objects in the response body:
HTTP/1.1 200 OK
Content-Type: application/json
{
"@odata.context": "https://graph.microsoft.com/beta/$metadata#Collection(microsoft.graph.exchangeMessageTraceDetail)",
"value": [
{
"id": "7e3b2b2e-1b5e-4b17-80cc-2af6c1d9a3b1",
"messageId": "<d9683b4c-127b-413a-ae2e-fa7dfb32c69d@contoso.com>",
"dateTime": "2025-06-13T10:30:05Z",
"event": "Receive",
"action": "",
"description": "Message received by: MN2PR00MB0670.namprd00.prod.outlook.com",
"data": "<root><MEP ... String=\"Message Body\" /></root>"
},
{
"id": "7e3b2b2e-1b5e-4b17-80cc-2af6c1d9a3b1",
"messageId": "<d9683b4c-127b-413a-ae2e-fa7dfb32c69d@contoso.com>",
"dateTime": "2025-06-13T10:30:10Z",
"event": "Deliver",
"action": "",
"description": "The message was successfully delivered.",
"data": "<root><MEP ... String=\"Message Body\" /></root>"
}
]
}
Throttling
To protect Exchange Online resources, ensure service availability, and provide a predictable experience for all tenants, the Graph-based message trace API enforces rate-based throttling. All calls to message trace and message trace detail APIs share the same quota. For more information see Microsoft Graph throttling guidance.
Throttling limits
For each tenant:
- A maximum of 100 requests is allowed within a 5-minute rolling window.
- Throttling is applied only when the request rate exceeds this limit.
- If your automation issues requests more frequently, update it to stay within the allowed threshold.
Request volume versus result size
The number of requests and the number of returned results are evaluated separately:
- A single message trace request can return up to 5,000 results.
- Within a 5-minute rolling window, you can retrieve up to 500,000 results (100 requests × 5,000 results).
- When requests are evenly distributed over time, you can retrieve up to 144 million results per day.
These limits ensure fairness and maintain service availability across all tenants.
Throttling behavior
If your requests exceed the throttling limit, the API returns the following error message:
Your recent queries have surpassed the permitted limit, please try again later.
Retry the request after the throttling window resets.
Summary of limits
| Method | Limit type | Limit |
|---|---|---|
| Message Trace | Per tenant | 100 requests per 5 minutes |
| Message Trace Detail | Per tenant | 100 requests per 5 minutes |
Additional Resources
- Microsoft Graph documentation: Microsoft Graph overview
- Graph-based Message Trace API resource: exchangeMessageTrace resource type
- Graph API Authentication: Microsoft Graph authentication and authorization overview