Skip to main content

Common Conventions

The parameter formats and response patterns that many routes share. The reference pages link here instead of repeating them, so read this page once before writing a script.

Pin one scan per script run

Start every script with getAllScans and pin the scanId you use, so every page and every call reads the same scan.

Scan IDs

Most inventory, security, policy and Advisor data is tied to a scan. Scan IDs look like scan-2026-10-14T02:00:00.000Z; URL-encode the colons (%3A) when building URLs by hand. Get them from GET /api/getAllScans, which lists only finished scans, newest first.

Many single-scan routes also accept the literal scanId=latest, meaning the most recent completed scan. Supported routes are marked accepts scanId=latest in the reference. Where it isn't supported, latest behaves like an unknown scan.

An unknown scanId usually returns 500, not 404

Most single-scan routes return 500 with a generic message for a scan that doesn't exist. Always take IDs from getAllScans rather than constructing them.

Scan Pairs (Comparisons)

Comparison routes take two required parameters: baseScanId is the older scan and compareScanId is the newer one. Change status values are added (only in the newer scan), modified (in both, different) and deleted (only in the older scan).

Scan-pair error responses
StatusMessageCause
400Please provide both 'baseScanId' and 'compareScanId' query parameters.Either parameter missing
404Base scan with ID '<id>' not found. or Compare scan with ID '<id>' not found.Unknown scan
400Base scan '<base>' must be older than compare scan '<compare>'.Pair reversed or equal

Don't add hierarchy counts across levels

Hierarchy change summaries count each change at subscription, resource-group and resource level. Summing across levels triple-counts.

Time Windows

Change, activity log and attribution routes take a window. Both ends are required, as ISO 8601 timestamps such as 2026-10-01T00:00:00Z. Start must be before end, and a window may span at most 366 days per call.

Bounds are inclusive to the whole second: the start is truncated to its second and the whole end second is included. To walk a longer period, start each next window at previous end + 1 second.

Time-window error messages
StatusMessage
400<name> must be a valid ISO timestamp
400<name> must be before <name>
400time window must not exceed 366 days

getChangeAttribution compares raw strings

That route compares your timestamps as you sent them, with no whole-second normalisation. Send whole-second Z timestamps for predictable edges.

Cost Date Ranges

Cost explorer and spend accountability take startDate and endDate in YYYY-MM-DD, inclusive. Send both or neither; what happens when only one is sent varies per route and is noted there. The range may span at most 366 days. This cap applies to every caller, including the web UI.

Cost date range error messages
StatusMessage
400Invalid date format. Use YYYY-MM-DD format.
400startDate must not be after endDate
400Invalid calendar date.
400Date range exceeds maximum supported span of 366 days

List Parameters

Two list formats exist. Each route says which it uses.

Plain comma list (CSV)

a,b,c. Used for GUIDs, ARM types and enum values.

Encoded list

Used by the role-assignments-details filters and getChangeAttribution subscriptionIds. Each value is percent-encoded first, then the values are joined with commas, then the whole parameter is URL-encoded as usual. So a value is encoded twice on the wire: the role name My, Role is sent as My%252C%2520Role. GUIDs and enum values contain nothing to encode, so a plain comma list works for them.

List parameter error messages
StatusMessageCause
400<name> contains a value that is not valid percent-encodingEncoded list with a malformed value
400<name> must list at most 200 valuesMost lists cap at 200 values. Split larger lists across calls

Entity Selectors

Detail routes for one subscription, resource group, resource or management group use entityType to pick the level, then need the identifiers for that level:

Identifiers required per entityType
entityTypeIdentifiers
subscriptionsubscriptionId
resourceGroupsubscriptionId + resourceGroupName
resourcesubscriptionId + resourceGroupName + resourceName
managementGroup (only where listed)managementGroupId
  • An entityType outside the route's list gives 400 entityType must be one of <values>. Exact missing-identifier messages vary per route and are listed there.
  • subscriptionId is usually matched exactly as stored, so copy it from a summary response. Resource group and resource names are matched case-insensitively.
  • Detail routes return items at exactly that level. A resource-group query does not include its resources' items unless the route says otherwise.

Paging

Most routes return everything in one response with no paging. Four paging patterns exist:

Paging patterns
PatternRoutesHow it works
pageSize + continuationTokengetScanResultsReal database paging. Follow pagination.continuationToken until hasMore is false. Send the same other parameters on every page
pageSize + continuationToken (offset)getScanDiffOptional. Omit pageSize to get the whole diff at once (recommended)
limit + offsetgetResourceGraphChangesOptional. The response has totalCount and hasMore
page + pageSizedefender-vulnerability-findings, getDefenderAssessmentDiffDetails, getDefenderAlertDiffDetails, getAdvisorRecommendationDiffDetails1-based. The response has totalCount, totalPages, currentPage. A page past the end returns the last page, so stop at totalPages
skip + takegetAuditLogsskip up to 10000, take up to 100

Compact Summaries and combinedCounts

"Summary" and "hierarchy" routes return compactSummaries[]: one row per entity with small count dictionaries, for example severityCounts: {"High": 3}.

combinedCounts keys join several dimensions with |, for example "High|Unhealthy|false|SoftwareUpdate". Each item is counted in exactly one key, so to count items matching several filters, sum the matching keys. Each route documents its key order. Some routes drop empty parts from the key, giving fewer segments.

Response Fields

  • Field names are camelCase. Timestamps are ISO 8601 UTC.
  • Optional fields are omitted when they have no value, rather than sent as null, unless a route says otherwise.
  • Many responses include internal bookkeeping fields: names starting with _ (_rid, _self, _etag, _attachments, _ts) and id, partitionKey, docType, firstScanSequence, lastScanSequence, scanIds. These are not part of the contract; ignore them.
  • Resource IDs come in two forms: resourceId is the lower-case ARM ID and originalResourceId keeps Azure's casing.

Hidden Items

Users can hide recommendations and Defender items in the UI. The API returns hidden items too. Defender and Azure Advisor items carry isHidden, and some Defender routes take a showHidden parameter. Security findings, sizing, orphaned and other recommendation routes have no hidden marker at all.

Currency

Cost amounts are in the currency of the underlying data; there is no conversion. Totals that span currencies are raw sums, so check currency and mixedCurrency before adding anything up. VM and disk sizing amounts are USD retail list prices.

Was this page helpful?