Skip to content

Copilot Cost Management API: What It Does and What to Use It For

Microsoft has released a Graph API that lets you read and change Copilot credits, spending policies and alert thresholds with a script. I called all 22 documented operations in a test tenant and show what comes back and when running your own analysis pays off.

By , Microsoft MVP Published

A man in a dark polo shirt holds three coin-like discs in his hand; a stream of purple light flows from them through the letters “API” toward a server rack on the right.
AI-generated image

The Microsoft 365 Copilot Cost Management API reads and controls your tenant’s credit consumption through Microsoft Graph. You can see how many credits were purchased and used, which spending policies apply, who gets alerts, and why a particular user can’t use a service.

The cost management dashboard in the Microsoft 365 admin center shows consumption by policy, user, group, agent, service and funding source. The API gives you the raw data, which you can feed into your own systems and combine with other data.

I ran it end to end in my test tenant on October 29, 2026. Here’s what it is, what comes back, and what I’d use it for. The dashboard I built from it is on the Lookbook page (in German) and on GitHub.

What is the Copilot Cost Management API?

It’s an extension of Microsoft Graph under the path /copilot/costManagement. It belongs to usage-based billing: services such as Copilot Cowork and Work IQ bill in Copilot credits, and admins use spending policies to decide who can consume how many. The API covers exactly that control.

One thing up front: the API lives under /beta. Microsoft’s documentation says beta APIs can change and aren’t supported in production applications. For your own reports and scripts, that means checking your calls regularly.

What does the API return, and what doesn’t it?

I sorted the functions from Microsoft’s documentation into six groups and added the permission each call needs.

Group What you get Permission
Tenant credit balance One row per billing method: purchased, consumed, remaining CopilotCostManagement.Read.All
Spending policies Create, read, update, delete; limits for the period and per user CopilotCostManagement-Policy.Read.All or .ReadWrite.All
A policy’s audience All users or selected groups CopilotCostManagement-Assignment.Read.All or .ReadWrite.All
Services per policy Which services a policy governs same as policies
Alerts Thresholds and recipients, notification only same as policies
User balances Per user and service: whether they can consume, and under which policy CopilotCostManagement-UserData.Read.All

What the API deliberately leaves out is also in the documentation: it’s denominated in credits and contains no currency amounts, invoices, prices or forecasts. You work out the dollar or euro amount yourself, using the price in your contract.

I ran into two limits myself. First, it returns snapshots. The credit balance carries only a timestamp for the last update, not a history. If you want to know how consumption develops over the weeks, you have to store the calls yourself on a schedule. Second, you can’t list all user balances: calling userBalances without a user ID ends in a 404. You query user by user, so you need the user list from another source.

What did I see in the test tenant?

I called all 22 documented operations, in 62 calls over about 19 seconds. 51 went through as expected, 11 ended in an error on purpose (ten while writing, plus the 404 on userBalances), and there were no unexpected responses. The write calls ran against a test policy that I created and deleted at the end. I’ve left out names, IDs and addresses here.

The credit balance

One call returns the balance for both billing methods:

GET https://graph.microsoft.com/beta/copilot/costManagement/getTenantCreditBalance
Billing method Purchased Consumed Remaining
Prepaid credits 50,000 22,265.38 25,029
Pay-as-you-go – 3,152.11 –

Two things stand out. The data was over an hour old when I called it: the timestamp said 09:50 UTC, and the call ran after 11:05. And 50,000 minus 22,265.38 is 27,734.62, but the API reports 25,029 as the remainder. I can’t explain the difference of roughly 2,706 credits from the responses. That’s why I don’t calculate the remaining balance myself and read the remainingQuantity field instead.

For pay-as-you-go, the API returns consumption only. At $0.01 per credit, as described in the article on the Copilot pricing model, that works out to roughly $31.52. The API doesn’t do that step for you.

The policies

My tenant has one policy named “All Users Policy.” The name sounds like everyone. The type in the response is selectedGroupsSpendingPolicy, though, and the policy applies to exactly one security group. If you go by the name alone, you read it wrong. The API shows the actual type, the assigned group, the four governed services (cowork, workIQ, sharePointCopilot, oneDriveCopilot) and the limits. Both limits are set to unlimited here.

An alert is attached to the same policy: enabled, with an absolute threshold of 25,000 credits. Percentage thresholds are also possible, as a whole number from 1 to 100 according to the documentation.

Why can’t someone use a service?

The user balance answers a support question that otherwise means clicking through the admin center. For the account I queried, this came back:

"unevaluatedServices": [
  { "serviceId": "cowork", "reason": "noApplicablePolicy" },
  { "serviceId": "workIQ", "reason": "noApplicablePolicy" }
]

No policy applies to this account for Cowork and Work IQ, and the list of service balances is empty. The only policy in the tenant applies to a single group. I read this as a missing assignment rather than a limit that was reached. I saw that on one account only, so check it against your own users.

A privacy warning: the list of alert recipients returns complete user objects, in my case including a phone number and a secondary address. Treat the result as personal data and store only what you need.

What happens when you write?

Write calls check a lot before they change anything. The error responses show the rules. I triggered ten of them on purpose. The last row (409) came when I tried to change the billing method of a disabled test policy that had no audience. My test plan allowed for either a 200 or a 409:

What I tried Response Meaning
Update a policy without If-Match 428 The policy’s ETag is required
Update with a stale ETag 412 The ETag no longer matches, for example because the policy changed in the meantime
Change the status field with PATCH 400 The server manages status
Add an unknown service 400 invalidService
Disable the last enabled service 409 atLeastOneServiceRequired
Alert threshold of 150% 400 invalidAlertThreshold
Enable alerting without recipients 400 alertRecipientsRequired
Recipient who isn’t a user in the tenant 400 alertRecipientNotFound
Remove the last recipient while alerting is enabled 400 alertRecipientsRequired
Remove the last assigned group 409 lastAssignedGroup
Change the billing method of the test policy 409 invalidTransition; the cause is open, Microsoft uses this code for a conflict during a concurrent state change

What that means for your scripts: every change to an existing policy starts with a read to get the current ETag and ends with a check of the response. Also, you can’t delete a service. According to the documentation, you set it to disabled, and the entry stays.

What do you use the API for?

The dashboard in the admin center answers the question “What has been consumed?” The API pays off when you have a different question. The points below are ideas that follow from the responses. I built the inventory dashboard further down, and I haven’t tried the rest.

How do you get the data into your own systems?

The responses are JSON, so you can write them wherever your team already works: a list, a database, a ticketing system or a flow. A nightly run could store the credit balance, which gives you the history the API doesn’t have. A ticket could be opened when a user shows noApplicablePolicy. And because policies can be read and changed, you can describe them in a file and compare that with the actual state before anyone changes them in the admin center.

What can you analyze in more detail?

The API gives you credits, not money. You can take the price from your contract, calculate each billing method separately and run scenarios: What does it cost if the pay-as-you-go group consumes twice as much? How far do the prepaid credits go at the pace of the last few weeks? Who is the biggest consumer per service? Answers like these need your own assumptions, and the API supplies the numbers for them.

What do you combine the data with?

The biggest benefit comes when you join the responses with data Microsoft doesn’t send along:

  • Group members from Microsoft Graph: Only then do you know how many people a policy actually covers. My collector script queries the members of the assigned groups for this.
  • Directory data such as department or cost center: This lets you allocate consumption to business units.
  • License assignments and usage reports: Who has a license but doesn’t use it, and who consumes credits without a policy?
  • Your own budgets: Credits set against finance’s plan.

Is there a ready-made dashboard?

This test produced a tool: the Copilot Cost Inventory. Two collector scripts (PowerShell for Windows, zsh for macOS) are read-only and send nothing but GET requests. The result is a JSON file. You drop it onto a single HTML file that runs offline in the browser and uploads nothing. There you see the credit balance, consumption per service and per policy, per-user limit usage, the top consumers and a diagnostic of every API call. I tested the macOS script. I haven’t run the PowerShell script for Windows myself.

In the Lookbook, the dashboard runs with made-up sample data from a fictional tenant, so you can try it there. The interface is in English. You can download the package with the dashboard file, both scripts and instructions there, free and without signing in. The source code is on GitHub under the MIT license. It’s a community project by Copilot Coaching and isn’t affiliated with Microsoft.

Two notes before you use it on your own tenant:

  • The generated JSON file contains names, sign-in names, consumption per person and alert recipients. Don’t share it and don’t put it in a repository.
  • On the first sign-in, the script asks an admin to consent to permissions for the “Microsoft Graph Command Line Tools.” That consent stays in the tenant until an admin removes it. The script points this out itself.

What should you know before you use it?

  • Permissions: Almost all operations support delegated permissions only, meaning a sign-in with a work or school account. Only the credit balance can also be read with an application permission. Creating a policy additionally requires the Billing Administrator or Global Administrator role.
  • Beta: Fields and error codes can change. Re-check a script after Microsoft makes changes.
  • One tenant: I tested the API in a single test tenant. I haven’t measured how it behaves in large tenants with many policies.
  • Write with care: Try every change on a test policy of your own first, the way I did.

If you want to put the API to work in your tenant or join the analysis with your own data, that’s a job for coaching for IT teams and admins.

Sources

As of October 29, 2026. The API is in beta, and fields, permissions and error codes tend to change without notice.