|
| 1 | +--- |
| 2 | +title: Graph REST APIs for custom graphs |
| 3 | +titleSuffix: Microsoft Security |
| 4 | +description: Learn how to use the Graph REST APIs to list and query custom graphs in the Microsoft Sentinel data lake. |
| 5 | +author: EdB-MSFT |
| 6 | +ms.service: microsoft-sentinel |
| 7 | +ms.subservice: sentinel-platform |
| 8 | +ms.topic: reference |
| 9 | +ms.date: 03/30/2026 |
| 10 | +ms.author: edbaynash |
| 11 | +ms.collection: ms-security |
| 12 | + |
| 13 | +#Customer intent: As a security engineer, I want to use the Graph REST APIs to programmatically list and query custom graphs in my Microsoft Sentinel data lake so that I can automate graph-based security analysis. |
| 14 | +--- |
| 15 | + |
| 16 | +# Graph REST APIs for custom graphs |
| 17 | + |
| 18 | +The Graph REST APIs let you list and query custom graphs in your Microsoft Sentinel data lake. Use these APIs to programmatically interact with your custom graphs from any HTTP client, automation pipeline, or custom application. |
| 19 | + |
| 20 | +For more information on creating custom graphs, see [Create custom graphs in the security data lake](create-custom-graphs.md). |
| 21 | + |
| 22 | +## Authentication |
| 23 | + |
| 24 | +The Graph REST APIs use OAuth 2.0 bearer token authentication. To call the APIs, obtain an access token from Microsoft Entra ID and include it in the `Authorization` header of each request. |
| 25 | + |
| 26 | +### Get an access token |
| 27 | + |
| 28 | +1. Register an application in Microsoft Entra ID, or use an existing app registration. For more information, see [Register an application](/entra/identity-platform/quickstart-register-app). |
| 29 | +1. Grant the application the required permissions for Microsoft Defender XDR. |
| 30 | +1. Request an access token using the OAuth 2.0 client credentials flow or on behalf of a signed-in user. |
| 31 | + |
| 32 | +### Include the token in requests |
| 33 | + |
| 34 | +Add the token to the `Authorization` header of every API request: |
| 35 | + |
| 36 | +```http |
| 37 | +Authorization: Bearer <access_token> |
| 38 | +``` |
| 39 | + |
| 40 | +## Base URL |
| 41 | + |
| 42 | +All Graph REST API endpoints use the following base URL: |
| 43 | + |
| 44 | +```http |
| 45 | +https://api.securityplatform.microsoft.com |
| 46 | +``` |
| 47 | + |
| 48 | +## List graphs |
| 49 | + |
| 50 | +List all custom graphs available in your tenant. |
| 51 | + |
| 52 | +### Request |
| 53 | + |
| 54 | +```http |
| 55 | +GET https://api.securityplatform.microsoft.com/graphs/graph-instances?graphTypes=Custom |
| 56 | +``` |
| 57 | + |
| 58 | +No request body is required. |
| 59 | + |
| 60 | +### Response |
| 61 | + |
| 62 | +```json |
| 63 | +{ |
| 64 | + "value": [ |
| 65 | + { |
| 66 | + "name": "custom_graph_10", |
| 67 | + "mapFileName": "custom_graph_10", |
| 68 | + "mapFileVersion": "1.0.0", |
| 69 | + "graphDefinitionName": "custom_graph_10", |
| 70 | + "graphDefinitionVersion": "1.0.0", |
| 71 | + "refreshFrequency": "00:00:00", |
| 72 | + "createTime": "11/04/2025 22:32:43", |
| 73 | + "lastUpdateTime": "11/04/2025 22:32:43", |
| 74 | + "lastSnapshotTime": "2025-11-04T22:34:04.7105015+00:00", |
| 75 | + "lastSnapshotRequestTime": "2025-11-04T22:32:52.0187838+00:00", |
| 76 | + "instanceStatus": "Ready" |
| 77 | + }, |
| 78 | + { |
| 79 | + "name": "notebook_graph_5", |
| 80 | + "mapFileName": null, |
| 81 | + "mapFileVersion": null, |
| 82 | + "graphDefinitionName": "notebook_graph_5", |
| 83 | + "graphDefinitionVersion": "1.0.0", |
| 84 | + "refreshFrequency": "00:00:00", |
| 85 | + "createTime": "11/04/2025 20:15:22", |
| 86 | + "lastUpdateTime": "11/04/2025 20:15:22", |
| 87 | + "lastSnapshotTime": null, |
| 88 | + "lastSnapshotRequestTime": null, |
| 89 | + "instanceStatus": "Creating" |
| 90 | + } |
| 91 | + ] |
| 92 | +} |
| 93 | +``` |
| 94 | + |
| 95 | +### Response properties |
| 96 | + |
| 97 | +| Property | Type | Description | |
| 98 | +|----------|------|-------------| |
| 99 | +| `name` | String | The name of the graph instance. | |
| 100 | +| `mapFileName` | String | The name of the map file associated with the graph. | |
| 101 | +| `mapFileVersion` | String | The version of the map file. | |
| 102 | +| `graphDefinitionName` | String | The name of the graph definition used to build this instance. | |
| 103 | +| `graphDefinitionVersion` | String | The version of the graph definition. | |
| 104 | +| `refreshFrequency` | String | How often the graph data is refreshed. | |
| 105 | +| `createTime` | String | When the graph instance was created. | |
| 106 | +| `lastUpdateTime` | String | When the graph instance was last updated. | |
| 107 | +| `lastSnapshotTime` | String | The timestamp of the most recent data snapshot. | |
| 108 | +| `lastSnapshotRequestTime` | String | When the last snapshot was requested. | |
| 109 | +| `instanceStatus` | String | The current status of the graph instance. | |
| 110 | + |
| 111 | +### Response status codes |
| 112 | + |
| 113 | +| Status code | Description | |
| 114 | +|-------------|-------------| |
| 115 | +| 200 OK | List retrieved successfully. | |
| 116 | + |
| 117 | +## Query a graph |
| 118 | + |
| 119 | +Query a custom graph using Graph Query Language (GQL). For more information on GQL, see [GQL reference for Microsoft Sentinel graph](gql-reference-for-sentinel-custom-graph.md). |
| 120 | + |
| 121 | +> [!NOTE] |
| 122 | +> `{graphName}` refers to the `name` of a graph returned from the list operation. |
| 123 | +
|
| 124 | +### Request |
| 125 | + |
| 126 | +```http |
| 127 | +POST https://api.securityplatform.microsoft.com/graphs/graph-instances/{graphName}/query |
| 128 | +Content-Type: application/json |
| 129 | +``` |
| 130 | + |
| 131 | +### Request body |
| 132 | + |
| 133 | +```json |
| 134 | +{ |
| 135 | + "query": "string", |
| 136 | + "queryLanguage": "GQL" |
| 137 | +} |
| 138 | +``` |
| 139 | + |
| 140 | +### Request body properties |
| 141 | + |
| 142 | +| Property | Type | Required | Description | |
| 143 | +|----------|------|----------|-------------| |
| 144 | +| `query` | String | Yes | The GQL query to execute. | |
| 145 | +| `queryLanguage` | String | Yes | The query language. Must be `GQL`. | |
| 146 | +| `responseFormats` | String array | No | Controls the format of the query response. Accepts one or both of the following values: `Table`, `Graph`. Defaults to `Table` if not specified. | |
| 147 | + |
| 148 | +### Response formats |
| 149 | + |
| 150 | +The `responseFormats` property controls the structure of the response: |
| 151 | + |
| 152 | +| Format | Description | |
| 153 | +|--------|-------------| |
| 154 | +| `Table` | Returns raw tabular data (default if not specified). | |
| 155 | +| `Graph` | Returns graph-structured data with nodes and edges. | |
| 156 | + |
| 157 | +You can request one or both formats: |
| 158 | +- `["Table"]` - Returns only table format. |
| 159 | +- `["Graph"]` - Returns only graph format. |
| 160 | +- `["Table", "Graph"]` - Returns both formats in the response. |
| 161 | + |
| 162 | +### Example: Basic query |
| 163 | + |
| 164 | +```http |
| 165 | +POST https://api.securityplatform.microsoft.com/graphs/graph-instances/{graphName}/query |
| 166 | +Content-Type: application/json |
| 167 | +
|
| 168 | +{ |
| 169 | + "query": "MATCH (u)-[v]->(w) RETURN * LIMIT 2", |
| 170 | + "queryLanguage": "GQL" |
| 171 | +} |
| 172 | +``` |
| 173 | + |
| 174 | +### Example: Query with both response formats |
| 175 | + |
| 176 | +```http |
| 177 | +POST https://api.securityplatform.microsoft.com/graphs/graph-instances/{graphName}/query |
| 178 | +Content-Type: application/json |
| 179 | +
|
| 180 | +{ |
| 181 | + "query": "MATCH (n:User)-[r:HasAccess]->(m:Resource) RETURN n, r, m LIMIT 100", |
| 182 | + "responseFormats": ["Table", "Graph"], |
| 183 | + "queryLanguage": "GQL" |
| 184 | +} |
| 185 | +``` |
| 186 | + |
| 187 | +### Sample response (both formats) |
| 188 | + |
| 189 | +```json |
| 190 | +{ |
| 191 | + "status": 200, |
| 192 | + "result": { |
| 193 | + "rawData": { |
| 194 | + "tables": [ |
| 195 | + { |
| 196 | + "tableName": "PrimaryResult", |
| 197 | + "columns": [ |
| 198 | + { |
| 199 | + "columnName": "u", |
| 200 | + "dataType": "dynamic" |
| 201 | + }, |
| 202 | + { |
| 203 | + "columnName": "r", |
| 204 | + "dataType": "dynamic" |
| 205 | + }, |
| 206 | + { |
| 207 | + "columnName": "g", |
| 208 | + "dataType": "dynamic" |
| 209 | + } |
| 210 | + ], |
| 211 | + "rows": [ |
| 212 | + [ |
| 213 | + { |
| 214 | + "oid": "node-user-001", |
| 215 | + "labels": ["User"], |
| 216 | + "properties": { |
| 217 | + "name": "Aino Rebane", |
| 218 | + |
| 219 | + "department": "Engineering" |
| 220 | + } |
| 221 | + }, |
| 222 | + { |
| 223 | + "oid": "edge-001", |
| 224 | + "labels": ["HasRole"], |
| 225 | + "sourceOid": "node-user-001", |
| 226 | + "targetOid": "node-group-001", |
| 227 | + "properties": { |
| 228 | + "assignedDate": "2024-01-15T10:30:00Z", |
| 229 | + |
| 230 | + } |
| 231 | + }, |
| 232 | + { |
| 233 | + "oid": "node-group-001", |
| 234 | + "labels": ["Group"], |
| 235 | + "properties": { |
| 236 | + "name": "Administrators", |
| 237 | + "description": "System administrators group", |
| 238 | + "memberCount": 25 |
| 239 | + } |
| 240 | + } |
| 241 | + ] |
| 242 | + ] |
| 243 | + } |
| 244 | + ] |
| 245 | + }, |
| 246 | + "graph": { |
| 247 | + "nodes": [ |
| 248 | + { |
| 249 | + "id": "node-user-001", |
| 250 | + "labels": ["User"], |
| 251 | + "properties": { |
| 252 | + "name": "Aino Rebane", |
| 253 | + |
| 254 | + "department": "Engineering" |
| 255 | + } |
| 256 | + }, |
| 257 | + { |
| 258 | + "id": "node-group-001", |
| 259 | + "labels": ["Group"], |
| 260 | + "properties": { |
| 261 | + "name": "Administrators", |
| 262 | + "description": "System administrators group", |
| 263 | + "memberCount": 25 |
| 264 | + } |
| 265 | + }, |
| 266 | + { |
| 267 | + "id": "node-group-002", |
| 268 | + "labels": ["Group"], |
| 269 | + "properties": { |
| 270 | + "name": "Engineering Team", |
| 271 | + "description": "Software engineering team", |
| 272 | + "memberCount": 150 |
| 273 | + } |
| 274 | + } |
| 275 | + ], |
| 276 | + "edges": [ |
| 277 | + { |
| 278 | + "id": "edge-001", |
| 279 | + "sourceId": "node-user-001", |
| 280 | + "targetId": "node-group-001", |
| 281 | + "labels": ["HasRole"], |
| 282 | + "properties": { |
| 283 | + "assignedDate": "2024-01-15T10:30:00Z", |
| 284 | + |
| 285 | + } |
| 286 | + }, |
| 287 | + { |
| 288 | + "id": "edge-002", |
| 289 | + "sourceId": "node-user-001", |
| 290 | + "targetId": "node-group-002", |
| 291 | + "labels": ["HasRole"], |
| 292 | + "properties": { |
| 293 | + "assignedDate": "2024-02-01T14:20:00Z", |
| 294 | + |
| 295 | + } |
| 296 | + } |
| 297 | + ] |
| 298 | + } |
| 299 | + }, |
| 300 | + "correlationId": "aaaa0000-bb11-2222-33cc-444444dddddd" |
| 301 | +} |
| 302 | +``` |
| 303 | + |
| 304 | +### Response status codes |
| 305 | + |
| 306 | +| Status code | Description | |
| 307 | +|-------------|-------------| |
| 308 | +| 200 OK | Query executed successfully. | |
| 309 | +| 404 Not Found | The specified graph instance doesn't exist. | |
| 310 | + |
| 311 | +### Error response example |
| 312 | + |
| 313 | +```json |
| 314 | +{ |
| 315 | + "error": { |
| 316 | + "code": "GraphInstanceNotFound", |
| 317 | + "message": "Graph Instance CustomGraph1 does not exist.", |
| 318 | + "target": null, |
| 319 | + "details": [] |
| 320 | + } |
| 321 | +} |
| 322 | +``` |
| 323 | + |
| 324 | +## Next steps |
| 325 | + |
| 326 | +- [Create custom graphs in the security data lake](create-custom-graphs.md) |
| 327 | +- [GQL reference for Microsoft Sentinel graph](gql-reference-for-sentinel-custom-graph.md) |
| 328 | +- [Microsoft Sentinel graph Python SDK provider reference](sentinel-graph-provider-reference.md) |
| 329 | +- [VS Code extension notebooks](notebooks.md) |
0 commit comments