Get from tenant consent to billing leakage insight.
This guide covers the practical setup steps for MSP License Tracker: connecting your clients' Microsoft 365 tenants, running scans, reading reports, using the REST API, and troubleshooting the common deployment issues.
Security
Tenant-scoped access
Microsoft Graph
Admin consent required
Secrets
Server-side only
Support
Ticket workflow built in
Getting started
Create your workspace
Sign in, complete onboarding, and confirm the company details that will appear on client-facing reports.
Connect Microsoft Entra
Use an admin account from the client tenant, grant admin consent, and make sure the app has the Graph permissions requested during connection.
Run the first scan
Start a tenant sync from onboarding or the Tenants page. The scan imports users, subscriptions, license assignments, sign-in signals, Copilot usage, and billing alerts where Microsoft permits them.
Review leakage
Use Dashboard, License Leakage, Inactive Users, and Billing Alerts to prioritize savings before the next client invoice. Leakage combines the cost of inactive-user seats and unassigned (purchased-but-unallocated) seats.
Microsoft tenant setup
Who creates the app registration?
You own the multitenant app registration in your Microsoft Entra tenant. Client tenant admins only grant consent to that app.
Which account grants consent?
Use a Global Administrator or another role allowed to approve Microsoft Graph permissions in the client tenant.
Which permissions matter?
Directory, organization, license assignment, users, and audit/sign-in permissions power the reports. Premium-only APIs may fail on tenants without the right license.
What does Copilot tracking need?
Microsoft 365 Copilot usage requires the Reports.Read.All permission and an admin role (Global Administrator, Global Reader, or Reports Reader) on the connected account. Without it the Copilot tab shows an access-denied notice instead of usage data.
How do scans work?
The app uses stored tenant connection metadata and server-side credentials to fetch Graph data, then writes normalized license and alert records to the database.
Disconnect vs. delete a tenant?
Disconnecting stops syncs but keeps the plan slot so you can reconnect later. Deleting hides the tenant from all reports and frees the slot — its history is retained but excluded everywhere.
API & webhooks
The REST API and outbound webhooks are available on the Pro plan. Generate an API key under Settings → API access — the key is shown once, so copy it immediately.
Authentication
Send your key as a bearer token on every request:
curl https://www.msplicensetracker.com/api/v1/tenants \ -H "Authorization: Bearer mlt_live_xxxxxxxxxxxxxxxx"
Endpoints
GET /api/v1/tenants
Connected tenants with license, cost, and leakage summary.
GET /api/v1/summary
Account-wide totals across every connected tenant.
GET /api/v1/alerts
The 100 most recent alerts.
Webhooks
Add a webhook URL under Settings → API access to receive an alert.created event whenever an alert fires. Every request carries an X-MLT-Signature header of the form sha256=<hmac> — an HMAC-SHA256 of the raw request body, keyed with your signing secret. Recompute it on your side and compare before trusting the payload.
Troubleshooting
Invalid client secret
Use the Microsoft client secret value, not the secret ID. If it was lost, create a new secret in App registrations and update your environment variable.
Insufficient privileges
The client tenant admin must grant admin consent for the requested Microsoft Graph permissions. Some APIs also require Entra ID P1/P2 or specific tenant capabilities.
Local database not loading
Set DATABASE_URL before running Prisma or the local dev server. Railway internal URLs only work inside Railway; use the public proxy URL locally.
Consent screen blocks unverified app
For customer tenants, Microsoft may require verified publisher status. In early testing, use an admin-controlled tenant where consent policy allows the app.