Microsoft 365 licensing

How to check licence subscription status in Microsoft 365

Check each subscription's status and next date with Microsoft Graph PowerShell, read Your products in the Microsoft 365 admin centre, or run Altivane's Licensing report for products needing attention.

By the Published

To check licence subscription status in Microsoft 365, read each subscription's status and next lifecycle date with Microsoft Graph and look at any that isn't Enabled. The date is when the subscription moves to its next state if it isn't renewed, and the admin centre names the states differently from Graph.

Choose the method that fits the job
MethodBest fit
PowerShellA CSV of every subscription with its status and next date, those needing attention first.
Admin centreA billing review of 1 tenant, with why a subscription expired or was disabled.
AltivaneRecommended for regular licence reviews, with the products needing attention beside the rest of the licence figures.

Before you start

Use an account with a role that can read subscriptions through Microsoft Graph, such as Global Reader or Directory Readers. The PowerShell example requests Organization.Read.All, the least privileged permission Microsoft lists for the call; your organisation may require administrator consent. The admin centre needs an administrator who can open the Billing pages, such as a Billing administrator.

Know what the list holds. It is every commercial subscription the organisation has acquired, trials included, with the number of licences in each, read when you run it. The examples read and export; they don't renew, cancel or reactivate anything.

Option 1

Check subscription status with PowerShell

Install the modules once, then connect and export every subscription. The script marks a subscription due soon when its next lifecycle date is within 30 days, comparing in UTC.

PowerShell
# Install once, if the modules are not already installed.
Install-Module Microsoft.Graph.Authentication -Scope CurrentUser
Install-Module Microsoft.Graph.Identity.DirectoryManagement -Scope CurrentUser
PowerShell
$ErrorActionPreference = 'Stop'
Connect-MgGraph -Scopes 'Organization.Read.All' -NoWelcome
try {
    $soon = (Get-Date).ToUniversalTime().AddDays(30)
    $subscriptions = @(Get-MgDirectorySubscription -All)
    if ($subscriptions.Count -eq 0) {
        Write-Output 'No subscriptions were found.'
        return
    }
    $report = @($subscriptions | ForEach-Object {
        $next = $_.NextLifecycleDateTime
        [pscustomobject]@{
            SkuPartNumber = $_.SkuPartNumber
            Status        = $_.Status
            IsTrial       = $_.IsTrial
            TotalLicenses = $_.TotalLicenses
            NextLifecycle = $next
            DueSoon       = [bool]($next -and $next.ToUniversalTime() -lt $soon)
            Created       = $_.CreatedDateTime
        }
    } | Sort-Object @{ Expression = { $_.Status -eq 'Enabled' } }, NextLifecycle)
    $report | Export-Csv -Path './subscription-status.csv' -NoTypeInformation -Encoding utf8
    $attention = @($report | Where-Object { $_.Status -ne 'Enabled' -or $_.DueSoon })
    Write-Output "$($attention.Count) of $($report.Count) subscriptions need a look."
} finally {
    Disconnect-MgGraph | Out-Null
}

Subscriptions that aren't Enabled come first, then the rest by their next date. Status is Enabled, Warning, Suspended, Deleted or LockedOut. Part numbers such as ENTERPRISEPACK are not product names: Microsoft publishes a page that maps one to the other. Change AddDays(30) to look further ahead.

Check seats in grace or suspended

Read the seats in each state for every product, with the same scope.

PowerShell
$ErrorActionPreference = 'Stop'
Connect-MgGraph -Scopes 'Organization.Read.All' -NoWelcome
try {
    Get-MgSubscribedSku -All | Select-Object SkuPartNumber, CapabilityStatus,
        @{ Name = 'Warning'; Expression = { $_.PrepaidUnits.Warning } },
        @{ Name = 'Suspended'; Expression = { $_.PrepaidUnits.Suspended } }
} finally {
    Disconnect-MgGraph | Out-Null
}

Warning counts licences in the grace period after a subscription expires. Suspended counts licences past that grace period: they can't be assigned but can still be reactivated before they're deleted.

Option 2

Check subscription status in the admin centre

  1. Sign in to the Microsoft 365 admin centre for the correct tenant.
  2. Go to Billing > Your products. In the simplified view, select Subscriptions instead.
  3. On the Products tab, read Subscription status for each subscription.
  4. Select a subscription to see why it has expired or been disabled, and its dates.
  5. Leave without changing recurring billing or reactivating anything.

The admin centre uses its own words for the lifecycle: Active, then Expired, Disabled and Deleted. It suits a billing review of 1 tenant; for a file to compare month to month, use PowerShell or Altivane.

Common questions

What do Warning, Suspended and LockedOut mean?

Warning is a subscription that has expired and is in its grace period to renew. Suspended is the next state if it isn't renewed: its licences can't be assigned, but it can still be reactivated before it's deleted. Microsoft describes LockedOut only as a subscription the customer cancelled.

Why does a subscription that renews show a next date?

The next lifecycle date is when it would move to its next state if it isn't renewed, so a subscription that renews has one too. Check its recurring billing in the admin centre before you act on the date.

How many of the licences are in use?

Status says whether a subscription is current, not whether its licences are assigned. See how to find unused licences in Microsoft 365.

Microsoft references

Technical references checked on 7 November 2026. The example scripts have been reviewed and syntax checked; they have not been run against a live tenant.

Talk to us about Altivane

Questions, or pricing? Get in touch.

Contact us