# Microsoft 365 Copilot Setup

> Connect a Microsoft 365 tenant so ZopNight can track Copilot seats, usage and cost. Lists the exact Microsoft Graph permissions, the admin role needed to approve them, and the optional billing role.

Source: https://zop.dev/developer-docs/integrations/microsoft-365-copilot

---

The **Microsoft 365 Copilot** integration shows how many Copilot seats you pay for, who uses them,
and which seats sit idle. It has two views:

- **Cost**: **Costs → Reports → AI Spend → Seat licences**. What the seats cost each month, seats
  never assigned, and what you could reclaim.
- **Usage**: **AI Estate → AI Gateway → Seat licences**. Who uses Copilot, how often, in which apps,
  and adoption over time.

ZopNight only reads data. It never assigns or removes licences.

## Before you start

| Need | Detail |
|---|---|
| Microsoft 365 Copilot licences | The tenant must hold at least one Copilot licence. |
| An admin who can grant consent | A **Global Administrator** or **Privileged Role Administrator**. |
| A ZopNight **Admin** | Only Admins can connect or disconnect a tenant. |
| For prices (optional) | A Microsoft Customer Agreement or Microsoft Partner Agreement billing account. |

Application Administrator and Cloud Application Administrator
[can't grant Microsoft Graph application permissions](https://learn.microsoft.com/en-us/entra/identity/enterprise-apps/grant-admin-consent),
so they can't complete this setup.

You don't need to create an app registration or share a secret. ZopNight uses its own multi-tenant
app and stores only your tenant ID.

## Access to grant

### Microsoft Graph application permissions

The admin approves these four read-only permissions on one consent screen. Each is the permission
Microsoft lists for the API ZopNight calls.

| Permission | Why ZopNight needs it |
|---|---|
| `Organization.Read.All` | Tenant name, licence SKUs and seat counts, renewal dates |
| `User.Read.All` | The users who hold a Copilot licence |
| `Reports.Read.All` | Copilot usage per user, and Microsoft 365 activity |
| `ReportSettings.Read.All` | Whether reports hide user names |

Microsoft's pages for each API, with the permission it needs:

- `Organization.Read.All`:
  [organization](https://learn.microsoft.com/en-us/graph/api/organization-list?view=graph-rest-1.0),
  [subscribedSkus](https://learn.microsoft.com/en-us/graph/api/subscribedsku-list?view=graph-rest-1.0),
  [subscriptions](https://learn.microsoft.com/en-us/graph/api/directory-list-subscriptions?view=graph-rest-1.0)
- `User.Read.All`: [List users](https://learn.microsoft.com/en-us/graph/api/user-list?view=graph-rest-1.0)
- `Reports.Read.All`:
  [Copilot usage](https://learn.microsoft.com/en-us/microsoft-365/copilot/extensibility/api/admin-settings/reports/copilotreportroot-getmicrosoft365copilotusageuserdetail),
  [user count trend](https://learn.microsoft.com/en-us/microsoft-365/copilot/extensibility/api/admin-settings/reports/copilotreportroot-getmicrosoft365copilotusercounttrend),
  [active users](https://learn.microsoft.com/en-us/graph/api/reportroot-getoffice365activeuserdetail?view=graph-rest-1.0)
- `ReportSettings.Read.All`:
  [Get adminReportSettings](https://learn.microsoft.com/en-us/graph/api/adminreportsettings-get?view=graph-rest-1.0)

### Billing role (optional, for prices)

To show what each seat costs, grant the ZopNight app **Billing account reader** on the billing
account that pays for Copilot. **Billing profile reader** on the right billing profile also works.
A billing account owner or a Global Administrator can do this. See
[Billing roles for Microsoft Customer Agreements](https://learn.microsoft.com/en-us/azure/cost-management-billing/manage/understand-mca-roles).

On the cost view, **Grant access** opens these steps in ZopNight.

1. Open [Billing scopes in the Azure portal](https://portal.azure.com/#blade/Microsoft_Azure_GTM/ModernBillingMenuBlade/AllBillingScopes).
2. If the list is empty and you are a Global Administrator, tick **As a Global administrator, check
   this box to view all Microsoft Customer Agreement (MCA) scopes**
   ([why](https://learn.microsoft.com/en-us/azure/cost-management-billing/manage/elevate-access-global-admin)).
3. Pick the billing account whose **Products + services** lists Microsoft 365 Copilot. With more
   than one, grant on each that does.
4. Open **Access control (IAM)** and click **Add**.
5. Choose **Billing account reader**, search for **zopnight**, and click **Add**.

You can also assign it with the
[Billing Role Assignments API](https://learn.microsoft.com/en-us/rest/api/billing/billing-role-assignments/create-by-billing-account?view=rest-billing-2024-04-01).

**Note**

ZopNight reads prices from **Microsoft Customer Agreement** and **Microsoft Partner Agreement**
accounts. A
[Partner Agreement account belongs to a CSP partner](https://learn.microsoft.com/en-us/azure/cost-management-billing/manage/view-all-accounts),
so it applies when your partner connects the tenant. **Enterprise Agreement** and **Microsoft
Online Services Program** accounts are skipped. You still get seat counts and usage, but no prices.

### Tenant setting (for per-person usage)

Microsoft hides user names in reports by default. With names hidden, ZopNight can count seats but
can't say which person is idle. To show names, a **Global Administrator** goes to
**Microsoft 365 admin center → Settings → Org settings → Services → Reports**, clears **Conceal
user, group, and site names in all reports**, and saves. See
[Show user, group, or site details in usage reports](https://learn.microsoft.com/en-us/microsoft-365/admin/activity-reports/activity-reports?view=o365-worldwide#show-user-group-or-site-details-in-usage-reports).

## Set it up

**Start the connection**

In ZopNight, open **Settings → Integrations → AI Seat Licences** and click **Connect** on the
**Microsoft 365 Copilot** tile.

**Sign in to Microsoft**

Sign in with a work account in the tenant you want to connect. ZopNight uses this step to learn
which tenant it is.

**Approve the permissions**

Microsoft shows the consent screen with the four permissions above. A Global Administrator or
Privileged Role Administrator approves it for the whole organisation.

**Wait for the first sync**

You return to ZopNight and see **Microsoft 365 connected**. Seat data appears after the next sync.
Microsoft publishes Copilot usage
[within about 48 hours of the end of each day](https://learn.microsoft.com/en-us/microsoft-365/admin/activity-reports/microsoft-365-copilot-usage?view=o365-worldwide),
so usage lags behind seat counts.

To connect more tenants, use **Connect another tenant** on the same tile. Each tenant can belong to
only one ZopNight organisation.

## Reading the seat pages

| Term | Meaning |
|---|---|
| **Healthy** | Used Copilot on at least Microsoft's adoption target of 12 active days in 28, about three a week. For other windows ZopNight scales it: 3 of 7 days, 39 of 90. |
| **Below threshold** | Used Copilot in the window, on fewer days than that. |
| **Idle** | No Copilot activity in any app in the window, including a licensed seat that was never used. |
| **Not reported** | Microsoft sent no usage for the seat, so it is not counted as idle. It has its own colour and badge. |
| **Enabled** | On the adoption chart: the people Microsoft counts as enabled for Copilot that day. It comes from Microsoft's usage report and can differ from the licences assigned on the seat count, which comes from your licence directory. |

On the usage view:

- **Seat status** shows the share of seats in each status. If Microsoft sends no per-person usage
  for the tenant, the status counts are left blank rather than shown as 0.
- **Time since last activity** groups seats by when they last used Copilot, coloured by status. A
  bracket above the columns counts the idle seats.
- **Adoption over time** shades any day Microsoft published no figure for. The sentence above it
  compares the latest day with the first day in the window on the same weekday, since use drops at
  weekends. A window of 7 days or fewer has no such day, so it states the latest day only.
- **Seats** lists people with the seats needing attention first, and the apps each person has ever
  used. Select a person to see the decision for that seat, what it costs, and each app with the
  days used in the window and the last day used. An app shows **Not used** when Microsoft reported
  the person's other apps but no use of that one, and **Not reported** when a reported app's
  figure could not be read, since ZopNight then cannot tell which apps were used.

The usage view's date picker offers **Last 7, 28 or 90 Days**, which are Microsoft's own report
windows, and any **custom range** of up to 180 days. A custom range is rebuilt from the daily
readings ZopNight has stored since the tenant connected. A day with no reading, whether it came
before you connected the tenant or Microsoft skipped it, counts as no data, and the page says how
many days have one. Prompts are available for 7, 28 or 90 days only. Costs and reclaim advice always
use 28 days.

## Disconnect and remove access

**Settings → Integrations → AI Seat Licences → Disconnect** removes the tenant and its data from
ZopNight. It changes nothing in your Microsoft tenant. To remove access fully:

1. [Delete the ZopNight enterprise app](https://learn.microsoft.com/en-us/entra/identity/enterprise-apps/delete-application-portal):
   in the Microsoft Entra admin center, open **Enterprise apps → All applications**, pick
   **zopnight**, open **Properties** and click **Delete**. This needs a Cloud Application
   Administrator, an Application Administrator, or the app's owner.
2. Remove the billing role from the ZopNight app under **Cost Management + Billing → Access control
   (IAM)**, if you granted it.

## Troubleshooting

| Problem | Cause and fix |
|---|---|
| Consent fails, or the tile never connects | The approver wasn't a Global or Privileged Role Administrator. Ask one to connect again. |
| Seat counts show, but no usage | Microsoft hasn't published usage yet. Wait up to two days after connecting. |
| Usage is shown without names | Reports hide user names. Change the tenant setting above. |
| No prices | Click **Grant access** on the cost view for the steps. Either no billing role was granted, it was granted on a billing account that doesn't pay for Copilot, or the account isn't a Customer or Partner Agreement. |
| A custom range is refused | Ranges can span at most 180 days and start no earlier than 180 days ago. |
| Tenant already connected to a different ZopNight organisation | Another ZopNight organisation owns this tenant. Contact support to move it. |
