Cisco Meraki – Gather license information through the API

When managing multiple organizations and networks, it can be difficult to get an overview of all licenses. Instead of manually reviewing each organization, you can leverage the API to gather the necessary information. For example, this can be used to store and track license expirations as assets in a CRM.

API User

Create an administrator account with read privileges for the organization and add it to the networks you want to gather information from. In the profile settings, generate a new API key and securely store it for later use.

License overview

Using PowerShell, we can easily export all license-related information to a CSV. Save this script as a .ps1 file in a directory.

ShellScript
Param(
    [Parameter(Mandatory = $true)]
    [string]$BearerToken
)

# Define API headers
$headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$headers.Add("datatype", "json")
$headers.Add("Authorization", "Bearer $BearerToken")  

# Get all organizations
$orgs = Invoke-WebRequest `
    -UseBasicParsing `
    -Uri "https://api.meraki.com/api/v1/organizations" `
    -Method GET `
    -Headers $headers | ConvertFrom-Json

# Initialize list to store results
$licenseList = @()

# Loop through each organization to get license info
foreach ($org in $orgs) {
    $orgId = $org.id
    Write-Host "Fetching license info for Organization ID: $orgId"

    # Fetch licenses overview
    try {
        $licensesOverview = Invoke-WebRequest `
            -UseBasicParsing `
            -Uri "https://api.meraki.com/api/v1/organizations/$orgId/licenses/overview" `
            -Method GET `
            -Headers $headers | ConvertFrom-Json
    }
    catch {
        Write-Host "Failed to fetch licenses overview for Org ID $orgId. Skipping..."
        continue
    }

    # Parse Date
    $expirationDateRaw = $licensesOverview.expirationDate
    # fallback if parsing fails
    $expirationDateFormatted = $expirationDateRaw

    if ($expirationDateRaw) {
        # Remove trailing ' UTC' if present
        $expirationDateTrimmed = $expirationDateRaw -replace ' UTC$', ''
        try {
            # Let PowerShell parse the date automatically (handles single/double digit days)
            $parsedDate = [DateTime]::Parse($expirationDateTrimmed)
            $expirationDateFormatted = $parsedDate.ToString("yyyy-MM-dd HH:mm:ss")
        }
        catch {
            # If parsing fails, just keep $expirationDateFormatted as the raw string
        }
    }

    # Fetch coterm licenses
    try {
        $cotermLicenses = Invoke-WebRequest `
            -UseBasicParsing `
            -Uri "https://api.meraki.com/api/v1/organizations/$orgId/licensing/coterm/licenses" `
            -Method GET `
            -Headers $headers | ConvertFrom-Json
    }
    catch {
        Write-Host "Failed to fetch coterm licenses for Org ID $orgId. Skipping..."
        continue
    }

    # Filter valid license keys: where expired is false and invalidated is false
    $validLicenseKeys = $cotermLicenses |
    Where-Object { $_.expired -eq $false -and $_.invalidated -eq $false } |
    Select-Object -ExpandProperty key -ErrorAction SilentlyContinue
    # Convert $null to empty array to avoid errors
    $validLicenseKeys = @($validLicenseKeys)
    $validLicenseKeysString = [string]::Join(", ", $validLicenseKeys)

    # Filter expired/invalid license keys: where expired is true or invalidated is true
    $invalidLicenseKeys = $cotermLicenses |
    Where-Object { $_.expired -eq $true -or $_.invalidated -eq $true } |
    Select-Object -ExpandProperty key -ErrorAction SilentlyContinue
    # Convert $null to empty array to avoid errors
    $invalidLicenseKeys = @($invalidLicenseKeys)
    $invalidLicenseKeysString = [string]::Join(", ", $invalidLicenseKeys)

    # Create a custom object to store the desired details
    $licenseData = [PSCustomObject]@{
        OrgId                = $orgId
        OrgName              = $org.name
        OverviewStatus       = $licensesOverview.status
        ExpirationDate       = $expirationDateFormatted
        LicensedDeviceCounts = ($licensesOverview.licensedDeviceCounts | ConvertTo-Json -Compress)
        ValidLicenseKeys     = $validLicenseKeysString
        InvalidLicenseKeys   = $invalidLicenseKeysString
    }

    $licenseList += $licenseData
}

# Export to CSV
$csvPath = "$PSScriptRoot\meraki_license.csv"
$licenseList | Export-Csv -Path $csvPath -NoTypeInformation -Encoding UTF8

Write-Host "Export complete! CSV saved to $csvPath"

To run the script, open PowerShell and navigate to the directory where the script is located. Use the -BearerToken parameter to pass the API token.

ShellScript
.\get_all_devices_claimed_at.ps1 -BearerToken YOURTOKENHERE

The script will generate a .csv file in the same directory where the script is stored. The CSV will include the OrgID, Name, Status, Expiration Date, Device Count, Valid Licenses, and Invalid Licenses.

Kommentare

Schreiben Sie einen Kommentar

Ihre E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert